Dashboard 2 - Rolling Text Display - how to?

Hey Guys,

I would like to implement a rolling dashboard display - say 10 lines high - preferably in Dashboard 2

Essentially what i want to do is maintain a queue of messages (probably store in global context) - the display would read from the Queue and would display each message in a 10 line window - say for 10 seconds, then would pop the top one off the screen and move everything up one position and retrieve the next item in the queue and put that at the bottom.

I would use a seperate process to manage the items in the queue - and remove them as required.

The idea is that i could have a schedule of upcoming actions in my home automation system - lets say

6:35 am - Dawn over - external motion sensor off
6:50 am - Cameras being changed over to daylight mode
7:00 am - battery system moving from arbitrage to Zero Grid
7:05 am - Electricity price spike - battery moving back to arbitrage mode

etc etc

Events that were one offs would be deleted out of the queue by a separate process and recurring tasks would be added by their respective process throughout the day - the Global Object would probably be a Javascript array of objects that could be cycled through.

Anyone done something like this or have pointers as to which UI elements could be used ??

Craig

Actually a bit more intelligent searching and browsing on the forum led me to a post by @Steve-Mcl which has pretty close to what i want to achieve.

It will be a good start for my first foray into Dashboard 2

Craig

1 Like

Please note: These suggestions are for Dashboard 1 (will probably need modifying for DB-2).

I made a train arrivals board a few years ago using the 'ring buffer' node.


Here's part of the NR flow...

[{"id":"4dc1bb2f.93f96c","type":"group","z":"f233685a.5de4f","name":"","style":{"stroke":"#000000","fill":"#d1d1d1","fill-opacity":"0.51","label":true},"nodes":["f55aa089.ee3a1","10c76796.2a23a8","721e03ac.771e2c","70a4fcad.b5751c","962557b.b9a27a8","e254e87b.dc563","15aba88d.bdb8df","67a87dfc.d11bd4","ea595c5.e38f9a"],"x":1314,"y":779,"w":1032,"h":222},{"id":"f55aa089.ee3a1","type":"ui_template","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","group":"e6d438e4.34caf8","name":"PR arrivals board","order":1,"width":"8","height":"5","format":"<div ng-bind-html=\"msg.payload\" style=\"overflow:auto\"></div>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":2230,"y":960,"wires":[[]]},{"id":"10c76796.2a23a8","type":"function","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Move message up the board","func":"let msgArray = msg.payload;\nlet arrLen = msgArray.length;\nlet outLine = \"\";\nfor (let i=0; i < arrLen; i++) {\n    outLine = outLine + msgArray[i];\n}\n\nmsg.payload = outLine;\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1980,"y":960,"wires":[["f55aa089.ee3a1"]]},{"id":"721e03ac.771e2c","type":"ring-buffer","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","capacity":"10","order":"old-to-new","sendOnlyIfFull":false,"pushAfterClear":false,"extra":false,"perTopic":false,"x":1750,"y":960,"wires":[["10c76796.2a23a8"]]},{"id":"70a4fcad.b5751c","type":"link in","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","links":["f739b4fd.7fc93"],"x":1355,"y":960,"wires":[["e254e87b.dc563"]]},{"id":"962557b.b9a27a8","type":"inject","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Clear message board","props":[{"p":"type","v":"clear","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":1460,"y":880,"wires":[["e254e87b.dc563"]]},{"id":"e254e87b.dc563","type":"function","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Colour-code stations","func":"if (msg.type == \"clear\") {\n    // Clear the ring buffer and pre-load it with newlines <br>\n    // This will ensure the user message scrolls from the bottom edge\n    \n    node.send({'payload.clear':true});\n    \n    for (let i=0; i<10; i++) {\n        node.send ({payload:`${i}<br>`});    \n    }\n}\nelse if (msg.station ==\"pr\") {\n    var train = msg.train;\n    var signal = msg.signal;\n    var train_time = msg.train_time;\n    var station= msg.station;\n    var color = \"green\";\n    \n    switch (station) {\n\n    case \"hw\":\n        color = \"#097479\"\n        break;\n        \n    case \"pr\" : \n        color = \"#ffdf80\";\n        break;\n    }\n    msg.payload = `<p><font color=\"white\">${train_time} >> </font><font color=${color}>Train-Id: ${train} arrived at Signal-Id: ${signal}</font></p>`;\n    return msg;\n}\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1540,"y":960,"wires":[["721e03ac.771e2c"]]},{"id":"15aba88d.bdb8df","type":"ui_button","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"","group":"e6d438e4.34caf8","order":2,"width":0,"height":0,"passthru":false,"label":"Click to clear - Arrivals board","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":1460,"y":820,"wires":[["67a87dfc.d11bd4"]]},{"id":"67a87dfc.d11bd4","type":"change","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Clear message board","rules":[{"t":"set","p":"type","pt":"msg","to":"clear","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1720,"y":820,"wires":[["e254e87b.dc563"]]},{"id":"ea595c5.e38f9a","type":"comment","z":"f233685a.5de4f","g":"4dc1bb2f.93f96c","name":"Colour-code the stations on the Arrivals board at PR","info":"","x":2090,"y":820,"wires":[]},{"id":"e6d438e4.34caf8","type":"ui_group","name":"Activity at Princes Risborough","tab":"2333e020.8e09e","order":4,"disp":true,"width":"8","collapse":false},{"id":"2333e020.8e09e","type":"ui_tab","name":"Trainspotting","icon":"dashboard","order":56,"disabled":false,"hidden":false}]

Just recently I made a Node Reporting Queue using some JavaScript to create a 'stack manager' where items are pushed onto the bottom of the stack and popped off of the top.


Here's part of the NR flow...

[{"id":"3163af1e1fc49405","type":"function","z":"0f43c63d6bea2b09","name":"Stack manager","func":"let stack = flow.get('stack') || [];\nlet queue_length = flow.get(\"queue_length\") || 0;\n\nif (msg.topic == \"push\") {\n    //let stack = flow.get('stack') || [];\n\n    let my_node = { \"nodeID\": msg.payload.nodeID, \"location\": msg.payload.location }\n    stack.push(my_node);\n    flow.set('stack', stack);\n    queue_length = queue_length + 1;\n    flow.set(\"queue_length\", queue_length);\n    return msg;\n}\nelse if (msg.topic == \"pop\") {\n    //let stack = flow.get('stack') || [];\n    stack.shift();\n    // stack.pop();\n    flow.set('stack', stack);\n    if (queue_length > 0) {\n        queue_length = queue_length - 1;\n        flow.set(\"queue_length\", queue_length);\n    }\n    else {\n        flow.set(\"queue_length\", 0);\n    }\n    return msg;\n}\nelse if (msg.topic == \"reset_stack\") {\n    flow.set('stack', []);\n    queue_length = 0;\n    flow.set(\"queue_length\", queue_length);\n    //Send payload to clear the UI display\n    msg.payload = [];\n    return msg;\n}\nelse {\n    return null;\n}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1240,"y":480,"wires":[["c6e3cfdfc9b87adf","30627e1f6e7c8560"]]},{"id":"24ebbf98111b8823","type":"change","z":"0f43c63d6bea2b09","name":"Push node onto stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"push","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":480,"wires":[["3163af1e1fc49405"]]},{"id":"adcad4254556d85f","type":"change","z":"0f43c63d6bea2b09","name":"Empty the stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"reset_stack","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":980,"y":520,"wires":[["3163af1e1fc49405"]]},{"id":"61b35001b103e551","type":"change","z":"0f43c63d6bea2b09","name":"Remove node from stack","rules":[{"t":"set","p":"topic","pt":"msg","to":"pop","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1010,"y":440,"wires":[["3163af1e1fc49405"]]},{"id":"9c7a40c5da74e610","type":"ui_table","z":"0f43c63d6bea2b09","group":"b917a40b6565668d","name":"","order":1,"width":6,"height":10,"columns":[{"field":"nodeID","title":"NodeID","width":"30%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}},{"field":"location","title":"Location","width":"70%","align":"left","formatter":"plaintext","formatterParams":{"target":"_blank"}}],"outputs":0,"cts":false,"x":1490,"y":520,"wires":[]},{"id":"9f0d5c43cfe4f9a7","type":"debug","z":"0f43c63d6bea2b09","name":"debug 3450","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1230,"y":560,"wires":[]},{"id":"c6e3cfdfc9b87adf","type":"function","z":"0f43c63d6bea2b09","name":"Clear table then send array","func":"msg.payload = [];\nnode.send(msg);\n\nlet stack = flow.get('stack') || [];\nmsg.payload = stack;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1280,"y":520,"wires":[["9c7a40c5da74e610","9f0d5c43cfe4f9a7"]]},{"id":"34be0cc278da508e","type":"ui_text","z":"0f43c63d6bea2b09","group":"b917a40b6565668d","order":8,"width":3,"height":1,"name":"Queue length","label":"","format":"Queue length {{msg.payload}}","layout":"row-left","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":980,"y":640,"wires":[]},{"id":"30627e1f6e7c8560","type":"change","z":"0f43c63d6bea2b09","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"queue_length","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":980,"y":600,"wires":[["34be0cc278da508e"]]},{"id":"b917a40b6565668d","type":"ui_group","name":"Node Reporting Queue","tab":"b73bebe42aae7406","order":2,"disp":true,"width":"6","collapse":false,"className":""},{"id":"b73bebe42aae7406","type":"ui_tab","name":"Global Node Monitor (GNM) v11","icon":"dashboard","order":4,"disabled":false,"hidden":false}]

Thanks Dave,

Yes i have one from about 5 years ago for Dashboard 1 and it works well - just looking for something for Dashboard 2 - thanks for stepping up - i will have a look at Steves code and see if i can work out what is going on and how it all works

Craig

Is this the post you were referring to?

Yes it was - i see i forgot to also put a link to it - DOH !!

Thanks

Craig

If you want this on dashboard-2.0 - the equivalent of the ui-table node (used above) in dashboard 2.0 is @omrid01/node-red-dashboard-2-table-tabulator, which needs to be installed on top of the built-in dashboard 2.0 nodes.

Excellent - thanks for the pointer.

I will start with @Steve-Mcl sample stuff first and try to get to grips with all the CSS and HTML (i do networking and security for a living - but am absolute crap at Design, HTML, CSS etc) so it is something new for me.

Once i understand how it all comes together i may challenge myself with your node

regards

Craig

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.