Frameless Magic Mirror

Frameless Magic Mirror

Two years ago, my Dad and I built a Magic Mirror out of an old TV and made a frame for it. I really wanted one for my room, so let's go through my internal monologue of the process.

I wanted to use an OLED display as it would be less bright at night, but nobody manufactured one in the size that I needed. Looking around, I found a LCD TV that had Android built-in on sale at some random Target, so I drove all the way down to there and bought the last one.

scary MSRP price (bought for $169.99)

Well, that solves the problem of finding a display, but as soon as I turned on the TV, the Android system crashed regularly (not a surprise, as these TVs are notorious for having abysmally low amounts of RAM.)  Instead, I used a Google TV to run Android instead. I still had the issue of how I was going to get the MagicMirror software on the Google TV.

Originally, I was going to create a Daydream that just loaded a WebView of the interface, but Google being Google, they decided that they're now using their own private "Ambient Mode" on the GTV. Nothing that a simple pm delete can't fix :p.

I deleted Ambient Mode from the Google TV, and sure enough, there was no screensaver functionality, so I was free to implement my own. This would be the second custom application that I've written for Android. I originally tried to hook into the Daydream system, thinking that I would be able to do some magic to select it through the shell, but that didn't work. I then thought about running a countdown timer in the background that would reset itself on every keypress and it would run an Activity when it hits zero.

With the help of an AccessibilityService, I was able to receive keypresses from the remote, broadcast them to a service that would receive those keypresses, and reset the countdown timer. Additionally, I added logic that ignored the timer ending if there was media playing, which let me still use the TV as normal if I wanted to. This solution was working great until I tried to exit out of my Activity, and I wasn't able to.

The MagicMirror software is intended to be run on the display itself, and while I could do that, it was way more work then I felt like doing, and one of my custom modules required a bit more CPU than the Google TV provided.

Poking around the documentation, there's a serveronly mode that lets you start the service headless and allow other devices to load the MM UI.

I installed the MM software in Docker on my lab and configured it to show the weather, time, some news, and a custom Spotify module that has live lyrics (which I may write about in the future)

Magic Mirror hosted webpage.

I installed the app and it worked! The TV would turn on, you could do whatever, and after 5 minutes of inactivity, the screensaver activity started.

One of the main issues with the Google TV is that its implementation of HDMI-CEC is absolutely atrocious and can be compared to a rock. It wouldn't even turn off the TCL TV, let alone the soundbar. I made an automation in Home Assistant that would manually shut off the TCL when the Google TV was detected to have been turned off.

With the TV setup and out of the way, I needed to source a custom two-way mirror that fit the TCL. I wanted it to have a lip around the edge so you wouldn't be able to see the TV if you were looking directly at it from the front, and to hide LED strips for Hyperion ambient lighting.

I went to a couple of local glass suppliers and asked if they sourced two-way mirror glass. The majority of them quoted prices well above $500 which was way out of my budget. I looked around online and found Fab Glass & Mirror, and ended up buying the mirror from them as it was way cheaper.

Well, it came, and we had a fun family afternoon activity of trying to mount the TV to the glass while keeping it level and centered. I tried to get pictures of this, but it was too stressful. I ended up disassembling the TV down to just the plastic bezel and then aligning & mounting that using heavy-duty 3M mounting tape. That worked until I tried to get the LCD panel back together. Who knew that you weren't supposed to disassemble the TV?

So, with the main pieces of the project finally coming together, I wanted to add something that really made it pop. Well, what's a better thing to add than programmable LEDs?

With the help of everyone's favorite Chinese reseller, I was able to get REELS of ws2812 strips for just $13 each.

I originally put the strips around the bezel on the mirror that I mentioned earlier, but as it's a two-way mirror, there wasn't anything behind it, so you were able to see through the areas where it overhung the TV. I took off the LED strips and covered the areas with standard black craft vinyl and re-attached the strips to the vinyl.

I ran out of black LED strips on the left side oops

To drive the LEDs, I used an ESP8266 running WLED, which allowed me to integrate it into Home Assistant. Hyperion also worked with WLED, which I wanted to use to add Ambilight functionality to the TV.

I installed Hyperion on our local server as well and configured it to send data to the WLED server that ran the LEDs. I used the Hyperion Android Grabber application to send the screen frames over to Hyperion for processing.

I'm super happy with how this project turned out. I learned a lot about Android development in the process, and hopefully the glass doesn't fall off one night.