Using an OR to test multiple MQTT states

I’m mostly new to Node-Red (but I did stay at a Holiday Inn Express last night), but managing to pick up bits and pieces each time I try a new automation with it! So, there’s hope for me!

Background: I have a couple of 3d printers in my workshop. I also have a couple of Zigbee lights overhead that turn on with motion in the workshop. I’m trying to keep the lights on while any of the printers is printing since only one of the printers has an IR capable camera on it.

So, I’ve created a test flow in NR (using the first 2 printers to simplify the logic, and adding the 3rd one in later) that takes input from the MQTT/HA integration in Octoprint. I have the following flow, so far:

[{"id":"bfb0b07dd6dfa394","type":"tab","label":"3D Printers","disabled":false,"info":"","env":[]},{"id":"29e9942ff8311ff3","type":"mqtt in","z":"bfb0b07dd6dfa394","name":"","topic":"drevil/hass/is_printing","qos":"2","datatype":"auto-detect","broker":"8e73d9db192d604b","nl":false,"rap":true,"rh":0,"inputs":0,"x":160,"y":320,"wires":[["d3dad7929cfc4312"]]},{"id":"e6aadefea1af51ad","type":"mqtt in","z":"bfb0b07dd6dfa394","name":"","topic":"minime/hass/is_printing","qos":"2","datatype":"auto-detect","broker":"8e73d9db192d604b","nl":false,"rap":true,"rh":0,"inputs":0,"x":160,"y":420,"wires":[["d3dad7929cfc4312"]]},{"id":"78d6794c8939841e","type":"api-call-service","z":"bfb0b07dd6dfa394","name":"","server":"a3c613d7.a1f6","version":5,"debugenabled":false,"domain":"light","service":"turn_on","areaId":[],"deviceId":[],"entityId":["light.craft_room_fan_lights"],"data":"{\"brightness\":255}","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":910,"y":320,"wires":[[]]},{"id":"d3dad7929cfc4312","type":"BooleanLogic","z":"bfb0b07dd6dfa394","name":"","operation":"OR","inputCount":2,"topic":"result","x":450,"y":320,"wires":[["78d6794c8939841e","5cdfd82f7821bb57"]]},{"id":"5cdfd82f7821bb57","type":"Invert","z":"bfb0b07dd6dfa394","name":"Invert","x":670,"y":420,"wires":[["cfed703b2a989f57"]]},{"id":"cfed703b2a989f57","type":"api-call-service","z":"bfb0b07dd6dfa394","name":"","server":"a3c613d7.a1f6","version":5,"debugenabled":false,"domain":"light","service":"turn_off","areaId":[],"deviceId":[],"entityId":["light.craft_room_fan_lights"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":910,"y":420,"wires":[[]]},{"id":"8e73d9db192d604b","type":"mqtt-broker","name":"","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"a3c613d7.a1f6","type":"server","name":"Home Assistant","version":4,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m"}]

But, I’m running into an annoying issue and I can’t figure out if I’m simply doing something wrong or not. The lights DO turn on when either of the two printers start printing, but, the lights immediately turn right back off regardless of the printer state (even if the MQTT topic still shows either printer “is_printing=True” state. Am I simply doing something wrong or taking the wrong approach?

TLDR: I want the lights to come on (if not already) and remain on while any of the 3D printers are on and in a state of “is_printing=true” in MQTT.

I haven’t used those boolean nodes before (I would tend to use persisted flow context instead). However, from the example in their documentation:

The node has been configured for two topics, with the operation OR.

  1. Topic ‘A’ with value false arrives - only one topic seen so no output.
  2. Topic ‘B’ with value true arrives - two topics seen so the node evaluates the received topics and outputs true.
  3. Topic ‘C’ arrives. This is the third topic which is one more than the configured number so the node resets and will not output another value until two new topics have been received. Note that when resetting it does not output any value.

Unless you’re also using ‘retain’ on your mqtt messages, you might have problems with point 1 after each deploy. Regardless, the only example seems to be an edge-case, so it’s not really clear what happens if you get A-true, B-false, A-false but let’s assume the OR will output true when B-false is received and then false when A-false is received (both A and B are now false). Then the INVERT will turn true to false and false to true as appropriate.

The problem is there is nothing between these logic nodes and the ‘call service’ nodes, so they will be run regardless of the message being true or false. So any message coming out from the OR will cause the light to be turned on and then off.

You should put a ‘switch’ node before each of the ‘call service’ nodes to only proceed if the payload is true.

I suspect also that A-true, B-false, A-true, A-true (etc) will turn the light on when it is already on. This may or may not be a problem for your use case (eg. you can also turn the light off manually).

The way I’d approach this is to make binary sensors for all the printers inside HA. Then you can use 2 trigger nodes.

This will trigger the lights on when ANY entity is switched on

image

This will turn off the lights only when ALL conditions are true.

I added a 5 min delay that resets if one of the entities goes on before the 5 min elapses.

[{"id":"1a4afc368897676f","type":"trigger-state","z":"f80b6c338afd5483","name":"","server":"","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":["motion","printer1","printer2","printer3"],"entityidfiltertype":"list","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"on"}],"inputs":0,"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","enableInput":false,"x":1040,"y":880,"wires":[["14363df8f5c20274","6298b579e35ac6c1"],[]]},{"id":"14363df8f5c20274","type":"api-call-service","z":"f80b6c338afd5483","name":"","server":"","version":5,"debugenabled":false,"domain":"light","service":"turn_on","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1690,"y":880,"wires":[[]]},{"id":"63509c684481036e","type":"trigger-state","z":"f80b6c338afd5483","name":"","server":"","version":2,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":["motion","printer1","printer2","printer3"],"entityidfiltertype":"list","debugenabled":false,"constraints":[{"targetType":"entity_id","targetValue":"motion","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"},{"targetType":"entity_id","targetValue":"printer1","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"},{"targetType":"entity_id","targetValue":"printer2","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"},{"targetType":"entity_id","targetValue":"printer3","propertyType":"current_state","propertyValue":"new_state.state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"off"}],"inputs":0,"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","enableInput":false,"x":1040,"y":940,"wires":[["37476d9a0b30ec4c"],[]]},{"id":"2f2d97cc568bab0d","type":"api-call-service","z":"f80b6c338afd5483","name":"","server":"","version":5,"debugenabled":false,"domain":"light","service":"turn_off","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1690,"y":940,"wires":[[]]},{"id":"37476d9a0b30ec4c","type":"delay","z":"f80b6c338afd5483","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1520,"y":940,"wires":[["2f2d97cc568bab0d"]]},{"id":"6298b579e35ac6c1","type":"change","z":"f80b6c338afd5483","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"},{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1340,"y":900,"wires":[["37476d9a0b30ec4c"]]}]

Thanks for the insight! I’ll carry that thinking into the next automation! I’m looking at using Mikefila’s solution, because I already have all the needed sensors and such as part of the Octoprint MQTT discovery plugin (in Octoprint), so I have all the needed “…is_printing” binary sensors already provided.

Of note, I never really saw any of the “1” cases you mentioned, but I did fear that the “3” case could be valid once I add in the 3rd printer to the flow. Again, something I’ll pay attention to should I run across it in future automations.

Thanks again!

Mikefila - Thank you! This was an approach I would have not thought of, and it did indeed work perfectly! As a bonus, the HA discovery plugin in Octoprint already provides virtually everything as some sort of sensor or switch in HA (via MQTT), so I didn’t even need to create any of the binary sensors, they were already there!

I’m still trying to grasp what the “change” node actually does or the reason for it, but I’ll figure it out eventually.

Thank you for the suggestion!

When the on trigger fires, it resets or clears the delay node. Say you leave the room printers are off, motion goes off now the 5 min delay to shut off starts. If you walk back into the room and trigger the motion sensor again before the light shuts off, it will clear the waiting off message.

Ah! Nice! Thank you! I can use that in some other automations that could benefit from that knowledge!!!