Howdy. We have been playing around with Node-RED for the past half year and totally love this stuff. Fabulous tools and great forum! So here is our 2 cents back to the community.
Need
We had a need to create a SCADA-like HMI mimic for monitoring engine and electrical signals. One specific request was to be able to draw lines between equipment and put some "breakers" on them. Just like they do in real SCADA mimics. We tried to look for various ready-made tools, but all of those felt a bit too heavy for our very simple needs. We also wanted to maintain the general look and feel of the Dashboard.
Steps taken
After a bit of tinkering and fiddling with the Dashboard node, we ended up with a three layer split screen, where we added in a full-page wide group in the middle for our line art. And then added in there in that group our lines, which we created with simple svg. Creating a breaker on a line is as easy as making an SVG path and passing a payload value to the path.
Breaker code
This is the small bit that makes the "breaker". You see that we use a msg.payload as the value for the breakers upper end to move.
<!-- SG2 breaker -->
<path d="M 1125 70 v -15 l {{msg.payload}} -25" stroke-linejoin="round" style="fill:transparent;stroke:#6e6e6e;stroke-width:4" />
Full code/flow
[{"id":"edf08104.4351e","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"90836bed.157498","order":1,"width":"6","height":"4","gtype":"gage","title":"SG 4 (640kW)","label":"kW","format":"{{payload[\"27\"]}}","min":0,"max":"640","colors":["#00b500","#e6e600","#ca3838"],"seg1":"450","seg2":"550","x":1080,"y":1100,"wires":[]},{"id":"96e69974.590068","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"1d865536.eb801b","order":2,"width":"6","height":"4","gtype":"gage","title":"SG 3 (1400kW)","label":"kW","format":"{{payload[\"26\"]}}","min":0,"max":"1400","colors":["#00b500","#e6e600","#ca3838"],"seg1":"700","seg2":"1100","x":1260,"y":1100,"wires":[]},{"id":"1ffdd31e.5a990d","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"b5d39406.6debf8","order":2,"width":"6","height":"4","gtype":"gage","title":"DG 2 (875kW)","label":"kW","format":"{{payload[\"23\"]}}","min":0,"max":"875","colors":["#00b500","#e6e600","#ca3838"],"seg1":"550","seg2":"700","x":1080,"y":1200,"wires":[]},{"id":"67219259.c8fcdc","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"e9ed4336.19b7f","order":2,"width":"6","height":"4","gtype":"gage","title":"MSB Produced Power","label":"kW","format":"{{payload[\"28\"]}}","min":0,"max":"1750","colors":["#00b500","#e6e600","#ca3838"],"seg1":"600","seg2":"1200","x":1360,"y":1200,"wires":[]},{"id":"3aedbc92.8f2d34","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"e9ed4336.19b7f","order":5,"width":"6","height":"4","gtype":"gage","title":"DG FO. Flowmeter","label":"kg/h","format":"{{payload[\"3\"]}}","min":0,"max":"300","colors":["#00b500","#e6e600","#ca3838"],"seg1":"120","seg2":"160","x":1370,"y":1260,"wires":[]},{"id":"ae5f7de7.789c","type":"ui_template","z":"2ac8f2df.82ad9e","group":"b5d39406.6debf8","name":"Port side","order":3,"width":"9","height":"5","format":"<style>\n table {\n color: #d1d1d1;\n width: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n font-size: 11px;\n }\n td, 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 text-align: left;\n }\n th {\n background: #6e6e6e;\n font-weight: bold;\n }\n td {\n background: #6e6e6e;\n padding-left: 5px;\n }\n /* Cells in even rows (2,4,6...) are one color */\n tr:nth-child(even) td {\n background: #4b4b4b;\n height: 23px;\n }\n /* Cells in odd rows (1,3,5...) are another (excludes header cells) */\n tr:nth-child(odd) td {\n background: #3f3f3f;\n height: 23px;\n }\n tr td:hover {\n background: #8c8c8c;\n color: #d1d1d1;\n }\n .container\n {\n /*overflow-y: scroll;*/\n overflow-x: hidden;\n }\n .nr-dashboard-theme .nr-dashboard-template ::-webkit-scrollbar-track {\n background-color: #1a1a1a;\n }\n .value\n {\n width: 100px;\n color: #e6e6e6;\n font-size: 13px;\n font-weight:600;\n text-align: center;\n }\n .port\n {\n text-align: right;\n }\n .unit\n {\n text-align: center;\n }\n</style>\n<div>\n <div class=\"container\">\n <table>\n <tbody>\n <tr>\n <td class=\"port\">CHG. Air Temp</td>\n <td class=\"unit\">°C</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[108]\"></span></td>\n </tr>\n <tr>\n <td class=\"port\">EXHAUST Temp</td>\n <td class=\"unit\">°C</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[107]\"></span></td>\n </tr>\n <tr>\n <td class=\"port\">LO Press</td>\n <td class=\"unit\">Bar</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[101]\"></span></td>\n </tr> \n <tr>\n <td class=\"port\">LT Press</td>\n <td class=\"unit\">Bar</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[106]\"></span></td>\n </tr> \n <tr>\n <td class=\"port\">HT Press</td>\n <td class=\"unit\">Bar</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[102]\"></span></td>\n </tr> \n <tr>\n <td class=\"port\">FO Press</td>\n <td class=\"unit\">Bar</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[100]\"></span></td>\n </tr> \n <tr>\n <td class=\"port\">LO Temp</td>\n <td class=\"unit\">°C</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[104]\"></span></td>\n </tr>\n <tr>\n <td class=\"port\">HT Temp</td>\n <td class=\"unit\">°C</td>\n <td class=\"value\"><span ng-bind=\"msg.payload[105]\"></span></td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n<div></div>\n</body>\n</html>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1100,"y":1260,"wires":[[]]},{"id":"124ad50e.de713b","type":"ui_template","z":"2ac8f2df.82ad9e","group":"ea4f996c.f87158","name":"Starboard side","order":2,"width":"9","height":"5","format":"<style>\n table {\n color: #d1d1d1;\n width: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n font-size: 11px;\n }\n td, 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 text-align: left;\n }\n th {\n background: #6e6e6e;\n font-weight: bold;\n }\n td {\n background: #6e6e6e;\n padding-left: 5px;\n }\n /* Cells in even rows (2,4,6...) are one color */\n tr:nth-child(even) td {\n background: #4b4b4b;\n height: 23px;\n }\n /* Cells in odd rows (1,3,5...) are another (excludes header cells) */\n tr:nth-child(odd) td {\n background: #3f3f3f;\n height: 23px;\n }\n tr td:hover {\n background: #8c8c8c;\n color: #d1d1d1;\n }\n .container\n {\n /*overflow-y: scroll;*/\n overflow-x: hidden;\n }\n .nr-dashboard-theme .nr-dashboard-template ::-webkit-scrollbar-track {\n background-color: #1a1a1a;\n }\n .value\n {\n width: 100px;\n color: #e6e6e6;\n font-size: 13px;\n font-weight:600;\n text-align: center;\n }\n .port\n {\n text-align: right;\n }\n .unit\n {\n text-align: center;\n }\n</style>\n<div>\n <div class=\"container\">\n <table>\n <tbody>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[98]\"></span></td>\n <td class=\"unit\">°C</td>\n <td>CHG. Air Temp</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[97]\"></span></td>\n <td class=\"unit\">°C</td>\n <td>EXHAUST Temp</td>\n </tr> \n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[91]\"></span></td>\n <td class=\"unit\">Bar</td>\n <td>LO Press</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[96]\"></span></td>\n <td class=\"unit\">Bar</td>\n <td>LT Press</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[92]\"></span></td>\n <td class=\"unit\">Bar</td>\n <td>HT Press</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[90]\"></span></td>\n <td class=\"unit\">Bar</td>\n <td>FO Press</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[94]\"></span></td>\n <td class=\"unit\">°C</td>\n <td>LO Temp</td>\n </tr>\n <tr>\n <td class=\"value\"><span ng-bind=\"msg.payload[95]\"></span></td>\n <td class=\"unit\">°C</td>\n <td>HT Temp</td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n<div></div>\n</body>\n</html>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1620,"y":1260,"wires":[[]]},{"id":"8c6f799a.bf7128","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"ea4f996c.f87158","order":1,"width":"6","height":"4","gtype":"gage","title":"DG 1 (875kW)","label":"kW","format":"{{payload[\"22\"]}}","min":0,"max":"875","colors":["#00b500","#e6e600","#ca3838"],"seg1":"550","seg2":"700","x":1620,"y":1200,"wires":[]},{"id":"31ade0c9.b1fb9","type":"ui_template","z":"2ac8f2df.82ad9e","group":"c9a2551b.5b9168","name":"Lines","order":2,"width":"30","height":"2","format":"<style>\n .container\n {\n overflow-y: hidden;\n overflow-x: hidden;\n }\n</style>\n<div class=\"container\">\n <svg height=\"100\" width=\"1600\">\n <!-- to SG4 -->\n <line x1=\"150\" y1=\"0\" x2=\"150\" y2=\"70\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- vertical PS -->\n <line x1=\"148\" y1=\"70\" x2=\"702\" y2=\"70\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to DG2 -->\n <line x1=\"312\" y1=\"70\" x2=\"312\" y2=\"100\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to SG3 -->\n <line x1=\"475\" y1=\"0\" x2=\"475\" y2=\"30\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- SG3 breaker -->\n <path d=\"M 475 70 v -15 l {{msg.payload}} -25\" stroke-linejoin=\"round\" style=\"fill:transparent;stroke:#6e6e6e;stroke-width:4\" />\n <!-- vertical PS BT -->\n <line x1=\"475\" y1=\"15\" x2=\"752\" y2=\"15\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to PS BT -->\n <line x1=\"750\" y1=\"0\" x2=\"750\" y2=\"15\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n\n <!-- to MSB -->\n <line x1=\"700\" y1=\"70\" x2=\"700\" y2=\"100\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to MSB -->\n <line x1=\"900\" y1=\"70\" x2=\"900\" y2=\"100\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- vertical SB -->\n <line x1=\"898\" y1=\"70\" x2=\"1452\" y2=\"70\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- vertical SB BT -->\n <line x1=\"848\" y1=\"15\" x2=\"1125\" y2=\"15\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to SB BT -->\n <line x1=\"850\" y1=\"0\" x2=\"850\" y2=\"15\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to SG2 -->\n <line x1=\"1125\" y1=\"0\" x2=\"1125\" y2=\"30\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- SG2 breaker -->\n <path d=\"M 1125 70 v -15 l {{msg.payload}} -25\" stroke-linejoin=\"round\" style=\"fill:transparent;stroke:#6e6e6e;stroke-width:4\" />\n <!-- to DG1 -->\n <line x1=\"1288\" y1=\"70\" x2=\"1288\" y2=\"100\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n <!-- to SG1 -->\n <line x1=\"1450\" y1=\"0\" x2=\"1450\" y2=\"70\" style=\"stroke:#6e6e6e;stroke-width:4\" />\n </svg>\n</div>\n</body>\n</html>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1350,"y":1060,"wires":[[]]},{"id":"5249259c.8f706c","type":"ui_template","z":"2ac8f2df.82ad9e","group":"65f6f27e.a1f1ec","name":"Bowthruster","order":2,"width":"6","height":"4","format":"<style>\n .container\n {\n overflow-y: hidden;\n overflow-x: hidden;\n }\n .heading\n {\n height:100px;\n text-align:center;\n }\n .center\n {\n text-align:center;\n padding-bottom: 10px;\n }\n\n</style>\n<div class=\"container\">\n <div class=\"heading\">\n Bowthrusters\n </div>\n <div class=\"center\">\n AFT No.2 FWD No.1\n </div> \n <div class=\"center\">\n <i class=\"material-icons\" style=\"font-size: 60px\">toys</i>\n \n <i class=\"material-icons\" style=\"font-size: 60px\">toys</i>\n </div> \n</div>\n</body>\n</html>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1370,"y":1140,"wires":[[]]},{"id":"5528b9b1.bbdfb8","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"fa92953a.7a1b58","order":1,"width":"6","height":"4","gtype":"gage","title":"SG 1 (640kW)","label":"kW","format":"{{payload[\"24\"]}}","min":0,"max":"640","colors":["#00b500","#e6e600","#ca3838"],"seg1":"450","seg2":"550","x":1620,"y":1100,"wires":[]},{"id":"93701fab.567f","type":"ui_gauge","z":"2ac8f2df.82ad9e","name":"","group":"b238e66b.53c658","order":2,"width":"6","height":"4","gtype":"gage","title":"SG 2 (1400kW)","label":"kW","format":"{{payload[\"25\"]}}","min":0,"max":"1400","colors":["#00b500","#e6e600","#ca3838"],"seg1":"700","seg2":"1100","x":1440,"y":1100,"wires":[]},{"id":"2b4d5c75.692d14","type":"ui_template","z":"2ac8f2df.82ad9e","group":"e9ed4336.19b7f","name":"Description","order":7,"width":"12","height":"1","format":"<style>\n .center\n {\n text-align: center;\n font-size: 13px;\n }\n</style>\n<div>\n <div class=\"center\">\n DG SFOC = AUX Fuel / DG1+2 Power ME SFOC = ME Fuel / Propulsion power\n </div>\n</div>\n<div></div>\n</body>\n</html>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1430,"y":1420,"wires":[[]]},{"id":"50c86ca5.8de244","type":"smooth","z":"2ac8f2df.82ad9e","name":"Smooth","property":"payload.sfocAux","action":"mean","count":"5","round":"0","mult":"single","reduce":false,"x":1240,"y":1320,"wires":[["ea6573a6.199f9"]]},{"id":"d7869207.2b2a2","type":"smooth","z":"2ac8f2df.82ad9e","name":"Smooth","property":"payload.sfoc","action":"mean","count":"5","round":"0","mult":"single","reduce":false,"x":1500,"y":1320,"wires":[["e6c691ea.9f50f"]]},{"id":"ea6573a6.199f9","type":"ui_level","z":"2ac8f2df.82ad9e","group":"e9ed4336.19b7f","order":4,"width":"3","height":"4","name":"DG SFOC","label":"DG SFOC","colorHi":"#e60000","colorWarn":"#ff9900","colorNormal":"#00b33c","colorOff":"#595959","min":"100","max":"300","segWarn":"225","segHigh":"270","unit":"g/kWh","layout":"sv","channelA":"","channelB":"","decimals":0,"animations":"off","shape":"1","colorschema":"fixed","textoptions":"default","colorText":"#eeeeee","fontLabel":"","fontValue":"","fontSmall":"","colorFromTheme":true,"textAnimations":false,"hideValue":false,"tickmode":"segments","peakmode":false,"property":"payload.sfocAux","peaktime":3000,"x":1310,"y":1360,"wires":[]},{"id":"e6c691ea.9f50f","type":"ui_level","z":"2ac8f2df.82ad9e","group":"e9ed4336.19b7f","order":6,"width":"3","height":"4","name":"ME SFOC","label":"ME SFOC","colorHi":"#e60000","colorWarn":"#ff9900","colorNormal":"#00b33c","colorOff":"#595959","min":"100","max":"300","segWarn":"225","segHigh":"270","unit":"g/kWh","layout":"sv","channelA":"","channelB":"","decimals":0,"animations":"off","shape":"1","colorschema":"fixed","textoptions":"default","colorText":"#eeeeee","fontLabel":"","fontValue":"","fontSmall":"","colorFromTheme":true,"textAnimations":false,"hideValue":false,"tickmode":"segments","peakmode":false,"property":"payload.sfoc","peaktime":3000,"x":1550,"y":1360,"wires":[]},{"id":"9d0aff26.b57db","type":"inject","z":"2ac8f2df.82ad9e","name":"Close breaker","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1170,"y":1020,"wires":[["31ade0c9.b1fb9"]]},{"id":"412fc689.a556a8","type":"inject","z":"2ac8f2df.82ad9e","name":"Open breaker","topic":"","payload":"15","payloadType":"num","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":1180,"y":1060,"wires":[["31ade0c9.b1fb9"]]},{"id":"90836bed.157498","type":"ui_group","z":"","name":"SG4","tab":"d0e5d7d6.5b1ae8","order":1,"disp":false,"width":"6","collapse":false},{"id":"1d865536.eb801b","type":"ui_group","z":"","name":"SG3","tab":"d0e5d7d6.5b1ae8","order":2,"disp":false,"width":"6","collapse":false},{"id":"b5d39406.6debf8","type":"ui_group","z":"","name":"DG2","tab":"d0e5d7d6.5b1ae8","order":7,"disp":false,"width":"9","collapse":false},{"id":"e9ed4336.19b7f","type":"ui_group","z":"","name":"MSB","tab":"d0e5d7d6.5b1ae8","order":8,"disp":false,"width":"12","collapse":false},{"id":"ea4f996c.f87158","type":"ui_group","z":"","name":"DG1","tab":"d0e5d7d6.5b1ae8","order":9,"disp":false,"width":"9","collapse":false},{"id":"c9a2551b.5b9168","type":"ui_group","z":"","name":"lines","tab":"d0e5d7d6.5b1ae8","order":6,"disp":false,"width":"30","collapse":false},{"id":"65f6f27e.a1f1ec","type":"ui_group","z":"","name":"Bow thruster","tab":"d0e5d7d6.5b1ae8","order":3,"disp":false,"width":"6","collapse":false},{"id":"fa92953a.7a1b58","type":"ui_group","z":"","name":"SG1","tab":"d0e5d7d6.5b1ae8","order":5,"disp":false,"width":"6","collapse":false},{"id":"b238e66b.53c658","type":"ui_group","z":"","name":"SG2","tab":"d0e5d7d6.5b1ae8","order":4,"disp":false,"width":"6","collapse":false},{"id":"d0e5d7d6.5b1ae8","type":"ui_tab","z":"","name":"nauticAi Elec","icon":"dashboard","order":3,"disabled":false,"hidden":false}]