# Node Red: A widget based dashboard working with Homey trough MQTT

**URL:** <https://community.homey.app/t/node-red-a-widget-based-dashboard-working-with-homey-trough-mqtt/18798>\
**Category:** Apps\
**Created:** [October 3, 2019, 10:05am UTC](https://community.homey.app/t/node-red-a-widget-based-dashboard-working-with-homey-trough-mqtt/18798 "2019-10-03T10:05:10Z")\
**Posts on this page:** 1\
**Showing post:** 584

<div class="post-metadata">

**Author:** ![RogerSt](https://sea1.discourse-cdn.com/flex025/user_avatar/community.homey.app/rogerst/32/12432_2.png) [@RogerSt](https://community.homey.app/u/RogerSt)\
**Post date:** [September 11, 2020, 6:23pm UTC](https://community.homey.app/t/node-red-a-widget-based-dashboard-working-with-homey-trough-mqtt/18798/584 "2020-09-11T18:23:25Z")

</div>

Hi all,

After having leeched a ton of information from this topic, I think it’s time to also share a bit of information.  
Please keep in mind that I am not a programmer, have barely any knowledge of JavaScript, CSS etc. so I’m sure things can be done more efficiently, but nevertheless I hope someone can appreciate this post.

I created a ‘top x’ large electricity consumers, which creates a sorted list of devices currently consuming the most electricity. Personally I find this useful functionality; perhaps others can see a use for it as well.

The dashboard uses the awesome CSS with homey-look as posted earlier by @DeepBlueNine; but I believe any CSS should be able to use the tools I post here.

The dashboard displays this list:  
 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/1/5/1551ab32199566a4f7efd9f167fc9abea18cc8e9.png)

For this to work, I used several things in node-red.

1. First, I created a JavaScript Map object in the global namespace. For this I created a Function that I triggered once with a timestamp message using an inject node connected to this function. The code for the javascript Map is this:

> [{“id”:“c30332a9.8b807”,“type”:“function”,“z”:“9235bbe0.d90a78”,“name”:“createGlobal Map object for grootverbruikers”,“func”:“var map = new Map();\nglobal.set("GrootverbruikersMap", map);\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:“”,“finalize”:“”,“x”:1190,“y”:1760,“wires”:[]}]

1. Next I used function nodes that already register electricity consumption, e.g. from INNR Plug, or Fibaro Plugs, and had them populate the Map every time a new power measure comes in. The code inside this function node is:

> var gvb = new Map(global.get(“GrootverbruikersMap”));  
> gvb.set(pl, power);  
> global.set(“GrootverbruikersMap”, gvb);

where **pl** could be the name of the device (like ‘dishwasher’) and **power** would be the current power consumption, like 100.

After some time, most devices have posted their power consumption to the map, resulting in a Map object that has payload similar to this debug output:

 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/3/e/3e85c87e95b04f7c22233200cc0ee86957476092.png)

1. The next challenge is that the map is not a sorted list, and I believe it cannot be sorted as far as I can tell. the list is ordered in the sequence entries are added, so first device added is first device in the list.

To overcome this, I needed to make sure that I use an object that can be sorted, and I chose the JavaScript Array.

On the destination tab, so where I needed the list to appear, I created three nodes, a repeating timestamp injector, to trigger my flow periodically, e.g. 4 times per minute, a function node to create the sorted list, and the ui template to show the list in my dashboard.  
 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/0/d/0d29a3f317b0900dba3e991f976a036f026484ff.png)

The function node has the Map → Array conversion and the sort-by-power-column-descending code.

> // sorteren grootverbruikers
> 
> var grootverbruikers = new Map(global.get(“GrootverbruikersMap”));
> 
> function compare(a, b) {  
> // Use toUpperCase() to ignore character casing  
> const powerA = a.value;  
> const powerB = b.value;
> 
> let comparison = 0;  
> if (powerA \> powerB) {  
> comparison = 1;  
> } else if (powerA \< powerB) {  
> comparison = -1;  
> }  
> return comparison \*-1; // multiply with -1 for reverse sorting order  
> }
> 
> var gvbArray = Array.from(grootverbruikers, ([name, value]) =\> ({ name, value }));  
> [//console.log](https://console.log)(gvbArray);  
> gvbArray.sort(compare);  
> [//console.log](https://console.log)("Sorted: " + gvbArray);
> 
> msg.payload=gvbArray;  
> return msg;

The return message would contain a sorted array.

1. The last bit is getting the list displayed. I use the UI template node, and plain HTML table, listing the first 8 elements in the array statically. I know I could iterate the entire array, but I consciously decided that it does not make sense to show more than 5…8 devices for my purposes…  
 ![image](https://us1.discourse-cdn.com/flex025/uploads/athom/original/3X/1/c/1cd7b68d968397f0f948570c034160d18670059d.png)

The code for the above three nodes is listed here:

> [{“id”:“2c319ac.1847166”,“type”:“function”,“z”:“7a3033ea.2f403c”,“name”:“sorteerGrootverbruikers”,“func”:“// sorteren grootverbruikers\n\n/_\nconst singers = [\n { name: ‘Steven Tyler’, band: ‘Aerosmith’, born: 1948 },\n { name: ‘Karen Carpenter’, band: ‘The Carpenters’, born: 1950 },\n { name: ‘Kurt Cobain’, band: ‘Nirvana’, born: 1967 },\n { name: ‘Stevie Nicks’, band: ‘Fleetwood Mac’, born: 1948 },\n]; \n_/\n\nvar grootverbruikers = new Map(global.get("GrootverbruikersMap"));\n\nfunction compare(a, b) {\n // Use toUpperCase() to ignore character casing\n const powerA = a.value;\n const powerB = b.value;\n\n let comparison = 0;\n if (powerA \> powerB) {\n comparison = 1;\n } else if (powerA \< powerB) {\n comparison = -1;\n }\n return comparison _-1; // multiply with -1 for reverse sorting order\n}\n\n\n//\n\n\n\n/_\nconst iterator1 = grootverbruikers.entries();\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n console.log(iterator1.next().value);\n\*/\n\nvar gvbArray = Array.from(grootverbruikers, ([name, value]) =\> ({ name, value }));\n//console.log(gvbArray);\ngvbArray.sort(compare);\n//console.log("Sorted: " + gvbArray);\n\n\nmsg.payload=gvbArray;\nreturn msg;\n\n\n”,“outputs”:1,“noerr”:0,“initialize”:“”,“finalize”:“”,“x”:490,“y”:1340,“wires”:[[“66e2da5b.1f8d94”]]},{“id”:“d51e14d5.87d178”,“type”:“inject”,“z”:“7a3033ea.2f403c”,“name”:“”,“props”:[{“p”:“payload”},{“p”:“topic”,“vt”:“str”}],“repeat”:“10”,“crontab”:“”,“once”:true,“onceDelay”:0.1,“topic”:“”,“payload”:“”,“payloadType”:“date”,“x”:280,“y”:1340,“wires”:[[“2c319ac.1847166”]]},{“id”:“66e2da5b.1f8d94”,“type”:“ui\_template”,“z”:“7a3033ea.2f403c”,“group”:“fce2a100.6e2d6”,“name”:“sortedGrootverbruikers”,“order”:1,“width”:6,“height”:6,“format”:“\<span style="vertical-align:middle; font-size:15px; color: rgb(255, 255, 255); text-align: left; " class="fr-class-transparency"\>\n\n \<table width="100%"\>\n **{{msg.payload[0].name}}:**\<td width="30%" align="right"\>{{msg.payload[0].value}}**&nbsp;[W]**\n **{{msg.payload[1].name}}:**\<td width="30%" align="right"\>{{msg.payload[1].value}}**&nbsp;[W]**\n **{{msg.payload[2].name}}:**\<td width="30%" align="right"\>{{msg.payload[2].value}}**&nbsp;[W]**\n **{{msg.payload[3].name}}:**\<td width="30%" align="right"\>{{msg.payload[3].value}}**&nbsp;[W]**\n **{{msg.payload[4].name}}:**\<td width="30%" align="right"\>{{msg.payload[4].value}}**&nbsp;[W]**\n **{{msg.payload[5].name}}:**\<td width="30%" align="right"\>{{msg.payload[5].value}}**&nbsp;[W]**\n **{{msg.payload[6].name}}:**\<td width="30%" align="right"\>{{msg.payload[6].value}}**&nbsp;[W]**\n **{{msg.payload[7].name}}:**\<td width="30%" align="right"\>{{msg.payload[7].value}}**&nbsp;[W]**\n \n ”,“storeOutMessages”:true,“fwdInMessages”:true,“resendOnRefresh”:true,“templateScope”:“local”,“x”:740,“y”:1340,“wires”:[]},{“id”:“fce2a100.6e2d6”,“type”:“ui\_group”,“z”:“”,“name”:“Grootverbruikers”,“tab”:“9184a885.936cb8”,“order”:5,“disp”:true,“width”:“6”,“collapse”:true},{“id”:“9184a885.936cb8”,“type”:“ui\_tab”,“z”:“”,“name”:“Energie”,“icon”:“dashboard”,“order”:3,“disabled”:false,“hidden”:false}]

Hope this helps - have fun!

---

_[View the full topic](https://community.homey.app/t/node-red-a-widget-based-dashboard-working-with-homey-trough-mqtt/18798)._
