-
-
Notifications
You must be signed in to change notification settings - Fork 52
Example Thermostat
Characteristic | Optional/Required | Characteristic Properties (to enable property) |
---|---|---|
TargetHeatingCoolingState | Required | |
CurrentHeatingCoolingState | Required | |
TargetTemperature | Required | |
CurrentTemperature | Required | |
TemperatureDisplayUnits | Required | |
CurrentRelativeHumidity | Optional | { "CurrentRelativeHumidity": true } |
TargetRelativeHumidity | Optional | { "TargetRelativeHumidity": true } |
CoolingThresholdTemperature | Optional | only relevant when HeatingCoolingState = 3 |
HeatingThresholdTemperature | Optional | only relevant when HeatingCoolingState = 3 |
Characteristic | Format | Accepted Values | Notes |
---|---|---|---|
TargetHeatingCoolingState | int | 0, 1, 2, 3 | off = 0, heating = 1, cooling = 2, auto = 3; valid states can be defined in characteristics definition |
CurrentHeatingCoolingState | int | 0, 1, 2, 3 | off = 0, heating = 1, cooling = 2, auto = 3; valid states can be defined in characteristics definition |
TargetTemperature | float | 10 - 38 | always in Degree Celsius; in mode auto this is the average between cooling and heating thresholds |
CurrentTemperature | float | 10 - 38 | always in Degree Celsius |
TemperatureDisplayUnits | int | 0, 1 | Degree Celsius = 0, Degree Fahrenheit = 1; has no effect on displayed values, as these are controlled by regional settings in iOS |
CurrentRelativeHumidity | float | 0 - 100 | |
TargetRelativeHumidity | float | 0 - 100 | |
CoolingThresholdTemperature | float | 0 - 100 | defines down to which temperature the appliance will cool, only used in mode auto |
HeatingThresholdTemperature | float | 0 - 100 | defines up to which temperature the appliance will cool, only used in mode auto |
These examples are meant to be copied into your Node-RED system and adapted to your setup.
This flow contains two thermostats. One is only for heating and can be switched on/off, the other has all 4 operating modes.
The flow looks like this:
In Home.app, you will get this:
Icon view
Set temperature
Choose mode
Detailed view
Icon view
Set temperatures
Choose mode
Copyable Node-RED flow:
[{"id":"71bb32de.e0b0ac","type":"inject","z":"aacd89c2.2cf708","name":"CurrentHeatingCoolingState off","topic":"","payload":"{\"CurrentHeatingCoolingState\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":620,"wires":[["eb3f7f35.275ed"]]},{"id":"120a8ce.c6a3373","type":"debug","z":"aacd89c2.2cf708","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":870,"y":960,"wires":[]},{"id":"f42d56a1.db50d8","type":"inject","z":"aacd89c2.2cf708","name":"TargetHeatingCoolingState off","topic":"","payload":"{\"TargetHeatingCoolingState\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":460,"y":620,"wires":[["eb3f7f35.275ed"]]},{"id":"7349e2ee.759fac","type":"inject","z":"aacd89c2.2cf708","name":"CurrentTemperature 10","topic":"","payload":"{\"CurrentTemperature\":10}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":800,"wires":[["eb3f7f35.275ed"]]},{"id":"8f22babf.1332a8","type":"inject","z":"aacd89c2.2cf708","name":"TargetTemperature 10","topic":"","payload":"{\"TargetTemperature\":10}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":800,"wires":[["eb3f7f35.275ed"]]},{"id":"9c3496bd.fe8328","type":"inject","z":"aacd89c2.2cf708","name":"CurrentHeatingCoolingState heat","topic":"","payload":"{\"CurrentHeatingCoolingState\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":660,"wires":[["eb3f7f35.275ed"]]},{"id":"17b83efb.5df391","type":"inject","z":"aacd89c2.2cf708","name":"TargetHeatingCoolingState heat","topic":"","payload":"{\"TargetHeatingCoolingState\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":660,"wires":[["eb3f7f35.275ed"]]},{"id":"2e02c54b.ee4eca","type":"inject","z":"aacd89c2.2cf708","name":"CurrentHeatingCoolingState cool","topic":"","payload":"{\"CurrentHeatingCoolingState\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":700,"wires":[["eb3f7f35.275ed"]]},{"id":"bdf35b08.d58578","type":"inject","z":"aacd89c2.2cf708","name":"TargetHeatingCoolingState cool","topic":"","payload":"{\"TargetHeatingCoolingState\":2}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":700,"wires":[["eb3f7f35.275ed"]]},{"id":"9f1612bb.200ea","type":"inject","z":"aacd89c2.2cf708","name":"CurrentTemperature 20","topic":"","payload":"{\"CurrentTemperature\":20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":840,"wires":[["eb3f7f35.275ed"]]},{"id":"5ceff715.5df388","type":"inject","z":"aacd89c2.2cf708","name":"TargetTemperature 20","topic":"","payload":"{\"TargetTemperature\":20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":840,"wires":[["eb3f7f35.275ed"]]},{"id":"7e073e90.31c72","type":"inject","z":"aacd89c2.2cf708","name":"CurrentTemperature 30","topic":"","payload":"{\"CurrentTemperature\":30}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":880,"wires":[["eb3f7f35.275ed"]]},{"id":"89402a3d.d581a8","type":"inject","z":"aacd89c2.2cf708","name":"TargetTemperature 30","topic":"","payload":"{\"TargetTemperature\":30}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":420,"y":880,"wires":[["eb3f7f35.275ed"]]},{"id":"f00041a2.ce66e","type":"inject","z":"aacd89c2.2cf708","name":"TemperatureDisplayUnits Celsius","topic":"","payload":"{\"TemperatureDisplayUnits\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":940,"wires":[["eb3f7f35.275ed"]]},{"id":"73c1a173.df287","type":"inject","z":"aacd89c2.2cf708","name":"TemperatureDisplayUnits Fahrenheit","topic":"","payload":"{\"TemperatureDisplayUnits\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":980,"wires":[["eb3f7f35.275ed"]]},{"id":"9975b2ea.252e5","type":"inject","z":"aacd89c2.2cf708","name":"CurrentRelativeHumidity 20","topic":"","payload":"{\"CurrentRelativeHumidity\":20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":1040,"wires":[["eb3f7f35.275ed"]]},{"id":"e0b641c8.151a7","type":"inject","z":"aacd89c2.2cf708","name":"TargetRelativeHumidity 20","topic":"","payload":"{\"TargetRelativeHumidity\":20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":430,"y":1040,"wires":[["eb3f7f35.275ed"]]},{"id":"173f83f.569c57c","type":"inject","z":"aacd89c2.2cf708","name":"CurrentRelativeHumidity 30","topic":"","payload":"{\"CurrentRelativeHumidity\":30}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":1080,"wires":[["eb3f7f35.275ed"]]},{"id":"261af724.7d14e8","type":"inject","z":"aacd89c2.2cf708","name":"TargetRelativeHumidity 30","topic":"","payload":"{\"TargetRelativeHumidity\":30}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":430,"y":1080,"wires":[["eb3f7f35.275ed"]]},{"id":"f63235a2.c01fc8","type":"inject","z":"aacd89c2.2cf708","name":"CurrentRelativeHumidity 40","topic":"","payload":"{\"CurrentRelativeHumidity\":40}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":1120,"wires":[["eb3f7f35.275ed"]]},{"id":"bc0b38d8.8b19a8","type":"inject","z":"aacd89c2.2cf708","name":"TargetRelativeHumidity 40","topic":"","payload":"{\"TargetRelativeHumidity\":40}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":430,"y":1120,"wires":[["eb3f7f35.275ed"]]},{"id":"e36bdcc9.32c29","type":"inject","z":"aacd89c2.2cf708","name":"CoolingThresholdTemperature 23","topic":"","payload":"{\"CoolingThresholdTemperature\":23}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1220,"wires":[["eb3f7f35.275ed"]]},{"id":"91b5fbc2.81d1f8","type":"inject","z":"aacd89c2.2cf708","name":"HeatingThresholdTemperature 21","topic":"","payload":"{\"HeatingThresholdTemperature\":21}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":1220,"wires":[["eb3f7f35.275ed"]]},{"id":"b52ecac9.c3f698","type":"inject","z":"aacd89c2.2cf708","name":"CoolingThresholdTemperature 25","topic":"","payload":"{\"CoolingThresholdTemperature\":25}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1260,"wires":[["eb3f7f35.275ed"]]},{"id":"67476ce3.ae9c54","type":"inject","z":"aacd89c2.2cf708","name":"HeatingThresholdTemperature 22","topic":"","payload":"{\"HeatingThresholdTemperature\":22}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":1260,"wires":[["eb3f7f35.275ed"]]},{"id":"7716264a.e09b98","type":"inject","z":"aacd89c2.2cf708","name":"HeatingThresholdTemperature 18","topic":"","payload":"{\"HeatingThresholdTemperature\":18}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":1180,"wires":[["eb3f7f35.275ed"]]},{"id":"b60f3788.4adb68","type":"inject","z":"aacd89c2.2cf708","name":"CoolingThresholdTemperature 20","topic":"","payload":"{\"CoolingThresholdTemperature\":20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":1180,"wires":[["eb3f7f35.275ed"]]},{"id":"29c352ee.0f465e","type":"inject","z":"aacd89c2.2cf708","name":"CurrentHeatingCoolingState auto","topic":"","payload":"{\"CurrentHeatingCoolingState\":3}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":740,"wires":[["eb3f7f35.275ed"]]},{"id":"9102b724.964998","type":"inject","z":"aacd89c2.2cf708","name":"TargetHeatingCoolingState auto","topic":"","payload":"{\"TargetHeatingCoolingState\":3}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":740,"wires":[["eb3f7f35.275ed"]]},{"id":"eb3f7f35.275ed","type":"function","z":"aacd89c2.2cf708","name":"","func":"\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":960,"wires":[["a523fb3e.497ea8","f50c12fc.0eeeb"]]},{"id":"a523fb3e.497ea8","type":"homekit-service","z":"aacd89c2.2cf708","bridge":"27eae9d3.b636b6","name":"Heating/Cooling Thermostat","serviceName":"Thermostat","topic":"","manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n}","x":660,"y":1000,"wires":[["120a8ce.c6a3373"]]},{"id":"f50c12fc.0eeeb","type":"homekit-service","z":"aacd89c2.2cf708","bridge":"27eae9d3.b636b6","name":"Heating Thermostat","serviceName":"Thermostat","topic":"","manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n \"TargetHeatingCoolingState\": {\n \"validValues\": [0, 1]\n },\n \"CurrentHeatingCoolingState\": {\n \"validValues\": [0, 1]\n }\n}","x":630,"y":940,"wires":[["120a8ce.c6a3373"]]},{"id":"27eae9d3.b636b6","type":"homekit-bridge","z":"","bridgeName":"4","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number"}]
Example of thermostat (Heating only) logic below. It turns on ({"CurrentHeatingCoolingState":1}
) and off ({"CurrentHeatingCoolingState":0}
) depending of CurrentTemperature
. This example would be applicable to radiator heater valves, plug-in heaters, and other similar equipment.
You should save T1.target_temperature
somehow (DB is a good choice) to store it after NodeRED restart, or you can face serious troubles in real environment. At the very least it is recommended to have the default value for T1.target_temperature
(line 2 in the function node) be a nice temperature for your house in case the system restarts and sets the temperature back to default.
Generally the current temperature and humidity will be determined by a sensor in your automation setup. The target temperature will be determined by your thermostat and/or your setting in the Home app. Put simply, this flow will send a payload to Output
of {"CurrentHeatingCoolingState":0}
or {"CurrentHeatingCoolingState":1}
depending on if current temperature or target temperature is a higher number.
[{"id":"dcf59f2.d7469e","type":"inject","z":"e639a8b0.423e8","name":"Request off","topic":"","payload":"{\"TargetHeatingCoolingState\":0}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":180,"wires":[["a99fd29a.401ce8"]]},{"id":"a99fd29a.401ce8","type":"homekit-service","z":"e639a8b0.423e8","isParent":true,"bridge":"6a8d3ef1.88061","parentService":"","name":"CleverThermostat","serviceName":"Thermostat","topic":"","filter":false,"manufacturer":"Default Manufacturer","model":"Default Model","serialNo":"Default Serial Number","characteristicProperties":"{\n \"TargetHeatingCoolingState\": {\n \"validValues\": [0, 1]\n },\n \"CurrentHeatingCoolingState\": {\n \"validValues\": [0, 1]\n }\n}","x":510,"y":380,"wires":[["912314ac.d24818","4c937b1c.5ee9cc"]]},{"id":"b1ec7a7e.af4b","type":"inject","z":"e639a8b0.423e8","name":"Current 68 F (20 C)","topic":"","payload":"{\"CurrentTemperature\": 20}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":300,"wires":[["a99fd29a.401ce8"]]},{"id":"ca31c1b0.a9716","type":"inject","z":"e639a8b0.423e8","name":"Target 73 F (23 C)","topic":"","payload":"{\"TargetTemperature\": 23}","payloadType":"json","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":230,"y":420,"wires":[["a99fd29a.401ce8"]]},{"id":"ff94240f.bb096","type":"inject","z":"e639a8b0.423e8","name":"Target 50 F (10 C)","topic":"","payload":"{\"TargetTemperature\": 10}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":460,"wires":[["a99fd29a.401ce8"]]},{"id":"c790acf0.96924","type":"inject","z":"e639a8b0.423e8","name":"Current 59 F (15 C)","topic":"","payload":"{\"CurrentTemperature\": 15}","payloadType":"json","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":230,"y":340,"wires":[["a99fd29a.401ce8"]]},{"id":"912314ac.d24818","type":"function","z":"e639a8b0.423e8","name":"Save TEMP/HUM/TT","func":"var T1 = context.get(\"T1\")||{\n \"target_temperature\": 12,\n \"temperature\": 10,\n \"humidity\": 11,\n \"targetHeatCoolState\": 0\n};\n\nvar OutMsg = {};\n\nif (msg.payload.TargetHeatingCoolingState !== undefined){\n T1.targetHeatCoolState = msg.payload.TargetHeatingCoolingState;\n}\n\nif (msg.payload.CurrentTemperature !== undefined) {\n T1.temperature = msg.payload.CurrentTemperature;\n}\n\nif (msg.payload.CurrentRelativeHumidity !== undefined) {\n T1.humidity = msg.payload.CurrentRelativeHumidity;\n}\n\nif (msg.payload.TargetTemperature !== undefined) {\n T1.target_temperature = msg.payload.TargetTemperature;\n}\n\nif (T1.targetHeatCoolState == 1){\n if (T1.temperature >= T1.target_temperature) {\n OutMsg.payload = { \n CurrentHeatingCoolingState: 0\n };\n } else {\n OutMsg.payload = { \n CurrentHeatingCoolingState: 1\n };\n }\n} else if (T1.targetHeatCoolState === 0){\n OutMsg.payload = {\n CurrentHeatingCoolingState: 0\n };\n}\n\ncontext.set(\"T1\",T1);\n\nreturn OutMsg;\n","outputs":1,"noerr":0,"x":500,"y":540,"wires":[["a99fd29a.401ce8"]]},{"id":"4c937b1c.5ee9cc","type":"debug","z":"e639a8b0.423e8","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":750,"y":380,"wires":[]},{"id":"fcd747b4.f92588","type":"inject","z":"e639a8b0.423e8","name":"Current 77 F (25 C)","topic":"","payload":"{\"CurrentTemperature\": 25}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":230,"y":260,"wires":[["a99fd29a.401ce8"]]},{"id":"70eb57cd.8d1cb","type":"inject","z":"e639a8b0.423e8","name":"Request heat","topic":"","payload":"{\"TargetHeatingCoolingState\":1}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":140,"wires":[["a99fd29a.401ce8"]]},{"id":"e59b81d7.0473e8","type":"inject","z":"e639a8b0.423e8","name":"Check every 5 sec","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":true,"onceDelay":0.1,"x":240,"y":540,"wires":[["912314ac.d24818"]]},{"id":"6a8d3ef1.88061","type":"homekit-bridge","z":"","bridgeName":"Garage","pinCode":"111-11-111","port":"","allowInsecureRequest":false,"manufacturer":"Garrett","model":"Pi HAT","serialNo":"3","customMdnsConfig":false,"mdnsMulticast":true,"mdnsInterface":"","mdnsPort":"","mdnsIp":"","mdnsTtl":"","mdnsLoopback":true,"mdnsReuseAddr":true}]