I am trying to program a traffic light that is powered by OPC UA Data

Good day dear forum.

I am trying to display OPC UA data as a traffic light, but I am not getting anywhere. My first try was to create a bulb that changes color with the ng-if statement via a set msg.payload.
This works for one machine, but not for two. The blub flicker and only one is displayed at a time.
After that I tried using js and changing the background color to solve the problem, but that doesn't work either.
I think the problem is not too hard, but alone I can not solve it. can someone help me?

first try

<style>
    .redButton{
        background-color: red;
    }
    
    .yellowButton{
        background-color: yellow;
    }
    
    .greenButton{
        background-color: green;
    }
    .normalAmpel{
        position: absolute;
        width: 50px;
        height: 50px;
        border-radius: 50%;
        color: white;
        padding-left: 10px;
        padding-top: 10px;
        font-size: 16px;
        z-index: 5;
    }
    
    .machine1{
        top: 150px;
        left: 100px;
    }
    
    .machine2{
        top: 100px;
        left: 150px;
    }
    
</style>


<!-- Machine 1 -->
<div id= machine1>
    <div ng-if="msg.payload==='red.machine1'" class="redButton normalAmpel machine1"></div>
    <div ng-if="msg.payload==='green.machine1'" class="greenButton normalAmpel machine1"></div>
    <div ng-if="msg.payload==='yellow.machine1'" class="yellowButton normalAmpel machine1"></div>
</div>


<!-- Machine 2 -->
<div id= machine2>
    <div ng-if="msg.payload==='red.machine2'" class="redButton normalAmpel machine2"></div>
    <div ng-if="msg.payload==='green.machine2'" class="greenButton normalAmpel machine2"></div>
    <div ng-if="msg.payload==='yellow.machine2'" class="yellowButton normalAmpel machine2"></div>
</div>

second try

<style>
    .redButton{
        background-color: red;
    }
    
    .yellowButton{
        background-color: yellow;
    }
    
    .greenButton{
        background-color: green;
    }
    .normalAmpel{
        position: absolute;
        width: 50px;
        height: 50px;
        border-radius: 50%;
        color: white;
        padding-left: 10px;
        padding-top: 10px;
        font-size: 16px;
        z-index: 5;
        background-color: black;
    }
    
    .machine1{
        top: 150px;
        left: 100px;
    }
    
    .machine2{
        top: 100px;
        left: 150px;
    }
    
</style>


<!-- Machine 1 -->
<div id= machine1 class="normalAmpel machine2"></div>


<!-- Machine 2 -->
<div id= machine2 class="normalAmpel machine2"></div>

<script>
    document.getElementbyId("machine1").style.color = color_func_machine1;
    document.getElementbyId("machine2").style.color = color_func_machine2;
    
    function color_func_machine1 (red_machine1, green_machine1, yellow_machine1 ){
        let = color;
        
        if (red_machine1== true){
            color = red;
            }
            else
        if (green_machine1== true){
            color = green;
            }
            else
         if (yellow_machine1== true){
            color = yellow;
            }
        return color;
    }
    
    function color_func_machine2 (red_machine2, green_machine2, yellow_machine2){
        let = color;
        
        if (red_machine2 == true){
            color = 'red';
            }
            else
        if (green_machine2 == true){
            color = 'green';
            }
            else
         if (yellow_machine2 == true){
            color = 'yellow';
            }
        return color;
    }
</script>

Hello and welcome to the Node-RED forum.

I think you need to give us a bit more information and post your flow so people can help you.
Also are you talking about a real bulb or a virtual bulb??

PS:
I know nothing about OPCUA - but assume you are checking if an output is between a certain range of values to decide which bulb to illuminate?

PPS:
You can read how to post a flow here...

hello dynamicdave,

I am programming a view of machines that whose status should be shown in a visualization. There are 3 states, on, off and standby. The 3 states should be displayed in the correct color.

I can not send you the complete flow, because server and node ids are included. but I send the part after the opc ua nodes.

Only boolean values are sent from the OPC ua server to the part. The current question is not so much about opc ua, because that works reliably.

my problem is much more the ng-if statement in the template. there the traffic lights are displayed. with one data string everything works fine, if a second one is added, both traffic lights start to flicker and are not displayed at the same time.

[{"id":"7e3348b2.34bc08","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"356cbc14.13c304","type":"debug","z":"7e3348b2.34bc08","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":580,"wires":[]},{"id":"973f2476.f56778","type":"debug","z":"7e3348b2.34bc08","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":780,"wires":[]},{"id":"8ffd67eb.b456e8","type":"switch","z":"7e3348b2.34bc08","name":"off","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":670,"y":420,"wires":[["646e0e0e.81aa4"],["e918cb9a.33b7f8"]]},{"id":"646e0e0e.81aa4","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"red_machine1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":420,"wires":[["ed6054a0.5a2668"]]},{"id":"d7d93678.bc7b58","type":"switch","z":"7e3348b2.34bc08","name":"standby","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":700,"wires":[["4da1c7fc.dfaaf8"],["a0af85e3.0347a8"]]},{"id":"4da1c7fc.dfaaf8","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"yellow_machine1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":950,"y":700,"wires":[["ed6054a0.5a2668"]]},{"id":"d547629e.aa75","type":"switch","z":"7e3348b2.34bc08","name":"on","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":670,"y":880,"wires":[["84b93439.3b00f8"],["69bf8640.a81a28"]]},{"id":"84b93439.3b00f8","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"green_machine1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":880,"wires":[["ed6054a0.5a2668"]]},{"id":"a0af85e3.0347a8","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":780,"wires":[]},{"id":"e918cb9a.33b7f8","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":900,"y":520,"wires":[]},{"id":"69bf8640.a81a28","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":860,"y":980,"wires":[]},{"id":"1446d565.c391cb","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":1120,"wires":[]},{"id":"5d9501ce.0fb01","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":1380,"wires":[]},{"id":"83443921.f68a48","type":"debug","z":"7e3348b2.34bc08","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":1580,"wires":[]},{"id":"fdb8ec22.77eb","type":"switch","z":"7e3348b2.34bc08","name":"off","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":670,"y":1220,"wires":[["83e251fa.b9952"],["bfb3c1a6.f1c5b"]]},{"id":"83e251fa.b9952","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"red_machine2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":1220,"wires":[["ed6054a0.5a2668"]]},{"id":"963d97d1.37ec68","type":"switch","z":"7e3348b2.34bc08","name":"standby","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":1500,"wires":[["555da881.af6b18"],["fecb80f3.9b133"]]},{"id":"555da881.af6b18","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"yellow_machine2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":950,"y":1500,"wires":[["ed6054a0.5a2668"]]},{"id":"1527e7ad.7a4ac8","type":"switch","z":"7e3348b2.34bc08","name":"on","property":"payload","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":670,"y":1680,"wires":[["9220cba5.232898"],["95797ba8.6cbb58"]]},{"id":"9220cba5.232898","type":"change","z":"7e3348b2.34bc08","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"green_machine2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":1680,"wires":[["ed6054a0.5a2668"]]},{"id":"fecb80f3.9b133","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":1580,"wires":[]},{"id":"bfb3c1a6.f1c5b","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":900,"y":1320,"wires":[]},{"id":"95797ba8.6cbb58","type":"debug","z":"7e3348b2.34bc08","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":860,"y":1780,"wires":[]},{"id":"ed6054a0.5a2668","type":"ui_template","z":"7e3348b2.34bc08","group":"e3008e05.4d498","name":"","order":4,"width":"23","height":"20","format":"\n<style>\n    .redButton{\n        background-color: red;\n    }\n    \n    .yellowButton{\n        background-color: yellow;\n    }\n    \n    .greenButton{\n        background-color: green;\n    }\n    .normalAmpel{\n        position: absolute;\n        width: 50px;\n        height: 50px;\n        border-radius: 50%;\n        color: white;\n        padding-left: 10px;\n        padding-top: 10px;\n        font-size: 16px;\n        z-index: 5;\n        background-color: black;\n    }\n    \n    .machine1{\n        top: 150px;\n        left: 100px;\n    }\n    \n    .machine2{\n        top: 100px;\n        left: 150px;\n    }\n    \n</style>\n\n\n<!-- Machine 1 -->\n<div id= machine1 class=\"normalAmpel machine2\"></div>\n\n\n<!-- Machine 2 -->\n<div id= machine2 class=\"normalAmpel machine2\"></div>\n\n<script>\n    document.getElementbyId(\"machine1\").style.color = color_func_machine1;\n    document.getElementbyId(\"machine2\").style.color = color_func_machine2;\n    \n    function color_func_machine1 (red_machine1, green_machine1, yellow_machine1 ){\n        let = color;\n        \n        if (red_machine1== true){\n            color = red;\n            }\n            else\n        if (green_machine1== true){\n            color = green;\n            }\n            else\n         if (yellow_machine1== true){\n            color = yellow;\n            }\n        return color;\n    }\n    \n    function color_func_machine2 (red_machine2, green_machine2, yellow_machine2){\n        let = color;\n        \n        if (red_machine2 == true){\n            color = 'red';\n            }\n            else\n        if (green_machine2 == true){\n            color = 'green';\n            }\n            else\n         if (yellow_machine2 == true){\n            color = 'yellow';\n            }\n        return color;\n    }\n</script>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1930,"y":1140,"wires":[[]]},{"id":"e3008e05.4d498","type":"ui_group","name":"Test","tab":"cbad0788.89be9","order":1,"disp":false,"width":"25","collapse":false},{"id":"cbad0788.89be9","type":"ui_tab","name":"Test","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

There must be something else to check as the content of all the payloads looks the same in your flow.

Here's a very simple flow using a slider to simulate an input value between 1 and 9.
The function node checks the value and sends a color command to the button (simulated bulb).

If input is greater than 6, bulb is red.
If input is greater than 3, bulb is yellow.
Otherwise bulb is green.

Screen Shot 08-27-21 at 05.53 AM
Screen Shot 08-27-21 at 05.59 AM

[{"id":"361c193df2f00de3","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"670e1c025fc55d0e","type":"ui_button","z":"361c193df2f00de3","name":"","group":"3957cd51c5b78ad8","order":2,"width":"2","height":"1","passthru":false,"label":"button","tooltip":"","color":"{{btn_color}}","bgcolor":"black","icon":"wb_incandescent","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":610,"y":260,"wires":[[]]},{"id":"fbd1f28b9dd9c112","type":"ui_slider","z":"361c193df2f00de3","name":"","label":"slider","tooltip":"","group":"3957cd51c5b78ad8","order":1,"width":"1","height":"6","passthru":true,"outs":"all","topic":"topic","topicType":"msg","min":"1","max":"9","step":1,"x":280,"y":260,"wires":[["927c27ba72f9d66a"]]},{"id":"927c27ba72f9d66a","type":"function","z":"361c193df2f00de3","name":"","func":"if (msg.payload > 6) {\n    msg.btn_color=\"red\";\n}\nelse if (msg.payload > 3) {\n    msg.btn_color=\"yellow\";\n}\nelse {\n    msg.btn_color = \"green\";\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":260,"wires":[["670e1c025fc55d0e"]]},{"id":"3957cd51c5b78ad8","type":"ui_group","name":"slider","tab":"5819c9d13b89c74e","order":1,"disp":true,"width":"6","collapse":false},{"id":"5819c9d13b89c74e","type":"ui_tab","name":"Color_button","icon":"dashboard","order":3,"disabled":false,"hidden":false}]

Here's another demo flow that detects the msg.payload and checks if it is... "on", "standby" or "off"

Screen Shot 08-27-21 at 06.46 AM 001
Screen Shot 08-27-21 at 06.46 AM

[{"id":"361c193df2f00de3","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"670e1c025fc55d0e","type":"ui_button","z":"361c193df2f00de3","name":"","group":"3957cd51c5b78ad8","order":1,"width":"2","height":"1","passthru":false,"label":"bulb","tooltip":"","color":"{{btn_color}}","bgcolor":"black","icon":"wb_incandescent","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":610,"y":320,"wires":[[]]},{"id":"927c27ba72f9d66a","type":"function","z":"361c193df2f00de3","name":"","func":"if (msg.payload == \"on\") {\n    msg.btn_color=\"red\";\n}\nelse if (msg.payload == \"standby\") {\n    msg.btn_color=\"yellow\";\n}\nelse if (msg.payload == \"off\") {\n    msg.btn_color = \"green\";\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":320,"wires":[["670e1c025fc55d0e"]]},{"id":"bd0001fef0a974e2","type":"inject","z":"361c193df2f00de3","name":"on","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"on","payloadType":"str","x":270,"y":180,"wires":[["927c27ba72f9d66a"]]},{"id":"4eb46cd028e77730","type":"inject","z":"361c193df2f00de3","name":"standby","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"standby","payloadType":"str","x":270,"y":300,"wires":[["927c27ba72f9d66a"]]},{"id":"10e310cb54a4effe","type":"inject","z":"361c193df2f00de3","name":"off","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"off","payloadType":"str","x":270,"y":420,"wires":[["927c27ba72f9d66a"]]},{"id":"6987248a66e90538","type":"ui_button","z":"361c193df2f00de3","name":"","group":"3957cd51c5b78ad8","order":2,"width":"2","height":"1","passthru":false,"label":"on","tooltip":"","color":"","bgcolor":"","icon":"","payload":"on","payloadType":"str","topic":"topic","topicType":"msg","x":250,"y":220,"wires":[["927c27ba72f9d66a"]]},{"id":"0bb9c726e105f390","type":"ui_button","z":"361c193df2f00de3","name":"","group":"3957cd51c5b78ad8","order":3,"width":"2","height":"1","passthru":false,"label":"standby","tooltip":"","color":"","bgcolor":"","icon":"","payload":"standby","payloadType":"str","topic":"topic","topicType":"msg","x":260,"y":340,"wires":[["927c27ba72f9d66a"]]},{"id":"d8b0978c24c2483f","type":"ui_button","z":"361c193df2f00de3","name":"","group":"3957cd51c5b78ad8","order":4,"width":"2","height":"1","passthru":false,"label":"off","tooltip":"","color":"","bgcolor":"","icon":"","payload":"off","payloadType":"str","topic":"topic","topicType":"msg","x":250,"y":460,"wires":[["927c27ba72f9d66a"]]},{"id":"3957cd51c5b78ad8","type":"ui_group","name":"Demo","tab":"5819c9d13b89c74e","order":1,"disp":true,"width":"2","collapse":false},{"id":"5819c9d13b89c74e","type":"ui_tab","name":"Color_button","icon":"dashboard","order":3,"disabled":false,"hidden":false}]
1 Like

Thanks for the help.

I think my problem was not understood correctly, but I'll try to describe it again and share my approach.

The problem is that a live traffic light should be displayed on an image. It is quickly done to implement a simple traffic light. The difficulty arises from the fact that in the background a picture should be displayed, on which the traffic light is located on a certain point.

The goal is to quickly and intuitively see in a floor plan which machine is currently in operation and which is not.

The data comes live via an OPC UA server into the dashboard. My solution approach is this:

I save all data in a JSON file and then display the saved values per machine.

In my code shown above, the problem is that I forgot that the data keeps overwriting each other and nothing is displayed at the same time. the template is passed through displays machine one and then two and not one and two.

If I get the code done I will share it again.

If other ideas come up through the description I would be very happy.