Some of you may remember when I first started building the 43" Magic Mirror that I was intending to put in my room. Well, two months later, I've finally finished it.
I originally was planning to use a 43" OLED panel from LG but they literally don't exist. I found a TCL that had Android TV built-in on sale for $160 (aka the best deal ever) at Target, so I drove all the way down to Christiansburg and grabbed the last available one.
Well, that solves the problem of finding a display, but as soon as I turned on the TV, the Android system decided to start crashing regularly. I just got a
Chromecast Google TV to run Android instead. Well, I still had the issue of actually running the MagicMirror software on the Google TV.
I was originally going to create a Daydream that just loaded a WebView of the MagicMirror interface, but apparently, Google decided that they're now using their own private "Ambient Mode." 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 ADB magic to select it through the shell, but alas, Google removed everything related to Daydreams on the Google TV. I then thought about running a countdown timer in the background that would reset itself on every keypress and it would run the MagicMirror activity when it hits zero.
With the help of an AccessibilityService, I was able to receive keypresses and broadcast them over an intent. I started a service on boot that would receive those keypresses and reset a "watchdog" of some sort (really just a loop that ran every 10s comparing two timestamps.) I ended up adding in behavior that if there was media playing, the watchdog would be constantly reset, causing the MagicMirror never to appear during playback as this was going to function as a TV.
This was working great until I tried to exit out of the activity, and I wasn't able to.
Turns out, if a WebView errors out, there's a bug that prevents it from releasing focus back to the activity, preventing it from being closed. Well, I needed to set up the actual Mirror webpage anyway, so this would be a good time to do so.
Of course, I used Docker, who wouldn't 😁
I hosted the MagicMirror software on our local server here 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)
I installed the app and STILL ran into issues closing the activity. I ended up programmatically disabling the keypress listener when the activity is focused to allow certain keypresses to map to media controls on the MagicMirror interface (play/pause, ff, rewind)
One of the widespread issues with the Google TV device is that its implementation of HDMI-CEC is absolutely atrocious and has trouble supporting anything other than a simple TV. Well, it happened, it wouldn't even turn off the TCL TV. Luckily, they both run Android (and have ADB.) 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.
I went to a couple of local glass suppliers, but when I asked if they sourced Pilkington's MirroView and MirroPane, they literally hung up on me. Well, guess Roanoke Glass won't be getting my business. I called the company who did our windows when we renovated the house, but they didn't have anything currently in stock. I looked around online and found Fab Glass & Mirror. I ended up buying the mirror from them as it had free, insured shipping and it was cheaper than any other retailer.
Well, it came and we had a fun family 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. It worked well enough, or so I thought. I finally got it aligned and mounted, but it took almost a whole day of trial and error for me to get the ~0.5mm thick LCD panel aligned back in the bezel without cracking it.
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?
the answer: nothing. programmable LEDs are the best invention ever. thank u worldsemi.
Well, I originally put the strips around that 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.
To drive the LEDs, I settled on an ESP-12F attached to a custom PCB that ran the WLED firmware. This allowed me to integrate it into Home Assistant and it still supported Hyperion, 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.
Overall, I'm super happy with how this project turned out. I learned a ton doing it and I really love how crisp everything is even with the mirrored finish.