Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VitoConnect 100 mit Raspberry PI als Proxy #425

Open
muu55 opened this issue Oct 5, 2018 · 50 comments
Open

VitoConnect 100 mit Raspberry PI als Proxy #425

muu55 opened this issue Oct 5, 2018 · 50 comments

Comments

@muu55
Copy link

muu55 commented Oct 5, 2018

Meine neue Heizung (Vitodens-222 F) kann ich mittels der ViCare App "fernbedienen", leider ist der Funktionsumfang dieser App, na sagen wir mal, "begrenzt". Das schreit nach einer Verbesserung, wobei ich die wesentlichen Komponenten ja bereits habe und auch in ihrer bisherigen Funktion erhalten möchte.

Am schönsten wäre natürlich, ich könnte mich auf der VitoConnect anloggen und direkt
(also ohne das Internet) meine Heizung abfragen und steuern. Das wüde den Nutzen so
einer Box erheblich steigern, ist vom Hersteller aber wohl nicht vorgesehen (?).
Also hab ich mir etwas ausgedacht.

Benötigte Bauteile: Eine Viessman Heizumg mit VitoConnect 100 Typ OPTO1,
ein Raspberry PI Zero WH und ein CP2102 USB-Seriell Adapter.

Um sowohl zu verstehen, was die VitoConnect 100 mit meiner Heizung redet, als auch eigene Kommandos zu senden, habe ich zwischen das original OPTO-Link Kabel und die VitoConnect 100 einen Raspberry PI Zero gehängt, den ich um einen CP2102 USB-Seriell-Adapter erweitert habe.

Das Optolink Kabel verbinde ich über ein "USB-A Buchse auf Micro-USB Stecker"-Kabel mit der USB-Buchse vom PI-Zero. Den CP2102 Adapter verbinde ich über drei Leitung (GND, Tx, Rx) mit dem seriellen Port des PI Zero auf der GPIO Pinleiste und auf der USB-Seite mit der Vitoconnect 100.
Fertig ist die Hardware. Dazu noch ein kleines Programm, das die beiden seriellen Schnitstellen miteinander verbindet und die Daten beim Durchreichen mitprotokolliert.
Schon hat man einen einfachen Proxy mit man-in-the-middle Option.

Erste Erkenntnis: Die VitoConnect 100 redet ununterbrochen mit der Heizung.
Also nicht nur, wenn ich mit der ViCare App eine Verbindung aufbaue oder etwas abfrage.
Offenbar wird dabei das Protokoll 300 (bzw. eine erweiterte Variante) verwendet.

Ich sammle erstmal noch Daten. Sobald ich mehr davon verstehe, versuche ich auch eigene Kommandos auszuführen. Wer so einen Proxy nachbauen will oder wem diese kurze Beschreibung nicht konkret genug war, bitte einfach melden.

@GolterU
Copy link

GolterU commented Oct 5, 2018

Zum Thema Mitschneiden des Datenverkehrs der vitoconnect 100 s.a. Bauanleitung USB_Duo Sniffer. Dort ist eine alternative Hardware dafür beschrieben und es sind ein paar daraus gewonnene Erkenntnisse beschrieben.

@muu55
Copy link
Author

muu55 commented Oct 5, 2018

Ja, diese Bauanleitung habe ich gesehen und gelesen, da hatte ich meine Hardware schon fertig.
Schaue ich mein Logfile an, kann ich die dort berichteten Ergebnisse bestätigen. Wenn ich die Verbindung zwischen VitoConnect100 und der Heizung im Proxy abschalte, dann "pingt" die Vitoconnect nach der Heizung mit 0x04 0x16 0x00 0x00. Dauert die Auszeit nicht zu lang, dann findet die VitoConnect die Heizung wieder und plappert erneut drauf los.

@muu55
Copy link
Author

muu55 commented Oct 5, 2018

Ich schau mal, ob ich das vcontrold auf dem PI an meinen Proxy "anflanschen" kann.
Sobald das klappt, poste ich wie es geht.

@DivisionDurchNull
Copy link

Hallo muu55,

ich habe einen ähnlichen Aufbau mit meinem Raspi3 versucht:

  • Optolink-Kabel an /ttyUSB0
  • USB-UART-Adapter1 an /ttyUSB1
  • VitoConnect mit zweitem USB-UART-Adapter2
  • die beiden USB-UARTs mit GND und gekreuzten TX und RX verbunden

Mit python ein paar zeilen Code geschrieben:

  • beide serielle Schnittstellen werden mit ( 4800, 8, 2, E) geöffnet
  • in zwei Threads wird jeweils die eine Schnittstelle gelesen und die Daten an die andere gesendet

Bisher kann ich sehen, dass vom Optrolink periodisch 0x05 geschickt wird, was auch an den VitoConnect rausgeht - dieser reagiert aber garnicht (sendet auch nichts von sich aus ...)

Habe ich etwas vergesen? Hast Du vielleicht eine Idee oder Dein Beispiel-Code?

P.S.: Losgelöst von diesem Versuch funktioniert die ViCare-App und ich kann auch einige Daten manuell auslesen.

@muu55
Copy link
Author

muu55 commented Oct 7, 2018

Also ich vermute, die VitoConnect erwartet an ihrem USB-Port einen USB-Seriell Adapter mit CP210x Chip, der dieselbe Vendor:Chip ID wie das Optolink-Kabel hat. Also z.B. die in Uwes Bauanleitung aufgeführten "CJMCU CP2102 MICRO USB to UART TTL Module 6 Pin serial Converter".
Genau so einen habe ich auch benutzt.

@muu55 muu55 closed this as completed Oct 7, 2018
@muu55 muu55 reopened this Oct 7, 2018
@muu55
Copy link
Author

muu55 commented Oct 7, 2018

Das kleine C-Programm findet sich hier: https://github.com/muu55/vitolog.git

@muu55
Copy link
Author

muu55 commented Oct 7, 2018

Hier die Addressen+Länge, die von "meiner" VitoConnect100 laufend abgefragt werden:

00 F0 02
00 F8 01
00 F8 08 GWG_SystemIdent
00 F9 01 GWG_Kennung
00 FA 01 WPR_Hardware_Index
00 FB 01 SystemIdent_SW1
00 FC 01 WPR_Protokollversion_LDAP
00 FD 01 WPR_Protokollversion_RDAP
00 FE 01 WPR_Software_Version_Byte1
00 FF 01 WPR_Software_Version_Byte2

08 10 04 TiefpassTemperaturwert_KTS
08 3A 01 TemperaturFehler_ATS
08 3B 02 TemperaturFehler_KTS
08 8E 08 Uhrzeit
08 96 06 TiefpassTemperatur_RTS_A1M1
08 9C 03 NRF_TemperaturFehler_RTS_M1

20 00 30 WPR_HK1_Normaltemperatur
20 30 08 Durchfluss
21 00 30
21 30 08 mBusNRZ012130Stichtag02
22 00 30
22 30 08
23 06 2C BedienRTSolltemperaturA1M1
23 09 19 FerienBeginnA1M1
25 00 16 HK_RaumsolltemperaturaktuellA1M1
25 35 15 HK_FerienbetriebA1M1
27 D3 02 KD3_KonfiNeigungA1
29 00 02 Vorlauftemperatur
29 04 01 Vorlauftemperaturstatus
30 00 30 WPR_HK2_Normaltemperatur
30 30 08
31 00 30
31 30 08
32 00 30
32 30 08
33 06 2C BedienRTSolltemperaturM2
33 09 19 FerienBeginnM2
35 00 36 HK_AktuelleBetriebsartM2
35 49 01 ExtBetriebsartenumschaltung_M2
37 D3 02 KD3_KonfiNeigungM2D
39 00 02 VorlauftemperaturM2
39 04 01 Status_2_M2
40 00 30 WPR_HK3_Normaltemperatur
40 30 08
41 00 30
41 30 08
42 00 30
42 30 08
43 06 2C BedienRTSolltemperaturM3
43 09 10 FerienBeginnM3
45 00 16
45 35 01
45 49 01
47 D3 02
49 00 02
49 04 01 Status_2_M3
55 25 02 TiefpassTemperaturwert_ATS
55 D3 09 GWG_Flamme
57 21 03 K21_KonfiBetriebsstdBrenner_Wartung
57 24 01 K24_KonfiStatusWartung
57 38 01 K38_KonfiFehlerByteGFA
63 00 01 Bedien_WW_Solltemperatur
75 07 36 Fehlerhistorie
75 3D 24
75 61 0A
75 6C 08 LetzteIntervallWartung
77 00 01
77 7F 01
F0 00 20

@DivisionDurchNull
Copy link

Danke für den Hinweis.
Ich habe 3 verschiedene USB-UARTs ... leider alle mit einem PL2303-Chip :(
Mal sehen wann die Bestellung vom CP2102 eintrudelt (gab genau 1 Angebot aus DE auf ebay ...). Dann setze ich mich wieder dran ...

@speters
Copy link
Member

speters commented Oct 8, 2018

Hast du @muu55 eine Möglichkeit, die Kommunikation der VitoConnect mit dem Viessmann-Server mitzuschneiden (z.B. mitmproxy?
Ggf. liesse sich das API des Viessmann-Servers dann zu weiteren Erkenntnisgewinnen über Featuresets/Adressen/EventTypes anderer Anlagen nutzen. Die XML-Dateien der VitoSoft-Demo sind zwar schon sehr umfassend, allerdings auch relativ alt und nicht fehlerfrei.

Kannst du in den Logs Kommunikation finden, die nicht ReadData/0x01/Virtual_Read oder WriteData/0x02/Virtual_Write, sondern z.B. Funktion Calls/0x07/Remote_Procedure_Call sind? (wg. Ergänzung der Dokumentation von Protokoll 300)


Falls du die XML-Dateien der VitoSoft mal angeschaut hast:

Es gibt EventTypes mit der gleichen Adresse, aber unterschiedlicher BytePosition (quasi Offset). Kannst du erkennen, ob der Zugriff dann auf Adresse+BytePosition in ByteLength Länge stattfindet oder ob die Adresse in voller BlockLength abgefragt wird? Und wie sieht das beim Schreiben von EventTypes aus, die eine BitLength > 0 haben?
Hintergrund ist der, dass ich zunächst dachte, der Adressraum wäre linear und direkt adressierbar (was z.B. 0x00F8 ff. nahelegt), bis ich dann herausbekommen habe, dass das nicht so ist (konkret war das bei der Fehlerhistorie, die ich mal nicht in Vielfachen von (BlockLength/BlockFactor) ausgelesen hatte).

@GolterU
Copy link

GolterU commented Oct 8, 2018

Ich habe längere Zeit die Daten mit dem Sniffer aufgezeichnet, die Vitoconnect mit der Heizung (also auf der seriellen Ebene) austauscht. Zum Viessmann-Server sollte er dann wohl nichts anderes schicken können, als er von der Heizung geliefert bekommt. Auszug siehe Excel-Datei hier. In dieser Datei Vitoconnect-Output.zip
sind noch mehr Daten gespeichert, z.T. mit grafischer Auswertung, um 'rauszufinden, wann und wie häufig die Adressen abgefragt werden. Darin sieht man zwar die zyklischen Abfragen, aber auch, dass die Abfragen variiert werden und sich nicht 100% gleichartig wiederholen.

Was den beschriebenen Adressraum anbelangt: Ich glaube jetzt, dass die Adressen eher als Befehle zu verstehen sind, die die Heizungssteuerung mit unterschiedlich langen Datensätzen beantwortet. Damit werden nicht einfach Speicherplätze im Bereich von 0x0000 bis 0xFFFF adressiert und das dort gespeicherte Byte zurückgegeben.
Beispiel:
Die Abfrage der Adresse 0x2500 (Status Heizkreis A1M1) mit

41 05 00 41 25 00 16 81

liefert

xx xx xx xx xx xx xx 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 xx
41 1B 01 41 25 00 16 02 02 53 25 04 00 47 01 01 00 00 01 C8 00 00 00 00 47 01 00 C8 00 3A

Im Antwortdatensatz mit 22 Byte Nutzdaten stecken laut "ecnEventType.xml" (aus der Vitosoft-Demo)
an der Byteposition 1 (wird ab 0 gezählt) mit Länge 1 der Heizungsstatus als Integer,
ab Pos. 2 mit 4 Byte Länge der Aufheiztimer als Double in Sekunden,
ab Pos. 6 mit 2 Byte Länge die Vorlauf-Solltemperatur als Double (hier 32,7°C, Berechnung wie hier),
an Pos. 8 mit 1 Byte Länge der Heizkreisfreigabe-Status als Integer,
an Pos. 10 mit 1 Byte Länge der Status der Heizkreispumpe als Integer,
an Pos. 11 mit 1 Byte Länge die RSWS-Betriebsart (was immer das ist) als Integer,
ab Pos. 12 mit 2 Byte Länge die Raumsolltemperatur als Double (hier 20°C),
an Pos. 16 mit 1 Byte Länge der Zustand Frostgefahr.

Was mich irritiert: An der gleichen Adresse kann auch ein Datensatz mit 17 Byte Datensatzlänge abgefragt werden kann. Laut der obigen XML-Datei sind dann andere Daten unter den genannten Bytepositionen/Offsets verfügbar. Z.B. an Pos. 2 steht anstelle "HK_AufheiztimerA1M1" der Wert von "NRF_HK_VT_Solltemperatur_A1M1".

@speters
Copy link
Member

speters commented Oct 8, 2018

Danke für dein Log.
Habe gerade erst gesehen, dass da ja ganze 19 Sheets mit Daten drin sind.

Im 4. Byte der Antwort wo der klassischen P300 Protokolldefinition nach nur 0x01, 0x02, 0x07 vorkommen dürfte, sind Bits 7,6,5 offenbar als Zähler (0..7) verwendet worden (da kann man sich Anwendungsmöglichkeiten ausdenken: Erkennung fehlender Pakete, Zuordnen von Anfragen zu Antworten, ...).
Den Daten nach hast Du eine Systemkennung 0x20CB0009. Also 20CB Hardwarereindex 0, Softwarereindex 9. Bei meiner 0x20CB000B (ähnlich, nur Softwarerevision 11) kann ich diese Zählersache nicht beobachten.

Hast du ein Log, wo die Anfragen der Vitoconnect auch auftauchen?
Ein wenig stutzig macht mich die Logzeile
06 | 41 | 06 | 03 | 21 | 00 | F0 | 01 | 01 | 1C
Was für eine Anfrage produziert diesen Fehler? Die Adresse 0x00F0 (ecnsysDeviceIdentF0) und die Länge 1 müsste doch valide sein.

PS:
Ich kann auf die Schnelle nix sehen, aber hast du irgendwo geloggt, wie die Fehlerhistorie und die Fehlerhistorie des Feuerungsautomaten gelöscht werden?

@GolterU
Copy link

GolterU commented Oct 8, 2018

Danke für dein Log.
Habe gerade erst gesehen, dass da ja ganze 19 Sheets mit Daten drin sind.

Hallo Sönke,
die Logs in den ersten Blättern obiger Datei sind während der Zeit entstanden, als ich mir den USB-Sniffer ausdachte. Am Anfang war die Hardware so, dass nur die Antwortdaten der Heizungsregelung an die Vitoconnect aufgezeichnet wurden. Die Erläuterungen und Kommentare auf den einzelnen Blättern sind wahrscheinlich auch nicht sehr aufschlussreich. Es war halt nicht zur Veröffentlichung gedacht. Ab Tabellenblatt T8 sind auch Sendedaten enthalten. Jetzt (so auch hier) ist standardmäßig der Datenverkehr in beiden Richtungen gespeichert.

Im 4. Byte der Antwort wo der klassischen P300 Protokolldefinition nach nur 0x01, 0x02, 0x07 vorkommen dürfte, sind Bits 7,6,5 offenbar als Zähler (0..7) verwendet worden (da kann man sich Anwendungsmöglichkeiten ausdenken: Erkennung fehlender Pakete, Zuordnen von Anfragen zu Antworten, ...).
Den Daten nach hast Du eine Systemkennung 0x20CB0009. Also 20CB Hardwarereindex 0, Softwarereindex 9. Bei meiner 0x20CB000B (ähnlich, nur Softwarerevision 11) kann ich diese Zählersache nicht beobachten.
Hast du ein Log, wo die Anfragen der Vitoconnect auch auftauchen?

Meine Vermutungen zu diesen drei ominösen Bits (und was mir sonst noch so aufgefallen ist) hatte ich hier geschildert.
Da die drei Bits schon in den Anfragen an die Heizung hin und wieder als gesetzt auftauchen, kann es eigentlich nicht mit dem Softwarestand der Regelung zusammenhängen. Die scheint in ihren Antworten dieses Byte einfach aus der Anfrage zu wiederholen. Logs dazu siehe ebenfalls hier. Eine Systematik bezüglich der Werte dieser drei Bits habe ich bislang nicht erkannt.

Ein wenig stutzig macht mich die Logzeile
06 | 41 | 06 | 03 | 21 | 00 | F0 | 01 | 01 | 1C
Was für eine Anfrage produziert diesen Fehler? Die Adresse 0x00F0 (ecnsysDeviceIdentF0) und die Länge 1 müsste doch valide sein.

Die Adresse 0x00F0 erscheint in der "ecnDataPointType.xml" (aus der Vitosoft-Demo) nicht, jedenfalls nicht unter Device-ID "VScotHO1_4" - die hier zutreffen sollte. In der "ecnEventType.xml" (auch aus der Vitosoft-Demo) steht sie mit der Bezeichnung "KBUS_V300_T03_VirtKanal_07" und der Länge von zwei Byte.
Ich vermute, Du hast die Zeile aus dem Blatt T1 der "Vitoconnect-Output.xlsm". Dort hatte ich einfach mal den Beginn des Datenverkehrs zwischen Vitoconnect und Heizung aufgezeichnet, allerdings wie gesagt, nur die Antwortdaten. Warum Vitoconnect die Adresse benutzt, bevor der Typ der Steuerung abgefragt wird, erschließt sich mir nicht. Jedenfalls ist die Adresse 0x00F0 bei mir ungültig. Ich hatte mal die Heizung mit Hilfe des Programms "Vies-sion" mit allen Adressen 0...0xFFFF traktiert, dabei gibt es bei 0x00F0 auch einen Fehler.
Wenn es Dich interessiert, kann ich nochmal ein Log vom Startvorgang der Vitoconnect erzeugen, diesmal mit den Daten aus beiden Richtungen.

PS:
Ich kann auf die Schnelle nix sehen, aber hast du irgendwo geloggt, wie die Fehlerhistorie und die Fehlerhistorie des Feuerungsautomaten gelöscht werden?

Bislang habe ich nur ganz wenige Schreibvorgänge manuell ausgelöst und mitgeloggt. Die Fehlerhistorie (an 0x7507) habe ich nicht angefasst. Da dieser Datenpunkt als read/write ausgewiesen ist, kann man den Inhalt evtl. einfach auf Null setzen??

Gruß
Uwe aka Golter

@muu55
Copy link
Author

muu55 commented Oct 9, 2018

Mein Programm schreibt die Kommunikation zwischen Heizung und VitoConnect100 nach stdout.
Hier das Log der letzten Tage: vito100.log.gz Entpackt sind das 112 MB, die Datei enthält 987817 Frage/Antwort Pärchen.

Die Zeilen mit 0: kommen von der VitoConnect100, die Zeilen mit 1: von der Heizung.
Am Anfang sieht man wie sich die Geräte finden und danach beginnt das endlose Frage/Antwort-Spiel.

0: 04
1: 06 05
0: 16 00 00
1: 06
0: 41 05 00 81 00 F0 02 78
1: 06 41 07 01 81 00 F0 02 0B 00 86
0: 41 05 00 A1 00 F8 08 A6
1: 06 41 0D 01 A1 00 F8 08 20 CB 28 CB 00 00 01 0A 98
0: 41 05 00 C1 49 04 01 14
1: 06 41 06 01 C1 49 04 01 06 1C
0: 41 05 00 E1 39 04 01 24
1: 06 41 06 01 E1 39 04 01 06 2C
0: 41 05 00 01 29 04 01 34
1: 06 41 06 01 01 29 04 01 00 36
...

Um die Kommunikation von der VitoConnect nach Hause (Viessmann Server) zu analysieren,
müsste ich erst noch den Network Setup um die Box herum etwas umbauen.

@hendrikland
Copy link

  • Optolink-Kabel an /ttyUSB0
  • USB-UART-Adapter1 an /ttyUSB1
  • VitoConnect mit zweitem USB-UART-Adapter2
  • die beiden USB-UARTs mit GND und gekreuzten TX und RX verbunden

Mit python ein paar zeilen Code geschrieben:

  • beide serielle Schnittstellen werden mit ( 4800, 8, 2, E) geöffnet
  • in zwei Threads wird jeweils die eine Schnittstelle gelesen und die Daten an die andere gesendet

Könntest du den Python-Code sharen? Ich habe einen ähnlichen Aufbau vor, es geht erstmal nur darum die Daten mitzulesen. In meinem Fall ein Pellet-Kessel (Vitoligno 300-C), bei dem es nützlich wäre einige Werte zu erfassen (Anzahl Zündvorgänge, Brenndauer, Pelletverbrauch,...). Leider bietet die App nichts davon an, ich vermute aber das das Vitoconnect die Werte ausliest. Ziel wäre es, dieses auf dem Raspi abzuzweigen und separat wegzuschreiben (z.B. Grafana).

@DivisionDurchNull
Copy link

Hallo hendrikland,

hier mein Beispiel. Aufruf ist dann z.B.
python3 "programm.py" > "logfile"

Und es ist ein UART mit dem Chip CP2102 notwendig (PL2303 geht definitiv nicht) .


#!/usr/bin/python
#!/usr/bin/env python
import serial
import time
import threading

__ready  = b'\x05'

serv = serial.Serial("/dev/ttyUSB1",
                     baudrate=4800,
                     parity=serial.PARITY_EVEN,
                     stopbits=serial.STOPBITS_TWO,
                     bytesize=serial.EIGHTBITS,
                     timeout=0.3)

sero = serial.Serial("/dev/ttyUSB0",
                     baudrate=4800,
                     parity=serial.PARITY_EVEN,
                     stopbits=serial.STOPBITS_TWO,
                     bytesize=serial.EIGHTBITS,
                     timeout=0.3)

def serial_read(s,t, info):
    while True:
        msg = s.read(24)
        if msg:
            start_time = time.strftime("%d.%m.%Y %H:%M:%S")
            print(info,  end="")
            print(start_time, end="")
            print(" ", end="")
            for c in msg:
                print("%02x " % c, end="")
            print()
 
            t.write(msg)

#serial_read(sero, serv)

thread1 = threading.Thread(target=serial_read, args=(serv, sero, 'S ',),)
thread2 = threading.Thread(target=serial_read, args=(sero, serv,'R ',),)
thread2.start()
thread1.start()

@hydrax0
Copy link

hydrax0 commented Apr 8, 2020

@hendrikland
Hi. Ich habe auch eine Vitoligno 300-C und suche verzweifelt nach Adressen, vor allem den FehlerStatus. Ich bekomme korrekte Antworten bei der Fehlerhistorie der letzten 10 Fehler, aber der Status selbst funktioniert noch nicht.
Hattest du schon Erfolg und würdest du die Adressen mit mir teilen?
Grüsse Richard

@dima-357
Copy link

Please tell me the request address V100
boiler pump in operation or not /
It is not in the list of addresses of Viessmann-adresses

@TheCutter
Copy link

Könntest du den Python-Code sharen? Ich habe einen ähnlichen Aufbau vor, es geht erstmal nur darum die Daten mitzulesen. In meinem Fall ein Pellet-Kessel (Vitoligno 300-C), bei dem es nützlich wäre einige Werte zu erfassen (Anzahl Zündvorgänge, Brenndauer, Pelletverbrauch,...). Leider bietet die App nichts davon an, ich vermute aber das das Vitoconnect die Werte ausliest. Ziel wäre es, dieses auf dem Raspi abzuzweigen und separat wegzuschreiben (z.B. Grafana).

@hendrikland Bist du mit dem Vitoligno 300-C weiter gekommen? Ich würde meinen auch gerne anbinden und die Werte von dir interessieren mich auch. Danke und Gruß

@idstein
Copy link

idstein commented Jul 23, 2022

Wir standen vor dem gleichen Problem und wollten die VitoConnect 100 noch weiter laufen lassen. Da mir ein Raspberry für die Arbeit zu schade war und es mittlerweile für <10 € einen ESP32 DevBoard (mit CP2102 USB / UART Chip) gibt, wurde es dann eben eine minimale ESPHome Lösung.

Netterweise kann man den ESP direkt in den USB Port der VitoConnect 100 stecken und fleißig als Proxy den Traffic verfolgen oder eben weitere Requests einfließen lassen. Kleiner Bonus: Es läuft demnächst auch auf dem ESP ein kleiner Modbus Slave der unserer VitoCal 200-S die frei "verfügbare" PV-Strom Messwerte übergibt.
IMG_0912

Für Viessmann ist diese Variante ohne größeren Aufwand und bei ausschließlich mitlesendem Gebrauch quasi nicht detektierbar.

Wichtig! Es reicht kein ESP8266 und kein Software UART, da die Kommunikation doch schon sehr (A) zeitkritisch erfolgen muss und (B) doch einiges von der VitoConnect 100 abgerufen wird.

@h0nIg
Copy link

h0nIg commented Sep 4, 2022

@idstein wärst du bitte so nett und teilst kurz dein ESP Sources/Aufbau und eine kurze Beschreibung was du mit deinem DEV Board gemacht hast? Braucht keine große Beschreibung, vorallem interessiert mich wie du den USB Traffic forwardest / interceptest

@h0nIg
Copy link

h0nIg commented Sep 11, 2022

ich hab mir jetzt eine Bridge gebaut, womit man vcontrold und vitoconnect parallel betreiben kann und die fehlenden Werte kriegt: https://github.com/h0nIg/vcontrol-vitoconnect-bridge/

@egnerfl
Copy link

egnerfl commented Sep 15, 2022

Hi @idstein das sieht ja sehr spannend aus, kannst du deine ESPhome config teilen?

@m1k3f15h
Copy link

Hy @idstein

Echt cooles Projekt :)
würd auch gerne mehr darüber erfahren :)

mfg
Mike

@idstein
Copy link

idstein commented Oct 7, 2022

@idstein wärst du bitte so nett und teilst kurz dein ESP Sources/Aufbau und eine kurze Beschreibung was du mit deinem DEV Board gemacht hast? Braucht keine große Beschreibung, vorallem interessiert mich wie du den USB Traffic forwardest / interceptest

Aktueller Stand baut das ganze auf ESPHome bei mir lokal auf fürs Management, Updates, ein bisschen Security usw. Die Funktionalität die Werte konkret auszulesen habe ich noch nicht finalisiert, ich hoffe aber demnächst hier weiter zu kommen.

Funktion

  • VitoConnect Passthrough (ohne Sniffing)
  • ALE Energy Meter Simulator (Photovoltaik)

Roadmap

  • Parse data points already accessed via VitoConnect
  • Allow asking for specific data points independent of VitoConnect

Hardware

Software

substitutions:
  # Unique device ID
  device_id: "heating01"
  device_name: "Heizung Optolink"

esphome:
  name: ${device_id}
  includes:
    - viessmann-vitoconnect/optolink.h
    - viessmann-vitoconnect/optolink.cpp

external_components:
  - source: github://epiclabs-io/esphome-modbus-server@master
    refresh: 60s
    components:
      - modbus_server

esp32:
  board: az-delivery-devkit-v4

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    password: !secret wifi_ap_password

# Enable Home Assistant API
api:
  password: !secret api_password
  encryption:
    key: !secret api_encryption
# Enable over-the-air updates
ota:
  password: !secret ota_password

# Enable Web server
web_server:
  version: 2
  local: true
  port: 8080
  auth:
    username: !secret web_user
    password: !secret web_password

logger:
  baud_rate: 0 #disable logging over uart

uart:
 - id: vitoconnectOpto2
   tx_pin: GPIO1
   rx_pin: GPIO3
   baud_rate: 4800
   data_bits: 8
   parity: EVEN
   stop_bits: 2
#   debug:
#    direction: RX
#    after:
#      delimiter: [0x41]
 - id: vitocal200S
   tx_pin: GPIO17
   rx_pin: GPIO16
   baud_rate: 4800
   data_bits: 8
   parity: EVEN
   stop_bits: 2
#   debug:
#    after:
#      delimiter: [0x06, 0x41]
 - id: ale3energymeter
   tx_pin: GPIO32
   rx_pin: GPIO33
   baud_rate: 19200
   data_bits: 8
   parity: EVEN
   stop_bits: 1
#   debug:
#    dummy_receiver: true
#    after:
#      bytes: 8

sensor:
  # TODO replace with local Optolink reading; current value is based on reading EEBUS via GridX Box
  - platform: homeassistant
    id: heatpump_power_consumption
    entity_id: sensor.heatpump_power_consumption
    device_class: power
    unit_of_measurement: W
    accuracy_decimals: 0
  - platform: homeassistant
    id: meter_l1_power_supply
    entity_id: sensor.meter_l1_power_supply
    device_class: power
    unit_of_measurement: W
    accuracy_decimals: 0
  - platform: homeassistant
    id: meter_l2_power_supply
    entity_id: sensor.meter_l2_power_supply
    device_class: power
    unit_of_measurement: W
    accuracy_decimals: 0
  - platform: homeassistant
    id: meter_l3_power_supply
    entity_id: sensor.meter_l3_power_supply
    device_class: power
    unit_of_measurement: W
    accuracy_decimals: 0

button:
#  - platform: template
#    name: "Vitocal Send EOT"
#    on_press:
#      - uart.write: 
#          id: vitocal200S
#          data: [0x04]
#  - platform: template
#    name: "Vitocal Send Sync"
#    on_press:
#      - uart.write: 
#          id: vitocal200S
#          data: [0x16, 0x00, 0x00]
  - platform: template
    name: "Vitocal Request AT"
    on_press:
      - uart.write: 
          id: vitocal200S
          data: [0x41, 0x05, 0x00, 0x01, 0xF8, 0x02, 0x00]

custom_component:
  lambda: |-
    auto my_custom = new UartOptoLinkSensor(id(vitoconnectOpto2), id(vitocal200S));
    return {my_custom};

modbus_server:
  - id: modbuserver
    uart_id: ale3energymeter
    address: 60 # slave address
    holding_registers:
      - start_address: 0 # REG_FIRMWARE
        default: 10
      - start_address: 1 # REG_MODBUS_REG
        default: 52
      - start_address: 2 # REG_MODBUS_FLAGS
      - start_address: 3 # REG_BAUDRATE_HIGH
      - start_address: 4 # REG_BAUDRATE_LOW
        default: 0x4B00
      - start_address: 5 # REG_TYP_ASN_FN_1
        on_read: return atoi("AL");
      - start_address: 6 # REG_TYP_ASN_FN_2
        on_read: return atoi("E3");
      - start_address: 7 # REG_TYP_ASN_FN_3
        on_read: return atoi("D5");
      - start_address: 8 # REG_TYP_ASN_FN_4
        on_read: return atoi("FD");
      - start_address: 9 # REG_TYP_ASN_FN_5
        on_read: return atoi("10");
      - start_address: 10 # REG_TYP_ASN_FN_6
        on_read: return atoi("C2");
      - start_address: 11 # REG_TYP_ASN_FN_7
        on_read: return atoi("A0");
      - start_address: 12 # REG_TYP_ASN_FN_8
        on_read: return atoi("00");
      - start_address: 13 # REG_HW_VERSION
        default: 11
      - start_address: 14 # REG_SN_HIGH
        default: 0x1234
      - start_address: 15 # REG_SN_LOW
        default: 0x5678
      - start_address: 21 # REG_STATUS
        on_read: |
          // No problem=0, Communication problem=1
          return api_apiserver->is_connected() ? 0 : 1; 
      - start_address: 24 # REG_ERROR_REG
        default: 0 # None=0, L1=1, L2=2, L1L2=3, L3=4, L1L3=5, L2L3=6, L1L2L3=7
      - start_address: 26 # REG_TARIFF
        default: 0 # TARIF_T1=0, TARIF_T2=4
      - start_address: 27 # REG_TARIF1_ENERGY_TOTAL_HIGH
      - start_address: 28 # REG_TARIF1_ENERGY_TOTAL_LOW
      - start_address: 29 # REG_TARIF1_ENERGY_PARTIAL_HIGH
      - start_address: 30 # REG_TARIF1_ENERGY_PARTIAL_LOW
      - start_address: 31 # REG_TARIF2_ENERGY_TOTAL_HIGH
      - start_address: 32 # REG_TARIF2_ENERGY_TOTAL_LOW
      - start_address: 33 # REG_TARIF2_ENERGY_PARTIAL_HIGH
      - start_address: 34 # REG_TARIF2_ENERGY_PARTIAL_LOW
      - start_address: 35 # REG_PHASE_1_VOLTAGE
      - start_address: 36 # REG_PHASE_1_CURRENT
      - start_address: 37 # REG_PHASE_1_POWER 1545 = 15,45 kVA
        on_read: |
          if (!api_apiserver->is_connected() || !id(meter_l1_power_supply)->has_state() || !id(heatpump_power_consumption)->has_state())
            return 0;
          return (id(meter_l1_power_supply)->state - id(heatpump_power_consumption)->state / 3) / 10;
      - start_address: 38 # REG_PHASE_1_REACTIVE_POWER
      - start_address: 39 # REG_PHASE_1_COS_PHI
      - start_address: 40 # REG_PHASE_2_VOLTAGE
      - start_address: 41 # REG_PHASE_2_CURRENT
      - start_address: 42 # REG_PHASE_2_POWER 1545 = 15,45 kVA
        on_read: |
          if (!api_apiserver->is_connected() || !id(meter_l2_power_supply)->has_state() || !id(heatpump_power_consumption)->has_state())
            return 0;
          return (id(meter_l2_power_supply)->state - id(heatpump_power_consumption)->state / 3) / 10;
      - start_address: 43 # REG_PHASE_2_REACTIVE_POWER
      - start_address: 44 # REG_PHASE_2_COS_PHI
      - start_address: 45 # REG_PHASE_3_VOLTAGE
      - start_address: 46 # REG_PHASE_3_CURRENT
      - start_address: 47 # REG_PHASE_3_POWER 1545 = 15,45 kVA
        on_read: |
          if (!api_apiserver->is_connected() || !id(meter_l3_power_supply)->has_state() || !id(heatpump_power_consumption)->has_state())
            return 0;
          return (id(meter_l3_power_supply)->state - id(heatpump_power_consumption)->state / 3) / 10;
      - start_address: 48 # REG_PHASE_3_REACTIVE_POWER
      - start_address: 49 # REG_PHASE_3_COS_PHI
      - start_address: 50 # REG_TOTAL_POWER
      - start_address: 51 # REG_TOTAL_REACTIVE_POWER

@m1k3f15h
Copy link

Hy @idstein

Echt ein MEGA-COOLES Projekt :)
Werde das gespannt weiterverfolgen und hoffentlich hab ich bald mal Zeit das "Nachzubauen".
Erstmals werde ich das ohne dem "Modbus-Energymeter-Simulator" machen... Soll aber mit der PV dann auch noch folgen.

Danke, dass du das Projekt mit uns teilst 😄

Mfg
Mike

@challo2018
Copy link

challo2018 commented Dec 7, 2022

Hi @idstein,
cooles Projekt ich verwende momentan die Viessmann API um über das Vitoconnect100 die Daten in mein Loxone Smarthome zu bekommen. Allerdings ist die API sehr eingeschränkt und teilweise jetzt auch kostenpflichtig. Wegen der Garantieverlängerung würde ich aber gerne das Vitoconnect weiter in betrieb lassen. Daher wäre es echt cool wenn man mit deiner einfachen Lösung das Vitoconnect weiterverwenden kann und zusätzlich Daten lokal abfragen und auch setzen kann. Bin mit ESP Home bisher noch nicht ganz firm. Kannst du kurz den aktuellen Stand nochmal etwas detaillierter beschreiben?
Ich habe verstanden, dass die Daten zwischen dem IR Modul und dem Vitoconnect in beide Richtungen durchgereicht werden.
Zusätzlich schleifst du PV Daten hier ein.
Können auch Daten aus dem Traffic ausgelesen werden ? Vorlauftemperatur oder so?
Wie läuft die Installation auf dem ESP32. ESPHome flashen und dann zusätzlich VitoWifi?

Vielen Dank!

@m1k3f15h
Copy link

Hi @idstein,
Gibts zu dem Projekt schon was neues?

mfg
Mike

@philippoo66
Copy link

Moin ihr!
hab ich das richtig verstanden - ihr habt eine Wärmepumpe mit Optolink? Wenn dem so ist, könnt ihr mir mal die 4 Bytes ab Adr. F8 und ein Byte an Adr. F0 sagen?
danke & beste Grüsse!
Phil

@m1k3f15h
Copy link

Morgen,
Kann ich leider nicht, da bei mir noch alles original ist und ich nichts auslese.

mfg
mike

@philippoo66
Copy link

aber da is eine Vitotronic drin, oder? da könnte dan im Menü unter 'Service' ganz hinten ein Punkt 'Software Information' oder so sein. Das Passwort dafür ist 'vimaster'

grafik

HW/SW Index sind das 3. und 4. Byte von F8, ich glaube die Zahl vor dem Punkt ist F0. Ich gehe davon aus, dass bei einer Vitotronic die ersten beiden F8 Bytes 20 CB sind...

@philippoo66
Copy link

könntest du das mal checken beizeiten? ;-)

@m1k3f15h
Copy link

m1k3f15h commented Feb 6, 2023

@philippoo66
Bei mir sieht das alles komplett anders aus als bei dir.. ich denke du hast eine andere Heizungssteuerung als ich..
meine sieht aus wie die aus [idstein]s post weiter oben

@philippoo66
Copy link

philippoo66 commented Feb 6, 2023

wenn du den vom Jul 23, 2022 meinst - das ist eine HO2B. Meine ist eine HO2C. Die beiden Steuerungen unterscheiden sich nur minimal in der grafischen Darstellung. Diesen Bildschirm wirst du auch kennen?

grafik

Wenn man da nach rechts scrollt, gibt es 'Servicefunktionen', dahinter dann wieder rechts gibt es den Punkt Softwareinformation...

Ist aber auch nicht so wichtig, hätte mich nur interessiert. Ich war nämlich etwas verwundert, dass ich in dem alten Vitosoft Kram die DP Adresslisten für Wärmepumpen gefunden hatte, aber scheibar ist das ja erklärbar. Und wenn du die API benutzt, hast du wohl auch keine Verwendung für Optolink Adressen. Ich dachte nur, weil du den eingeschränkten Umfang bei der API moniertest.... Mit Optolink kann man halt alles machen. Sogar die Gerätekennung ändern. Ziemlich nutzlos, aber zeigt was geht... ;-)

@m1k3f15h
Copy link

m1k3f15h commented Feb 7, 2023

Nein den bildschirm kenne ich ned xD
Sieht anders aus bei mir...

IMG_20230206_173053.jpg

Aktuell mach ich alles über die sche.... API.. würd aber gern auf einen esp32 als "optolink-proxy" wechseln, der dann auch genauer und hochauflösender ausließt

Mfg
Mike

@challo2018
Copy link

@m1k3f15h : so würde ich es auch gerne machen da ich wegen der Garantie dass vitoconnect weiterlaufen lassen möchte....

@m1k3f15h
Copy link

m1k3f15h commented Feb 7, 2023

@challo2018 : Ja leider meldet sich @idstein aktuell nicht mehr.. Der hat ja da schon was zusammen gebracht :)
allerdings wär mir das ganze auf Tasmota-Basis lieber :D

@mattjes04
Copy link

mattjes04 commented Mar 23, 2023

ich hab mir jetzt eine Bridge gebaut, womit man vcontrold und vitoconnect parallel betreiben kann und die fehlenden Werte kriegt: https://github.com/h0nIg/vcontrol-vitoconnect-bridge/

Amazing work! I'm using a rpi1 with the same setup @DivisionDurchNull mentioned in his post. But as proxy script I copied your bridge.py and just changed the serial targets towards my setup. Vcontrol-Service also runs on the raspberry and queries the tcp-socket opened by the bridge.py. Vcontrol is then queried by the Vcontrold-Addon in Homeassistant which pushes the values to mqtt an makes them available in Homeassistant. So far everything is working flawless. ViCare-App seems not to notice any interruption. Kudos to @h0nIg & @DivisionDurchNull

@challo2018
Copy link

@mattjes04 : does this solution also allow to set values with vcontrold?

@mattjes04
Copy link

@mattjes04 : does this solution also allow to set values with vcontrold?

Jup, Warmwasserbereitung auf Anforderung funktioniert einwandfrei.

@challo2018
Copy link

@mattjes04 : does this solution also allow to set values with vcontrold?

Jup, Warmwasserbereitung auf Anforderung funktioniert einwandfrei.

Hört sich auch nach einer guten Lösung an, allerdings wäre man hier dann nochmal auf rasperry basis.
Bei der Lösung von @idstein, läuft das ganze nur über ein ESP. Ich habe allerdings kein homeassistant, daher kann ich mit dem yaml file für espHome nicht so viel anfangen. Wenn man auf Basis von VitoWifi auf dem ESp32 noch ein passthrough für das vitoconnect einbauen würde, hätte man eine coole lösung. Vielleicht kann @idstein doch nochmal etwas unterstützen?

@ckoeber83
Copy link

Hi,
suche auch eine Lösung die VControld und Vitoconnect im Parallelbetrieb zu betreiben und die Werte in den ioBroker zu bringen.
Hat da schon jemand was und kann eine Step by Step Anleitung machen, mit Hardware- und Software-Seite?

THX!

@ckoeber83
Copy link

Von: Phil <notifications@github.com> 
Gesendet: Donnerstag, 31. August 2023 03:49
An: openv/openv <openv@noreply.github.com>
Betreff: Re: [openv/openv] VitoConnect 100 mit Raspberry PI als Proxy (#425)

Moin!
verstehe ich das richtig, dass du per Vitoconnect Viessmann deine Daten auslesen lassen möchtest, das aber mit vcontrold 'mitlesen' und auf MQTT posten?
bist du der koeber aus dem Viessmann Forum?
Grüsse!
Phil

@philippoo66 ja genau der 😊

Ja ich will die Serielle Kommunikation mitschneiden und dann via vcontrold den ioBroker.viessmann Adapter anflanschen, um die Daten im ioBroker als Datenpunkte zu erhalten, zur Visualisierung in Grafana.

Mein bisheriges Grafana Dashboard mit Daten aus der Viessmann API

koeber_0-1693399259599(1)

@ggrote
Copy link

ggrote commented Aug 31, 2023

Wie hast du die Bedeutung und IDs der Datenpunkte rausgefunden? Das frage ich mich schon länger. Habe eine Pelletheizung von Viessmann und bisher noch keine Infos dazu gefunden. Würde aber auch ungern extra das Vitoconnect dafür kaufen und in Betrieb nehmen.
Dein Dashboard sieht super aus! Habe auch Grafana am Start, aber mit direkter Verbindung zu InfluxDB, wo über Node-Red Daten reingeschrieben werden.

@ckoeber83
Copy link

ckoeber83 commented Aug 31, 2023

@ggrote meine Dashboard läuft mit der Viessmann API und die Vitoconnect übermittelt die Daten in die API.
Das ist noch keine lokale Geschichte mit vcontrold oder so.
Da man mit vcontrold aber mehr Datenpunkte auslesen kann, als über die Viessmann API und ich aber die Vitoconnect nicht missen möchte, ist der Wunsch nach einem Proxy, der die Serielle Verbindung zwischen WMP und Vitoconnect mitschneidet und mittels vcontrold und ioBroker.viessmann Adapter in den ioBroker bringt zur Weiterverarbeitung.

Die Unterstützten API Datenpunkte kann man im ioBroker schön mittels Objektbaum auslesen. (Meine genutzten von Vitocal 333G)
Bzw. stehen auch Data Points im Viessmann Dev Portal

Bzgl. Node-Red
Der Christoph Krzikalla hat mal im Viessmann Forum und auf seinem Blog eine geile Viessmann API und Node-Red Anleitung gemacht. 👍

Auch ein schöner Weg 😊

@ggrote
Copy link

ggrote commented Aug 31, 2023

Ich bevorzuge halt Cloudfreie Lösungen und habe gerne alles lokal in meinem Netzwerk, daher kommt für mich die Viessmann Api mit Hilfe von Vitoconnect nicht in Frage. Aber danke für den Hinweis mit dem Dev Portal. Muss ich mich mal anmelden, ggf. finde ich dort ein paar Datenpunkte für meinen Vitoligno 300-C Pelletkessel.

Node-Red ist wirklich super und mega vielseitig. Zusammen mit MQTT, Influx und Grafana meiner Meinung nach unschlagbar. Aber jeder wie er mag. ;)

@philippoo66
Copy link

philippoo66 commented Aug 31, 2023

Moin ihr! :-)

@ggrote die Datenpunkte findest du mit aller Wahrscheinlichkeit so wie hier beschrieben https://github.com/philippoo66/ViessData21/blob/master/DataPoints_ReadMe.txt und schau auch noch was dazu unter https://github.com/philippoo66/ViessData21 steht, wie man möglicherweise auch noch an welche kommt, die evtl. nicht in der Liste sind. Dann noch einen Optolink Adapter gebastelt oder gekauft, und du hast die volle Bandbreite Datenpunkte ohne blöde Cloud und Heizung im Internet und ohne teures Vitoconnect.

@ckoeber83 die Lösung deines Anliegens steht doch eigentlich schon oben. bridge.py realisiert ja das, was ich im V Forum beschrieben hatte, und es scheint ja doch nicht zu Timeout zu führen, was ich befürchtet hatte. Und du liest eben nicht (nur) mit, sondern hast eine vollständige 'quasi-parallele' Kommunikation.

beste Grüsse!

@ggrote
Copy link

ggrote commented Aug 31, 2023

@ggrote die Datenpunkte findest du mit aller Wahrscheinlichkeit so wie hier beschrieben https://github.com/philippoo66/ViessData21/blob/master/DataPoints_ReadMe.txt und schau auch noch was dazu unter https://github.com/philippoo66/ViessData21 steht, wie man möglicherweise auch noch an welche kommt, die evtl. nicht in der Liste sind. Dann noch einen Optolink Adapter gebastelt oder gekauft, und du hast die volle Bandbreite Datenpunkte ohne blöde Cloud und Heizung im Internet und ohne teures Vitoconnect.

Wahnsinn! Danke! Hoffe da ist auch was für die Vitoligno 300-C bei.

@philippoo66
Copy link

um die Gerätekennung und ggf. ecnsysDeviceIdent auszulesen brauchst du natürlich schon einen Kommunikationsadapter... hast du einen?

@ggrote
Copy link

ggrote commented Aug 31, 2023

Noch nicht, aber alles für da. Muss quasi nur noch zusammengebaut werden. Dafür fehlt mir bei gefühlt 500 anderen Projekten im und ums Haus aber die Zeit. Trotzdem verfolge ich hier alles.

@ckoeber83
Copy link

ckoeber83 commented Sep 4, 2023

UPDATE!
Mir fehlte das PySerial package für python3!

Installing PySerial package on Linux using PIP
Step 1: Install the latest version of Python3 on Linux Machine using the following command in the terminal:
sudo apt-get install python3

Step 2: Now, using the following command we install the pip module which is required to install and manage all the packages of Python3:
sudo apt install python3-pip

Step 3: Using the following command we install the PySerial package:
sudo pip3 install pyserial

Verifying PySerial package installation on Linux using PIP
python3 -m pip show pyserial


_Hi,

ich kann die vcontrol-vitoconnect-bridge nicht öffnen.
Ich erhalte:

./bridge.py", line 5, in <module>
    import serial
ModuleNotFoundError: No module named 'serial'

Serial devices habe ich aber euf meine entsprechenden angepasst:
usb 1-1.3: cp210x converter now attached to ttyUSB0 > vitoconnect
usb 1-1.4: cp210x converter now attached to ttyUSB1 > Vitotronic 200, Typ WO1C Regelung

## open devices
ser_heating = serial.Serial("/dev/ttyUSB1",
                     baudrate=4800,
                     parity=serial.PARITY_EVEN,
                     stopbits=serial.STOPBITS_TWO,
                     bytesize=serial.EIGHTBITS,
                     timeout=1)
ser_vitoconnect = serial.Serial("/dev/ttyUSB0",
                     baudrate=4800,
                     parity=serial.PARITY_EVEN,
                     stopbits=serial.STOPBITS_TWO,
                     bytesize=serial.EIGHTBITS,
                     timeout=1)

Fehlt mir hier ein Modul in Python?
THX!_

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests