Bosch Junkers Control CT100

Begonnen von Mike_GKA, 21 Juli 2017, 11:10:45

Vorheriges Thema - Nächstes Thema

Mike_GKA

Hi,
Dieser Fehler taucht bei mir auch immer wieder auf, wobei der Timeout ein Folgefehler sein muss. Ursprünglich hatte ich angenommen, dass dieser Fehler "nur" bei mir auftaucht, da ich einiges an meinem Raspberry "herumgeschraubt" hatte.
Ich habe den Log von nefit durchforstet. Er steht bei mir unter /root/.pm2/logs/start-nefit-easy-http-server-out-1.log. Den Pfad bekommt man heraus über:

sudo pm2 show start_nefit-easy-http-server

Hier finde ich dann als Ursache "Error: MAX_RETRIES_REACHED"
Dieser Fehler wurde auch schon an Robert Klep gemeldet: https://github.com/robertklep/nefit-easy-http-server/issues/15
Der letzte Eintrag: 11.6.18: "I'm still working on trying to find a fix."

Den Zusammenhang mit "Zwangstrennung" bzw. "Neuverbindung" habe ich nicht erkannt. Aber da scheint was dran zu sein. In meinem Logfile (2 MB) finde ich lediglich 3 Ausnahmen, wobei ich nicht analysieren kann, ob da wegen Provider Störungen nicht auch eine Neuverbindung stattfand.

Als recht unsaubere Umgehungslösung habe ich jetzt folgendes gemacht:
Ich habe ein Skript angelegt mit:


#!/bin/bash
sudo pm2 stop start_nefit-easy-http-server
sudo pm2 start start_nefit-easy-http-server


Und starte dieses per Cron stündlich.

Ich hoffe, Robert Klep findet bald eine Lösung.
Es gibt wohl die Vermutung, dass dieser Fehler mit einem anderen Problem zusammenhängt: https://github.com/robertklep/nefit-easy-core/issues/14
Und hier gibt es Hoffnung.
Robert Klep Gestern: Let's keep it running for a day or so, if no other issues emerge I'm going to declare this a win (at least for you and me) and push a new version :D


SouzA

Moin!
Mit Antworten bist du ja immer schnell... ;D ;)
Auf der Github-Seite habe ich mittlerweile auch die Aussage gefunden, dass er an etwas bastelt. Wir warten...

Frage zu
Zitat von: Mike_GKA am 21 Juni 2018, 11:22:24
Als recht unsaubere Umgehungslösung habe ich jetzt folgendes gemacht:
Ich habe ein Skript angelegt mit:


#!/bin/bash
sudo pm2 stop start_nefit-easy-http-server
sudo pm2 start start_nefit-easy-http-server


Und starte dieses per Cron stündlich.

Kann man dieses Script nicht starten und stoppen, wenn im Log die Fehlermeldungen auftauchen?
So etwa:

define di_nefit_restart DOIF
dev:
([":^Read callback: Error: read from http://127.0.0.1:80 timed out"])
({system(STOP);;return 0})
({system(START);;return 0})
attr wait 0,30
attr do always


Wobei ich nicht weiß, wie in einem DOIF die Ausführungen heißen müssen?!
Weißt du das?

Bis denn
SouzA
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

Mike_GKA

Hi,

gute Idee, aber so richtig kenne ich mich an dieser Ecke auch nicht aus.
Meiner Meinung müsste es wie folgt heißen:
({system(sudo <Pfad-Name zum Restart-Skript>);;return 0})
und ein "else" braucht man nicht.

Funktioniert das mit "([":^Read callback: Error: read from http://127.0.0.1:80 timed out"])", ist mir nämlich auch unbekannt.

Folgende Alternative ist vielleicht einfacher. Man erweitert das Skript zum Restart.
Folgendes kann vielleicht funktionieren:

#!/bin/bash
if curl http://127.0.0.1:3000/api/status | grep -q "timeout"
then
sudo pm2 stop start_nefit-easy-http-server
sudo pm2 start start_nefit-easy-http-server
fi


Ich habe das jetzt nicht ausprobiert!

SouzA

Zitat von: Mike_GKA am 21 Juni 2018, 14:28:41
Funktioniert das mit "([":^Read callback: Error: read from http://127.0.0.1:80 timed out"])", ist mir nämlich auch unbekannt.

Aus der commandref von DOIF:
([":^temp"]) triggert auf beliebige Devices, die im Event mit "temp" beginnen

ich denke schon.
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

Mike_GKA


Automatischer Restart nefit-easy


Das war gar nicht so leicht, wie zuerst angenommen.
Wenn man auf die Fehlermeldung von netfit-easy triggert und ein Restart macht, dann kommt es in aller Regel vor, dass dieser Restart ein zweites und evtl. noch weitere Male ausgelöst wird, bevor der erste Restart ordnungsgemäß beendet wurde. Das muss man vermeiden.
Ich habe deshalb ein Skript geschrieben, das überprüft ob es bereits läuft.
Um etwas Übersicht zu haben, habe ich unter /home/pi ein Subdirectory angelegt: /home/pi/Progs.
Dort habe ich das Skript "php_shell.sh" angelegt mit dem Inhalt

#!/bin/bash

lockdir=/home/pi/Progs/LogDirToAvoidProcessStartWhenAlreadyRunning
mkdir $lockdir  || {
sudo date >> /home/pi/Progs/restart_nefit.log
sudo echo "Process already running" >> /home/pi/Progs/restart_nefit.log
sudo echo ------------------- >> /home/pi/Progs/restart_nefit.log
exit 1
}

# take pains to remove lock directory when script terminates
trap "rmdir $lockdir" EXIT INT KILL TERM


sudo date >> /home/pi/Progs/restart_nefit.log
sudo echo Restart nefit-easy-http-server >> /home/pi/Progs/restart_nefit.log

sudo pm2 stop start_nefit-easy-http-server
sudo pm2 start start_nefit-easy-http-server

sleep 10

sudo echo Restart finished >> /home/pi/Progs/restart_nefit.log
sudo date >> /home/pi/Progs/restart_nefit.log
sudo echo ------------------- >> /home/pi/Progs/restart_nefit.log


Der Name "php_shell.sh" mag hier etwas irritieren (man kann es ja auch anders nennen), aber ich selbst verwende das ausschließlich aus php heraus (s.u.).

Jetzt sollte man aus fhem heraus dieses Skript im Fehlerfall aufrufen:

{system(sudo /home/pi/Progs/php_shell.sh);;return 0}

Dies habe ich nicht ausprobiert, da ich das Skript anderweitig verwende.
Die Logdatei findet man unter /home/pi/Progs/restart_nefit.log.

Ich rufe nefit-easy auch aus anderen Anwendungen heraus auf. Dazu habe ich eine kleine php-Anwendung, die alle Aufrufe kapselt. In dieser php-Anwendung prüfe ich jetzt ob das Ergebnis von nefit-easy korrekt ist, bzw, ob ein Fehler gemeldet wurde. Im Falle eines Fehlers rufe ich obiges Skript auf.
ABER, aus php heraus kann man i.A. kein "sudo" machen. Das wäre ja sicherheitstechnisch irgendwo worstcase. Deshalb habe ich einen kleinen Wrapper geschrieben, der sich root Rechte holt und damit das Skript ausführt.

Das ist dann ein kleines C-Programm (wrapper.c), das ich auch auf /home/pi/Progs anlege:


#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int
main (int argc, char **argv)
{
setuid (0);
if (argc == 2) {
char str[255];
strcpy(str, "/bin/sh /home/pi/Progs/");
strcat(str , argv[1]);
system (str);
} else {
system ("/bin/sh /home/pi/Progs/php_shell.sh");
}

return 0;
}


Das muss man dann natürlich übersetzen und die Eigenschaften entsprechend setzen.

gcc wrapper.c -o php_root
sudo chown root php_root
sudo chmod u=rwx,go=xr,+s php_root


Das aufrufbare Programm heißt jetzt also: /home/pi/Progs/php_root

Die kleine php-Anwendung, die alle Aufrufe kapselt, heißt bei mir nefit.php und steht natürlich im www-Verzeichnis (/var/www/html)

<?php

$basicurl "http://127.0.0.1:3000";
$defaultapicall "/api/status";

$_GET_lower array_change_key_case($_GETCASE_LOWER);
$apicall $_GET_lower['api'] ;
if(empty($apicall)) {
$apicall $defaultapicall;


$data file_get_contents($basicurl $apicall);


$pos strpos($data '{"'); //check if the result is possible a json-string
if ($pos === false) {
     exec('/home/pi/Progs/php_root'); //result cannot be a json, restart nefit-easy

else {
if ($pos != 0) {
     exec('/home/pi/Progs/php_root'); //result cannot be a json, restart nefit-easy
}
}

ob_end_clean();
header("Connection: close\r\n");
header('Content-Type: application/json');
ob_start();
Echo $data;
$size ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();

?>



Mittels file_get_contents wird also nefit-easy abgefragt. Das Ergebnis wird analysiert. Wenn es nicht korrekt als JSON aufgebaut ist, gehe ich von einem Fehler aus und starte nefit-easy neu exec('/home/pi/Progs/php_root')
Im korrekten Fall wird einfach das Ergebnis weitergereicht.

nefit.php versteht einen Parameter "api" in der URL. Damit wird gezielt der api-Aufruf von nefit-easy gesteuert.
Also z.B.:
http://127.0.0.1/nefit.php?api=/api/status
http://127.0.0.1/nefit.php?api=/bridge/heatingCircuits/hc1/actualSupplyTemperature
usw.

Für fhem habe ich eine php-Anwendung (heizung.php), die viele Werte aus nefit-easy abfragt und als JSON an fhem gibt:

<?php

$basicurl "http://127.0.0.1/nefit.php";
$result = array();

$json json_decode(file_get_contents($basicurl "?api=/api/status"), true);
$result['t_inhouse'] = $json['in house temp'];
$result['t_setpoint'] = $json['temp setpoint'];
$result['t_outdoor'] = $json['outdoor temp'];
if ($json['boiler indicator'] == "off") {
$result['boiler'] = 0;
} else {
$result['boiler'] = 1;
}

$json json_decode(file_get_contents($basicurl "?api=/api/pressure"), true);
$result['pressure'] = $json['pressure'];

$json json_decode(file_get_contents($basicurl "?api=/bridge/ecus/rrc/recordings/yearTotal"), true);
$result['yearTotal'] = $json['value'];

$json json_decode(file_get_contents($basicurl "?api=/bridge/heatingCircuits/hc1/actualSupplyTemperature"), true);
$result['actualSupplyTemperature'] = $json['value'];

header('Content-Type: application/json');
Echo json_encode($result);
?>



Dies hole ich mit HTTPMOD in fhem ab und parse die JSON Felder.

defmod heizung HTTPMOD http://127.0.0.1/heizung.php 300
attr heizung userattr reading01JSON reading01Name reading02JSON reading02Name reading03JSON reading03Name reading04JSON reading04Name reading05JSON reading05Name reading06JSON reading06Name reading07JSON reading07Name
attr heizung enableControlSet 1
attr heizung reading01JSON t_inhouse
attr heizung reading01Name t_inhouse
attr heizung reading02JSON t_setpoint
attr heizung reading02Name t_setpoint
attr heizung reading03JSON t_outdoor
attr heizung reading03Name t_outdoor
attr heizung reading04JSON boiler
attr heizung reading04Name boiler
attr heizung reading05JSON pressure
attr heizung reading05Name pressure
attr heizung reading06JSON yearTotal
attr heizung reading06Name yearTotal
attr heizung reading07JSON actualSupplyTemperature
attr heizung reading07Name actualSupplyTemperature


Dies läuft jetzt bei mir seit 3 Tagen fehlerfrei.

SouzA

#35
Hi,
Da hat aber jemand gebastelt. Respekt dafür.

Ich musste das für mich einfacher Regeln.
Ich hatte beobachtet, dass die Readings aus dem JSON nicht mehr aktualisiert werden, wenn der nefit weg ist. Auch die Zeitstempel werden nicht mehr aktualisiert.

define restart_nefit-easy-http-server DOIF
(
[Therme:actualSupplyTemperature]
)
({system('sudo pm2 restart /home/pi/start_nefit-easy-http-server.sh');;return 0})

attr do resetwait
attr wait 950


Wenn jetzt innerhalb 950 Sekunden das Reading aktualisiert wird, dann wird das Wait zurück gesetzt und beginnt von vorne.

Btw. Das funktioniert dann natürlich nur mit pm2. Dementsprechend ist mein Startscript aus dem rc.local geflogen und wird jetzt von pm2 gestartet und gestopt.
Ja, ich hab pm2 doch noch installiert bekommen... ;)

Bis denn
SouzA

Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

Mike_GKA

echt raffiniert und um Längen einfacher als meine Lösung.
Ich musste erst im fhem-wiki nachlesen, wie das funktioniert: resetwait und wait kannte ich bei DOIF noch gar nicht.

Leider löst das bei mir aber "nur" gut 90 % der Probleme, da ich nefit-easy auch aus nicht-fhem-Applikaitonen vielfach nutze.

SouzA

Naja, eben. Hatte schon erkannt, dass deine Ausarbeitung für größeres bestimmt ist.
Nur deshalb habe ich die vereinfachte Version hier gebracht, falls jemand den Nefit, so wie ich, nur aus fhem benutzt.

Bis denn
SouzA
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

SouzA

#38
Hi, ich hätte da gerne mal wieder ein Problem...

Hab nach einer kleinen Havarie den Raspi neu aufgesetzt.
Was ich mir damals nicht notiert hatte war, dass ich dem User fhem Root-Rechte verpasst hatte. Is soweit auch nicht schlimm, wenn der Pi nicht von außen erreichbar ist. Allerdings hat sich bei mir die Nutzung der Sprachsteuerung eingeschlichen und der pi ist von außen erreichbar.
Dementsprechend will ich dem User fhem nicht alle Rechte zusprechen.
Allerdings nun die Frage, wie kann ich pm2 jetzt den restart-Befehl geben?

Hat da jemand einen Tipp?

Vielen Dank
Bis denn
SouzA

EDIT: Gelöst!
Meine Doku enthält nun folgendes:
ZitatUm ein Restart des nefit-servers durchführen zu können und zusätzlich den User fhem keine root-Rechte verpassen zu müssen erstellen wir ein zusätzliches script:
→ sudo nano /home/pi/restart_nefit.sh
Dieses script mit
#!/bin/sh
sudo pm2 restart /home/pi/start_nefit-easy-http-server.sh
füllen.
Um dem User fhem die Rechte zum ausführen zu geben, bearbeiten wir die sudoers Datei:
   → sudo nano /etc/sudoers
Am Ende folgende Zeile anfügen:
   → fhem ALL=NOPASSWD: /home/pi/restart_nefit.sh, /home/pi/next.sh
Damit hat fhem die root-Rechte nur zum ausführen des Scripts.
Raspi 4, EnOcean TCM310 USB, HM-MOD-UART-USB, Jeelink, hue, AMAD, fully, FRITZBOX, Signalbot, VIERA, Presence BT/Mac, TPLink, Gassistant, Shelly, fhempy, ZigBee

Mike_GKA

Das ist ja das gleiche Problem wie ich mit dem Aufruf aus php hatte.
In https://forum.fhem.de/index.php?topic=74483.msg814386#msg814386 ist das ja beschrieben.

Hier der wesentliche Auszug:
Deshalb habe ich einen kleinen Wrapper geschrieben, der sich root Rechte holt und damit das Skript ausführt.

Das ist dann ein kleines C-Programm (wrapper.c), das ich auch auf /home/pi/Progs anlege:


#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int
main (int argc, char **argv)
{
setuid (0);
if (argc == 2) {
char str[255];
strcpy(str, "/bin/sh /home/pi/Progs/");
strcat(str , argv[1]);
system (str);
} else {
system ("/bin/sh /home/pi/Progs/php_shell.sh");
}

return 0;
}


Das muss man dann natürlich übersetzen und die Eigenschaften entsprechend setzen.

gcc wrapper.c -o php_root
sudo chown root php_root
sudo chmod u=rwx,go=xr,+s php_root


Das aufrufbare Programm heißt jetzt also: /home/pi/Progs/php_root

php_root besorgt sich jetzt die root-Rechte (sudo) und führt damit das Skript aus.

Die Namen php_root und php_shell.sh sind jetzt in Deinem Kontext natürlich nicht besonders sinnvoll, und solltest Du bei Bedarf entsprechend anpassen.

Übrigens: Es gibt ein Update vom nefit-easy, das das ursächliche Problem beseitigen sollte.
Ich habe bei mir letzte Woche dieses Update eingespielt. Allerdings taucht das Problem weiterhin auf, wenn auch wesentlich seltener und im Kontext etwas anders. Ich habe aber den Eindruck, dass das schlicht und einfach daran liegt, dass Server temporär immer mal wieder überhaupt nicht erreichbar ist. Da kann man dann softwaremäßig eh nichts mehr machen.

grappa24

#40
hat schon mal jemand von Euch ein CT200 mit dem netfit-easy-server angesprochen?

Ich kann zwar meine Heizung via CT200 und der Bosch EasyControl app (Android) steuern, bekomme aber keinen Zugriff via netfit-easy-server (XMPP authentication failure).
FHEM 6.1, 2 x RasPi 3B+, Debian Buster; KNX, FS20, HM, HUE, Tradfri, Shellies, KLF200
Rollo-/Lichtsteuerung/-szenarien, T-Sensoren, Fensterkontakte, Heizungssteuerung, HEOS, Sprachsteuerung mit Alexa-FHEM, Netatmo, Nuki, ...

Mike_GKA

Dieses Problem wurde auch schon an Robert Klep gemeldet: https://github.com/robertklep/nefit-easy-http-server/issues/30
Aber Robert Klep hat keinen Zugriff auf eine CT200, d.h. ich befürchte, da wird es so schnell keine Lösung geben.
Auch ich habe keine CT200, kann also reineweg nichts machen, sorry.
Wie es scheint wurde die Authentifizierung geändert.
Da Bosch das nicht transparent macht und alles verschlüsselt abläuft, ist es sehr schwer bis unmöglich, das zu "knacken". Da müsste man mit "man in the middle attack" ran, und das wäre eh nichts für meine eher bescheidenen Fähigkeiten.

grappa24

Danke Mike, dann kann ich mich ja jetzt entspannen  ;)  ... und ggf abwarten  :(
FHEM 6.1, 2 x RasPi 3B+, Debian Buster; KNX, FS20, HM, HUE, Tradfri, Shellies, KLF200
Rollo-/Lichtsteuerung/-szenarien, T-Sensoren, Fensterkontakte, Heizungssteuerung, HEOS, Sprachsteuerung mit Alexa-FHEM, Netatmo, Nuki, ...

grappa24

"Wenn der Berg nicht zum Propheten kommt .... "   ;)

Ich hab mir jetzt einen gebrauchten CT100 zum Testen bestellt, brauche den ganzen Schnickschnack des CT200 eh nicht ...  8)
(keine Anwesenheitserkennung, kein Näherungssensor, keine Thermostatsteuerung, ...) Hauptsache FHEM-Anbindung
FHEM 6.1, 2 x RasPi 3B+, Debian Buster; KNX, FS20, HM, HUE, Tradfri, Shellies, KLF200
Rollo-/Lichtsteuerung/-szenarien, T-Sensoren, Fensterkontakte, Heizungssteuerung, HEOS, Sprachsteuerung mit Alexa-FHEM, Netatmo, Nuki, ...

grappa24

CT100 angekommen, funktioniert perfekt wie hier beschrieben mit dem netfit-easy-server. Würde ihn aber gern wieder verkaufen, da ich auf CW400/MB LAN2/Heatronic-Modul umsteigen werde. Bei Interesse gerne PN.


FHEM 6.1, 2 x RasPi 3B+, Debian Buster; KNX, FS20, HM, HUE, Tradfri, Shellies, KLF200
Rollo-/Lichtsteuerung/-szenarien, T-Sensoren, Fensterkontakte, Heizungssteuerung, HEOS, Sprachsteuerung mit Alexa-FHEM, Netatmo, Nuki, ...