Dies ist ein Follow-up von den ersten Artikel: Fenix TFT Wifi Thermostat API reverse engineering für Home Assistant mit Node Red Das ist die Grundlage für diesen Artikel. Hier geht es darum die Temperatur von einem oder mehreren Fenix Thermostaten mit Node-Red einzustellen. Den Source Code für Node-Red gibt es wie immer ganz unten.
Je nachdem ob wir ein oder mehrere Fenixe haben, legen wir im configuration.yaml neue „Input Number“ Elemente an und starten den Home Assistant neu:
input_number:
#Fenix Wohnzimmer Ambient Temperature
fenix_wohnzimmer_ambient_temperature:
name: Wohnzimmer Temperatur
min: -20
max: 100
step: 0.1
unit_of_measurement: °C
icon: mdi:home-thermometer-outline
Wenn Ihr auch so ein schönes „Plus / Minus“ Eingabeinterface haben wollt braucht ihr noch die „numberbox-card“. Diese bekommt ihr über den HACS Store.
Dieses Lovelace Element hat bei mir folgende Config und ich habe das Verhalten von der Fenix App einfach nachgebaut mit den jeweiligen Temperaturbereichen und Temperaturschritten.
type: custom:numberbox-card
border: true
entity: input_number.fenix_wohnzimmer_setpoint_temperature
icon: mdi:thermometer
delay: '2000'
min: 5
max: 35
step: 0.5
speed: '500'
Node-Red
Im Node Red importiert ihr den Flow von unten und verschiebt die importierten Elemente in den Flow wo ihr die restlichen Fenix Thermostat Elemente drin habt aus dem vorherigen Artikel von mir.
Der Flow ist denkbar einfach aufgebaut:
Das/die state_changed elemente hören auf eine Änderung des Wertes im Lovelace Dashboard (das Element was wir vorhin im configuration.yaml angelegt haben und im Lovelace Dashboard anzeigen und mit den „plus/minus“ Buttons ändern können.
Bei mir sind es zwei Thermostate, deswegen zwei state_changed Elemente. Jedes dieser Elemente reichert den Flow mit einer eigenen msg.ID an.
Bei dieser msg.ID handelt es sich um die Sensor/Geräte ID von Eurem Fenix Thermostat. Ihr müsstet die aus dem vorherigen Blogpost noch kennen. Schaut da mal nach und kopiert die ID hier in das Wertefeld hinein.
Im „Read JWT Token“ lesen wir uns den aktuellen JWT Token ein und geben ihn als Variable der nächsten Function Node mit.
Weil die Fenix Thermostate intern mit Grad Fahrenheit arbeiten rechnen wir uns aus dem Grad Celsius erstmal den Fahrenheit Wert aus, multiplizieren ihn mit 10 und runden ihn um keine Nachkommastellen mehr zu haben.
Die Function Node bastelt den HTTP Request zusammen und übergibt ihn der HTTP Request Node.
Deploy nicht vergessen 🙂
Das wars auch schon. Jetzt solltet ihr die Temperatur über das Lovelace Dashboard einstellen können.
Ausblick
Jetzt, wo wir Temperaturen automatisiert setzen können, können wir selbst Temperaturprofile fahren- Zeitgesteuert oder Eventgesteuert. In meinem Fall handelt es sich um eine Fußbodenheizung, die super träge ist und wo sich eine kurze Temperaturänderung kaum lohnt. Was aber spannend ist, dass der Request mit der „TypeValue=6“ in der function Node vermutlich auch den Modus des Thermostats steuert und wir damit das Thermostat auch aus oder an schalten können. Das ist für mich super spannend weil meine Fenixe direkt an den Haustüren hängen und wenn ich lüfte oder raus und rein gehe kalte Luft an die Thermostate kommt und sie so recht schnell versuchen wieder eine ordentliche Raumtemperatur herzustellen. Das führt bei mir aktuell zu einer leichten Überheizung der Räume weil ja nur ein „schwall“ kalte Luft vorbei zieht, der Raum an sich aber schon die richtige Temperatur hat. Ich will also mit einem Türsensor das Thermostat für 5minuten nach dem Türe öffnen still legen und danach wieder aktivieren. So verhindere ich, das viel Energie verbraten wird nur weil das Thermostat etwas kalte Luft abbekommen hat.
Außerdem will ich in Zukunft, sobald wir eine Photovoltaikanlage haben überschüssige Energie in den Fußboden pumpen und den Raum etwas „überwärmen“, wenn absehbar ist, dass die Außentemperatur in den nächsten Stunden sowieso kühler werden wird.
Node-Red Flow
[{"id":"6bd77a28216ae902","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"b1ec2a63571cfb39","type":"server-state-changed","z":"6bd77a28216ae902","name":"","server":"86110a77.f6e448","version":3,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_number.fenix_wohnzimmer_setpoint_temperature","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,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"},{"property":"ID","propertyType":"msg","value":"ACXXXXXXXXX","valueType":"str"}],"x":310,"y":180,"wires":[["4dc344d45e940715"]]},{"id":"b6efbce1fd055cfc","type":"debug","z":"6bd77a28216ae902","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":410,"y":320,"wires":[]},{"id":"99b3ebe0a6a7487a","type":"http request","z":"6bd77a28216ae902","name":"","method":"use","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":190,"y":340,"wires":[[]]},{"id":"4ebd90952639ec27","type":"function","z":"6bd77a28216ae902","name":"","func":"//Calculate the Degree C in Degree F and round it for Fenix\nmsg.neuetemperatur = Math.round(((msg.payload * 9/5) + 32)*10)\n\nmsg.method = \"PUT\";\nmsg.url = \"https://vs2-fe-apim-prod.azure-api.net/iotmanagement/v1/devices/twin/properties/config/replace\";\nmsg.payload ={\"Id_deviceId\":msg.ID,\"S1\":msg.ID,\"configurationVersion\":\"v1.0\",\"data\":[{\"wattsType\":\"Dm\",\"wattsTypeValue\":6},{\"wattsType\":\"Ma\",\"wattsTypeValue\":msg.neuetemperatur}]};\nmsg.headers = {};\n//msg.headers[\"Host\"] = \"vs2-fe-identity-prod.azurewebsites.net\";\nmsg.headers[\"Content-Type\"] = \"application/json\";\nmsg.headers[\"User-Agent\"] = \"Watts.VisionSystem.Mobile/2101281503 CFNetwork/1329 Darwin/21.3.0\";\nmsg.headers[\"Accept\"] = \"application/json\";\n\nmsg.headers[\"Authorization\"] = \"Bearer \"+msg.token;\n\nreturn msg;\n\n\n\n\n\n\n\n\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":300,"wires":[["99b3ebe0a6a7487a"]]},{"id":"4dc344d45e940715","type":"change","z":"6bd77a28216ae902","name":"Read JWT Token from the Flow Store","rules":[{"t":"set","p":"token","pt":"msg","to":"JWTtoken","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":260,"wires":[["4ebd90952639ec27"]]},{"id":"cf2ebbece40e8400","type":"comment","z":"6bd77a28216ae902","name":"Set a temperature on a Fenix","info":"","x":160,"y":80,"wires":[]},{"id":"f90a101d633a1cbf","type":"server-state-changed","z":"6bd77a28216ae902","name":"","server":"86110a77.f6e448","version":3,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_number.fenix_buero_setpoint_temperature","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,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"},{"property":"ID","propertyType":"msg","value":"ACXXXXXXXXX","valueType":"str"}],"x":290,"y":220,"wires":[["4dc344d45e940715"]]},{"id":"86110a77.f6e448","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]