abbrechen
Suchergebnisse werden angezeigt für 
Anzeigen  nur  | Stattdessen suchen nach 
Meintest du: 
Beantwortet! Gehe zur Lösung.

How to avoid sudden death after 180 days – automatic initialization and refresh of the access and refresh tokens in Node-Red applications

Generating the access token for the very first time is a pain in the neck. All the more since the authorization code parameter which has to be created and used to get the authorization token, has a very short 20 seconds time to live (TTL). So, you’d better hurry up and be nimble with ctrl-c and ctrl-v actions when using (semi-)manual solutions with Node-Red snippets, bash or Postman.

Once you’ve generated the access token, refreshing the access token by means of the refresh token every 59 minutes or so, is a snap. However, after 180 days the TTL of the refresh token has expired and you have to go through the cumbersome first-time generation process for the tokens again.

I felt kind of fed up with this – so I played around a bit and came to the solution described here. Please bear with me if my explanations seem a bit trivial or lengthy – I am an amateur not a professional. It took me quite a while to wrap my brain about this, so I’d like to walk you through my train of thought.

I guess there are other solutions around e.g. this one using php: https://www.viessmann-community.com/t5/Getting-started-programming-with/To-help-get-started/td-p/181.... However, I wanted to stay within Node-Red’s environment.

 

Walk Through

Node-Red has webserver capability by means of two http nodes: http in and http response. They exist under the local address of http://localhost:1880

 

Step 1 – Authorization Request

To create the first call, you’ll need the following parameters:

 

client_id and redirect_uri

Both are set by means of the Developer Dashboard at: https://app.developer.viessmann.com/.
I’m assuming that you have already created an account.

 

 

CaCicala_0-1664025783017.png

 

The client_id is static, and does not change when you change the redirect_uri setting. It will be created during the first client setting but can be deleted and re-created as you like.

In the generic example the redirect_uri http://localhost:4200 is used. This works fine as long as you use a browser to generate the authorization code which can be copied from the URL field of the browser’s error message.
For our purposes however, we need to change this to http://localhost:1880/authcode. The path authcode can be anything but must be the same as the one used in the URL field of the http in node we’re going to use further down.

Don’t forget to turn off the Google CAPTCHA setting.

 

Fixed parameters

Scope is set to scope = "IoT User" this is important otherwise you won’t be able to do much.

Response Type is set to response_type = "code".

Code Challenge is set to
code_challenge=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c which is identical to the one used in the “Getting Started” chapter of Viessmann’s documentation. In my opinion you can continue to use that and forget about hashing and encoding as required by the oAuth method. I never was able to grasp the concept.

And, finally we must add the parameter offline_access to also get the refresh token lateron.

The URL assembled to generate the authorization request looks like this (blanks are ecoded by %20) :

 

 

 

https://iam.viessmann.com/idp/v2/authorize?client_id=my_oauth_client_ID&redirect_uri=http://localhost:1880/authcode&response_type=code&code_challenge=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c&scope=IoT%20User%20offline_access

 

 

Now we can drag an http request node to the development area of Node-Red, additionally a Trigger node and a debug node

CaCicala_1-1664025783018.png

 

The request Node is configured as follows:

Method is GET, URL is the one shown above, Payload is ignored, Basic Authentication is used and is set to your Viessman Login Username and Password, the rest stays as it is.

 

4_config_request_node.png

 

To receive this request, we need to set up a minimal webserver by using the http in and http response nodes. This looks like so:

CaCicala_3-1664025783028.png

 

The http in node is configured like this:

 

CaCicala_4-1664025783031.png

 

The URL field has to correspond to the path used in the redirect URI – without server name and port number.

The response node is set to status code 200

Please note that the request part and the response part are not connected by a wire. This is where Internet magic happens.

If all goes well, debug node at the receiving end should show the authorization code after you hit the trigger at the request side. The authorization code can be accessed by using msg.payload.code - we will need it in the following steps.

You will find the complete generic JSON code at the end of this article.

 

Step 2 – Authorization Code Exchange – initial generation of access and refresh tokens

Having created the authorization code represented by msg.payload.code, we can now continue along the Authentication chapter of the Viessmann doc pages. In Node-Red this looks like this:

 

CaCicala_5-1664025783050.png

 

The top left part we have already covered above.

 

The function node set payload & headers is configured like this:

 

 

 

msg.payload = `grant_type=authorization_code&client_id=my_oauth_client_ID&redirect_uri=http://localhost:1880/authcode&code_verifier=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c&code=${msg.payload.code}`;
msg.headers = {};
msg.headers['Content-Type'] = 'application/x-www-form-urlencoded';
return msg;

 

 

 

 

Watch out, the text after msg.payload is written as one single line only. Also observe the backtics which are necessary to concatenate the fixed part of the payload with the variable “msg.payload.code”. All in all, the JavaScript should consist of 4 lines. You will find the complete JSON (a pdf file) at the end of this article

 

The html request node 1st time token request looks like this:

 

CaCicala_6-1664025783057.png

 

Observe the setting: Return a parsed JSON object.

If all goes well, the JSON object contains both tokens which can be accessed by msg.payload.access_token and msg.payload.refresh_token.

 

Setting flow variables

In my implementation, I have everything concerning the ViCare API in one flow tab. Hence, I’m using flow variables. In case you have distributed the flows on several tabs, you should use global variables instead of flow variables.

Now it’s time to push our response into variables. I use a change node for that.

 

CaCicala_7-1664025783068.png

 

 

Retrieving Static values (once)

In addition, you will need the static values for InstallationID, gatewaySerial and deviceID.

You can either generate them once and hard-code them into your flow or re-request them every time, you’re running the initialization logic. In my example, I’m generating them during initialization. It’s a sequence of 3 requests, so we shouldn’t request these values too often – besides it’s unnecessary, they never change.

 

CaCicala_8-1664025783078.png

 

Refer to section IOT - Overview of the Viessman documentation for their creation or simply go through the JSON (pdf File) provided at the end of this article.

 

Notes

 

About refreshing the Access Token

Please note that the automatic Access Token refresh should occur every 59 minutes or so, just in time before the token expires. You could trigger the initialization routine described above. It would generate a new access token from scratch at regular intervals. However, this would eat into your requests allowance and also create extra load on Viessman’s servers.
I recommend to use a specialized refresh flow on the same tab that performs the refresh by using the refresh token. I have written about this in my article “Using Node-Red to visualize ViCare data”. The according JSON Routine is provided there as well.

 

About Triggering

How should you trigger this initialization process?

 

Manually

If your availability requirements are relaxed, you might as well trigger the initialization manually every time your application fails because of an expired refresh token i.e. every 180 days.

 

Automatically

As soon as the refresh token is no longer valid, the Viessmann server’s JSON response will contain a payload.error = "EXPIRED TOKEN" message. You can use this with a switch node to branch to the initialization routine in the rare event the refresh token is expired.

 

Using the API

Please refer to my article “Using Node-Red to visualize ViCare data”

 

I hope that you find this useful. Any comment is highly appreciated. The code can be found in the answer post below or at my website.

 

Christoph Krzikalla

 

CaCicala_9-1664025783092.png

 

 

2 AKZEPTIERTE LÖSUNGEN

Akzeptierte Lösungen

Ich habe hier nochmal das korrekte JSON per cut&paste eingefügt. Per pdf scheint das nicht zu funktionieren.

Sorry nochmal für die Verwirrung.

VG

Chris

+++++++++++++++++++++++++++++++++++++++++++++++

[
{
"id": "9d0e5593d53b55d0",
"type": "debug",
"z": "31c57f8640528976",
"name": "complete msg object",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1000,
"y": 340,
"wires": []
},
{
"id": "d6e3257c9c2d54ad",
"type": "http request",
"z": "31c57f8640528976",
"name": "1st time Token Request",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://iam.viessmann.com/idp/v2/token",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 730,
"y": 460,
"wires": [
[
"9d0e5593d53b55d0",
"a15685d5a21c73f4",
"4cd4555c4b8a54e4",
"e3bde0eca33a67c8"
]
]
},
{
"id": "46386b17e466c5b4",
"type": "function",
"z": "31c57f8640528976",
"name": "set payload & headers",
"func": "msg.payload = `grant_type=authorization_code&client_id=YOURCLIENTID&redirect_uri=http://localhost:1880/authcode&code_verifier=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c&code=...}`;\nmsg.headers = {};\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 460,
"wires": [
[
"d6e3257c9c2d54ad"
]
]
},
{
"id": "d5abc46074c395a0",
"type": "inject",
"z": "31c57f8640528976",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 290,
"y": 240,
"wires": [
[
"c765f5d53247981e"
]
]
},
{
"id": "595c3f168551465e",
"type": "debug",
"z": "31c57f8640528976",
"name": "Request Result",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 240,
"wires": []
},
{
"id": "904e0e39a0436cf7",
"type": "http in",
"z": "31c57f8640528976",
"name": "",
"url": "/authcode",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 240,
"y": 360,
"wires": [
[
"beb9836fcb2f735c",
"1282ee44e06b324d",
"46386b17e466c5b4"
]
]
},
{
"id": "beb9836fcb2f735c",
"type": "debug",
"z": "31c57f8640528976",
"name": "msg.payload.code",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.code",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 470,
"y": 320,
"wires": []
},
{
"id": "1282ee44e06b324d",
"type": "http response",
"z": "31c57f8640528976",
"name": "Reponse",
"statusCode": "200",
"headers": {},
"x": 440,
"y": 360,
"wires": []
},
{
"id": "13da70accda71262",
"type": "comment",
"z": "31c57f8640528976",
"name": "Generate authorization code",
"info": "",
"x": 320,
"y": 200,
"wires": []
},
{
"id": "c765f5d53247981e",
"type": "http request",
"z": "31c57f8640528976",
"name": "",
"method": "GET",
"ret": "txt",
"paytoqs": "ignore",
"url": "https://iam.viessmann.com/idp/v2/authorize?client_id=a602c3ccb073b72740420f03ad1b21f3&redirect_uri=h...",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "basic",
"senderr": false,
"headers": [],
"x": 450,
"y": 240,
"wires": [
[
"595c3f168551465e"
]
]
},
{
"id": "296e1357a73c8e32",
"type": "comment",
"z": "31c57f8640528976",
"name": "Click here -->",
"info": "",
"x": 110,
"y": 240,
"wires": []
},
{
"id": "751a30abd962d114",
"type": "comment",
"z": "31c57f8640528976",
"name": "after expiry",
"info": "",
"x": 100,
"y": 200,
"wires": []
},
{
"id": "a15685d5a21c73f4",
"type": "debug",
"z": "31c57f8640528976",
"name": "access_token",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 420,
"wires": []
},
{
"id": "e3bde0eca33a67c8",
"type": "debug",
"z": "31c57f8640528976",
"name": "refresh_token",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 380,
"wires": []
},
{
"id": "4cd4555c4b8a54e4",
"type": "change",
"z": "31c57f8640528976",
"name": "set token flow variables",
"rules": [
{
"t": "set",
"p": "accessToken",
"pt": "flow",
"to": "payload.access_token",
"tot": "msg"
},
{
"t": "set",
"p": "refreshToken",
"pt": "flow",
"to": "payload.refresh_token",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1010,
"y": 460,
"wires": [
[
"0a5b06420e87d77f"
]
]
},
{
"id": "3d828c3c867062b0",
"type": "http request",
"z": "31c57f8640528976",
"name": "Installation ID",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/installations",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 680,
"y": 600,
"wires": [
[
"f32181561f6a81ab"
]
]
},
{
"id": "0a5b06420e87d77f",
"type": "function",
"z": "31c57f8640528976",
"name": "Auth Header",
"func": "var atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 600,
"wires": [
[
"3d828c3c867062b0"
]
]
},
{
"id": "d189c65f2d221d39",
"type": "http request",
"z": "31c57f8640528976",
"name": "Gateway Serial",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/gateways",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 680,
"y": 640,
"wires": [
[
"a92443f4485556c4"
]
]
},
{
"id": "f32181561f6a81ab",
"type": "change",
"z": "31c57f8640528976",
"name": "set flow.installationID",
"rules": [
{
"t": "set",
"p": "installationID",
"pt": "flow",
"to": "payload.data[0].id",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 600,
"wires": [
[
"dadfb8ae29d2643b"
]
]
},
{
"id": "a92443f4485556c4",
"type": "change",
"z": "31c57f8640528976",
"name": "set flow.gatewaySerial",
"rules": [
{
"t": "set",
"p": "gatewaySerial",
"pt": "flow",
"to": "payload.data[0].serial",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 640,
"wires": [
[
"5cfecbbe8f899905"
]
]
},
{
"id": "dadfb8ae29d2643b",
"type": "function",
"z": "31c57f8640528976",
"name": "Auth Header",
"func": "var atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 640,
"wires": [
[
"d189c65f2d221d39"
]
]
},
{
"id": "f52e123cdd02a6bc",
"type": "http request",
"z": "31c57f8640528976",
"name": "DeviceID",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/installations/{{iid}}/gateways/{{gws}}/devices/ ",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 660,
"y": 680,
"wires": [
[
"e553113d728f21a8"
]
]
},
{
"id": "e553113d728f21a8",
"type": "change",
"z": "31c57f8640528976",
"name": "",
"rules": [
{
"t": "set",
"p": "deviceID",
"pt": "flow",
"to": "payload.data[0].id",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 870,
"y": 680,
"wires": [
[]
]
},
{
"id": "5cfecbbe8f899905",
"type": "function",
"z": "31c57f8640528976",
"name": "extended auth header",
"func": "//var o = parseFloat(flow.get('2vo1'));\n//var atoken = msg.token\nvar atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nmsg.iid = flow.get('installationID');\nmsg.gws = flow.get('gatewaySerial');\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 680,
"wires": [
[
"f52e123cdd02a6bc"
]
]
},
{
"id": "27904bd00d57b5f8",
"type": "comment",
"z": "31c57f8640528976",
"name": "get tokens 1st time",
"info": "",
"x": 290,
"y": 420,
"wires": []
},
{
"id": "5ddbfc6f31907258",
"type": "comment",
"z": "31c57f8640528976",
"name": "get/set invariable parameters",
"info": "",
"x": 320,
"y": 540,
"wires": []
}
]

Lösung in ursprünglichem Beitrag anzeigen

Mittlerweile habe ich einige meiner Tutorials auf Deutsch umgestellt, aktualisiert und auf meinem kleinen Tech-Blog veröffentlicht. Ihr findet das auf https://rustimation.eu - wird je nach Erkenntnisfortschritt erweitert und ergänzt.

Chris

Lösung in ursprünglichem Beitrag anzeigen

7 ANTWORTEN 7

Irgendwie wäre es schön, wenn es für derlei Tutorials einen eigenen Forenbereich gäbe. Ferner würde ich mir wünschen, als Autor nachträglich och Änderungen vornehmen zu können. 
Oder wäre es besser, nur einen kurzen Einleitungstext zu schreiben und das Tutorial dann als pdf anzuhängen?

Hey.

Great help for my first time start with NodeRed.

But when I copy/paste the initialize token text and import it in NodeRed I get a error message 

SyntaxError: Unexpected string in JSON at position 4745

tot": "msg"↵"reg": false


Any idea where my mistake is?

BR

oops!!

Da hat mir der pdf Konverter einen Streich gesielt und zu lange Zeilen mit einem Zeilenumbruchzeichen "verschönert".

Abhilfe fürs Erste: Text mit Ctrl-C und Ctrl-V (bzw. Strg-...) kopieren und in einen Editor pasten. Dann bei den im Import angegebenen Zeilen

hier zum Beispiel Zeile 60 die Zeilen zusammenfügen:

CaCicala_0-1665174244992.png

Tut mir ausgesprichen leid. Ich versuche das in der kommenden Woche irgendwie zu beheben. Saublöd. dass man keine JSON oder TXT Dateien im Forum Hochladen kann...

VG

Chris

 

Ich habe hier nochmal das korrekte JSON per cut&paste eingefügt. Per pdf scheint das nicht zu funktionieren.

Sorry nochmal für die Verwirrung.

VG

Chris

+++++++++++++++++++++++++++++++++++++++++++++++

[
{
"id": "9d0e5593d53b55d0",
"type": "debug",
"z": "31c57f8640528976",
"name": "complete msg object",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1000,
"y": 340,
"wires": []
},
{
"id": "d6e3257c9c2d54ad",
"type": "http request",
"z": "31c57f8640528976",
"name": "1st time Token Request",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://iam.viessmann.com/idp/v2/token",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 730,
"y": 460,
"wires": [
[
"9d0e5593d53b55d0",
"a15685d5a21c73f4",
"4cd4555c4b8a54e4",
"e3bde0eca33a67c8"
]
]
},
{
"id": "46386b17e466c5b4",
"type": "function",
"z": "31c57f8640528976",
"name": "set payload & headers",
"func": "msg.payload = `grant_type=authorization_code&client_id=YOURCLIENTID&redirect_uri=http://localhost:1880/authcode&code_verifier=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c&code=...}`;\nmsg.headers = {};\nmsg.headers['Content-Type'] = 'application/x-www-form-urlencoded';\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 460,
"wires": [
[
"d6e3257c9c2d54ad"
]
]
},
{
"id": "d5abc46074c395a0",
"type": "inject",
"z": "31c57f8640528976",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 290,
"y": 240,
"wires": [
[
"c765f5d53247981e"
]
]
},
{
"id": "595c3f168551465e",
"type": "debug",
"z": "31c57f8640528976",
"name": "Request Result",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 240,
"wires": []
},
{
"id": "904e0e39a0436cf7",
"type": "http in",
"z": "31c57f8640528976",
"name": "",
"url": "/authcode",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 240,
"y": 360,
"wires": [
[
"beb9836fcb2f735c",
"1282ee44e06b324d",
"46386b17e466c5b4"
]
]
},
{
"id": "beb9836fcb2f735c",
"type": "debug",
"z": "31c57f8640528976",
"name": "msg.payload.code",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload.code",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 470,
"y": 320,
"wires": []
},
{
"id": "1282ee44e06b324d",
"type": "http response",
"z": "31c57f8640528976",
"name": "Reponse",
"statusCode": "200",
"headers": {},
"x": 440,
"y": 360,
"wires": []
},
{
"id": "13da70accda71262",
"type": "comment",
"z": "31c57f8640528976",
"name": "Generate authorization code",
"info": "",
"x": 320,
"y": 200,
"wires": []
},
{
"id": "c765f5d53247981e",
"type": "http request",
"z": "31c57f8640528976",
"name": "",
"method": "GET",
"ret": "txt",
"paytoqs": "ignore",
"url": "https://iam.viessmann.com/idp/v2/authorize?client_id=a602c3ccb073b72740420f03ad1b21f3&redirect_uri=h...",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "basic",
"senderr": false,
"headers": [],
"x": 450,
"y": 240,
"wires": [
[
"595c3f168551465e"
]
]
},
{
"id": "296e1357a73c8e32",
"type": "comment",
"z": "31c57f8640528976",
"name": "Click here -->",
"info": "",
"x": 110,
"y": 240,
"wires": []
},
{
"id": "751a30abd962d114",
"type": "comment",
"z": "31c57f8640528976",
"name": "after expiry",
"info": "",
"x": 100,
"y": 200,
"wires": []
},
{
"id": "a15685d5a21c73f4",
"type": "debug",
"z": "31c57f8640528976",
"name": "access_token",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 420,
"wires": []
},
{
"id": "e3bde0eca33a67c8",
"type": "debug",
"z": "31c57f8640528976",
"name": "refresh_token",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 980,
"y": 380,
"wires": []
},
{
"id": "4cd4555c4b8a54e4",
"type": "change",
"z": "31c57f8640528976",
"name": "set token flow variables",
"rules": [
{
"t": "set",
"p": "accessToken",
"pt": "flow",
"to": "payload.access_token",
"tot": "msg"
},
{
"t": "set",
"p": "refreshToken",
"pt": "flow",
"to": "payload.refresh_token",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1010,
"y": 460,
"wires": [
[
"0a5b06420e87d77f"
]
]
},
{
"id": "3d828c3c867062b0",
"type": "http request",
"z": "31c57f8640528976",
"name": "Installation ID",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/installations",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 680,
"y": 600,
"wires": [
[
"f32181561f6a81ab"
]
]
},
{
"id": "0a5b06420e87d77f",
"type": "function",
"z": "31c57f8640528976",
"name": "Auth Header",
"func": "var atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 600,
"wires": [
[
"3d828c3c867062b0"
]
]
},
{
"id": "d189c65f2d221d39",
"type": "http request",
"z": "31c57f8640528976",
"name": "Gateway Serial",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/gateways",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 680,
"y": 640,
"wires": [
[
"a92443f4485556c4"
]
]
},
{
"id": "f32181561f6a81ab",
"type": "change",
"z": "31c57f8640528976",
"name": "set flow.installationID",
"rules": [
{
"t": "set",
"p": "installationID",
"pt": "flow",
"to": "payload.data[0].id",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 600,
"wires": [
[
"dadfb8ae29d2643b"
]
]
},
{
"id": "a92443f4485556c4",
"type": "change",
"z": "31c57f8640528976",
"name": "set flow.gatewaySerial",
"rules": [
{
"t": "set",
"p": "gatewaySerial",
"pt": "flow",
"to": "payload.data[0].serial",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 880,
"y": 640,
"wires": [
[
"5cfecbbe8f899905"
]
]
},
{
"id": "dadfb8ae29d2643b",
"type": "function",
"z": "31c57f8640528976",
"name": "Auth Header",
"func": "var atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 450,
"y": 640,
"wires": [
[
"d189c65f2d221d39"
]
]
},
{
"id": "f52e123cdd02a6bc",
"type": "http request",
"z": "31c57f8640528976",
"name": "DeviceID",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.viessmann.com/iot/v1/equipment/installations/{{iid}}/gateways/{{gws}}/devices/ ",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 660,
"y": 680,
"wires": [
[
"e553113d728f21a8"
]
]
},
{
"id": "e553113d728f21a8",
"type": "change",
"z": "31c57f8640528976",
"name": "",
"rules": [
{
"t": "set",
"p": "deviceID",
"pt": "flow",
"to": "payload.data[0].id",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 870,
"y": 680,
"wires": [
[]
]
},
{
"id": "5cfecbbe8f899905",
"type": "function",
"z": "31c57f8640528976",
"name": "extended auth header",
"func": "//var o = parseFloat(flow.get('2vo1'));\n//var atoken = msg.token\nvar atoken = flow.get('accessToken')\nmsg.headers = {\n Authorization: \"Bearer \"+ atoken\n}\nmsg.iid = flow.get('installationID');\nmsg.gws = flow.get('gatewaySerial');\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 480,
"y": 680,
"wires": [
[
"f52e123cdd02a6bc"
]
]
},
{
"id": "27904bd00d57b5f8",
"type": "comment",
"z": "31c57f8640528976",
"name": "get tokens 1st time",
"info": "",
"x": 290,
"y": 420,
"wires": []
},
{
"id": "5ddbfc6f31907258",
"type": "comment",
"z": "31c57f8640528976",
"name": "get/set invariable parameters",
"info": "",
"x": 320,
"y": 540,
"wires": []
}
]

Großartig! Import hat auf Anhieb funktioniert.

Vielen Dank!!!

Alter Schwede.
Ich habe mich jetzt echt ne weile mit der API gequält.

Das war der Beitrag, den ich gebraucht habe.

Danke Chris

Mittlerweile habe ich einige meiner Tutorials auf Deutsch umgestellt, aktualisiert und auf meinem kleinen Tech-Blog veröffentlicht. Ihr findet das auf https://rustimation.eu - wird je nach Erkenntnisfortschritt erweitert und ergänzt.

Chris