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 Spezialrechner auf Linux Basis (z.B. CCU3) oder Windows PCs etc. gelten unter Umständen andere Voraussetzungen – zum Beispiel spezielle Client Firewall Regeln und Port-Einstellungen, die hier nicht behandelt werden. Ich kann hier auch nur eingeschränkten Support leisten.

Ich habe mir mal die Mühe gemacht, und den IO Broker nebst integriertem Node-Red Adapter auf einem Raspi installiert. Abgesehen davon, dass ich den IO Broker für ein hoffnungslos überladenes Klickibunti halte, hat alles astrein 1:1 funktioniert. Bei der Instanziierung darauf achen, dass die NR Portnummer 1880 gesetzt wird. Läuft auch noch der Viessmann Adapter auf dem Broker, müssen (wahrscheinlich) zwei URIs bei der Edit Client Seite bei Viessmann eingetragen werden. Siehe unten.

A propos Firewall: Der Router braucht keine Portfreischaltung im Firewall. Hütet euch ferner davor, den Node-Red Port 1880 im Router freizuschalten. Damit hättet ihr ein riesiges Sicherheitsproblem.

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

Client 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 angelegt werden. Normalerweise braucht du nur eine URI. Zwei URIs sind ggf. vonnöten, wenn Node-Red zusammen mit dem Viessmann API Adapter auf einem IO Broker laufen soll.

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, wenn du am Ende “Save Client” anklickst.

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 beliebiger Pfad, der unbedingt erforderlich ist, sonst ruft Viessmann den Node-Red Editor anstatt des Flows auf. Merke dir diesen Pfad, du brauchst ihn in den nächsten Schritten.

Für den Anwendungsfall IOBroker mit Viessmann Adaper und gleichzeitig installiertem  Node-Red Adapter muss dann noch gemäß Vorschrift im Broker eine 2. URI (http://localhost:4200) angelegt werden.

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 uns 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.

Wichtig ist ferner, die redirect_uri  absolut identisch zu der im Viessmann Edit Client Prozess zu halten. Das gilt auch für den nachlaufenden Schrägstrich “/” : entweder beide Male oder gar nicht.

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 Viessmann „Edit Client“ Fenster) 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.

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

  1. Hallo, bei mir läuft Node Red direkt auf der CCU3. Bedienung über Win 10 PC.
    Bekomme auch immer die Fehlermeldung „ ErrorCannot GET /authcode“.
    Habe zur Probe meine Firewall abgeschaltet—> gleicher Fehler
    Den/die o. a. Code/Programmierung habe ich so übertragen.

    Port 1880 ist in der CCU freigegeben.
    Abfrage des Codes über Browser funktioniert.
    Im Dev Portal von Viessmann stimmen die Einstellungen auch.

    Was muss ich einstellen, damit ich den Authcode via Node Red abrufen kann?

    1. Hallo,
      Bin grad unterwegs. Mit CCU3/Homematic kenne ich mich überhaupt nicht aus. Wenn das Teil auf Linux läuft, dann probiere mal diese Hilfestellung:

      Checke nochmal die ClientID Geschichte beim Developer.viessmann.com Dashboard:

      Google Captcha muss ausgeschaltet sein
      Redirect URI muss http://localhost:1880/authcode lauten. Keine IP Adresse verwenden.
      im Node Red http request folgende URL eintragen (nur mit deiner Client ID anpassen, den Rest genau so lassen.)

      https://iam.viessmann.com/idp/v3/authorize?client_id=deineClientIDKommtHierHin&redirect_uri=http://localhost:1880/authcode&response_type=code&code_challenge=2e21faa1-db2c-4d0b-a10f-575fd372bc8c-575fd372bc8c&scope=IoT%20User%20offline_access
      Nicht vergessen, die Daten für das Basic Authentifizierungs Login einzutragen. Das ist dasselbe Login, dass du auch für deinen Viessmann Account oder die ViCare App verwendest.

      Das MUSS funktionieren, d.h. im Debug Node (Request Result) steht dann der Auth Code. Wenn nicht, dann mal die URL Zeile in den Browser eingeben, dich mit deinem Viessmann Login einloggen. Es erscheint eine Verbindung Fehlgeschlagen Seite aber in der URL Zeile vom Browser steht jetzt etwas der Art: http://localhost:1880/authcode?code=1ewaadBgBpQchLjJN4hh-z4RMVR8FJ5dvG5heuZp23k

      Wenn das geht, dann hast du etwas bei Node Red oder deinem Hardware Setup verkehrt. Wenn nein, würde ich vorschlagen, mit Michael Hanna von Viessmann Kontakt aufzunehmen.

      1. Hi!
        Danke für die schnelle Antwort.
        Wie beschrieben passt die Config von Viessmann etc. . Wenn ich den Request im Browser ausführe, bekomme ich den Code.

        Bzgl. der Einstellungen im Node Red bin ich absoluter Rookie.
        Evtl. benötigt man in diesem Setup hier einen anderen Port, den man (zusätzlich) freigeben muss.

        Werde mal den Kollegen von Viessmann kontaktieren. Danke für den Hinweis 🙂

        1. Hi,
          Probiere mal die ersten drei Nodes aus dem Kapitel „Authcode abrufen“. Im Debug Node steht das Resultat. Wie du den http Request Node konfigurierst steht im Text.
          Normalerweise läuft Node-Red auf Port 1880. Evtl mal in der Konfigurationsdatei nachsehen, ob da ein anderer Port eingestellt ist.
          Viele Ostermontags-Grüße
          Chris

            1. Hallo,
              Bei Linux steht die Datei settings.js im versteckten Node-Red Verzeichnis unterhalb deines Home Directories. Also z.B. /home/philipp/.node-red/settings.js
              Aber wenn du Node-Red über die url http://deinServerName:1880 aufrufen kannst, dann ist das auch die Portnuummer für das Viessmann Gedöns.
              VG
              Chris

              1. ******Dieser Post ist fälschlicherweise vom Spamfilter aussortiert worden – sorry! *******

                Hallo,

                eine Abfrage mit GET (wie im Text beschrieben) im ersten http-Request liefert kein Ergebnis.
                Grundsätzlich funktioniert diese URL für eine Abfrage via Browser bei Viessmann.

                Bei einer Abfrage mit POST via Node Red mit gleicher URL kommt folgendes Ergebnis heraus:

                302 FoundFoundThe document has moved here.

                Zumindest wird da der Authcode angezeigt.

                Ist es möglich dieses Ergebnis im Node Red so aufzubereiten, dass nur der Code-Teil im msg.payload abgespeichert wird?

                1. Hallo,
                  ich muss da leider passen. Die Abfrage sollte mit einem GET Request funktionieren. Da ich das ganze für einen Raspberry Pi entwickelt habe, kann es durchaus sein, dass ein anderes Gerät mit Linux Kern nicht ganz so funktioniert wie gewünscht, da dort irgendwelche Standardkomponenten fehlen, deaktiviert oder anders konfiguriert sind. Im Prinzip ist eine z.B. Fritz!Box auch bloß ein Linux Rechner, aber die Viessmann API wirst du damit nur mit erheblichem Aufwand zum Laufen bringen. Bei der CCU3 ist das vielleicht auch so.
                  Notbehelf: Access und Refresh Token auf anderem Weg erzeugen (Postman, Funktion bei developer.viessmann.com) in Node-Red einbauen und laufen lassen. Nach 180 Tagen widerholen.
                  Viel Erfolg noch
                  Chris

  2. 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!

  3. 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

  4. 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

  5. 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