So, I found the right type of mirror, bought the monitor, built a new casing, installed the hardware and configured the Raspberry Pi. Now it’s time for the final part of the project: the development of the interface.
Edit 2016/04/11: A new version of the interface is available. Including an installer and integrated web server.
Requirements & Features
When I started the project, I figured the interface would not allow any direct interaction with using the mirror. This would result in grease and smudges on my shiny mirror, but more important: there are better devices for user interaction. I wanted the Magic Mirror to be a passive source of information.
What was even more important is the fact that the mirror should be usable as a mirror, and thus it should not be completely filled with (useless) information. Only the outer corners should be used for content. Leaving enough room to see my shiny self.
If figured I needed to following content to fulfill my need for information:
- A Compliment What’s better then to start your day with a nice compliment?
- Weather That shirt I’m wearing? Looks nice! But is it warm enough to wear a t-shirt?
- Clock and calendar Am I in a hurry? Or is there enough time to enjoy my reflection?
- News feed Should I only be worried about my shiny appearance? Or is there more to worry about?
Of course, there are plenty of possibilities for the future. But for now above list will suffice.
Basic setup
As mentioned before, the interface is not a magical application built on top the Raspberry Desktop. It’s simply a full-screen website. This allows me to use HTML, CSS and Javascript. And as a added bonus, it allows me to develop and test the interface on my Mac, before pushing it to the Magic Mirror.
In addition to some self written code, I use a few opensource libraries to speed things up:
As almost any site, Magic Mirror uses Jquery to ease the DOM manipulation. Perfect for lazy people like me.
This will help me to do some easy timestamp manipulation. A huge timesaver when working with dates and times.
A convinient way to convert RSS feeds into javascript usable JSON data.
Does some conversion of iCal data to JSON. Unfortunately this Library isn’t very polished, so it needed some additional work.
Above libraries, combined with my own HTML and Javascript is enough to make the Mirror do the Magic.
Design
Of course, my Magic Mirror needs a shiny design. And since I’m a hardcore Apple Fanboy, this design should fit in Apple’s Design Guidelines:
Bezels, gradients, and drop shadows sometimes lead to heavier UI elements that can overpower or compete with the content. Instead, focus on the content and let the UI play a supporting role.
Use plenty of negative space. Negative space makes important content and functionality more noticeable and easier to understand. Negative space can also impart a sense of calm and tranquility, and it can make an app look more focused and efficient.
How to achieve this? Clean typography by using Helvetica Neue, and matching iconography for the weather information.
Since the mirror will only function as a mirror when there’s no light behind the mirror. It’s important to use a black background. For the best contrast the content will therefor be white. And some shades of grey. Let’s say 50 …
Of course I could add some colors, but for now i go for the clean black and white approach. I didn’t want my mirror to be more colorful than my own reflection.
API’s
To retrieve the data I want to display on the Mirror, I use some open API’s and Feeds. For those of you who don’t know what an API is, Wikipedia has an wonderfull description:
In computer programming, an application programming interface (API) specifies how some software components should interact with each other.
I lust like to look at an API like all the connections on the back of your DVD player: the device becomes much more useful when you connect other devices to it. Those connections are essentially API’s. API’s make stuff powerful. And fun … for the average nerd.
Openweathermap.org
Openweathermap has an excellent API for free weather and forecast data. It allows you to do a query based on a location and specify what data is desired. In this case, I use two links: one for the current weather. And one for the forecast.
iCal Calendar
iCloud allows you to share an calendar using the iCal format. Now, since javascript is not allowed to do such a request (because of Cross-site scripting security), I need to open this data via a PHP proxy. This is actually pretty easy. It’s only 3 lines of code:
<?php
$url = 'https://p01-calendarws.icloud.com/ca/subscribe/1/mysupersecreticloudhash';
echo file_get_contents($url);
This will make the calendar available on the same server as the interface, by just requestingcalendar.php
.
The earlier mentioned iCal parser helps me to parse the information into usable information. Unfortunately, iCloud uses some none standard tags in their feeds, so I added some extra lines of parsing script to my javascript file.
NOS News Feed
The news feed is just the RSS news feed of Holland’s public broadcasting cooperation. Unfortunately they don’t support a JSON format, therefore I use the FeedToJson plugin to convert the RSS data to JSON.
All other content, like the current date and time, and the compliments are all just some simple javascripts.
Auto refresh
Since you made it so far in this blogpost, you might be ready for some more complex info. Buckle up, and read on …
During the development I stumbled into one discomfort of not heaving a keyboard and mouse connected to the Magic Mirror: If I updated the interface, there was no easy way to refresh the site on the Magic Mirror. The easiest solution was to restart the whole Raspberry, but that would take me ages to check every update.
Since I update te files using the GIT version control system, I figured every update has it’s own commit hash, which I was able to readout using PHP. This gave me the idea to add a small piece of script that compares the commit hash on the localhost webserver and the one that it currently displayed. If those two don’t match, the script will reload the site and display the latest version.
To get the current commit hash on webserver, I used the following PHP code:
<?php
echo json_encode(array('gitHash'=>trim(`git rev-parse HEAD`)));
The comparison is done in the main javascript file. But this is only possible if the HTML file has the hash of the current version available:
<script type="text/javascript">
var gitHash = '<?php echo trim(`git rev-parse HEAD`) ?>';
</script>
Now, the comparison is pretty straight forward, and done every 3 seconds:
(function checkVersion()
{
$.getJSON('githash.php', {}, function(json, textStatus) {
if (json) {
if (json.gitHash != gitHash) {
window.location.reload();
window.location.href=window.location.href;
}
}
});
setTimeout(function() {
checkVersion();
}, 3000);
})();
All this magic allows me to simply update the Magic Mirror interface, by logging into the Raspberry using SSH, changing to the appropriate folder, and executing a git pull
.
Show me the code!
Ok, ok… You might be a bit curious how everything added up. Therefor all code is available on GitHub. But I must warn you: the code is poorly commented, filled with spagetty code, and full of TODO’s. But hey, If you’re feeling adventurous, feel free to dive into the code.
The future
Of course, the Magic Mirror is capable of much more. It will be an ongoing process. And any suggestions of new features are highly appreciated. Let me know what you think I should add to the interface. But remember. Less is more. :)
This concludes the project for now. All tough a lot of additions might follow. Keep an eye on my blog, I’ll post some extra photo’s to show the end result.