Soll-Temperatur etc. mit Node-Red ändern
This post is a sequel to the two previous posts I've created concerning the Viessmann API in conjunction with Node-Red.
1. Automatic initialization of access and refresh tokens in Node-Red Applications
2. Using Node Red to visualize ViCare data
Both focus on getting access and visualizing data grabbed from the Viessmann servers.
Now it's about time to actually manipulate your heating's settings:
This example is about changing the temperature setting for operation mode "normal" of heating circuit 0.
We can build on the universal header function node introduced in post #2 stated above
The Function node looks like this - pls bear with me for using the german UI of NR:
The setTo variable in line 5 contains the target value set in the slider node - msg.payload is converted to a context variable called flow.fbhSetNormal thereafter.
Variable atoken contains our old acquantance access token from my previous posts. The same goes for the other context variables installationID, gatewaySerial, and deviceID.
The http Request Node looks like this:
Please note that this is a POST request. Otherwise we couldn't send the header data with it.
The URL looks like this:
https://api.viessmann.com/iot/v1/equipment/installations/{{installationID}}/gateways/{{gatewaySerial}}/devices/{{deviceId}}/features/heating.circuits.1.operating.programs.normal/commands/setTemperature
That's it! I hope you find this useful. Any comments and cudos are greatly appreciated. Below is the JSON code representation which can also be found at my website including more detailed explanations in German.
Have a nice day!
Chris
[
{
"id": "99b3d95f7fa3ad1d",
"type": "http request",
"z": "31c57f8640528976",
"name": "Set Feature",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/installations/{{installationID}}/gateways/{{gatewaySerial}}/devices/{{deviceId}}/features/heating.circuits.1.operating.programs.normal/commands/setTemperature",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 630,
"y": 2600,
"wires": [
[
"4605eaf04f3c2604"
]
]
},
{
"id": "c842be0ce0f3e826",
"type": "function",
"z": "31c57f8640528976",
"name": "Headers & Parameter",
"func": "var atoken = flow.get('accessToken')\nvar setTo = flow.get('fbhSetNormal')\n\nmsg.payload = {\n \"targetTemperature\": setTo\n}\nmsg.headers = {};\nmsg.headers['content-type'] = 'application/json',\nmsg.headers['Authorization'] = \"Bearer \" + atoken;\n\nmsg.installationID = flow.get('installationID');\nmsg.gatewaySerial = flow.get('gatewaySerial');\nmsg.deviceId = flow.get('deviceID');\n;\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 2600,
"wires": [
[
"99b3d95f7fa3ad1d"
]
]
},
{
"id": "4605eaf04f3c2604",
"type": "debug",
"z": "31c57f8640528976",
"name": "debug 15",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 800,
"y": 2600,
"wires": []
},
{
"id": "9a849f443a5d2d2b",
"type": "ui_slider",
"z": "31c57f8640528976",
"name": "Slider sets temperature",
"label": "Soll °C FBH",
"tooltip": "",
"group": "f0f24855fdba9035",
"order": 7,
"width": 0,
"height": 0,
"passthru": false,
"outs": "end",
"topic": "topic",
"topicType": "msg",
"min": "5",
"max": "30",
"step": 1,
"className": "",
"x": 430,
"y": 2520,
"wires": [
[
"1fca8de48b2fca36"
]
]
},
{
"id": "1fca8de48b2fca36",
"type": "change",
"z": "31c57f8640528976",
"name": "Set Flow variable ",
"rules": [
{
"t": "set",
"p": "fbhSetNormal",
"pt": "flow",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 690,
"y": 2520,
"wires": [
[
"c842be0ce0f3e826"
]
]
},
{
"id": "f0f24855fdba9035",
"type": "ui_group",
"name": "Status",
"tab": "7e5ee24d.2d5ae4",
"order": 4,
"disp": true,
"width": "6",
"collapse": false,
"className": ""
},
{
"id": "7e5ee24d.2d5ae4",
"type": "ui_tab",
"name": "Heating",
"icon": "dashboard",
"order": 3,
"disabled": false,
"hidden": false
}
]
Update:The flow can be simplified a bit by connecting the silder's payload directly to the function node. That way no context variable for the temperature setting is needed. The function node then looks like this:
var atoken = flow.get('accessToken')
var setTo = msg.payload
msg.payload = {"targetTemperature": setTo}
msg.headers = {};
msg.headers['content-type'] = 'application/json',
msg.headers['Authorization'] = "Bearer " + atoken;
msg.installationID = flow.get('installationID');
msg.gatewaySerial = flow.get('gatewaySerial');
msg.deviceId = flow.get('deviceID');
return msg;
and the simplified flow looks like this:
5 minutes to late - did it the same way myself.
You could connect the reading from the API to the input of the slider - it will now show the current settings.
Thanks for your work !!
Hallo Jörg,
thats what I did in my own setup. Feed back the setting from the API to the slider node. Accidently I created an endless loop by setting the slider's config checkmark at If msg arrives on input, pass through to output:
This behaviour eats up your "number of requests" quota much faster. In fact, it's doubling your number of requests. And worse with several sliders. So take care to uncheck this feature.
For improved usability (avoiding accidential setting of the slider especially on mobile devices) I have separated temperature setting and issuing the command. Check this out at my website.
Have fun!
Chris