HowTo: Node Red / Magic Mirror – Display data from Node Red on the mirror

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.

View of the login dialog. Here you have to enter the login data that you specified during the configuration of the login. You can find information about this in the article NodeRed - set up user login.

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.

JSON data as displayed to you in the Firefox browser. This is good for debugging because it also shows errors in the JSON structure.

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
So open the configuration file of your MagicMirror and insert the module configuration.
{
   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
   }
}
Of course, first replace “IP_EURER_NODE_RED_INSTALLATION” with the IP address of the RaspberryPi# on which your MagicMirror is running.

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 the still uncorrected file you have to find the line with “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){
The corrected line then looks like this.
Then save the file again by pressing “CTRL+X” and then confirming with “Y”…
...and leave the file with “Enter”.

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. 🙂

Buy Me a Coffee at ko-fi.com       

9 comments

  1. 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

    1. 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

  2. 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

      1. 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 ?

        1. 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

  3. Thanks for the tutorial!
    I had the bug that the module only displayed “Awaiting json data…” at the beginning.
    A reboot fixed that.

Kommentar hinterlassen

Your email address will not be published. Erforderliche Felder sind mit * markiert

This site uses Akismet to reduce spam. Learn how your comment data is processed.