Trigger State to register but only if specific attribute has changed?

I have Lovelace control over 5 Honeywell thermostats all in the same warehouse. I’m trying to setup NodeRED so any manual change made at any thermostat will be sent to all of the other thermostats. To do so, I’m using a trigger state to watch climate.warehouse_hvac*.

So, any climate device prefixed with warehouse_hvac will trigger.

The challenge is in the conditions for the trigger. I have a few challenges:

  1. Only listen to the initial triggering device. Disable the trigger state node upon initial trigger to prevent subsequent matches. Figure out a way to confirm all units have responded before re-enabling the trigger state node.

  2. Only call the resulting service for the other thermostats. In other words, if you adjust thermostat 1, we don’t need to send a service call to adjust thermostat 1. It has already been adjusted. If you adjust #2, then 1, 3, 4, 5 would be updated. And so on.

  3. Only pass the trigger state node if a specific property has changed. The condition would be “this entity property X should be the only property we consider in order for the state change to be recognized.”

In the Property conditions dropdown, I would expect to see “has changed” or “has not changed” or “is equal to previous” or something of that nature.

I’m currently testing

"This Entity" 
"Property: new_state.attributes.temperature"
"is not" J: $entity().old_state.attributes.temperature

But I don’t know if that’s working.

Any ideas on this?

This could be a starting for you.

[{"id":"3a69902b.e5f44","type":"server-state-changed","z":"51045e07.bbf87","name":"Thermostat 1","server":"d177950.2a5aa68","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac1","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":250,"y":140,"wires":[["d6247d62.d1efb"]]},{"id":"cbcf6ea7.03a24","type":"server-state-changed","z":"51045e07.bbf87","name":"Thermostat 2","server":"d177950.2a5aa68","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac2","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":250,"y":180,"wires":[["d6247d62.d1efb"]]},{"id":"698598de.bc8ac8","type":"server-state-changed","z":"51045e07.bbf87","name":"Thermostat 3","server":"d177950.2a5aa68","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac3","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":250,"y":220,"wires":[["d6247d62.d1efb"]]},{"id":"46b231ab.3c135","type":"server-state-changed","z":"51045e07.bbf87","name":"Thermostat 4","server":"d177950.2a5aa68","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac4","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":250,"y":260,"wires":[["d6247d62.d1efb"]]},{"id":"8234df4c.d8a04","type":"server-state-changed","z":"51045e07.bbf87","name":"Thermostat 5","server":"d177950.2a5aa68","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac5","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":250,"y":300,"wires":[["d6247d62.d1efb"]]},{"id":"d6247d62.d1efb","type":"trigger","z":"51045e07.bbf87","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"0","extend":false,"overrideDelay":false,"units":"ms","reset":"True","bytopic":"all","topic":"topic","outputs":1,"x":460,"y":220,"wires":[["7d89ff8.1fa81","7c26cf19.e56a8"]]},{"id":"1c6e466c.3d57aa","type":"api-render-template","z":"51045e07.bbf87","name":"Check equal","server":"d177950.2a5aa68","template":"{{states('climate.warehouse_hvac1')|float == states('climate.warehouse_hvac2')|float == states('climate.warehouse_hvac3')|float ==states('climate.warehouse_hvac4')|float ==states('climate.warehouse_hvac5')|float}}\n","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":810,"y":140,"wires":[["d6247d62.d1efb"]]},{"id":"7d89ff8.1fa81","type":"trigger","z":"51045e07.bbf87","name":"","op1":"ok","op2":"0","op1type":"str","op2type":"str","duration":"-5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":640,"y":140,"wires":[["1c6e466c.3d57aa"]]},{"id":"7c26cf19.e56a8","type":"api-call-service","z":"51045e07.bbf87","name":"Call service to set Temperature of Others","server":"d177950.2a5aa68","version":1,"debugenabled":false,"service_domain":"climate","service":"set_temperature","entityId":"","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":740,"y":220,"wires":[[]]},{"id":"d177950.2a5aa68","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Is this critical conditon because we are trying to set the conditions of all the thermostat the same so even if we call the service for the initiator thermostat, it really shouldn’t matter.

This can be achieved by using a render template node.

I’ve been working this angle:

[{"id":"96c66197.9fb4c","type":"trigger-state","z":"f2a57f2f.5ea0a","name":"Watch for Changed Temperature Setting","server":"b650d991.c980b8","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"climate.sanctuary*","entityidfiltertype":"regex","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"jsonata","comparatorValue":"$prevEntity().attributes.temperature","propertyValue":"new_state.attributes.temperature"},{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"re","comparatorValue":"^null$","propertyValue":"new_state.attributes.temperature"},{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"re","comparatorValue":"^null$","propertyValue":"old_state.attributes.temperature"}],"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","x":260,"y":520,"wires":[["d044a8d0.2f9ed8"],[]]},{"id":"d044a8d0.2f9ed8","type":"debug","z":"f2a57f2f.5ea0a","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":460,"wires":[]},{"id":"b650d991.c980b8","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

This is one of three separate trigger state nodes, each of which can be disabled while the rest of the automation runs.

The “Watched for Changed Temperatures Setting” trigger state node looks watches all of the climate.sanctuary* entities using Regex.

The conditions:

  • the triggering entity’s new temperature setting cannot be the same as the previous temperature setting.
  • the triggering entity’s new temperature cannot be null - this happens when the HVAC mode is turned to OFF.
  • the triggering entity’s old temperature cannot be null - this prevents triggering when the mode is changed from off to either Heat or Cool.

There are two other trigger states, one that watches the fan_mode and one that watches the state.

At this point, I’ve only dialed in the triggers to deliver the message when the conditions are right. The next step will be to create an array of all climate.sanctuary* entities from which I can create a service call for each in the list except for the one that triggered the flow in the first place.

Then, I’ve used a ‘get states’ node which finds all climate.sanctuary* entities that meet a certain condition and output a count. This will be to count the number of HVAC units that have reached the desired state, and when the count is correct, the flow will move forward.

[{"id":"7605d2f8.de440c","type":"server-state-changed","z":"d4450f17.60952","name":"Triggers","server":"9405c3fe.d0a6c","version":1,"exposeToHomeAssistant":true,"haConfig":[{"property":"name","value":"triggers"},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac*","entityidfiltertype":"regex","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":140,"y":460,"wires":[["25a21aed.0eabb6"]]},{"id":"25a21aed.0eabb6","type":"switch","z":"d4450f17.60952","name":"Has temp changed?","property":"data.new_state.attributes.temperature","propertyType":"msg","rules":[{"t":"neq","v":"data.old_state.attributes.temperature","vt":"msg"}],"checkall":"true","repair":false,"outputs":1,"x":320,"y":460,"wires":[["bd27169e.3b1648"]]},{"id":"34f2de16.fb00a2","type":"api-call-service","z":"d4450f17.60952","name":"disable trigger","server":"9405c3fe.d0a6c","version":1,"debugenabled":false,"service_domain":"homeassistant","service":"turn_off","entityId":"switch.triggers","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":700,"y":460,"wires":[["5c546f0a.1a032","3b953a4d.35db16"]]},{"id":"fea7e18d.067a1","type":"ha-wait-until","z":"d4450f17.60952","name":"Device 1 updated?","server":"9405c3fe.d0a6c","outputs":1,"entityId":"{{devices.0.entity_id}}","entityIdFilterType":"exact","property":"attributes.temperature","comparator":"is","value":"targetTemp","valueType":"msg","timeout":0,"timeoutType":"num","timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":1250,"y":300,"wires":[["9b4c68a8.38df68"]]},{"id":"5c546f0a.1a032","type":"ha-get-entities","z":"d4450f17.60952","server":"9405c3fe.d0a6c","name":"Get remaining devices","rules":[{"property":"entity_id","logic":"includes","value":"climate.1, climate.2, climate.3, climate.4, climate.5","valueType":"str"},{"property":"entity_id","logic":"is_not","value":"topic","valueType":"msg"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"devices","output_results_count":1,"x":960,"y":400,"wires":[["fea7e18d.067a1"]]},{"id":"9b4c68a8.38df68","type":"ha-wait-until","z":"d4450f17.60952","name":"Device 2 updated?","server":"9405c3fe.d0a6c","outputs":1,"entityId":"{{devices.1.entity_id}}","entityIdFilterType":"exact","property":"attributes.temperature","comparator":"is","value":"targetTemp","valueType":"msg","timeout":0,"timeoutType":"num","timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":1250,"y":340,"wires":[["daa13b9d.e926f8"]]},{"id":"daa13b9d.e926f8","type":"ha-wait-until","z":"d4450f17.60952","name":"Device 3 updated?","server":"9405c3fe.d0a6c","outputs":1,"entityId":"{{devices.2.entity_id}}","entityIdFilterType":"exact","property":"attributes.temperature","comparator":"is","value":"targetTemp","valueType":"msg","timeout":0,"timeoutType":"num","timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":1250,"y":380,"wires":[["be7cdbff.64d328"]]},{"id":"be7cdbff.64d328","type":"ha-wait-until","z":"d4450f17.60952","name":"Device 4 updated?","server":"9405c3fe.d0a6c","outputs":1,"entityId":"{{devices.3.entity_id}}","entityIdFilterType":"exact","property":"attributes.temperature","comparator":"is","value":"targetTemp","valueType":"msg","timeout":0,"timeoutType":"num","timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":1250,"y":420,"wires":[["7fcd28c1.d74a48"]]},{"id":"7fcd28c1.d74a48","type":"api-call-service","z":"d4450f17.60952","name":"enable trigger","server":"9405c3fe.d0a6c","version":1,"debugenabled":false,"service_domain":"homeassistant","service":"turn_on","entityId":"switch.triggers","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1480,"y":420,"wires":[[]]},{"id":"3b953a4d.35db16","type":"ha-get-entities","z":"d4450f17.60952","server":"9405c3fe.d0a6c","name":"Get remaining devices","rules":[{"property":"entity_id","logic":"includes","value":"climate.1, climate.2, climate.3, climate.4, climate.5","valueType":"str"},{"property":"entity_id","logic":"is_not","value":"topic","valueType":"msg"}],"output_type":"split","output_empty_results":false,"output_location_type":"msg","output_location":"devices","output_results_count":1,"x":960,"y":500,"wires":[["89dad3e5.5d17b"]]},{"id":"6e06d33f.8c731c","type":"api-call-service","z":"d4450f17.60952","name":"Set temperature","server":"9405c3fe.d0a6c","version":1,"debugenabled":false,"service_domain":"climate","service":"set_temperature","entityId":"{{payload}}","data":"{\"temperature\": \"{{targetTemp}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1450,"y":500,"wires":[[]]},{"id":"bd27169e.3b1648","type":"change","z":"d4450f17.60952","name":"Save taget temp","rules":[{"t":"set","p":"targetTemp","pt":"msg","to":"data.new_state.attributes.temperature","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":460,"wires":[["34f2de16.fb00a2"]]},{"id":"89dad3e5.5d17b","type":"template","z":"d4450f17.60952","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{payload.entity_id}}","output":"str","x":1140,"y":500,"wires":[["94a4a79b.bc66f8"]]},{"id":"94a4a79b.bc66f8","type":"join","z":"d4450f17.60952","name":"","mode":"custom","build":"string","property":"payload","propertyType":"msg","key":"topic","joiner":",","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1270,"y":500,"wires":[["6e06d33f.8c731c"]]},{"id":"9405c3fe.d0a6c","type":"server","name":"Home Assistant","addon":true}]

I have not been able to test it out thoug, it must have some flaws.

there’s the danger that you manipulate the thermostat manually while the trigger node is disabled so it will cripple your flow. I don’t see the harm in calling the service more than once, why do you? in fact, once you call the set temp service, you can be positive they’ve already changed.

I also don’t see the harm in doing that… It’s just easier and I don’t see any inconvenience. Why do you find an inconvenience with that? I mean, if you manipulate one, just set the temperature of them all to that temp.

This is done by the “Has temp changed?” switch. All your demands I believe are achieved by that flow.

Personally I would do just this:

[{"id":"9b8333ae.59eb6","type":"server-state-changed","z":"d4450f17.60952","name":"Triggers","server":"9405c3fe.d0a6c","version":1,"exposeToHomeAssistant":true,"haConfig":[{"property":"name","value":"triggers"},{"property":"icon","value":""}],"entityidfilter":"climate.warehouse_hvac*","entityidfiltertype":"regex","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":160,"y":780,"wires":[["6bd8dee4.91fc1"]]},{"id":"6bd8dee4.91fc1","type":"switch","z":"d4450f17.60952","name":"Has temp changed?","property":"data.new_state.attributes.temperature","propertyType":"msg","rules":[{"t":"neq","v":"data.old_state.attributes.temperature","vt":"msg"}],"checkall":"true","repair":false,"outputs":1,"x":340,"y":780,"wires":[["609abfe0.ff551"]]},{"id":"609abfe0.ff551","type":"api-call-service","z":"d4450f17.60952","name":"Set temperature","server":"9405c3fe.d0a6c","version":1,"debugenabled":false,"service_domain":"climate","service":"set_temperature","entityId":"climate.1, climate.2, climate.3, climate.4, climate.5","data":"{\"temperature\": \"{{targetTemp}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":560,"y":780,"wires":[[]]},{"id":"9405c3fe.d0a6c","type":"server","name":"Home Assistant","addon":true}]

The Honeywell My Total Comfort Connect API has an unknown-to-me call limit, so making sure that there are as few instructions being sent to their website as possible is the goal. I was locked out once before because I forgot to stop each other device from triggering over and over again for ALL state changes (thermometer, mode, temp, etc.).

Here’s what I’ve come up with:

[{"id":"96c66197.9fb4c","type":"trigger-state","z":"f2a57f2f.5ea0a","name":"Watch for Changed Temperature Setting","server":"b650d991.c980b8","exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"climate.sanctuary*","entityidfiltertype":"regex","debugenabled":false,"constraints":[{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"jsonata","comparatorValue":"$prevEntity().attributes.temperature","propertyValue":"new_state.attributes.temperature"},{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"re","comparatorValue":"^null$","propertyValue":"new_state.attributes.temperature"},{"targetType":"this_entity","targetValue":"","propertyType":"property","comparatorType":"is_not","comparatorValueDatatype":"re","comparatorValue":"^null$","propertyValue":"old_state.attributes.temperature"}],"outputs":2,"customoutputs":[],"outputinitially":false,"state_type":"str","x":200,"y":520,"wires":[["34f62620.b3e8ca"],[]]},{"id":"d044a8d0.2f9ed8","type":"debug","z":"f2a57f2f.5ea0a","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1790,"y":700,"wires":[]},{"id":"34f62620.b3e8ca","type":"trigger","z":"f2a57f2f.5ea0a","name":"Stop State Triggers Temporarily","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"0","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":290,"y":580,"wires":[["a09aa918.4dced8"]]},{"id":"a09aa918.4dced8","type":"ha-get-entities","z":"f2a57f2f.5ea0a","server":"b650d991.c980b8","name":"Get Thermostats","rules":[{"property":"entity_id","logic":"is","value":"climate.sanctuary*","valueType":"re"}],"output_type":"array","output_empty_results":false,"output_location_type":"msg","output_location":"payload","output_results_count":1,"x":530,"y":520,"wires":[["96479c8a.b8749"]]},{"id":"ead552d2.6a74e","type":"split","z":"f2a57f2f.5ea0a","name":"Split Array into individual messages","splt":"5","spltType":"str","arraySplt":"1","arraySpltType":"len","stream":false,"addname":"","x":840,"y":520,"wires":[["5ba820b2.0e9a3"]]},{"id":"5ba820b2.0e9a3","type":"switch","z":"f2a57f2f.5ea0a","name":"Do Not Include Original Triggered Entity","property":"topic","propertyType":"msg","rules":[{"t":"neq","v":"payload.entity_id","vt":"msg"}],"checkall":"true","repair":false,"outputs":1,"x":980,"y":580,"wires":[["441d9d54.23ce34"]]},{"id":"96479c8a.b8749","type":"change","z":"f2a57f2f.5ea0a","name":"Define Target Temp in MSG","rules":[{"t":"set","p":"target_temp","pt":"msg","to":"data.event.new_state.attributes.temperature","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":580,"wires":[["ead552d2.6a74e"]]},{"id":"441d9d54.23ce34","type":"simple-queue","z":"f2a57f2f.5ea0a","name":"Queue Up Temperature Change Messages","firstMessageBypass":true,"bypassInterval":"0","x":1230,"y":520,"wires":[["268a1df3.bd42f2"]]},{"id":"268a1df3.bd42f2","type":"api-call-service","z":"f2a57f2f.5ea0a","name":"Set Temperature on Unit","server":"b650d991.c980b8","version":1,"debugenabled":false,"service_domain":"climate","service":"set_temperature","entityId":"{{payload.entity_id}}","data":"{\"temperature\":\"{{target_temp}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1350,"y":580,"wires":[["d044a8d0.2f9ed8","6c472b35.1ce404","84cf5314.a0e02"]]},{"id":"6c472b35.1ce404","type":"change","z":"f2a57f2f.5ea0a","name":"Trigger Message Queue Next Message","rules":[{"t":"set","p":"trigger","pt":"msg","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1590,"y":460,"wires":[["441d9d54.23ce34"]]},{"id":"84cf5314.a0e02","type":"switch","z":"f2a57f2f.5ea0a","name":"Was that the last message?","property":"_queueCount","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":1660,"y":580,"wires":[["1097b14a.24510f"]]},{"id":"1097b14a.24510f","type":"stoptimer","z":"f2a57f2f.5ea0a","duration":"5","units":"Second","payloadtype":"num","payloadval":"0","name":"Wait 5 Seconds","x":1900,"y":580,"wires":[["522e42e2.f0b81c"],[]]},{"id":"522e42e2.f0b81c","type":"link out","z":"f2a57f2f.5ea0a","name":"Re-Route to Unblock Trigger","links":["c5edb66a.40b5b8"],"x":2035,"y":580,"wires":[]},{"id":"c5edb66a.40b5b8","type":"link in","z":"f2a57f2f.5ea0a","name":"Inbound Unblock Trigger","links":["522e42e2.f0b81c"],"x":75,"y":640,"wires":[["f1de7660.eb13c8"]]},{"id":"f1de7660.eb13c8","type":"change","z":"f2a57f2f.5ea0a","name":"Reset Trigger Blocking","rules":[{"t":"set","p":"reset","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":220,"y":640,"wires":[["34f62620.b3e8ca"]]},{"id":"b650d991.c980b8","type":"server","name":"Home Assistant","legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Here’s how it works:

Watch for Changed Temperature Setting : Trigger State

With conditions, this watches all climate.sanctuary* entities of which there are 5. It excludes state changes that are anything BUT temperature changes, and it prevents recognition of events that cause null temperature setting values, like changing the hvac_mode to OFF, which nullifies the temperature setting.

Stop State Triggers Temporarily : Trigger

Sends the existing message through and stops to wait for a msg.reset value.

Get Thermostats : Get Entities

Using Regex, it gets the states of all climate.sanctuary* entities and stores this as an array.

Define Target Temp in MSG : Change

This node takes the target temperature set in the initial triggering entity and stores it in msg.target_temp.

Split Array into individual messages : Split

This node splits the object in the message into individual messages.

Do Not Include Original Triggered Entity : Switch

This node looks at the msg.topic, which is defined at the initial trigger based upon the triggering entity and compares that value against the entity_id in the payload. Where the values are the same, the message is ignored, passing through only messages where the entity to be updated is not equal to the entity which triggered the flow.

Queue Up Temperature Change Messages : Simple Queue

Simple Queue allows the first message to pass through, then holds the remaining messages in a queue to be triggered later for release one at a time.

Set Temperature On Unit : Call Service

The call service uses the value in {{payload.entity_id}}' which is that of the entity that is being changed and inserts the {{target_temp}}` defined in a previous node. I had to do this because we still need the triggering entity’s new value but we filtered out that message a few nodes ago.

Trigger Message Queue Next Message : Change

This node sets msg.trigger to 1 and routes back to the Queue Message node which then triggers the next message in line.

Was That the Last Message? : Switch

Every time a message is released from the Simple Queue, it has a value stored in _queueCount which decrements to Zero, signaling the final message in the queue. This node simply checks that value for 0.

Wait 5 Seconds (Just precautionary…)

Link Out Node

If you don’t know the Link In/Out nodes, they’re very useful in keeping your workflow organized and in re-routing signals across wide expanses without having obnoxious strings all over the place. We no like spaghetti.

This link out node re-routes the message back to the beginning into the final node.

Reset Trigger Blocking : Change

This sets msg.reset to 1 and injects the message back into the Trigger node to re-set it and thereby allowing additional trigger states to be detected.

Now, whether someone uses Lovelace, the actual Thermostat, or the interface on MyTotalConnectComfort.com, this automation will ensure that we only have to change ONE of the thermostats to change all of them.

If at any point someone happens to manually change one of the other thermostats in the middle of this automation while the trigger is blocked, the consequences will be minimal, and this would be highly unlikely anyway.

1 Like