I installed two Trane XR524 Model TZEMT524AA21MA. It’s great. I like that it can run a schedule on it’s own without any automation. But I realized, without further control, I could set the temp from HA, but if the schedule was running, it only would set a ‘temporary override’. So at the next schedule interval it would change again. I wanted to be able to set Hold like I could from the device itself.
First, I watched the Zwave log when I changed the modes on the device and it emitted config parameter value changes to param id’s 76 and 77. Open Zwave has these set to something else. So I modified the zwcfg*.xml under both thermostat nodes to:
<Value type="list" genre="config" instance="1" index="76" label="Run Schedule" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="1" vindex="0" size="1">
<Help>0=hold 1=run</Help>
<Item label="Hold" value="0" />
<Item label="Run" value="1" />
</Value>
<Value type="list" genre="config" instance="1" index="77" label="ESM Mode" units="" read_only="false" write_only="false" verify_changes="false" poll_intensity="0" min="0" max="2" vindex="0" size="1">
<Help>0 = esm off, 2 esm on</Help>
<Item label="Off" value="0" />
<Item label="On" value="2" />
</Value>
Now I could turn off the schedule from my phone. This left me with no feedback however of what the value actually was on the device. While OpenZwave logged the information, config parameter changes aren’t something that fires an event in HA.
With a LOT of help from the community, I ended up with a node-red flow that will track and modify these states with just a few input booleans setup.
I added a couple carefully named input booleans to my config. My thermostats are nodes 3 and 4.
input_boolean:
xc_esm_3:
name: ds esm
xc_hold_3:
name: ds hold
xc_esm_4:
name: up sem
xc_hold_4:
name: up hold
[{"id":"1ba1a15b.b3001f","type":"server-state-changed","z":"b5543901.4c5968","name":"esm or hold toggle toggled","server":"d812fdda.9bbad","entityidfilter":"input_boolean.xc_(esm|hold)_\\d+","entityidfiltertype":"regex","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"","halt_if_compare":"is","outputs":1,"x":110,"y":80,"wires":[["145b7ed2.fac491"]]},{"id":"145b7ed2.fac491","type":"function","z":"b5543901.4c5968","name":"convert to svc params","func":"var regExp =/xc_(esm|hold)_(\\d+)/\nvar results = regExp.exec(msg.data.entity_id);\nvar paramId = 0;\nvar theVal = \"\";\nvar nodeid = results[2];\nif (results[1]==\"esm\") {\n paramId=77;\n if (msg.payload==\"on\") {\n theVal=\"On\";\n } else {\n theVal=\"Off\";\n }\n}else {\n if (results[1]==\"hold\") {\n paramId=76;\n if (msg.payload==\"on\") {\n theVal=\"Hold\";\n } else {\n theVal=\"Run\";\n }\n} else {\n return null;\n}\n}\nmsg = { \n payload: {\n domain: \"zwave\", \n service: \"set_config_parameter\",\n data: {\n node_id: nodeid,\n parameter: paramId,\n value: theVal\n }\n }\n};\n\nreturn msg;","outputs":1,"noerr":0,"x":460,"y":80,"wires":[["954469f6.871698"]]},{"id":"3fd81dd.7113ae2","type":"catch","z":"b5543901.4c5968","name":"","scope":null,"x":100,"y":40,"wires":[[]]},{"id":"954469f6.871698","type":"api-call-service","z":"b5543901.4c5968","name":"call it!","server":"d812fdda.9bbad","service_domain":"","service":"","data":"","render_data":false,"mergecontext":"","output_location":"payload","output_location_type":"msg","x":650,"y":120,"wires":[[]]},{"id":"511b76b3.5583e8","type":"tail","z":"b5543901.4c5968","name":"ozwlog tail","filetype":"text","split":true,"filename":"/config/OZW_Log.txt","x":60,"y":160,"wires":[["320d0fb8.4b689"]]},{"id":"320d0fb8.4b689","type":"switch","z":"b5543901.4c5968","name":"Only Config Reports","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"Info, Node\\d{3}, Received Configuration report","vt":"str","case":true}],"checkall":"true","repair":false,"outputs":1,"x":260,"y":160,"wires":[["26863c8b.fa61d4"]]},{"id":"26863c8b.fa61d4","type":"function","z":"b5543901.4c5968","name":"mkServiceCall","func":"var regExp =/Info, Node0*(\\d+), Received Configuration report: Parameter=(\\d+), Value=(\\d+)/\nvar results = regExp.exec(msg.payload);\nvar nodeId = results[1]; \nvar parmIndex= results[2]; \nvar parmValue= results[3];\nvar swtype=\"\";\nvar action=\"\";\nif (parmIndex==\"76\") {\n swtype=\"hold\";\n if (parmValue==\"0\") {\n action=\"turn_on\";\n } else {\n action=\"turn_off\"\n }\n} else {\n if (parmIndex==\"77\"){\n swtype=\"esm\";\n if (parmValue==\"0\") {\n action=\"turn_off\";\n } else {\n action=\"turn_on\"\n }\n }else {\n return null;\n }\n}\n\nvar entid=\"input_boolean.xc_\" + swtype + \"_\" + nodeId;\nmsg = { \n payload: {\n domain: \"input_boolean\", \n service: action,\n data: {\n entity_id: entid\n }\n }\n};\nreturn msg;","outputs":1,"noerr":0,"x":480,"y":160,"wires":[["954469f6.871698"]]},{"id":"d812fdda.9bbad","type":"server","z":"","name":"Home Assistant"}]