Who couldn’t use a MagicMirror? I saw this project and immediately wanted to toss our dry-erase calendar in the garbage. Michael Teeuw has done an outstanding job of building a nice extendable framework for us to join in on the fun. Please check out the MagicMirror site as well.
This guide is meant to give people ideas and resources on how to source and build their own MagicMirror. I will also be focusing on constructing the frame so please check out the video link below.
For those who are not familiar with the project, we are basically placing a monitor behind a one-way mirror (semi-transparent mirror). In ideal lighting conditions, everything on the screen that is black presents as a mirror while white (or other high-contrast colors) shine through. My goal was to make a decorative family dashboard which would sync calendars, shopping lists, weather, and possibly AlexaPi (more on that later). The sales pitch was made to my wife about how it would improve our family life and production started.
Parts / Materials
- Glass (Mirror) – Pilkington Mirrorpane
Glass was the most expensive part of my build ($200.00 CDN). Reading though various posts, others said they ended up with a fun house effect when using one-way film on acrylic. I had a local glass supplier cut me this piece of 6mm Pilkington Mirrorpane. I find it works well in the right lighting conditions, if it’s too bright it doesn’t allow much graphics to come through. The manufacturer recommends a light ratio of 8:1 from front to back for good results. It also has an amber hue which looks nice but your stuck with that color tone.
- Screen – 39″ LED TV Insignia NS-39D400NA14
A Craigslist bargain at $150.00 CDN. I had issues with HDMI CEC commands for turning the display on and off but got around that issue another way (more on that later)
- Wood – Walnut Plywood With Solid Edging
I’m a hobbyist woodworker so my frame is made from scrap. There really isn’t that much wood here though and solid wood edging certainly not necessary but I prefer it.
- Raspberry Pi3
A Pi3 is nice if you plan to use the integrated WiFi but others have built them with a Pi2 or even a Pi0
Make the Frame
Check out the following video I made on building of the frame. The design slightly deviated from the original CAD rendering.
Installed modules to date:
As long as you have enabled the alert module (default), the magic mirror will poll every modules associated git repositories and alert you if you are behind on any commits. I thought this was cool but I ended writing the following script in /home/pi/myscripts/mm_update.sh to automate updating to every midnight.
#!/bin/bash # Update modules for d in /home/pi/MagicMirror/modules/* ; do (cd "$d" && git pull && npm install); done # Update MM cd "/home/pi/MagicMirror/"; git pull && npm install # Restart MM sudo /sbin/shutdown -r now
chmod the script to make it executable
chmod +x /home/pi/myscripts/mmm_update.sh
Then edit your crontab:
sudo crontab -e
Add the following line to run the update script every midnight
AlexaPi is an awesome initiative. There are also two MagicMirror modules designed to display or integrate with Alexa, These modules are called MMM-alexa and MMM-awesome-alexa. I was really exited to have Alexa built right into my mirror but found that configuring AlexaPi and the MagicMirror modules to be a little too finiky. I also prefer just having Alexa display her status via a dedicated response LED so I just installed AlexaPi without integrating it into the MagicMirror frame work. For AlexaPi installation, I head over to their wiki for instructions.
My AlexaPi installation combined with a low cost USB microphone does not yield the best results however. Currently, Alexa only listens to men but maybe messing with pocketsphinx or Snowboy might improve those results. Here is a picture of the top of my mirror with the LED and motion sensor mounts.
Motion On / Off
Having the mirror go to sleep while no one is there to admire it was was big on my list. The MMM-PIR-Sensor does this pretty well, especially if your TV native supports all HDMI CEC commands. My TV only supported the status command, for reasons unknown. I chose to use the Pi’s GPIO (PIN 15) to pull the TV’s factory power button the ground, which is effectively simulating a user pressing the power button.
After installing the HDMI CEC utility I created a python script to run as a daemon and monitor the motion sensor and turn the TV on and off when required. I uploaded the script to /home/pi/myscripts/ty_manager.py
</pre> #!/usr/bin/env python import os, sys, subprocess, time, argparse, logging, datetime import RPi.GPIO as GPIO from apscheduler.schedulers.background import BackgroundScheduler PWR_PIN = 15 PIR_PIN = 14 isdisplayon = False def monitor_checkstatus(): global isdisplayon logging.debug('[*] CEC -> check current status of display') process_echo = subprocess.Popen(["echo", "pow", "0"], stdout=subprocess.PIPE, shell=False) process_cec = subprocess.Popen(["cec-client", "-s", "-d", "1"], stdin=process_echo.stdout, stdout=subprocess.PIPE, shell=False) process_echo.stdout.close() ret = process_cec.communicate().splitlines() if 'on' in ret: logging.debug("[*] Display is currently on") isdisplayon = True else: logging.debug("[*] Display is currently off") isdisplayon = False def monitor_toggle(): GPIO.output(15, GPIO.LOW) time.sleep(1) GPIO.output(15, GPIO.HIGH) def main(argv): global isdisplayon parser = argparse.ArgumentParser( description='A Power managment daemon for issuing CEC commands' ) parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) logging.debug('[*] Launching powermanager.py in DEBUG mode') GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(PWR_PIN, GPIO.OUT, initial=GPIO.HIGH) scheduler = BackgroundScheduler() job = scheduler.add_job(monitor_checkstatus, 'interval', minutes=20) scheduler.start() monitor_checkstatus() GPIO.setmode(GPIO.BCM) GPIO.setup(PIR_PIN, GPIO.IN) while True: # PIR triggered if GPIO.input(PIR_PIN): if not isdisplayon: logging.debug('[*] Motion detected, CEC -> Turning on display') monitor_toggle() isdisplayon = True else: if isdisplayon: logging.debug('[*] No motion, CEC -> Turning off display') monitor_toggle() isdisplayon = False time.sleep(1) GPIO.cleanup() if __name__ == "__main__": main(sys.argv) <pre>
Then create a the following systemd service file /usr/lib/systemd/tv_manager.service
[Unit] Description=TV Power Manager Service After=multi-user.target [Service] Type=idle ExecStart=/home/pi/myscripts/tv_manager.py [Install] WantedBy=multi-user.target
That wraps up this build post. Please hit me back with any questions/comments!