How To Make a MagicMirror From Scratch

  • Aaron
  • December 14, 2023
  • 10min
Magic Mirror Finished Product
MagicMirror is an open platform to combine a modern mirror with LED display, i use it for some more practical reasons...

Two issues immediately surfaced up after we moved into our house in Woburn

  1. The baby room gets either too hot or too cold
  2. There are so many windows and doors can be left opened


It would be amazing to have a “display” that shows which doors/windows left open and what temperature for each room is, back in 2017, there weren’t many solutions to centralize all the information in one place

So why not make one?

Of course it would be quite easy to make a web page to display all the information if i could find all the endpoints to fetch, and i can just mount a monitor on the wall like those you see in the bank displaying your place in the queue. but that idea got killed immediately by my wife, we are not a bank and practically nobody can see the text clearly once it’s hanging on the wall.

I came across this really cool MagicMirror community a while back and thought it was cool, and i remember seeing some widgets that showing weather info, a slider showing notes etc, so essentially it’s a hub to display information, awesome!!

I googled all the beautiful MagicMirror photos and sent to my wife

MagicMirror Stock Photo

Not knowing the final products probably would never look that neat, she green-lighted it.

I separated the project into three chunks:

  1. Build the mirror frame
  2. Build the Raspberry Pi that powers the mirror
  3. Code the modules that display all the information i need.

Building the mirror frame

The woodworking part is quite simple, if you have made a picture frame in the past, this is no different, here are the materials i used: ($236)

Item Price
Walnut S4S by the Piece, 3/4" X 3" X 48" from Rockler $30 x 2
Clear Framing Grade Glass (optional, you can replace it with IR touch frame for touch support ) $56
SUPREMETECH 24 x 36 x 0.12 Inch Acrylic See-Through Mirror, 30% Transparent $90
Blackout Privacy Window Vinyl Film $26
Selected pine for mounting support.  $10

For assembling order, check this diagram:

Magic Mirror Assembly Diagram

For my build, here’s what i end up with:  Frame -> Glass -> 2-way mirror -> Blackout film for the reflecting part -> Monitor for display

Some pictures from the woodworking part:


Building the Raspberry Pi that powers the mirror

Materials i used: ($76 total)

Item Price
Raspberry Pi 3 $40
Raspberry Pi Case (for better mounting) $6
Raspberry Pi 3 Model B+ A+ Plus Power Supply Charger AC with Power On/Off Switch  $10
Micro USB memory card  Free
Raspberry Pi Camera Module V2-8 Megapixel,1080p (for gesture control) $20

Steps to build the raspberry pi

Manual Installation

  1. Install raspbian OS on the RPI, (follow this article)
  2. Download and install the latest Node.js version, follow this documentation: Linux based distributions
  3. Clone the repository and check out the master branch: git clone https://github.com/MagicMirrorOrg/MagicMirror
  4. Enter the repository: cd MagicMirror/
  5. Install the application: npm run install-mm
  6. Make a copy of the config sample file: cp config/config.js.sample config/config.js
  7. Start the application: npm run start
    For Server Only use: npm run server .
  8. Create a docker container with Ubuntu 22.04 and repeat the same steps: 2-6.
  9. Once the MagicMirror runs, push the code to my own github

[Update]:

Since then, there are a few more ways to do this, which simplified the process quite a bit

Automatic Installation Scripts

Docker Image

MagicMirror² can be deployed using Docker, head over to this repository  for more information.

Code the modules that display all the information i need.

Here’s a architectural diagram of what i did to accomplish this display:

Magic Mirror Architectural Diagram

Let's talk about XiaoMi Gateway, it's not the easiest IoT device to pull information from but here are the steps i followed: 

// For configurations:
 config: {
        gatewayIP: '192.168.1.75',
        gatewayToken: '[your gateway token, you can get it from miio]',
        outsideSensorId: '158d000223f705',
        showWindow: true,
        celcius: false,
        showVentilation: true,
        showLights: false,
        audioNotifications: false,
        showTrend: true,
        rooms: [
          {
            name: 'Outside',
            sortOrder: 1,
            devices: ['158d000223f705']
          },
          {
            name: 'Master',
            sortOrder: 2,
            devices: ['158d0001f2abe2']
          },
          {
            name: 'Kayley',
            sortOrder: 3,
            devices: ['158d00019cbad8']
          },
}

Steps to install miio:

pip install python-miio

Alternatively, you can install the latest development version from GitHub:

pip install git+https://github.com/rytilahti/python-miio.git

The miiocli command allows controlling supported devices from the command line, given that you know their IP addresses and tokens.

The simplest way to acquire the tokens is by using the miiocli cloud command, which fetches them for you from your cloud account using micloud:

miiocli cloud
                                                                            Username: example@example.com
                                                                            Password:
                                                                            == name of the device (Device offline ) ==
                                                                                Model: example.device.v1
                                                                                Token: b1946ac92492d2347c6235b4d2611184
                                                                                IP: 192.168.xx.xx (mac: ab:cd:ef:12:34:56)
                                                                                DID: 123456789
                                                                                Locale: cn
                                                                            

Alternatively, see the docs for other ways to obtain them.

After you have your token, you can start controlling the device. First, you can use info to get some generic information from any (even yet unsupported) device:

miiocli device --ip <ip> --token <token> info
                                                                            Model: rockrobo.vacuum.v1
                                                                            Hardware version: MW300
                                                                            Firmware version: 1.2.4_16
                                                                            Supported using: RoborockVacuum
                                                                            Command: miiocli roborockvacuum --ip 127.0.0.1 --token 00000000000000000000000000000000
                                                                            Supported by genericmiot: True
                                                                            
 

To start the mirror:

npm run server

what fascinates me the most is that the mirror system sits on top of Electron,  which is a framework to build desktop app that written completely in JS. Sounds horrible right? nope, it turns out to be really cool.

npm start dev  

for debugging. Since it's written in JS, you can just step through the code in the browser.

 

Additional useful information i compiled:

The config.js file is a challenge for new users. It is javascript code and gets included into the MM framework in runtime, meaning it needs to be free of any syntax errors. ( Debugging config.js)
That is quite a challenge, especially if you're using the console or simple text editors to edit config.js.
Fortunately there is an easy-to-understand implemented config check (a so-called js linter).
Run this in the Magic Mirror folder

npm run config:check

It will create an output showing all syntax errors.
Move into the respective line in the config.js and find the error. If you use nano as editor for your console, don't forget the -c flag which includes line numbers

nano -c config/config.js

Here's a video of it i took after i put on the led lights (of course)