Monitoring devices #2

Hello
I refer to the two closed themes:
monitoring devices
and
Monitoring IoT by Ping
I've modified the flow from Steve-Mcl so I read out the information from a file and also set the type of the device e.g. Server, NAS, IoT ... with the file.
Now I'm looking for a way to make the dashboard as flexible as possible when the IP list is scaled down or up.
This I can only do today if I go into the flow and "convert pingResults to array "and "build html table" by hand.
I'm sure this can be done more elegantly, but I lack of a idea how to do this conversion.
Currently the complete list has 8-9 types and >60 IP address

The whole flow at my site sends out information on the MQTT and telegram when an IoT or server is no longer available.

[{"id":"1e201073.c1f32","type":"tab","label":"Flow 4","disabled":false,"info":""},{"id":"b71f5aff.50fa78","type":"template","z":"1e201073.c1f32","name":"build html table","field":"html","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"\n<table width=\"100%\">\n  <tr>\n    <th>Server</th>\n    <th>IP</th> \n  </tr>\n  {{#tableDataServer}}\n  <tr class='{{rowclass}}'>\n    <td>{{{name}}}</td>\n    <td>{{host}}</i></td> \n  </tr>\n  {{/tableDataServer}}\n  <tr>\n    <th>NAS</th>\n    <th>IP</th> \n  </tr>\n  \n  {{#tableDataNAS}}\n  <tr class='{{rowclass}}'>\n    <td>{{{name}}}</td>\n    <td>{{host}}</i></td> \n  </tr>\n  {{/tableDataNAS}}\n</table>","x":840,"y":240,"wires":[["dc6ea9fd.0a1a08","3ef87434.0802fc"]]},{"id":"dc6ea9fd.0a1a08","type":"debug","z":"1e201073.c1f32","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1330,"y":300,"wires":[]},{"id":"69477805.043598","type":"inject","z":"1e201073.c1f32","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":240,"wires":[["26504327.cd405c"]]},{"id":"26504327.cd405c","type":"function","z":"1e201073.c1f32","name":"convert pingResults to array","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet now = new Date();\n\nlet tableDataIoT = [];\nlet tableDataServer = [];\nlet tableDataNAS = [];\nlet tableData = [];\n\n\n\nfor (let k in pingResults) {\n     let r = pingResults[k]; \n     \n      if(r.typ == \"NAS\"){\n        if(r.age > 18000){\n        r.state = \"old\"\n        }  \n        if(r.state == \"ok\"){\n           r.rowclass = \"good\";\n           r.stateInfo = '<i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i> OK'\n        } else if(r.state == \"ng\") {\n            r.rowclass = \"bad\";\n            r.stateInfo = '<i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i> NG'\n        } else {\n            r.rowclass = \"unknown\";\n            r.stateInfo = '<i class=\"fa question\" aria-hidden=\"true\"></i> Unknown'\n        }\n        tableDataNAS.push(r);\n        \n     } else if(r.typ == \"Server\"){\n          if(r.age > 18000){\n          r.state = \"old\"\n        }    \n        if(r.state == \"ok\"){\n           r.rowclass = \"good\";\n           r.stateInfo = '<i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i> OK'\n        } else if(r.state == \"ng\") {\n            r.rowclass = \"bad\";\n            r.stateInfo = '<i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i> NG'\n        } else {\n            r.rowclass = \"unknown\";\n            r.stateInfo = '<i class=\"fa question\" aria-hidden=\"true\"></i> Unknown'\n        }\n        tableDataServer.push(r); \n         \n     } else if(r.typ == \"IoT\"){\n         if(r.age > 18000){\n        r.state = \"old\"\n        } \n        if(r.state == \"ok\"){\n           r.rowclass = \"good\";\n           r.stateInfo = '<i class=\"fa fa-thumbs-up\" aria-hidden=\"true\"></i> OK'\n        } else if(r.state == \"ng\") {\n            r.rowclass = \"bad\";\n            r.stateInfo = '<i class=\"fa fa-thumbs-down\" aria-hidden=\"true\"></i> NG'\n        } else {\n            r.rowclass = \"unknown\";\n            r.stateInfo = '<i class=\"fa question\" aria-hidden=\"true\"></i> Unknown'\n        }\n        tableDataIoT.push(r); \n     }\n     \n     \n}// let k Ende\n\nmsg.tableDataIoT = tableDataIoT\nmsg.tableDataServer=tableDataServer;\nmsg.tableDataNAS=tableDataNAS;\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":460,"y":240,"wires":[["1dfed6ac.55ae89","b71f5aff.50fa78"]]},{"id":"51e44a3e.94c8e4","type":"ping","z":"1e201073.c1f32","mode":"triggered","name":"","host":"","timer":"20","inputs":1,"x":970,"y":180,"wires":[["76bf5002.a0065","c09585c7.65d828"]]},{"id":"76bf5002.a0065","type":"function","z":"1e201073.c1f32","name":"Store Results","func":"let pingResults = flow.get(\"pingResults\") || {}\nlet thisPing = pingResults[msg.topic] || {};\nlet success = msg.payload !== false && msg.payload >= 0;\n\nthisPing.typ = msg.ping.Typ;\nthisPing.name = msg.ping.name;\nthisPing.host = msg.ping.host;\nthisPing.timestamp = new Date();\nthisPing.responseTime = success ? msg.payload : null;\nthisPing.state = success ? \"ok\" : \"ng\" ;\n\npingResults[msg.topic] = thisPing;//store ping obj in pingResults\nflow.set(\"pingResults\",pingResults);//save pingResults in flow context\n\nmsg.payload = thisPing;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1120,"y":180,"wires":[[]]},{"id":"3ef87434.0802fc","type":"ui_template","z":"1e201073.c1f32","group":"8a4980c8.b3942","name":"","order":3,"width":"6","height":"5","format":"<style>\ntable {\n    color: #333;\n    font-family: Helvetica, Arial, sans-serif;\n    width: 100%;\n    border-collapse: collapse;\n    border-spacing: 0;\n}\ntd, th {\n    border: 1px solid transparent;\n    /* No more visible border */\n    height: 30px;\n    transition: all 0.3s;\n    /* Simple transition for hover effect */\n}\nth {\n    background: #DFDFDF;\n    /* Darken header a bit */\n    font-weight: bold;\n}\ntd {\n    background: #FAFAFA;\n    text-align: center;\n}\n\n/* Cells in even rows (2,4,6...) are one color */\n\ntr:nth-child(even) td {\n    background: #F1F1F1;\n}\n\n/* Cells in odd rows (1,3,5...) are another (excludes header cells)  */\n\ntr:nth-child(odd) td {\n    background: #FEFEFE;\n}\ntr td:hover {\n    background: #666;\n    color: #FFF;\n}\n\n/* Hover cell effect! */    \n\ntr.good {\n    color: green;\n}\n\ntr.bad {\n    color: red;\n}\n\ntr.unknown {\n    color: orange;\n}\n\n    \n</style>\n<div ng-bind-html=\"msg.html\"></div>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1120,"y":240,"wires":[[]]},{"id":"1dfed6ac.55ae89","type":"debug","z":"1e201073.c1f32","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1330,"y":340,"wires":[]},{"id":"c09585c7.65d828","type":"debug","z":"1e201073.c1f32","name":"test","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1330,"y":180,"wires":[]},{"id":"fb0c0009.3abfe","type":"inject","z":"1e201073.c1f32","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":180,"wires":[["aceef166.c05ce"]]},{"id":"aceef166.c05ce","type":"file in","z":"1e201073.c1f32","name":"Liste Datei","filename":"/home/pi/ip2-list.json","format":"utf8","x":330,"y":180,"wires":[["b44069c7.912678"]]},{"id":"b44069c7.912678","type":"json","z":"1e201073.c1f32","name":"Konvertieren","property":"payload","action":"","pretty":false,"x":530,"y":180,"wires":[["c8c5f9a1.0e14f8"]]},{"id":"c8c5f9a1.0e14f8","type":"change","z":"1e201073.c1f32","name":"","rules":[{"t":"delete","p":"filename","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":180,"wires":[["51e44a3e.94c8e4"]]},{"id":"8a4980c8.b3942","type":"ui_group","z":"","name":"Default","tab":"18ca9017.e3f5e","order":1,"disp":false,"width":"6","collapse":false},{"id":"18ca9017.e3f5e","type":"ui_tab","z":"","name":"Home2","icon":"dashboard","disabled":false,"hidden":false}]

Changes to the original by Steve-Mcl:
read the information from the file and then inject it into Ping.
In Store Results the "typ" is included
In convert pingResults to array filter by type
Customizations in build html table

For suggestions or examples of similar projects I would be happy.
Thanks
Marc

what is the format of the input file?

Thank you for the question, I had forgotten that
it is a text file

[{"name":"FW2","host":"10.11.12.151"},{"name":"FW3","host":"10.11.12.153"},{"name":"FW","host":"10.11.12.150", "Typ":"Server"},{"name":"dns","host":"10.11.12.200","Typ":"NAS"},{"name":"smart_speaker","host":"192.168.0.52","Typ":"NAS"},{"name":"pi","host":"10.11.12.160","Typ":"Server"},{"name":"WRB","host":"10.11.12.110"}]

not all IP have been typed yet
Marc

1 Like

Marc, have you thought/tried using the ui-table? you would have to change your function node to create one array or use multiple tables, one for each batch of devices.

Thanks for the tip
no I do not know that yet.
I have just installed it and will deal with it. what I saw in the node red library looks interesting

Hello
I have for example 3 (ui_controll_tabel) in UI Tabel two questions.
Can the symbols under the column Mode be displayed in a different color
and
i try to pass different color to "legendColor". If I give "legendColor": "#FF0040" as a fixed value, then I can influence the color .Transfers fail with a variable and everything always appears in black.
Can anyone here tell me how I can pass these points from ui_control?

Example 3

[{"id":"cce17f4f.0e364","type":"inject","z":"fd256d9b.a2b1d","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"name\":\"MEQ0451495\",\"room\":\"Bathroom\",\"SET_TEMPERATURE-value\":22,\"ACTUAL_TEMPERATURE-value\":21.8,\"VALVE_STATE-value\":90,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":true,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875547\",\"room\":\"Living Room\",\"SET_TEMPERATURE-value\":12,\"ACTUAL_TEMPERATURE-value\":16.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":1},{\"name\":\"MEQ1875538\",\"room\":\"Living Room\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":19.5,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.6,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":2},{\"name\":\"MEQ0447462\",\"room\":\"Kitchen\",\"SET_TEMPERATURE-value\":17,\"ACTUAL_TEMPERATURE-value\":22.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":10,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":3},{\"name\":\"MEQ1875551\",\"room\":\"Office\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":20.2,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ0447425\",\"room\":\"Dining Room\",\"SET_TEMPERATURE-value\":19,\"ACTUAL_TEMPERATURE-value\":20.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875546\",\"room\":\"Dining Room\",\"SET_TEMPERATURE-value\":20,\"ACTUAL_TEMPERATURE-value\":18.8,\"VALVE_STATE-value\":99,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ0447483\",\"room\":\"Bedroom\",\"SET_TEMPERATURE-value\":17,\"ACTUAL_TEMPERATURE-value\":22.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875541\",\"room\":\"Child\",\"SET_TEMPERATURE-value\":18,\"ACTUAL_TEMPERATURE-value\":20.4,\"VALVE_STATE-value\":0,\"BATTERY_STATE-value\":2.7,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0},{\"name\":\"MEQ1875552\",\"room\":\"Guest Room\",\"SET_TEMPERATURE-value\":20,\"ACTUAL_TEMPERATURE-value\":21.1,\"VALVE_STATE-value\":9,\"BATTERY_STATE-value\":2.8,\"BOOST_STATE-value\":0,\"AUTO_MODE-value\":false,\"CONTROL_MODE-value\":0}]","payloadType":"json","x":380,"y":200,"wires":[["fb3b3b67.8a7318"]]},{"id":"fb3b3b67.8a7318","type":"change","z":"fd256d9b.a2b1d","name":"ui_control","rules":[{"t":"set","p":"ui_control","pt":"msg","to":"{\"tabulator\":{\"columnResized\":\"function(column){     var newColumn = {         field: column._column.field,         visible: column._column.visible,         width: column._column.width,         widthFixed: column._column.widthFixed,         widthStyled: column._column.widthStyled     }; this.send({topic:this.config.topic,ui_control:{callback:'columnResized',columnWidths:newColumn}}); }\",\"columnMoved\":\"function(column, columns){     var newColumns=[];     columns.forEach(function (column) {         newColumns.push({'field': column._column.field});     });     this.send({topic:this.config.topic,ui_control:{callback:'columnMoved',columns:newColumns}}); }\",\"groupHeader\":\"function (value, count, data, group) {return value + \\\"<span style='color:#d00; margin-left:10px;'>(\\\" + count + \\\" Termostat\\\"+((count>1) ? \\\"e\\\" : \\\"\\\") + \\\")</span>\\\";}\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"ROom\",\"field\":\"room\",\"width\":100,\"frozen\":true},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Device\",\"field\":\"name\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Type\",\"field\":\"deviceType\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Measurements\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"target\",\"field\":\"SET_TEMPERATURE-value\",\"formatter\":\"function(cell, formatterParams, onRendered){return cell.getValue()+'°C';}\",\"topCalc\":\"avg\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":10,\"max\":25,\"color\":[\"blue\",\"green\",\"red\"],\"legend\":\"function (value) {return '&nbsp;&nbsp;'+value+'°C';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"left\"},\"title\":\"current\",\"field\":\"ACTUAL_TEMPERATURE-value\",\"formatter\":\"progress\",\"topCalc\":\"avg\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":0,\"max\":99,\"color\":[\"gray\",\"orange\",\"red\"],\"legend\":\"function (value) {return (value>0)? '&nbsp;&nbsp;'+value+' %' : '-';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Valve\",\"field\":\"VALVE_STATE-value\",\"formatter\":\"progress\",\"topCalc\":\"max\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"min\":1.5,\"max\":4.6,\"color\":[\"red\",\"orange\",\"green\"],\"legend\":\"function (value) {return value+' V';}\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Batt\",\"field\":\"BATTERY_STATE-value\",\"formatter\":\"progress\",\"topCalc\":\"min\",\"width\":100}]},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Settings\",\"columns\":[{\"formatterParams\":{\"target\":\"_blank\",\"min\":0,\"max\":30,\"color\":[\"red\",\"orange\",\"green\"],\"legend\":\"function (value) {     if (value>0)         return \\\"<span style='color:#101010;'>\\\"+value+\\\" min</span>\\\";     else         return \\\"<span style='color:#A0A0A0;'>aus</span>\\\"; }\",\"legendColor\":\"#101010\",\"legendAlign\":\"center\"},\"title\":\"Boost\",\"field\":\"BOOST_STATE-value\",\"formatter\":\"progress\",\"width\":100},{\"formatterParams\":{\"target\":\"_blank\",\"allowEmpty\":true,\"allowTruthy\":true,\"tickElement\":\"<i class='fa fa-clock-o'></i>\",\"crossElement\":\"<i class='fa fa-ban'></i>\"},\"title\":\"Auto\",\"field\":\"AUTO_MODE-value\",\"formatter\":\"tickCross\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Mode\",\"field\":\"CONTROL_MODE-value\",\"formatter\":\"function(cell, formatterParams, onRendered){     var html=\\\"<i class=\\\\\\\"\\\";     switch(cell.getValue()) {         case 0: html+=\\\"fa fa-calendar-check-o\\\"; break;         case 1: html+=\\\"fa fa-hand-o-up\\\"; break;         case 2: html+=\\\"fa fa-suitcase\\\"; break;         case 3: html+=\\\"fa fa-spinner fa-spin fa-fw\\\"; break;     }     html+='\\\\\\\"></i>';     return html; }\",\"width\":100,\"align\":\"center\"},{\"formatterParams\":{\"target\":\"_blank\"},\"title\":\"Auto\",\"field\":\"AUTO_MODE-value\",\"formatter\":\"tick\",\"width\":100,\"align\":\"center\"}]}],\"layout\":\"fitColumns\",\"movableColumns\":true,\"groupBy\":\"\"},\"customHeight\":12}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":526,"y":200,"wires":[["9c614654.801878"]]},{"id":"4d541af5.cf35f4","type":"debug","z":"fd256d9b.a2b1d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":839,"y":200,"wires":[]},{"id":"9c614654.801878","type":"ui_table","z":"fd256d9b.a2b1d","group":"ef947603.971a28","name":"Thermostats","order":1,"width":"20","height":"7","columns":[],"outputs":1,"cts":true,"x":689,"y":200,"wires":[["4d541af5.cf35f4"]]},{"id":"ef947603.971a28","type":"ui_group","z":"","name":"ui_control","tab":"8418b74a.1f2958","order":1,"disp":true,"width":"22","collapse":false},{"id":"8418b74a.1f2958","type":"ui_tab","z":"","name":"Home","icon":"track_changes","order":1,"disabled":false,"hidden":false}]