FHEM2FHEM und RFHEM zusammenführen

Begonnen von Adimarantis, 06 September 2021, 15:43:22

Vorheriges Thema - Nächstes Thema

Adimarantis

Hallo,

ich hatte mit dem Gedanken gespielt die Maintenance von RFHEM zu übernehmen (Chris hätte nichts dagegen und hat keine Zeit mehr zu maintainen).
Allerdings stellt sich mir die Frage der Sinnhaftigkeit, denn in der Hauptsache überschneidet sich die Funktionalität weitgehend und FHEM2FHEM ist deutlich ausgefeilter implementiert.

Die meisten Anwender scheinen RFHEM dazu zu verwenden ein remote Kommando abzusetzen. Das liesse sich in FHEM2FHEM aber leicht implementieren (hab ich testweise auf 5 Minuten eingebaut - ok, natürlich nur quick&dirty).

FHEM2FHEM hat ja sowieso einen telnet port offen. Da jetzt noch ein "set cmd ..." anzubieten welches dann ein "syswrite" macht (mit evtl. ein paar Sicherheitschecks - z.B. sollte man evtl. nur "set" erlauben) würde RFHEM komplett obsolete machen.

RHFEM prüft halt noch über ping ob der gegenüber noch da ist. Ich hatte bei FHEM2FHEM (3 Systeme) schon mal den Fall, dass alle 3 blockiert waren, weil wohl eins kurz ausgefallen war. Evtl. kann man da noch etwas optimieren?

Ich möchte daher die entsprechende Erweiterung von FHEM2FHEM anregen und würde dann RFHEM in Rente schicken.

Was meint ihr (bersonders Rudi)?

Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

rudolfkoenig

Ich habe kein Problem FHEM2FHEM zu erweitern, ich brauche dazu weniger einen Patch, eher Problem- bzw. Aufgabenbeschreibungen.

Adimarantis

Ok,

Problembeschreibung:
- Anwender möchten auf einer Remote Instanz FHEM Befehle (wie set, setreading etc.) aus DOIF, notify etc. ausführen können
Lösungsidee:
- FHEM2FHEM stellt einen neuen set Befehl "cmd:Textfield" zur Verfügung.
- Dieser nutzt die bereits bestehende Verbindung um den übergebenen Befehl 1:1 an die remote Instanz zu schicken
- Falls möglich wird die Rückmeldung (üblicherweise nur bei Fehler) gelesen und im Logfile oder asynchron in einem "lastErr" Reading angezeigt
- Potentiell kann ein erster Plausicheck (gültiger Befehl) oder eine Einschränkung auf "einfache" Befehle erfolgen (wobei ich davon ausgehe würde das der Anwender hier weiss was er tut)

Nicht ganz so wichtig, weil selten, aber eine weitere Problembeschreibung:
- FHEM2FHEM bekommt potentiell nicht oder zu spät mit wenn die Verbindung zur Remote Instanz unterbrochen/wieder verfügbar ist
Lösungsvorschlag:
- Per Timer regelmässig (Attribut) einen Verbindungaufbau (open, ping...) durchführen und entsprechend den Verbindungsstatus aktualisieren
- Wenn eine unterbrochene Verbindung wiederhergestellt ist, automatisch reopen durchführen

Gruß,
Jörg

Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

rudolfkoenig

#3
Habe beides implementiert,  bitte um Feedback.

Achtung: die Fehlermeldung bei "set F2F cmd bla bla" sieht man in FHEMWEB nur in dem mehrzeiligen Befehlsdialog. Oder in einer Telnet-Sitzung.
Meldungen sieht man generell nur dann, falls der Befehl sofort was produziert, d.h. verzoegerte Ausgaben (wie bei get in manchen neueren Modulen ueblich) koennten zu unerwuenschten Nebeneffekten fuehren (vulgo: das habe ich nicht getestet).

Adimarantis

Hallo Rudi,

"cmd" und die unmittelbare Fehlermeldung im Log funktioniert in ersten Tests ganz gut.
Bei Signalbot habe ich einige asynchrone Aufrufe implementiert um FHEM nicht zu blockieren. Da es auch hier Fehler geben kann, schreibe ich die Rückmeldung dann in das Reading "lastErr", so dass der Anwender diese zumindest verzögert sehen kann (oder man sogar eine automatische Fehlerbehandlung über Event implementieren kann). Wäre eine Option um mit den verzögerten Ausgaben umzugehen. Fehlermeldungen sollte man ja von Events unterscheiden können.

Das "keepAlive" soll ja in der Hauptsache verhindern, dass eine bestehende Verbindung bein längerer Inaktivität geschlossen wird, richtig?

Der Ansatz den RFHEM hier verfolgt ist ein anderer:
Hier wird regelmäßig ein "ping" abgesetzt (ursprünglich über einen Shellaufruf des ping Kommandos, was ich schon mal durch Net::Ping ersetzt habe).  Dadurch soll wohl erkannt werden, ob der Kommunikationspartner noch da ist. Ich denke alternativ (und sogar noch zielgerichteter) wäre ein sysopen auf den Telnet Port.
Im Fehlerfall verbindet sich das ganze Modul neu.

Ob der ursprüngliche Autor hier ein echtes Problem beheben wollte weiss ich aber nicht.

Ich hatte nur selbst schon mal das Problem bei 3 Instanzen die mit FHEM2FHEM verbunden waren. Eine der Instanzen fiel aus und als sie wieder online kam musste ich feststellen, das eine der beiden anderen Instanzen komplett blockiert war und ich FHEM abschiessen musste. Ist jetzt aber nicht wirklich reproduzierbar.

Jörg

Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

rudolfkoenig

Die aktuelle Loesung verwendet fuer die Befehle die bereits existierende inform/Eventstrom Verbindung.

Die direkte Antwort der Gegenseite wird in \0 eingepackt, damit kann man es von den Events unterscheiden, und es presentieren.
Spaetere oder spontane Antworten (die mit asyncOutput) haben diese \0 "Umschlaege" nicht, und ich kann sie nicht von Events unterscheiden.
Eine Alternative waere eine weitere telnet Verbindung zu oeffnen und zu pflegen, kenne aber noch kein Use-Case, was davon profitiert.

Ich habe jetzt eindeutig als Antwort erkannte Daten (die in dem \0 "Umschlag") in dem cmdResponse Internal gespeichert.

mit dem keepaliveInterval Attribut wird regelmaessig ein {undef} gesendet, wodurch eine tote Verbindung vom OS entdeckt werden sollte.
Waere nett, wenn das jemand verifizieren kann, dafuer braucht man aber zwei Rechner, wo man die Netzwerkverbindung stillegen kann.

Adimarantis

Ok. Theoretisch hat ja ein Event im Gegensatz zu einer Fehlermeldung ein recht definiertes Format und man könnte es evtl. mit einem RegExp unterscheiden. Aber das ist jetzt wirklich ein Cornercase.
So ist es schon recht schön.

Ich habe jetzt mal mit meinem Test-Raspi ein paar Fälle durchgespielt.
Ein FHEM shutdown des remote systems wird zügig erkannt (hat jetzt mit dem keepalive denke ich nichts zu tun). Auch ein kill -9 wird sofort erkannt.

Wenn ich jedoch den Stecker am Rapsi ziehe, dann meldet das keepalive weiter 8 erfolgreiche übertragene Zeichen - auch noch nach ein paar Minuten. (han 10s intervall eingestellt)
FHEM2FHEM erkennt nicht, dass der gegenüber schon längst weg ist.

Ich hab jetzt mal nur zum Test einen "ping" implementiert:

sub
FHEM2FHEM_keepalive($)
{
  my ($hash) = @_;
  my $name=$hash->{NAME};
  my $ki = AttrVal($hash->{NAME}, "keepaliveInterval", 0);
  return if(!$ki || !$hash->{TCPDev});
  my $ret=syswrite($hash->{TCPDev}, "{undef}\n");
  Log3 $name, 3 , "Keepalive $ret";
  my $host=$hash->{Host};
  my @hostname=split(":",$host);
  $host=$hostname[0];
  Log3 $name, 3, "Ping on $host"; 
  my $p = Net::Ping->new();
eval { $ret=$p->ping($host,0.5) };
if (!$ret) {
Log3 $name, 3 , "Ping error";
FHEM2FHEM_Disconnected($hash);
} else {
Log3 $name, 3, "Ping successful";

}
$p->close();
  InternalTimer(gettimeofday()+$ki, "FHEM2FHEM_keepalive", $hash);
}


Das klappt dann eigentlich recht gut. Er merkt gleich beim ersten KeepAlive, dass der Rechner weg ist, geht in Disconnected State und merkt dann auch wenn der Rechner wieder hochkommt.
Vielleicht kann man das aber auch noch eleganter lösen (und sicher schöner implementieren)

Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

rudolfkoenig

Laut Internet-Weisheit kann es bis zu 15 Minuten dauern, bis Linux entdeckt, dass der Kabel raus ist.
Net::Ping ist mir zu bunt, selbst das oeffnen/schliessen einer temporaeren TCP-Verbindung ist mAn overkill.

Am liebsten wuerde ich die socket Option TCP_USER_TIMEOUT setzen, was ab linux 2.6.?? existiert, und auch in "neueren" perl Versionen vorhanden ist. Leider habe ich (nach halbe Stunde experimentieren) keinen Schimmer, wie man testet, ob die Perl Konstante Socket::TCP_USER_TIMEOUT zur Verfuegung steht.

rudolfkoenig

Ich habe eine neue Variante eingecheckt, der statt syswrite HttpUtils_Connect durchfuehrt, was im wesentlichen Net::Ping entspricht. Allerdings mit dem default Timeout von 4 Sekunden, da mir 0.5 Sekunden zu kurz vorkommen. Dafuer nicht blockierend.

Adimarantis

Zitat von: rudolfkoenig am 10 September 2021, 14:58:53
Ich habe eine neue Variante eingecheckt, der statt syswrite HttpUtils_Connect durchfuehrt, was im wesentlichen Net::Ping entspricht. Allerdings mit dem default Timeout von 4 Sekunden, da mir 0.5 Sekunden zu kurz vorkommen. Dafuer nicht blockierend.
Das hört sich doch gut an. Schau ich mir gleich an.
Bin voll bei dir das "Ping" etwas übertrieben ist - war eher ein "proof of concept".

Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

Adimarantis

Klappt gut. Stecker gezogen und kurz drauf hat er es bemerkt - genauso umgekehrt.
Habe jetzt meine Instanzen umgestellt mit 60s timeout für den Langzeittest.

Danke,
Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

Beta-User

Hallo zusammen,

evtl. sollte man sich (direkt im Zusammenhang mit 6.1?) gedanken machen, wie man den Phase-Out von RFHEM kommuniziert. Sonst implementiert das im schlechtesten Fall noch jemand...

Hintergrund:
Zitat von: Helmi55 am 25 September 2021, 10:00:12
Hallo Maci
RFHEM läuft seit Jahren bei mir problemlos.
Aber MQTT klingt natürlich verlockend...

Gruß
Helmut

Mindestens klare Hinweise in der commandref zu RFHEM und den Kurzbeschreibungen wären mAn. hilfreich, evtl. (neben in CHANGED) auch in UPDATE (analog  MQTT_BRIDGE).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Adimarantis

Ich habe einen deprecation Hinweis mit link auf das RFHEM Forum in die Detail Funktion eingebaut.
D.h. jeder der das Modul aufruft kriegt den Hinweis an prominenter Stelle.

Jörg
Raspberry 4 + HM-MOD-RPI-PCB (pivCCU) + RfxTrx433XL + 2xRaspberry 1
Module: 50_Signalbot, 52_I2C_ADS1x1x , 58_RPI_1Wire, (50_SPI_MAX31865)

Beta-User

Gute Idee, neben den Hinweisen in der commandref die Angaben als Ergänzung zu präsentieren :) .

Was meine eigenen Erfahrungen mit "Phase-out" angeht (Heating_Control): Selbst wenn man lange (da waren es deutlich mehr als 12 Monate) darauf hinweist, dass da was passieren wird, gibt es trotzdem vereinzelt User, die es nicht mitbekommen, weil sie nie updaten und dann erst im Zusammenhang mit einem sehr gelegentlichen Update direkt auf die Nase fallen oder nach einer Neuinstallation feststellen, dass etwas nicht mehr so tut wie erwartet.
Für RFHEM kann ich es nicht beurteilen, vermute aber, dass es da (wie bei MQTT_BRIDGE) so ist, dass ein Verschieben des Moduls nach contrib/deprecated (nach einer Übergangszeit für "fleißige updater") die richtige Variante wäre: Wer es installiert hat, kann es weiter nutzen und dann ggf. nach und nach umstellen, wer es bisher nicht genutzt hat, sieht es erst gar nicht...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files