For a long time I was looking for a way to display the data I collect with NodeRed from my SmartHome comfortably on the MagicMirror.
Thanks to the many plugins for the MagicMirror and NodeRed, this was implemented faster than expected. How it works is described in the following article.
Safety instructions
I know the following notes are always kind of annoying and seem unnecessary. Unfortunately, many people who knew "better" have lost eyes, fingers or other things due to carelessness or injured themselves. Data loss is almost negligible in comparison, but even these can be really annoying. Therefore, please take five minutes to read the safety instructions. Because even the coolest project is not worth injury or other trouble.
https://www.nerdiy.de/sicherheitshinweise/
Affiliate links/advertising links
The links to online shops listed here are so-called affiliate links. If you click on such an affiliate link and make a purchase via this link, Nerdiy.de will receive a commission from the relevant online shop or provider. The price does not change for you. If you make your purchases via these links, you support Nerdiy.de in being able to offer other useful projects in the future. 🙂
Requirements
Helpful articles:
Before you start with the installation you should prepare the RaspberryPi so that it is accessible via the network and controllable via SSH.
The following three articles describe what needs to be done to prepare the RaspberryPi:
RaspberryPi – setup for nerdiys!
RaspberryPi – The first configuration!
RaspberryPi – Control the RaspberryPi via SSH
MagicMirror - Installing the required software
MagicMirror - Install 3rd party modules
Required material:
In the following list you will find all the parts you need to implement this article.
Log into the NodeRed configuration interface
Before you can edit your NodeRed configuration, you must - if activated - first log into the NodeRed configuration interface.
Creating the data source in NodeRed as JSON
In this example, the MagicMirror displays data from the RaspberryPI running NodeRed.
NodeRed provides this data as JSON, which the MagicMirror fetches at regular intervals and displays on its screen. You don't need to install any new nodes, because the data source is assembled from the standard nodes.
To do this, you need to build the following flow.
It is easier to insert the following node code:
[{"id":"cc7a1b10.a7c038","type":"http in","z":"8c9f8f17.13eb78","name":"","url":"/daten.json","method":"get","upload":false,"swaggerDoc":"","x":320,"y":460,"wires":[["61e489ce.08eb68"]]},{"id":"89f4552e.8cc4f8","type":"http response","z":"8c9f8f17.13eb78","name":"","x":1040,"y":460,"wires":[]},{"id":"ced95c01.75153","type":"change","z":"8c9f8f17.13eb78","name":"Set Headers","rules":[{"t":"set","p":"headers","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"headers.content-type","pt":"msg","to":"application/json","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":880,"y":460,"wires":[["89f4552e.8cc4f8"]]},{"id":"a5b108a6.e68c88","type":"template","z":"8c9f8f17.13eb78","name":"page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{ }, "data": [ { "name": "RPi Temp", "value":"{{temp}}°C", "lastUpdate": "{{temp-timestamp}}" }, { }, "name": "CPU Load", "value":"{{load}}%", "lastUpdate":"{{load-timestamp}}" }, { }, "name": "Free Memory", "value":"{{free}}MB", "lastUpdate":"{{free-timestamp}}" } ] }","output":"str","x":720,"y":460,"wires":[["ced95c01.75153"]]},{"id":"c088c2a8.b53bc","type":"comment","z":"8c9f8f17.13eb78", "name": "Json Feed to feed the MagicMirror", "info":"", "x":240, "y":80, "wires":[]},{"id": "61e489ce.08eb68","type":"change","z":"8c9f8f17.13eb78","name":"Copy time","rules":[{"t":"set","p":"temp","pt":"msg","to":"temp","tot":"flow"},{"t":"set","p":"temp-timestamp","pt":"msg","to":"temp-timestamp","tot":"flow"},{"t":"set","p":"load","pt":"msg","to":"load","tot":"flow"},{"t":"set","p":"load-timestamp","pt":"msg","to":"load-timestamp","tot":"flow"},{"t":"set","p":"free","pt":"msg","to":"free","tot":"flow"},{"t":"set","p":"free-timestamp","pt":"msg","to":"free-timestamp","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":460,"wires":[["a5b108a6.e68c88"]]},{"id": "b64f17d1.b71778", "type": "comment", "z": "8c9f8f17.13eb78", "name": "Incoming data is cached here for later sending", "info":"", "x":480, "y":140, "wires":[]},{"id": "9eede084.b713a", "type": "comment", "z": "8c9f8f17.13eb78", "name": "Here the stored data are delivered as Json", "info":"", "x":410, "y":420, "wires":[]},{"id": "877b026b.7bbd9","type":"exec","z":"8c9f8f17.13eb78","command":"vcgencmd measure_temp","addpay":false,"append":"","useSpawn":"","timer":"","name":"RPi Temp.","x":510,"y":220,"wires":[["c71030c9.e8723"],[],[]]},{"id":"e2c23c0f.e6896","type":"inject","z":"8c9f8f17.13eb78","name":"","topic":"","payload":"","payloadType":"date","repeat":"10","crontab":"","once":false,"onceDelay":"","x":310,"y":220,"wires":[["877b026b.7bbd9","bd2a3aa8.b05be8","f6021bf6.b47108"]]},{"id":"c71030c9.e8723","type":"function","z":"8c9f8f17.13eb78","name":"cutString","func":"str = msg.payload msg.payload = str.substring(5,9); return msg;","outputs":1,"noerr":0,"x":700,"y":220,"wires":[["38abd283.af271e"]]},{"id":"bd2a3aa8.b05be8","type":"exec","z":"8c9f8f17.13eb78", "command": "top -d 1 -b -n2 | grep "Cpu(s)"|tail -n 1 | awk '{print $2 + $4}'", "addpay":false,"append":"","useSpawn":"","timer":"","oldrc":false,"name":"CPU Load","x":510,"y":280,"wires":[["966babc4.47d538"],[],[]]},{"id":"f6021bf6.b47108","type":"exec","z":"8c9f8f17.13eb78", "command": "free | grep Mem | awk '{print 100*($4+$6+$7)/$2}'", "addpay":false, "append":"", "useSpawn":"", "timer":"", "name": "Free Memory", "x":510, "y":340, "wires":[["350be0e6.dc723"],[],[]]},{"id":"ff73e7b0.560078","type":"change","z":"8c9f8f17.13eb78","name":"Store time","rules":[{"t":"set","p":"temp","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"temp-timestamp","pt":"flow","to":"timestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":220,"wires":[[]]},{"id":"ec6a82fb.238ff","type":"change","z":"8c9f8f17.13eb78","name":"Store time","rules":[{"t":"set","p":"load","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"load-timestamp","pt":"flow","to":"timestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":280,"wires":[[]]},{"id":"bd9b96f7.e4c268","type":"change","z":"8c9f8f17.13eb78","name":"Store time","rules":[{"t":"set","p":"free","pt":"flow","to":"payload","tot":"msg"},{"t":"set","p":"free-timestamp","pt":"flow","to":"timestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1170,"y":340,"wires":[[]]},{"id":"38abd283.af271e", "type": "function", "z": "8c9f8f17.13eb78", "name": "addTimestamp", "func": "msg.payload = msg.payload; var now = new Date(); var Hours=now.getHours(); var Minutes=now.getMinutes(); var Seconds=now.getSeconds(); if (Seconds<10) Seconds="0"+Seconds; if (Minutes<10) Minutes="0"+Minutes; if (Hours<10) Hours="0"+Hours; msg.timestamp=Hours+": "+Minutes+": "+Seconds; return msg;","outputs":1,"noerr":0,"x":960,"y":220,"wires":[["ff73e7b0.560078"]]},{"id":"9a625c6e.b43da","type":"function","z":"8c9f8f17.13eb78","name":"addTimestamp","func":"msg.payload = msg.payload; var now = new Date(); var Hours=now.getHours(); var Minutes=now.getMinutes(); var Seconds=now.getSeconds(); if (Seconds<10) Seconds="0"+Seconds; if (Minutes<10) Minutes="0"+Minutes; if (Hours<10) Hours="0"+Hours; msg.timestamp=Hours+": "+Minutes+": "+Seconds; return msg;","outputs":1,"noerr":0,"x":960,"y":280,"wires":[["ec6a82fb.238ff"]]},{"id":"a85eaa63.cad4a8","type":"function","z":"8c9f8f17.13eb78","name":"addTimestamp","func":"msg.payload = msg.payload; var now = new Date(); var Hours=now.getHours(); var Minutes=now.getMinutes(); var Seconds=now.getSeconds(); if (Seconds<10) Seconds="0"+Seconds; if (Minutes<10) Minutes="0"+Minutes; if (Hours<10) Hours="0"+Hours; msg.timestamp=Hours+": "+Minutes+": "+Seconds; return msg;","outputs":1,"noerr":0,"x":960,"y":340,"wires":[["bd9b96f7.e4c268"]]},{"id":"350be0e6.dc723","type":"function","z":"8c9f8f17.13eb78","name":"deleteWhitespace","func":"str = msg.payload msg.payload = str.trim(); return msg;","outputs":1,"noerr":0,"x":730,"y":340,"wires":[["a85eaa63.cad4a8"]]},{"id":"966babc4.47d538","type":"function","z":"8c9f8f17.13eb78","name":"deleteWhitespace","func":"str = msg.payload msg.payload = str.trim(); return msg;","outputs":1,"noerr":0,"x":730,"y":280,"wires":[["9a625c6e.b43da"]]}]
Now you will see the address (but pay attention to whether you have to prefix it with “https://” or “http://”.
https://IP_EURER_NODE_RED_INSTALLATION:1880/daten.json
will display a JSON with the data you entered. This can now in turn be displayed by a MagicMirror plugin on it.
Installing the module
In order for you to be able to display the data provided to you by NodeRed as JSON on the MagicMirror, you must then install the “MMM-JsonTable” module. You can find it under https://github.com/timdows/MMM-JsonTable.
Install this on your RaspberryPi. How to install modules is described in the following article:
MagicMirror - Install 3rd party modules
Configuration of the module
The configuration of the module is kept simple, as the structure of the displayed data is given by the JSON.
sudo nano ~/MagicMirror/config/config.js
{ module: 'MMM-JsonTable', position: 'top_right', header: 'raspi-status', config: { url: 'https://IP_EURER_NODE_RED_INSTALLATION:1880/daten.json', // Required arrayName: 'data', // Optional tryFormatDate: false } }
Modification of the module for self-signed SSL certificates
Unfortunately, there is a problem with the MagicMirror plugin (current: November 2018). This does not allow HTTPS connections if the SSL certificate in question is self-signed.
That is, if you have installed your NodeRed installation as described in the post NodeRed - Encrypt connection secured with a self-signed SSL certificate, the MagicMirror plugin will not be able to load or display the data from the JSON.
To solve this problem there is a small workaround that disables this security feature. This means the MagicMirror plugin can accept self-signed SSL certificates and displays the data of your JSON.
To do this, change to the module folder of the MagicMirror module you just installed.
cd MagicMirror/modules/MMM-JsonTable/
There you open the file “node_helper.js” with the following command:
sudo nano node_helper.js
In the opened file you should now find the line with the following content:
request({ url: url, method: 'GET'}, function (error, response, body) {
In this line you now have to insert the command “rejectUnauthorized: false” after the “…method: 'GET'”.
The line should then look like this:
request({ url: url, method: 'GET', rejectUnauthorized: false}, function (error, response, body){
Last but not least you have to restart your MagicMirror installation by entering the following command:
pm2 restart mm
After restarting and reloading the MagicMirror view, you will see the data from the JSON 🙂 .
More information
https://github.com/MichMich/MagicMirror
https://github.com/timdows/MMM-JsonTable
Have fun with the project
I hope everything worked as described for you. If not or you have questions or suggestions please let me know in the comments. I will then add this to the article if necessary.
Ideas for new projects are always welcome. 🙂
PS Many of these projects - especially the hardware projects - cost a lot of time and money. Of course I do this because I enjoy it, but if you think it's cool that I share the information with you, I would be happy about a small donation to the coffee fund. 🙂
Hi, great site! I'm just starting with RedNote and came across your site by accident. Top!
Magicmirror I run a little longer and my question is, can I display other JSon data ?
Greeting Stefan
Hi Stefan, thanks I'm glad 🙂
Of course, you can also change the data that is displayed. Basically you just need to change the data that is passed to the “cutString” or “deleteWhitespace” nodes.
Best regards
Fabian
Great, thank you very much. Then I try h that times...
But I am still struggling with the Weatherground. I can't get it to display correctly.
Greeting Stefan
Okay, feel free to let me know how it went 🙂 .
I haven't worked with weatherground at all yet. But here you can find my code for openweathermap.org 🙂
https://nerdiy.de/nodered-aktuelle-wetterdaten-von-openweathermap-beziehen/
Hi, sorry I meant your openweathermap.org... 😉
I somehow do not get it displayed under each other and also not everything.
But it'll be fine, I'll have to fiddle with it a bit.
Do you actually have a forum or something here where you can exchange ideas ?
Hey,
no problem. 🙂 What do you not get each other? The view in the dashboard?
Yes, I have once set up a forum. But must still expand something. I'll take care of it tomorrow. 🙂
Best regards
Fab
Hey Stefan,
I have now made the forum a little “prettier”. You can find the link to this in the top navigation bar. 🙂
Thanks for the tutorial!
I had the bug that the module only displayed “Awaiting json data…” at the beginning.
A reboot fixed that.
Hey Achim,
Thank you very much for the tip. Then I still have to write that to it. Thank you 🙂