Viessmann VitoConnect API

Begonnen von ritschi, 22 März 2018, 06:53:24

Vorheriges Thema - Nächstes Thema

renardfm

Meinst du die Messwerte?

Ich habe auf dem Handy Packet Capture installiert und das gestartet. Dann 1x die VicareApp benutzt. Dadurch wurde alles protokolliert und ich habe einfach nur den Quelltext durchsucht, bis ich was passendes gefunden habe.

seppe

Ja genau, das scheint mit dem Iphone leider nicht zu funktionieren...

dr_laplace

Hallo,
ich versuche mich mal einzuklinken. Hat jemand schon einmal die neue Viessmann-Api zum laufen bekommen? Ich bekomme beim Auslesen von "code" folgenden Fehler

PHP Notice:  Undefined offset: 0 in /home/ss/Downloads/Viessmann-Api-master/src/Oauth/ViessmannOauthClient.php on line 78
PHP Fatal error:  Uncaught TypeError: Return value of Viessmann\Oauth\ViessmannOauthClient::getCode() must be of the type string, null returned in /home/ss/Downloads/Viessmann-Api-master/src/Oauth/ViessmannOauthClient.php:78


Alternativ hab ich das Skript von den Franzosen ausprobiert.
https://www.jeedom.com/forum/viewtopic.php?f=31&t=31567&start=120#p644178
Hier bekomme ich zwar den "Code" jedoch beim Auslesen des Tokens die Fehlermeldung
{"statusCode":404,"error":"Not Found","message":"Params Validation Error"}

Beim der Anmeldung bei https://iam.viessmann.com/idp/v1/authorize? wird kurz vor der Umleitung das Token anzegeigt. Jedoch kommt dann nur eine Seite mit der Meldung "Permission denied".? Ist das richtig, oder wie sieht das bei euch aus?

https://abload.de/img/viessmannb6e2y.png




renardfm

#48
Ich versuche mal meinen Weg darzustellen - mit dem ich wieder (bis auf die Abgastemperatur und Speicher/ Heizungspumpe) alle Werte zur Verfügung habe.

1. php-Skript bearbeiten (User und Passwort der Vicare-App) eintragen. PHP Skript siehe Anhang. Ist die Basisversion aus dem Jeedom Forum.
2. php-Skript in den fhem-Ordner einfügen (oder copy& paste mit "sudo nano viessmann.php" in eine neue Daten einfügen)
3. viessmann.php ausführbar machen (sudo chmod +x viessmann.php)
4. fhem user zuweisen! (sudo chown fhem viessmann.php)
5. jetzt kann man diese datei mal über Kommandozeile/ssh testweise ausführen "sudo php viessmann.php" ... oder "sudo php /opt/fhem/viessmann.php"
    Man sollte jetzt einige Rückgabewerte bekommen.

Verknüpfung mit FHEM:
1. Dummy anlegen (bei mir Vicare300c, da ich einen Vitoladens300c) habe.
2. mittels at-Befehl in gewünschtem Interval die php-Datei ausführen lassen.
    Hier gab es für mich eine kleine Hürde. Wir brauchen ja die Ausgabe des perl-Skriptes. Diese Strings sollen in einen Dummy geschrieben werden. Damit lässt sich dann weiterarbeiten.
    Der Aufruf der PHP-Datei MIT Rückgabewerte über die Perl-Funktion system() läuft blocking. D.h. FHEM reagiert in der Zeit nicht.. ziemlich blöd.
    die non-blocking qx() funktion liefert aber keinen Rückgabewert, bzw. der steht dann nur im FHEM-Logfile, und da habe ich es nicht extrahieren können.
    Die Lösung ist mittels fhem-Funktion "systemCommand". Man muss das Modul noch in myUtils.pm kopieren.
    Damit habe ich dann also in fhem erstellt:
            define fetchVicare at +*00:02:00 {systemCommand('/opt/fhem/viessmann.php','Vicare300c rawData')}
    Die Rückgabewerte der php-Datei werden in das Reading "rawData" des Dummys "Vicare300x" geschrieben. Das ergibt dann so einen Inhalt:
rawData
Installation=xxx\Gateway=xxx\Aussentemperatur=15.3\Kesseltemperatur=57\supply_temperatur=57\room_temperatur=20\Solltemperatur_normal=22\Solltemperatur_reduziert=17\Speicher-Solltemperatur=58\Speicher-Isttemperatur=57.8\Betriebsart=dhw\Brennerzustand=ok\ErrorCode=0\Programmstatus=standby\Heizkurve_Niveau=4\Heizkurve_Steigung=1.4\Brenner=0\

3. Damit man einzelne Readings bekommt muss man das Attribut userReadings mit z.B. folgendem Inhalt anlegen
vicare_aussentemperatur {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Aussentemperatur=(\d+\.\d)/; return $1}, vicare_Kesseltemperatur {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Kesseltemperatur=(\d+\.?\d?)/; return $1}, vicare_Speicher-Isttemperatur {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Speicher-Isttemperatur=(\d+\.?\d?)/; return $1}, vicare_Speicher-Solltemperatur {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Speicher-Solltemperatur=(\d+\.?\d?)/; return $1}, vicare_Programmstatus {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Programmstatus=(normal|standby|reduced)/; return $1}, state {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Programmstatus=(normal|standby)/; return $1}, vicare_Solltemperatur-normal {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Solltemperatur_normal=(\d+\.?\d?)/; return $1}, vicare_Betriebsart {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Betriebsart=(dhw|forcedReduced|forcedNormal|dhwAndHeating)/; return $1}, vicare_Heizkurve_Niveau {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Heizkurve_Niveau=(\d+)/; return $1}, vicare_Heizkurve_Steigung {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Heizkurve_Steigung=(\d+\.\d)/; return $1}, Speichertemperatur_gerundet {sprintf("%.0f",ReadingsVal("Vicare300c","vicare_Speicher-Isttemperatur",0))}, vicare_Brenner {my $v= ReadingsVal("Vicare300c","rawData","0"); $v=~ /Brenner=(\d+)/; return $1}
4. Jetzt noch das Attribut stateFormat setzen mit Inhalt:
Speicher: vicare_Speicher-Isttemperatur °C,
Status: vicare_Programmstatus,
Flamme: vicare_Brenner


... jetzt lassen sich auch wieder schöne DOIFs und Plots generieren...

demnächst schreibe ich noch etwas zu den bash-Skripten, mit denen man die verschiedenen Modi und Temperaturen der Heizung mittels FHEM steuern kann.
Ich möchte damit versuchsweise meine Heizkurve selbständig adaptieren lassen, da man diese auch auslesen und verändern kann. Es ist ja quasi über Soll-Ist Temperatur-Deltas und Aktorpositionen erfassbar, ob die Vorlauftemperatur ausreicht oder zu gering/hoch ist. In Kombination mit der Aussentemperatur kann der Algorithmus dann entscheiden, ob Niveau, Steigung oder beides angepasst wird. Weiterhin soll die Wettervorhersage und Abwesenheit berücksichtigt werden...


btw. client-ID und client-Secret ist wohl immer gleich (das ließ sich über mitm-Attack rausfinden. Ich konnte es nicht nachvollziehen, musste die Werte aber auch nicht ändern.) Es reicht im php-Skript User und Passwort am Anfang zwischen die '' zu ergänzen.


edit: ich finde den Foren-Eintrag zur systemCommand Funktion nicht mehr , die man in die myUtils.pm kopieren muss.
    Hier der Auszug. Das stammt nicht von mir!!
sub systemCommand($;$) {

    my ($command, $reading) = @_;
$command = encode_base64($command,"");
$reading //= 0;
$reading = encode_base64($reading,"");
$command .= "|".$reading;
    my $hash = $defs{$command};
   
    Log3 "SystemCommand", 4, "Sub systemCommand - START: $command";   
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
    $hash->{helper}{RUNNING_PID} = BlockingCall("systemCommand_Run", $command, "systemCommand_Done", 60, "systemCommand_Aborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
    Log3 "SystemCommand", 4, "Sub systemCommand - START BLOCKING CALL - $command";
}

sub systemCommand_Run($) {

    my ($string) = @_;
    my ( $command, $reading ) = split("\\|", $string);
    my $result;
   
    Log3 "SystemCommand", 4, "Sub systemCommand - BEGIN SystemCommand: $command";
my $cmd = decode_base64($command);
$result = qx($cmd);
Log3 "SystemCommand", 4, "Sub systemCommand - END SystemCommand: $command, Result: $result";   
    if (!$result) {
$result = 0;
}
    $result = encode_base64($result,"");
    return "$command|$reading|$result";
}

sub systemCommand_Done($) {

    my ($string) = @_;
    my @a = split("\\|",$string);
    my $hash = $defs{$a[0]};
    my $name = $hash->{NAME};
    my $reading = $a[1];
my $result = $a[2];   
   
    delete($hash->{helper}{RUNNING_PID});
   
    Log3 "SystemCommand", 3, "Sub systemCommand_Done - $name) - Der Helper ist disabled. Daher wird hier abgebrochen" if($hash->{helper}{DISABLED});
    return if($hash->{helper}{DISABLED});
   
    $reading = decode_base64($reading);
if ($reading) {
if ((split(" ",$reading)) == 2 && $defs{(split(" ",$reading))[0]}) {
$result = decode_base64($result);
# add slashes at the end of lines for valid multiline readings
$result =~ s/\n/\\/g;
# $result =~ /(Sender:\s)(\+\d*)\s/;
fhem "setreading " . (split("\\|",$reading))[0] . " " . (split("\\|",$reading))[1] . " " . $result;
Log3 "SystemCommand", 4, "Sub systemCommand_Done - Result: $result, Reading: $reading";
} else {
Log3 "SystemCommand", 3, "Sub systemCommand_Done ERROR - device reading '$reading' not valid or device does not exist. Use setreading syntax like 'Device MyReading'";
}
} elsif ($result) {
Log3 "SystemCommand", 4, "Sub systemCommand_Done INFO - existing system command result has been ignored because you did not specify a device reading.";
}
       
}

sub systemCommand_Aborted($) {

    my ($hash) = @_;
    my $name = $hash->{NAME};

    delete($hash->{helper}{RUNNING_PID});
    Log3 "SystemCommand", 3, "Sub systemCommand_Aborted - $name - The BlockingCall Process terminated unexpectedly. Timedout.";
}


dr_laplace

Das PHP Script hat super funktioniert. Danke. TOP :)

ritschi

@renardfm Kurz und bündig: TOP Leistung!!!  8)

ritschi

Zitat von: renardfm am 15 September 2018, 22:38:57
demnächst schreibe ich noch etwas zu den bash-Skripten, mit denen man die verschiedenen Modi und Temperaturen der Heizung mittels FHEM steuern kann.


Ich habe mich mal an Hand der Informationen aus dem französischen Forum an den Bash Scripten probiert und ich muss sagen, dass wechseln der Modi an Hand von Anwesenheit oder Temperatur funktioniert wunderbar.

Dieses Script setzt die Heizung auf Heizen und Warmwasser (Vitodens 300) (mode:dhwAndHeating) (Warmwasser mode:dhw)
isiwebuserid & isiwebpasswd muss eingetragen werden, sowie in der unteren URL <ID> und <GATEWAY> (ID und GATEWAY findet man durch renardfm Beitrag heraus) 
#!/bin/bash
export CLIENTID=79742319e39245de5f91d15ff4cac2a8
export CLIENTSECRET=8ad97aceb92c5892e102b093c7c083fa
export TOKEN_EP=https://iam.viessmann.com/idp/v1/token
export AUTHZ_EP=https://iam.viessmann.com/idp/v1/authorize
export SCOPE=openid
export REDIRECTURI=vicare://oauth-callback/everest
export isiwebuserid=<BENUTZER>
export isiwebpasswd=<PASSWORT>
CODE=`curl -s -k --user "$isiwebuserid:$isiwebpasswd" "$AUTHZ_EP?client_id=$CLIENTID&scope=$SCOPE&redirect_uri=$REDIRECTURI&response_type=code"| grep -Eio 'code=(.)*"'|  cut -c"6-" | sed 's/.$//'`
#echo "CODE=$CODE"
TOKEN=`curl -s -k --user "$CLIENTID:$CLIENTSECRET" -d "code=$CODE&grant_type=authorization_code&client_id=$CLIENTID&redirect_uri=$REDIRECTURI" $TOKEN_EP | sed 's/{"access_token":"//' | sed 's/".*//'`
#REP_STATUS=`curl -k -H "AUTHORIZATION: Bearer $TOKEN" "https://api.viessmann-platform.io/operational-data/installations/votre_numero/gateways/votre_numero/devices/0/features/heating.circuits.0.operating.modes.active?expanded=false&"`
#echo "$REP_STATUS"
REP=`curl -X POST  https://api.viessmann-platform.io/operational-data/installations/<ID>/gateways/<GATEWAY>/devices/0/features/heating.circuits.0.operating.modes.active/setMode -S -s -H "Content-Type: application/json" -H "AUTHORIZATION: Bearer $TOKEN" -d '{"mode":"dhwAndHeating"}'`
echo "$REP"

CoolTux

Zitat von: renardfm am 15 September 2018, 22:38:57
edit: ich finde den Foren-Eintrag zur systemCommand Funktion nicht mehr , die man in die myUtils.pm kopieren muss.
    Hier der Auszug. Das stammt nicht von mir!!
sub systemCommand($;$) {

    my ($command, $reading) = @_;
$command = encode_base64($command,"");
$reading //= 0;
$reading = encode_base64($reading,"");
$command .= "|".$reading;
    my $hash = $defs{$command};
   
    Log3 "SystemCommand", 4, "Sub systemCommand - START: $command";   
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
    $hash->{helper}{RUNNING_PID} = BlockingCall("systemCommand_Run", $command, "systemCommand_Done", 60, "systemCommand_Aborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
    Log3 "SystemCommand", 4, "Sub systemCommand - START BLOCKING CALL - $command";
}

sub systemCommand_Run($) {

    my ($string) = @_;
    my ( $command, $reading ) = split("\\|", $string);
    my $result;
   
    Log3 "SystemCommand", 4, "Sub systemCommand - BEGIN SystemCommand: $command";
my $cmd = decode_base64($command);
$result = qx($cmd);
Log3 "SystemCommand", 4, "Sub systemCommand - END SystemCommand: $command, Result: $result";   
    if (!$result) {
$result = 0;
}
    $result = encode_base64($result,"");
    return "$command|$reading|$result";
}

sub systemCommand_Done($) {

    my ($string) = @_;
    my @a = split("\\|",$string);
    my $hash = $defs{$a[0]};
    my $name = $hash->{NAME};
    my $reading = $a[1];
my $result = $a[2];   
   
    delete($hash->{helper}{RUNNING_PID});
   
    Log3 "SystemCommand", 3, "Sub systemCommand_Done - $name) - Der Helper ist disabled. Daher wird hier abgebrochen" if($hash->{helper}{DISABLED});
    return if($hash->{helper}{DISABLED});
   
    $reading = decode_base64($reading);
if ($reading) {
if ((split(" ",$reading)) == 2 && $defs{(split(" ",$reading))[0]}) {
$result = decode_base64($result);
# add slashes at the end of lines for valid multiline readings
$result =~ s/\n/\\/g;
# $result =~ /(Sender:\s)(\+\d*)\s/;
fhem "setreading " . (split("\\|",$reading))[0] . " " . (split("\\|",$reading))[1] . " " . $result;
Log3 "SystemCommand", 4, "Sub systemCommand_Done - Result: $result, Reading: $reading";
} else {
Log3 "SystemCommand", 3, "Sub systemCommand_Done ERROR - device reading '$reading' not valid or device does not exist. Use setreading syntax like 'Device MyReading'";
}
} elsif ($result) {
Log3 "SystemCommand", 4, "Sub systemCommand_Done INFO - existing system command result has been ignored because you did not specify a device reading.";
}
       
}

sub systemCommand_Aborted($) {

    my ($hash) = @_;
    my $name = $hash->{NAME};

    delete($hash->{helper}{RUNNING_PID});
    Log3 "SystemCommand", 3, "Sub systemCommand_Aborted - $name - The BlockingCall Process terminated unexpectedly. Timedout.";
}


Hier ist das Original zu finden.
https://forum.fhem.de/index.php/topic,28753.msg501336.html#msg501336
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

thetrueavatar

#53
Hello, I'm the developer of the viessmann-api on https://github.com/thetrueavatar/Viessmann-API. I don't speak german but can write in english.
I have been developing the api for 2 week and now it's quite ok I guess.
The usage is quite simple. The api is package as a phar(php archive). You only need to download the release on https://github.com/thetrueavatar/Viessmann-Api/releases to use it in your php file by including it with the line:
include 'phar://'.__DIR__.'/Viessmann-Api-0.3-SNAPSHOT.phar/index.php'; The main object to use is ViessmannAPI that you can use with a
use Viessmann\API\ViessmannAPI; However, to ease the use of my api, I have done a couple of example in the example directory. In this directory the bootstrap.php does everything to instanciate the api. It use a credentials.properties file to get the viessmann credentials. So in practice you need to put the phar, the bootstrap.php and the credentials.properties in the same directory. THen fill in your credentials in the credentials.properties Then create your php file like this for instance:
<?php include __DIR__.'/bootstrap.php'
echo 
"Boiler temperature " $viessmannApi->getBoilerTemperature();
and voila this is it you get the boiler temperature. I have implemented generic method to get and set data but you'll receive and fill in json. I'm trying to implement easier method such as getBoilerTemperature() to hide the complexity of the json. Feel free to contact me through the github. Any pull request is appreciate too. Hope this help.

​​​​​​​I have tried to give so more documentation on the wiki page: https://github.com/thetrueavatar/Viessmann-Api/wiki

Frini

#54
Zitat von: renardfm am 15 September 2018, 22:38:57
Ich versuche mal meinen Weg darzustellen - mit dem ich wieder (bis auf die Abgastemperatur und Speicher/ Heizungspumpe) alle Werte zur Verfügung habe.

1. php-Skript bearbeiten (User und Passwort der Vicare-App) eintragen. PHP Skript siehe Anhang. Ist die Basisversion aus dem Jeedom Forum.
2. php-Skript in den fhem-Ordner einfügen (oder copy& paste mit "sudo nano viessmann.php" in eine neue Daten einfügen)
3. viessmann.php ausführbar machen (sudo chmod +x viessmann.php)
4. fhem user zuweisen! (sudo chown fhem viessmann.php)
5. jetzt kann man diese datei mal über Kommandozeile/ssh testweise ausführen "sudo php viessmann.php" ... oder "sudo php /opt/fhem/viessmann.php"
    Man sollte jetzt einige Rückgabewerte bekommen.


Ich hänge bei Punkt 5.
Ich habe mit sudo apt install php-curl nachinstalliert und auch neugestartet
Er installiert auch alles. Allerdings kann ich den Befehl sudo php viessmann.php nicht ausführen. Er erkennt den Command php nicht. Woran kann das liegen?

Edit:
Ein weitere Frage.
Ich habe in Deiner PHP Datei meine Anmeldenamen und mein Passwort eingetragen. Reicht das?
Ich habe ebenfalls versucht über Packet Capture die Daten der ViCare zu tracken, allerding meldet die App sobald ich diese starte, dass die Verbindung zum Server nicht gefunden wird und es kommen keine Daten an.  ???

Ich konnte den Fehler weiter eindämmen. In der ersten Zeile in viessmann.php steht usr/bin/php. Dieser Ordner wird bei mir gar nicht erstellt. Wo speichere ich denn die viessmann.php und was muss ich da reinschreiben?

onkeloki

cool hat auf anhieb funktioniert..
wie sieht es mit "brennerstarts" aus .. und es müsste doch auch funktionieren die werte zu setzen.. also "modus wechseln" usw?

Frini

Also ich habe es jetzt eine Stunde versucht. Mittagspause ist zu Ende.
Bei mir hängt es denke ich an php-Ausführung. Ich habe nun das aktuellste Stretch- auf meinem Raspberry laufen und mehrfach php installiert und deinstalliert. Das Verzeichnis
/usr/bin/php 
wird nicht angelegt. Allerdings erhalte ich mit der Abfrage
which php
genau den genannten Ordner.

Das aktuelle PHP ist bei in Version 7.0. und nicht wie verlinkt 5.6. Kann das daran liegen?

onkeloki

Zitat von: Frini am 25 September 2018, 14:16:59
Also ich habe es jetzt eine Stunde versucht. Mittagspause ist zu Ende.
Bei mir hängt es denke ich an php-Ausführung. Ich habe nun das aktuellste Stretch- auf meinem Raspberry laufen und mehrfach php installiert und deinstalliert. Das Verzeichnis
/usr/bin/php 
wird nicht angelegt. Allerdings erhalte ich mit der Abfrage
which php
genau den genannten Ordner.

Das aktuelle PHP ist bei in Version 7.0. und nicht wie verlinkt 5.6. Kann das daran liegen?

probiere:
php -f pfad/zur/datei.php

ich habe mit mittlweriwele dies angeguckt:
https://github.com/thetrueavatar/Viessmann-Api/tree/master
in den examples sind auch "set" methoden.. ich verusche gerade mal etwas wie "setnormal mode" und "set away mode" nach zu bauen

Frini


onkeloki

Zitat von: Frini am 25 September 2018, 15:03:28
Nein klappt leider nicht.


erstelle eine neue datei mit dem ihnalt
<?php echo "hallo welt"?>
speichere sie als test.php

und führe im terminal folgendes aus

php -f test.php

wie ist die ausgabe?

und was sagt
php -v