Autor Thema: Loops bei FHEM2FHEM vermeiden  (Gelesen 1032 mal)

Offline Adimarantis

  • Developer
  • Sr. Member
  • ****
  • Beiträge: 585
Loops bei FHEM2FHEM vermeiden
« am: 01 August 2021, 10:55:49 »
Hallo,

ich probiere jetzt schon eine Weile wie man am besten Readings auf zwei Instanzen spiegelt (man darf sie also auf beiden Instanzen ändern und bekommt das auf der jeweils anderen mit).
Egal welches Modul (FHEM2FHEM, RFHEM) man da nimmt, läuft man hier immer in Gefahr eine Schleife zu bauen.

Ich hätte da einen Vorschlag zu FHEM2FHEM, wie man Schleifen unterbindet und damit potentiell auch ein solches Mirroring machen könnte.
Grundprinzip: Änderungen innerhalb eines gewissen Zeitraums werden unterdrückt und damit Schleifen durchbrochen. Sofern der Anwendungsfall nicht erfordert Änderungen im Sekundentakt oder schneller durchzuführen, sollte dies für den Anwender keine Einschränkung bedeuten. Theoretisch reicht es, dies auf einer Instanz zu machen (dann kriegt man halt immer noch ein "Echo", was aber harmlos ist).

In meiner Bastelversion von FHEM2FHEM habe ich folgende Funktion hinzugefügt:
sub FHEM2FHEM_updateReading(@)
{
my ($name,$dev,$reading,$value,$trigger) = @_;

my $age = ReadingsAge($dev->{NAME},$reading,undef);
my $threshold = AttrVal($name,"loopThreshold",0);

#Only execute if last change is older than Threshold
if (!defined($age) || $age>$threshold) {
readingsSingleUpdate($dev,$reading,$value, $trigger);
} else {
Log3 $name, 4, "No update due to possible loop for $dev->{NAME} $reading $value (age:$age, threshold:$threshold)";
}
return undef;
}

Das neue Attribut "loopThreshold" wird dann z.B. auf 2 Sekunden gesetzt.
In der FHEM2FHEM_Read werden entsprechend die readingsSingleUpdate ersetzt durch:
FHEM2FHEM_updateReading($name,$defs{$rname}, $1, $2, 1);
Ich hänge das geänderte Modul mal an.

Speziell die Fragen an Rudi:
- Könntest du dir so eine Änderung vorstellen?
- Es gibt noch einen Fall im Code wo ein "AnalyzeCommand" angestossen wird - diesen berücksichtige ich jetzt nicht, verstehe aber auch nicht ganz wann dieser Zweig getriggert wird

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)

Offline Adimarantis

  • Developer
  • Sr. Member
  • ****
  • Beiträge: 585
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #1 am: 01 August 2021, 11:45:02 »
Bei weiteren Tests ist mir aufgefallen, das FHEM2FHEM bei zu großzügerer Regexp Definition auch versucht für andere Befehle als "set" ein ReadingsSingleUpdate zu triggern (z.B. wenn man den Devicenamen in ".*device.*" einbettet).
Um solche Querschläger gleich abzufangen würde es sich anbieten, Nachrichten von "global" mit
if ($dev->{NAME} eq "global") {
Log3 $name, 4, "Ignoring admistrative message $reading $value";
return undef;}

gleich zu ignorieren.

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

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 24916
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #2 am: 01 August 2021, 18:31:37 »
Das mag zwar in vielen Faellen funktionieren, aber z.Bsp. dann nicht, wenn ein Event eine Verarbeitung ausloest, was laenger als loopThreshold dauert.  Auch das Echo bzw. dass man es auf allen Seiten konfigurieren muss, ist unschoen => muss noch drueber nachdenken. Gibt es noch Andere, die das gleiche Problem haben?

Generell faende ich eine Loesung ueber MQTT besser, evtl. koennte ich MQTT2_CLIENT dafuer aufruesten.
Vmtl. geht das jetzt schon mit MQTT2_GENERIC_DEVICE, irgendwie.

Zitat
- Es gibt noch einen Fall im Code wo ein "AnalyzeCommand" angestossen wird - diesen berücksichtige ich jetzt nicht, verstehe aber auch nicht ganz wann dieser Zweig getriggert wird
Wenn man eventOnly und setState nicht gesetzt hat, remote ein set ausgeloest wird, und lokal ein Geraet mit dem gleichen Namen existiert.

Offline Adimarantis

  • Developer
  • Sr. Member
  • ****
  • Beiträge: 585
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #3 am: 01 August 2021, 20:54:31 »
Hi Rudi,

Das mag zwar in vielen Faellen funktionieren, aber z.Bsp. dann nicht, wenn ein Event eine Verarbeitung ausloest, was laenger als loopThreshold dauert.

Du meinst wenn die Loop aufgrund von Verzögerungen so lange dauert, dass sie nicht mehr erkannt wird. Naja, dann hätte man erstmal nichts verloren, da dies ja das aktuelle Verhalten ist - natürlich ungünstig für den Fall dass man sich drauf verlässt um den bidirektionalen Fall zu implementieren. Hier sollte aber helfen dann auf beiden Seiten ein loopThreshold zu haben - das Prozessing hat man selten auf beiden Seiten.

Insgesamt hat da der Push-Ansatz von RFHEM durchaus seinen Charme, allerdings müsste man die Befehle immer durch eine Remote Instanz (von RFHEM) kanalisieren, würde damit aber auch die Möglichkeit haben remote Kommandos abzusetzen, wozu manche Anwender anscheinend RFHEM parallel zu FHEM2FHEM betreiben (der readings update Teil von RFHEM ist aber unfertig und fehlerhaft - daher bin ich davon wieder abgekommen - siehe meine Diskussion mit Otto https://forum.fhem.de/index.php/topic,23638.msg1168650.html#new )

Wenn MQTT das abdecken kann ist das sicher eine Option. Habe mich damit noch nicht beschäftigt da mich auch gleich die komplexere Konfiguration und Notwendigkeit einer "Drittinstanz" (auch wenn die wieder auf FHEM laufen kann) abgeschreckt hat.

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

Offline Beta-User

  • Developer
  • Hero Member
  • ****
  • Beiträge: 16907
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #4 am: 02 August 2021, 10:10:24 »
Generell faende ich eine Loesung ueber MQTT besser, evtl. koennte ich MQTT2_CLIENT dafuer aufruesten.
Vmtl. geht das jetzt schon mit [...]
Soweit ich das bisher überblicke, braucht es wohl keine Erweiterung für MQTT2_CLIENT, die mit MQTT2-IO's kompatiblen Module einschl. MQTT_GENERIC_BRIDGE müßten eigentlich alles mitbringen, um das stressfrei und ohne loops umzusetzen.

Voraussetzung ist aber - wie üblich -, dass das sauber gemacht wird.

Ich habe auch noch nicht ganz verstanden, um was es eigentlich geht. Falls es
Einfach "blind" jede Änderung von a nach b und von b nach a replizieren.
sein sollte: Das ist immer nicht ganz easy, man muss sich jeweils sehr genau anschauen, was wo steht.
Wenn MQTT das abdecken kann ist das sicher eine Option. Habe mich damit noch nicht beschäftigt da mich auch gleich die komplexere Konfiguration und Notwendigkeit einer "Drittinstanz" (auch wenn die wieder auf FHEM laufen kann) abgeschreckt hat.
Na ja, für MQTT braucht es halt einen Server, aber mit MQTT2_SERVER auf einer Instanz sollte es in den meisten Fällen zu bewerkstelligen sein, und "über Kreuz" sollte eigentlich alles nach dem folgenden "Bauprinzip" abbildbar sein:
((Reales Device + MQTT_GENERIC_BRIDGE-Attribute) + (MQTT(2)-IO + MQTT_GENERIC_BRIDGE)) <= MQTT-Protokoll => (MQTT(2)-IO + MQTT2_DEVICE (ggf. via bridgeRegexp))
Das erfordert etwas Einarbeitung, aber dann läßt sich damit m.E. eigentlich recht einfach eine "eventsparende" und loopfreie Lösung basteln.

(Einen großen Bogen sollte man nur um diese "unselige" "SYS_MQTT-notify"-"Lösung" machen, die ihrerseits wieder unspezifische Events generiert...).

Demgegenüber sehe ich eine "timerbasiert aussortierende Pauschallösung" eher skeptisch (falls ich das vorgeschlagene Prinzip überhaupt korrekt erfasst haben sollte).
Server: HP-T620@Debian 11, 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:MySensors, Weekday-&RandomTimer, Twilight,  AttrTemplate {u.a. mqtt2, mysensors, zwave}
Informativ Informativ x 1 Liste anzeigen

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 24916
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #5 am: 02 August 2021, 15:38:38 »
Ich habe loopThreshold jetzt eingebaut, auch wenn das nicht perfekt ist, vielleicht hilft es jemandem.
Insb. in Zusammenhang mit den event-on-* Attributen sollte man aufpassen.
Informativ Informativ x 1 Liste anzeigen

Offline Adimarantis

  • Developer
  • Sr. Member
  • ****
  • Beiträge: 585
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #6 am: 26 August 2021, 14:17:08 »
Hallo Rudi,

Ich habe noch ein kleines Problem gefunden:
Wenn ein Reading nicht existiert, dann nimmst du es als "0" an, womit es immer ignoriert wird, wenn man ein threshold gesetzt hat.
D.h. man muss es erstmal mit "setreading" anlegen.
Habe gerade eine ganze Weile gesucht, warum ein neu angelegtes Device keine Werte bekommen hat.

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

Offline rudolfkoenig

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 24916
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #7 am: 26 August 2021, 18:49:58 »
Hab was eingebaut, aber nur oberflaechlich getestet, kannst Du es bitte auch testen und Feedback geben?

Offline Adimarantis

  • Developer
  • Sr. Member
  • ****
  • Beiträge: 585
Antw:Loops bei FHEM2FHEM vermeiden
« Antwort #8 am: 27 August 2021, 09:51:46 »
Hi Rudi,

ja das mit dem "undef" als Default klappt jetzt. Testweise neues Reading angelegt und das wurde anstandslos übernommen (und auch der Rest mit und ohne Thresholdunterschreitung funktioniert wie erwartet).

Danke & 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)