Viessmann API und Node-Red – Teil 2

Zugriff auf die API

Der Zugang zur Viessmann API ist nicht ganz trivial. Die Beschreibung auf den Viessmann Seiten lässt auch zu wünschen übrig. Trotzdem schadet es nicht, sich das alles dort einmal durchzulesen. Ich beschreibe hier den Ablauf analog dazu aber eben auf Node-Red angepasst. Ist der Flow erst einmal fertiggestellt, ist alles Weitere ein Klacks.

Schritt für Schritt

Vorbemerkung: diese Anleitung geht davon aus, dass Node-Red auf einem Linux Rechner, das heißt einem Raspberry Pi installiert wird. Für Windows PCs etc. gelten unter Umständen andere Voraussetzungen – zum Beispiel spezielle Client Firewall Regeln und Einstellungen, die hier nicht behandelt werden.
Der Router braucht keine Portfreischaltung im Firewall.

Voraussetzungen – Vorarbeiten

Grundvoraussetzung ist, die ViCare App zum Laufen zu bringen. Mit der App wird ein Viessmann Account angelegt und die Anlage registriert. Damit kennen die Viessmann-Server deine Installation. Es ist dann auch klar, dass die internetseitige Verbindung funktioniert. Darauf achten, dass das Vitoconnect Kästchen – sofern verwendet – eine ausreichende Empfangsstärke hat. 1 Balken ist definitiv zu wenig. Siehe Anleitung (Abschnitt Anleitung).

Anschließend, bzw. nach Erhalt und Quittierung des Bestätigungsmails sollte man sich bei developer.viessmann.com einloggen. Dabei sind dieselben Zugangsdaten zu verwenden,  die bei der Registrierung der ViCare App verwendet wurden. Das Ganze ist weitestgehend selbsterklärend.

Nach dem Login hat man Zugriff auf die Dokumentation und das Viessmann Developer Dahboard. Dort muss zuerst einmal die

Customer ID

angelegt werden. Mit Klick auf My Dashboard wird dieses angezeigt. Auf der Kachel “Your Clients” klicken wir das Stiftsymbol an. Es kann nur ein Client und nur eine funktionierende URI angelegt werden auch wenn die Website das Anlegen mehrerer URLs erlaubt.

Bei Name trägst du denselben Namen ein, den du deiner  Anlage in der App verpasst hast – ich bin mir aber nicht sicher, ob das wirklich so sein muss. Die Client ID wird automatisch erzeugt. Zuvor muss aber noch das Google reCAPTCHA ausgeschaltet und eine Redirect URI eingegeben werden. Die Redirect URI ist die Aufrufadresse (Callback Adresse) deiner Applikation, an die bei Aufruf ein AuthCode übermittelt wird. In der generischen Viessmann Anleitung steht  http://localhost:4200 . Wir hingegen verwenden http://localhost:1880/authcode  – das ist die Adresse bzw. der Port, auf dem Node-Red auf Input lauscht. Das /authcode ist ein optionaler, beliebiger Pfad. Merke dir diesen Pfad, du brauchst ihn in den nächsten Schritten.

Die Client ID ist statisch und bleibt so lange gültig, bis du sie im Dashboard löscht.

Authcode abrufen

Das Erzeugen der Client ID war der letzte manuelle Schritt und muss auch nur einmalig durchgeführt werden. Der Rest ist künftig automatisiert:

Wir ziehen und nun in Node-Red drei Nodes auf das Editiertableau und “verkabeln” diese.

Timestamp zum Triggern, http request zum Abfragen und Debug für das Ergebnis.

In die URL Zeile des  http request kommt folgender Inhalt:

Bisherige Nutzer der API aufgepasst: seit Februar 2023 gibt es eine neue Version des API Autentifizierungsprozesses: Anstatt https://iam.viessmann.com/idp/v2/authorize… heißt es jetzt https://iam.viessmann.com/idp/v3/authorizesonst ändert sich nichts. Der Vorteil liegt in konkreteren Fehlermeldungen beim Login. Siehe Viessmanm API Changelog Abschnitt Februar 2023. Übernimmt man die Änderung, sollte weiter unten d.h. bei https://iam.viessmann.com/idp/v3/token… ebenfalls v3 anstatt v2 verwendet werden.

Deine Client ID an der entsprechenden Stelle eintragen, den gesamten anderen Kram könnt ihr so stehen lassen. In der Viessmann Anleitung ist etwas von Oauth  die Rede für Code Challenge und -Response. Ich habe nie verstanden, wie das funktioniert. Es reicht, hier dieselbe Challenge/Response wie in der Viessmann Dokumentation zu nehmen.

scope= IoT User (bzw. scope=IoT%20User ) ist vorgegeben, offline_access veranlasst die API noch ein Refresh Token mitzugeben, was die spätere Nutzung deutlich vereinfacht.

Den Rest des http requests wie folgt ausfüllen:

Methode ist GET, Nutzdaten ignorieren, Basis Authentifizierung verwenden – hier die Viessmann Account Daten (Username/eMail und Passwort aus der App; nicht den Namen aus dem „Edit Client“ Fenster oben) eintragen – und schließlich bei Rückgabe eine UTF-8 Zeichenfolge auswählen.

So lange du die Client ID nicht änderst, brauchst du diese Blöcke nicht mehr anfassen.

Nach dem Deployen und Starten des Flows liefert Viessmann einen Code, den wir uns im Debugfenster ansehen können und im nächsten Schritt weiter verwenden. Achtung: der Code ist nur 20 Sekunden lang gültig. Der Authorization Code steckt in msg.payload. Für den Fall, dass da nichts Gescheites drinsteht (Fehlermeldung, html Code), erst noch mal die Client ID checken und ggf. löschen und neu anlegen. Erst wenn hier der Authorization Code angezeigt wird kannst du weitermachen.

Mit dem http Request Node haben wir die Anfrage losgeschickt, mit einem http In Node empfangen wir die Antwort. Im Prinzip bauen wir hier einen winzigen Webserver auf.

Der http In Node wird wie folgt konfiguriert:

Das URL Feld muss dem Pfad entsprechen, der beim Anlegen der Client ID verwendet wurde. Allerdings ohne Localhost und Portnummer.

Der Response Node wird lediglich auf Status 200 gesetzt. Bitte beachte, dass der Sende- und der Empfangsteil sind nicht miteinander verdrahtet sind. Hier zaubert das Internet.

Wenn alles funktioniert, sollte der Debug Node am Empfangsende den Authorization code anzeigen wenn der Trigger auf der Sendeseite ausgelöst wurde. Der Code steckt jetzt in msg.payload.code .

Den kompletten JSON Flow findest du am Ende des Artikels.

Access Token initial erzeugen

Die drei Nodes oben links kennen bzw. haben wir schon.

Kommen wir zum Funktionsnode set payload & headers, der den darauf folgenden http Request Node mit Daten auflädt. Der im vorherigen Schritt gewonnene Code wird per Stringvariable hinten angehängt.

Anders als der oben verwendete http Request ist der hier verwendete http Request Node ein POST Request, d.h. es werden Daten im http header anstatt in der URL transportiert. Er wird wie folgt konfiguriert. Darauf achten, dass die Rückgabe als “Ein parsed JSON Objekt” erfolgen soll.

Auch hier sollte wieder v3 anstatt v2 verwendet werden.

Wenn alles funktioniert, dann enthält das zurück geschickte JSON Objekt sowohl das Access Token als auch das Refresh Token. Die Token stecken in msg.payload.access_token bzw. msg.payload.refresh_token.

Mit dem Access Token könnten wir nun 3600 Sekunden oder eine Stunde lang arbeiten bevor es verfällt.

Sinnvollerweise packen wir die beiden Token in Flow Variable um sie weiter zu verwenden. Hast du die Viessmann Logik auf mehreren Node-Red Blätter verteilt, sollten sie in Global anstatt in Flow Variablen untergebracht werden.

Das geschieht am einfachsten mit einem Change Node:

Variable können auch innerhalb eines Function Nodes mit flow.set("FlowVariablenname", meineVariable)  gesetzt werden. Das macht vor allem innnerhalb komplexerer Funktionsblöcke Sinn.
Abgerufen werden die Flow Variablen mit einem Kommando der Art:
var meineVariable = flow.get("FlowVariablenname");

Sind wir wie oben beschrieben vorgegangen, können wir jetzt überall innerhalb des Flows (Tabellenblatt) auf die Tokens zugreifen.

Statische Parameter

Um mit der API zu arbeiten, benötigen wir noch drei statische Werte, welche am Gerät hängen und sich normalerweise nie ändern.

Wie man sie bekommt, ist in der Viessmann Doku beschrieben oder man nutzt diesen JSON Flow für Node Red:

Es bleibt dir überlassen, wo du diesen Teil einbaust. Im Prinzip kann man die drei Parameter Installation ID, Gateway Serial und Device ID ein einziges Mal abfragen und dann als fixe Werte weiterverarbeiten. Oder – so habe ich es gemacht – jedes Mal neu abfragen, wenn die Logik nach einem Neustart des Servers bzw. alle 180 Tage (siehe unten) initialisiert und die Token wieder neu generiert werden.

Refresh alle 3600 Sekunden

Jetzt endlich können wir mit der API arbeiten. Aber nach einer Stunde ist der Spaß vorbei, das Access Token ist abgelaufen. Um nun nicht wieder die gesamte obige Routine durchlaufen zu müssen, gibt es eine Abkürzung mit dem Refresh Token.

Hier wird der Trigger – auf “wiederhole automatisch alle 59 Minuten” eingestellt,

Der Funktionsnode hat folgenden Inhalt:

Wie du siehst, wird hier die Flow Variable “refreshToken” im Javascript ausgelesen. Deine Client ID muss ebenfalls wieder eingetragen werden und das Refresh Token wird als String hinten agehängt.

Einen http Request Node mit folgender Konfiguration:

Ferner noch ein Change Node, welcher die zurückgegebene Payload in die Access_Token Variable schreibt.

Und hier der zugehörige JSON Flow zum importieren:

Bisherige Nutzer achten wieder auf “v3” in der URL des Request Nodes.

Wird der Flow regelmäßig ausgeführt, hat man immer ein gültiges Access Token.

Refresh nach 180 Tagen erneuern

…zumindest für 180 Tage. Dann verfällt auch das Refresh Token und wir müssen tatsächlich wieder beim Kapitel Authcode abrufen einsteigen. Die Client ID muss aber nicht neu erzeugt werden. Das Triggern der Schritte kann natürlich auch automatisch erfolgen, sodaß es keinerlei menschlichen Eingriffs mehr bedarf. Das ist z.B. möglich, indem man in der “Access Token Refresh” Routine eine Abfrage nach dem Wert des erneuerten Access Tokens einbaut. Hat das Access Token den Wert “null” (das ist etwas anderes als der Wert 0), wird auf die Initialroutine verzweigt. Die Abfrage mittels Switch-Node sieht so aus:

 

Siehe auch unten abgebildeten Flow mit Kommentar.

Was auch möglich wäre, aber nicht so betriebssicher,  ist den Initialflow einfach alle 4319 Stunden (= 180 Tage minus 1 Stunde) per Trigger aufzurufen. Das wird aber nur funktionieren, wenn die ganze Viessmann Logik wirklich ununterbrochen durchläuft, damit der Trigger komplett abläuft. In 180 Tagen kann eine Menge passieren…

Im Prinzip spricht auch wenig dagegen, den “Refresh Token aktualisieren” Zyklus alle 24 Stunden oder so aufzurufen.

 

Gesamter Flow

Gesamter Autorisierungsflow mit Restart nach Ablauf des Refresh Tokens

JSON für dieses Kapitel

Weiter gehts mit dem nächsten Kapitel  Daten abfragen und visualisieren.

11 Gedanken zu „Viessmann API und Node-Red – Teil 2

  1. Moin, bin etwas am verzweifeln. Ich erhalte folgende Fehlermeldung “ErrorCannot GET /authcode”. Client-ID habe ich mehrfach neu angelegt.
    Ich habe NodeRed auf einer Diskstation laufen. Hast Du irgendwelche Ideen?
    Danke!
    Thilo

    1. Hi,
      Es könnte sich um ein Firewall Problem der Diskstation handeln. Port 1880 muss in der Diskstation explizit freigegeben werden. Im Router hingegen NICHT sonst bekommst du ein massives Sicherheisproblem.
      Gruß
      Chris
      Probier das mal

    2. ist mittlerweile erledigt … die Diskstation hatte eine Macke … Neustart hat es gebracht … bitte den Eintrag löschen … und sorry!

  2. Hallo Chris,
    vielen Dank für die super Anleitung und das gesamte Tutorial!
    Sogar ich als blutiger Anfänger auf dem Pi und mit Nodered finde mich gut zurecht.
    Ich habe jetzt den Flow soweit implementiert (mit der Schleife für den refresh Token) und mir ein Dashboard gebastelt. Das funktioniert auch soweit so gut.
    Leider kommt nach ca 1,5 Stunden ein Fehler und die function nodes für das Auslesen der Werte aus den Features laufen alle in die selbe Meldung: “TypeError: Cannot read properties of undefined (reading ‘findIndex’)”
    Also irgendetwas kann mit dem Index ausgelesen werden.
    Hast du eine Idee woran das liegen kann?
    Vielen Dank und Grüße
    Moritz

    1. Hi,
      Freut mich, wenn es dir hilft und gefallen hat. Das von dir beschriebene Problem tritt immer dann auf, wenn die Viessmann Server gerade nicht antworten.
      Nach ein paar Minuten oder auch vielen paar Minuten funktioniert es dann wieder.
      Viel Spaß noch
      Chris

  3. Hallo,
    erstmal vielen Dank für das super Tutorial.
    Kann mir bitte jemand die Integration für den 180 Tage refresh erklären.
    Leider bin ich in NoteRed noch purer Anfänger. Danke.

    1. Hallo Matthias,
      aler Anfang ist schwer…
      Danke für deine Frage, das hilft mir, Verständnisprobleme bei meinem Text zu erkennen. Ich passe mein Tutorial entsprechend an.
      Im Prinzip musst du beim “Refresh Access Token” Teil, der spätestens alle 3600 Sekunden aufgerufen werden muss, mit einem Switch Node abfragen, ob der Refresh geklappt hat. Falls nicht (d.h. msg.payload.access_token = null), wird ganz nach oben zur Initialroutine verzweigt.
      Alternativ kannst du den Trigger ganz am Anfang so einstellen, dass er vor dem Verfall des Refresh Tokens anspringt – z.B. alle 179 Tage.
      Viele Grüße und viel Spaß
      Chris

  4. Danke! habs mit minimalen Anpassungen integriert – klasse! Schon lustig, entweder ich habs in der viessmann-doku überlesen, oder es wird nicht wirklich präsent erwähnt, dass auch dieser token nach 180t abläuft .. naja, macht ja sinn trotzdem. VG

    1. Hi,
      freut mich, wenn ich dir damit helfen konnte. Du schreibst “minimale Anpassungen”… hast du einen Fehler entdeckt oder was konkret hast du abgeändert. Vielleicht macht das ja mehr Sinn.
      Danke Chris

      1. Ja, es war bei den Debug-Steinen “access_token” und “refresh_token” ein Fehler. Sie haben beide beides angezeigt. Hier musste der Payload gefiltert werden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert