Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Andrea S.
Published © CC BY

MagicMirror Alarm Clock

A compact alarm clock for your bedside table, with time, date, weather, news... and a relaxing sound to wake you up.

BeginnerFull instructions provided4 hours11,606
MagicMirror Alarm Clock

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
You may use versions 2, 3 or 4, with just an 8GB microSD. Also remember a suitable power adapter.
×1
Adafruit PiTFT 3.5" Touch Screen
This is the one I already had and you can see in the pictures
×1
Adafruit PiTFT 3.5" plus
This model is the new one, adapted to perfectly fit the new Raspberry 2, 3 or 4.
×1
Adafruit PiTFT Pibow+ Kit
The case is optional and you may choose a different one, just make sure you can easily connect your screen to the Raspberry Pi in its case.
×1
Generic Bluetooth speaker with USB charging cable
×1

Software apps and online services

Raspbian
Raspberry Pi Raspbian
The default OS for Raspberry Pi
MagicMirror²
The open source modular smart mirror platform
Free online sounds
Download mp3 noises & sound effects (sfx) for free

Story

Read more

Code

MagicMirror (day mode) config.js file

JavaScript
Start from this config file to obtain the day time screen configuration, modify your city name and id, insert your own Openweathermap key, choose your RSS feed news source and set the optional Tado module username and password.
/* Magic Mirror Config Sample
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 *
 * For more information on how you can configure this file
 * See https://github.com/MichMich/MagicMirror#configuration
 *
 */

var config = {
        address: "0.0.0.0",     // Address to listen on, can be:
                                // - "localhost", "127.0.0.1", "::1" to listen on loopback interface
                                // - another specific IPv4/6 to listen on a specific interface
                                // - "0.0.0.0", "::" to listen on any interface
                                // Default, when address config is left out or empty, is "localhost"
        port: 8080,
        basePath: "/",  // The URL path where MagicMirror is hosted. If you are using a Reverse proxy
                        // you must set the sub path here. basePath must end with a /
        ipWhitelist: ["127.0.0.1", "192.168.1.0/24", "::ffff:127.0.0.1", "::1"],       // Set [] to allow all IP addresses
                                                                                        // or add a specific IPv4 of 192.168.1.5 :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
                                                                                        // or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],

        useHttps: false,        // Support HTTPS or not, default "false" will use HTTP
        httpsPrivateKey: "",    // HTTPS private key path, only require when useHttps is true
        httpsCertificate: "",   // HTTPS Certificate path, only require when useHttps is true

        language: "it",
        logLevel: ["ERROR"],
        timeFormat: 24,
        units: "metric",
        zoom: 1.25,

        // serverOnly:  true/false/"local" ,
        // local for armv6l processors, default
        //   starts serveronly and then starts chrome browser
        // false, default for all NON-armv6l devices
        // true, force serveronly mode, because you want to.. no UI on this device

        modules: [
                {
                        module: "alert",
                },
                {
                        module: "clock",
                        position: "top_left",
                        config: {
                                dateFormat: "dddd, D MMM YYYY"
                        },
                },
                {
                        module: 'MMM-AlarmClock',
                        position: 'top_left',
                        config: {
                                alarms: [
                                                {time: "7:00", days: [1,2,3,4,5], title: "Wake up", message: "It's 7.00!", sound: "birds-in-the-forest.mp3"},
                                ],
                                format: 'dddd @ H:mm',
                                touch: 'true',
                                volume: 0.50,
                                timer: 180 * 1000
                        }
                },
                {
                        module: 'MMM-Tado',
                        position: 'top_left', // This can be any of the regions.
                        config: {
                                username: 'your_email@address.com',
                                password: 'your_password',
                                updateInterval: 600000
                        }
                },
                {
                        module: "currentweather",
                        position: "top_right",
                        config: {
                                location: "Your_city",
                                locationID: "1234567", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
                                appid: "_your_free_key_number_goes_here_",
                                decimalSymbol: ",",
                                appendLocationNameToHeader: false
                        }
                },

                {
                        module: "weatherforecast",
                        position: "top_right",
                        header: "Previsioni meteo:",
                        config: {
                                location: "Your_city",
                                locationID: "1234567", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
                                appid: "_same_free_key_number_as_above_",
                                maxNumberOfDays: 3,
                                showRainAmount: false,
                                colored: true,
                                decimalSymbol: ","
                        }
                },
                {
                        module: "newsfeed",
                        position: "bottom_left",
                        config: {
                                feeds: [
                                        {
                                                title: "Ultim'ora Televideo",
                                                url: "https://www.servizitelevideo.rai.it/televideo/pub/rss101.xml"
                                        }
                                ],
                                showSourceTitle: true,
                                showPublishDate: true,
                                broadcastNewsFeeds: false,
                                broadcastNewsUpdates: false,
                                reloadInterval: 600000,
                                ignoreOldItems: true,
                                ignoreOlderThan: 43200000 // 12h
                        }
                },
                {
                        module: "MMM-Online-State",
                        position: "bottom_right",
                },
        ]
};


/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {module.exports = config;}

MagicMirror (night mode) config.js file

JavaScript
This is the simpler configuration file to display only basic info during the night.
/* Magic Mirror Config Sample
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 *
 * For more information on how you can configure this file
 * See https://github.com/MichMich/MagicMirror#configuration
 *
 */

var config = {
        address: "0.0.0.0",     // Address to listen on, can be:
                                // - "localhost", "127.0.0.1", "::1" to listen on loopback interface
                                // - another specific IPv4/6 to listen on a specific interface
                                // - "0.0.0.0", "::" to listen on any interface
                                // Default, when address config is left out or empty, is "localhost"
        port: 8080,
        basePath: "/",  // The URL path where MagicMirror is hosted. If you are using a Reverse proxy
                        // you must set the sub path here. basePath must end with a /
        ipWhitelist: ["127.0.0.1", "192.168.1.0/24", "::ffff:127.0.0.1", "::1"],       // Set [] to allow all IP addresses
                                                                                        // or add a specific IPv4 of 192.168.1.5 :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
                                                                                        // or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],

        useHttps: false,        // Support HTTPS or not, default "false" will use HTTP
        httpsPrivateKey: "",    // HTTPS private key path, only require when useHttps is true
        httpsCertificate: "",   // HTTPS Certificate path, only require when useHttps is true

        language: "it",
        logLevel: ["ERROR"],
        timeFormat: 24,
        units: "metric",
        zoom: 1.25,

        // serverOnly:  true/false/"local" ,
        // local for armv6l processors, default
        //   starts serveronly and then starts chrome browser
        // false, default for all NON-armv6l devices
        // true, force serveronly mode, because you want to.. no UI on this device

        modules: [
                {
                        module: "alert",
                },
                {
                        module: "clock",
                        position: "middle_center",
                        config: {
                                dateFormat: "dddd, D MMMM YYYY",
                                clockBold: true,
                                displayType: "both",
                                analogSize: "240px",
                                analogFace: "face-010",
                                secondsColor: "#FF4000"
                        },
                },
                {
                        module: "MMM-Online-State",
                        position: "bottom_right",
                },
        ]
};


/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {module.exports = config;}

MagicMirror config.js file with ModuleScheduler

JavaScript
In this configuration example I use the ModuleScheduler to change what is displayed during the day (7-23) and during the night (23-7).
/* Magic Mirror Config Sample
 *
 * By Michael Teeuw https://michaelteeuw.nl
 * MIT Licensed.
 *
 * For more information on how you can configure this file
 * See https://github.com/MichMich/MagicMirror#configuration
 *
 */

var config = {
        address: "0.0.0.0",     // Address to listen on, can be:
                                // - "localhost", "127.0.0.1", "::1" to listen on loopback interface
                                // - another specific IPv4/6 to listen on a specific interface
                                // - "0.0.0.0", "::" to listen on any interface
                                // Default, when address config is left out or empty, is "localhost"
        port: 8080,
        basePath: "/",  // The URL path where MagicMirror is hosted. If you are using a Reverse proxy
                        // you must set the sub path here. basePath must end with a /
        ipWhitelist: ["127.0.0.1", "192.168.10.0/24", "::ffff:127.0.0.1", "::1"],       // Set [] to allow all IP addresses
                                                                                        // or add a specific IPv4 of 192.168.1.5 :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
                                                                                        // or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
                                                                                        // ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],

        useHttps: false,        // Support HTTPS or not, default "false" will use HTTP
        httpsPrivateKey: "",    // HTTPS private key path, only require when useHttps is true
        httpsCertificate: "",   // HTTPS Certificate path, only require when useHttps is true

        language: "it",
        logLevel: ["ERROR"],
        timeFormat: 24,
        units: "metric",
        zoom: 1.25,

        // serverOnly:  true/false/"local" ,
        // local for armv6l processors, default
        //   starts serveronly and then starts chrome browser
        // false, default for all NON-armv6l devices
        // true, force serveronly mode, because you want to.. no UI on this device

        modules: [
                {
                        module: "alert",
                },
                {
                        module: 'MMM-ModuleScheduler',
                        config: {
                                global_schedule: [
                                        {from: '00 07 * * *', to: '00 23 * * *', groupClass: 'daytime_scheduler'},
                                        {from: '00 23 * * *', to: '00 07 * * *', groupClass: 'nighttime_scheduler'},
                                ]
                        }
                },
                {
                        module: "clock",
                        position: "top_left",
                        config: {
                                dateFormat: "dddd, D MMM YYYY"
                        },
                        classes: 'daytime_scheduler'
                },
/*              This is a popular module to show the Earth in real time!
                {
                        module: "MMM-EARTH",
                        position: "top_left",
                        config: {
                                mode: "naturalThumb",
                                rotateInterval: 30*1000,
                                animationSpeed: 2000,
                                updateInterval: 60*60*1000,
                                MaxWidth: "100%",
                                MaxHeight: "100%",
                        },
                        classes: 'nighttime_scheduler'
                },
*/                {
                        module: 'MMM-AlarmClock',
                        position: 'top_left',
                        config: {
                                alarms: [
                                                {time: "07:00", days: [1,2,3,4,5], title: "Wakeup", message: "It's 7.00am!", sound: "birds-in-the-forest.mp3"}
                                ],
                                format: 'dddd @ H:mm',
                                touch: 'true',
                                volume: 0.50,
                                timer: 180 * 1000
                        }
                },
                {
                        module: 'MMM-Tado',
                        position: 'top_left', // This can be any of the regions.
                        config: {
                                username: 'user_name@domain.com',
                                password: 'you_password',
                                updateInterval: 600000
                        },
                        classes: 'daytime_scheduler'
                },
                {
                        module: "currentweather",
                        position: "top_right",
                        config: {
                                location: "Your_city",
                                locationID: "1234567", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
                                appid: "********************************",
                                decimalSymbol: ",",
                                appendLocationNameToHeader: false
                        },
                        classes: 'daytime_scheduler'
                },

                {
                        module: "weatherforecast",
                        position: "top_right",
                        header: "Previsioni meteo:",
                        config: {
                                location: "Your_city",
                                locationID: "1234567", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
                                appid: "********************************",
                                maxNumberOfDays: 3,
                                showRainAmount: false,
                                colored: true,
                                decimalSymbol: ","
                        },
                        classes: 'daytime_scheduler'
                },
                {
                        module: "newsfeed",
                        position: "bottom_left",
                        config: {
                                feeds: [
                                        {
                                                title: "Ultim'ora Televideo",
                                                url: "https://www.servizitelevideo.rai.it/televideo/pub/rss101.xml"
                                        }
                                ],
                                showSourceTitle: true,
                                showPublishDate: true,
                                broadcastNewsFeeds: false,
                                broadcastNewsUpdates: false,
                                reloadInterval: 600000,
                                ignoreOldItems: true,
                                ignoreOlderThan: 43200000 // 12h
                        },
                        classes: 'daytime_scheduler'
                },
                {
                        module: "MMM-Online-State",
                        position: "bottom_right",
                },
                {
                        module: "clock",
                        position: "top_right",
                        config: {
                                dateFormat: "dddd, D MMMM YYYY",
                                clockBold: true,
                                displayType: "both",
                                analogSize: "240px",
                                analogFace: "face-010",
                                secondsColor: "#FF4000",
                                lat: 45.079208,
                                lon: 7.533648
                        },
                        classes: 'nighttime_scheduler'
                }

        ]
};


/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {module.exports = config;}

main.css

CSS
I made slight modifications to improve the screen aspect (or simply customize it to my preference).
You may need different settings for different screen sizes and resolutions.
html {
  cursor: none;
  overflow: hidden;
  background: #000;
}

::-webkit-scrollbar {
  display: none;
}

body {
  margin: 20px;
  position: absolute;
  height: calc(100% - 40px);
  width: calc(100% - 40px);
  background: #000;
  color: #aaa;
  font-family: "Roboto Condensed", sans-serif;
  font-weight: 400;
  font-size: 2em;
  line-height: 1.5em;
  -webkit-font-smoothing: antialiased;
}

/**
 * Default styles.
 */

.dimmed {
  color: #777;
}

.normal {
  color: #999;
}

.bright {
  color: #fff;
}

.xsmall {
  font-size: 18px;
  line-height: 20px;
}

.small {
  font-size: 22px;
  line-height: 25px;
}

.medium {
  font-size: 32px;
  line-height: 35px;
}

.large {
  font-size: 65px;
  line-height: 65px;
}

.xlarge {
  font-size: 85px;
  line-height: 85px;
  letter-spacing: -3px;
}

.thin {
  font-family: Roboto, sans-serif;
  font-weight: 100;
}

.light {
  font-family: "Roboto Condensed", sans-serif;
  font-weight: 300;
}

.regular {
  font-family: "Roboto Condensed", sans-serif;
  font-weight: 400;
}

.bold {
  font-family: "Roboto Condensed", sans-serif;
  font-weight: 700;
}

.align-right {
  text-align: right;
}

.align-left {
  text-align: left;
}

header {
  text-transform: uppercase;
  font-size: 15px;
  font-family: "Roboto Condensed", Arial, Helvetica, sans-serif;
  font-weight: 400;
  border-bottom: 1px solid #666;
  line-height: 15px;
  padding-bottom: 5px;
  margin-bottom: 10px;
  color: #999;
}

sup {
  font-size: 50%;
  line-height: 50%;
}

/**
 * Module styles.
 */

.module {
  margin-bottom: 30px;
}

.region.bottom .module {
  margin-top: 20px;
  margin-bottom: 0;
}

.no-wrap {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pre-line {
  white-space: pre-line;
}

/**
 * Region Definitions.
 */

.region {
  position: absolute;
}

.region.fullscreen {
  position: absolute;
  top: -10px;
  left: -20px;
  right: -20px;
  bottom: -10px;
  pointer-events: none;
}

.region.fullscreen * {
  pointer-events: auto;
}

.region.right {
  right: 0;
  text-align: right;
}

.region.top {
  top: 0;
}

.region.top .container {
  margin-bottom: 25px;
}

.region.bottom .container {
  margin-top: 25px;
}

.region.top .container:empty {
  margin-bottom: 0;
}

.region.top.center,
.region.bottom.center {
  left: 50%;
  transform: translateX(-50%);
}

.region.top.right,
.region.top.left,
.region.top.center {
  top: 100%;
}

.region.bottom {
  bottom: 0;
}

.region.bottom .container:empty {
  margin-top: 0;
}

.region.bottom.right,
.region.bottom.center,
.region.bottom.left {
  bottom: 100%;
}

.region.bar {
  width: 100%;
  text-align: center;
}

.region.third,
.region.middle.center {
  width: 100%;
  text-align: center;
  transform: translateY(-50%);
}

.region.upper.third {
  top: 33%;
}

.region.middle.center {
  top: 50%;
}

.region.lower.third {
  top: 66%;
}

.region.left {
  text-align: left;
}

.region table {
  width: 100%;
  border-spacing: 0;
  border-collapse: separate;
}

Credits

Andrea S.

Andrea S.

5 projects • 19 followers
Technology enthusiast, problem solver, creative thinker!

Comments