IODev Handling durch device

Begonnen von noansi, 22 April 2021, 19:16:57

Vorheriges Thema - Nächstes Thema

noansi

Hallo Rudolf,

ZitatIch fuerchte da musst Du weiter ausholen, oder an die passende Stelle verweisen, da meine Erinnerung mich im Stich gelassen hat.
Das hat gar nichts mit Dir zu tun, sondern kam im IOgrp/IODev Zusammenhang im Homematic Forum wegen unterschiedlichen Werten zwischen Reading IODev und Attribut IODev.
Wenn man das Attribut IODev nicht anbietet, darf man aus dem Code raus auch sinnvollerweise nur das Internal setzen, sonst gibt es nach einem Save Config die "Strafe" beim nächsten FHEM Start in Form von Fehlermeldungen.
Und es soll ja auch Menschen geben, die sich den diesbezüglichen fhem.pl Code noch nicht angesehen haben, die Funktionen aber dennoch benutzen wollen. ;-)

Mit dem Weglassen des Angebots des Attributs IODev habe ich auch noch ein gedankliches Problem.
Wie schon geschrieben, gibt es Szenarien für einige oder auch alle HM devices, die das Attribut IODev benötigen.
Allerdings ist das beim CUL_HM Modul erst nach der kompletten Verarbeitung der Config klar, weil erst dann alle devices,
- somit auch die optionale VCCU als IO Verwaltungsinstanz, definiert sind
und
- erst dann der jeweilige HM device Typ und Subtyp via Attribut bekannt sind. Und damit auch ein eventueller Bedarf nach Attribut IODev.
D.h. alle Nutzer, die eine Konfiguration nur auf Basis von IODev fahren, bekämen nach einem Update erst mal ihre funktionsfähige IO Konfiguration unterm Hintern weggerissen. Wenn ich es auf den ersten Blick richtig sehe auch ohne die Möglichkeit einer automatischen Umschreibung von Attribut alt auf Attribut neu auf Basis des Frameworks.
Aus Kompatibilitätsgründen ist der Weg des kompletten Weglassen des Angebots wenig empfehlenswert.

Es bliebe noch die nicht ganz saubere Möglichkeit, das Attribut für die Initilisierungphase zu zu lassen und danach für ein neues Setzen zu entziehen, um eine Umschreibung einzubauen. Danach kann AssignIoPort genutzt werden, um nur das Internal IODev zu setzen, falls beim Umschreiben kein IO zugewiesen wurde, wie ich gesehen habe.

Zitatallerdings ist FinalizeInitFn prinzipiell auch nicht anders.
Wenn FinalizeInitFn nicht zweckgebunden definiert wird oder missbraucht wird, klar. Ein fehlendes $init_done=1 sorgt aber auch für Einschränkungen.

$init_done erst später zu setzen, z.B. wenn global INITIALIZED verarbeitet ist, würde vermutlich zu erheblichen Kompatibilitätsproblemen zu bestehenden Modulen führen.

Äquivalenz ließe sich vermutlich mit einem neuen beispielsweise global PREINITIALIZED vor INITIALIZED erreichen, wenn sich in DoTrigger und abhängigen Funktionen nicht noch ein verstecktes $init_done!=1 Problem auftut.

In's Timerhandling dafür noch eine Sonderbehandlung einzubauen fände ich deplatziert. Und kommt ohnehin erst nach dem INITIALIZED, damit auch im Ablauf nicht mehr sinnvoll.

Ich habe auch nicht generell NotifyFn und InternalTimer als Initialiserungsmöglichkeit nach dem FHEM Start kritisiert. Allerdings hast Du die finish_init() Funktion ja (rein auf das IODev Problem bezogen) auch nicht grundlos nicht via InternalTimer aufgerufen, sondern direkt im Init Ablauf, eben weil zu dem Zeitpunkt noch nichts anderes läuft, alles definiert ist und Du rechtzeitig IOs zuweisen wolltest.

ZitatNein, aber das ist kein Argument fuer ein Framework-Umbau, sondern eher eins fuer CUL_ReadAnswer bzw. CUL_DoInit Umbau.
Du bist nicht allein mit dem CUL Modul. Das wird auch in anderen IO-Modulen so gemacht. Ich müßte mich da mit TSCUL kompatibel auch vor dem "ersten Stein Werfer" in Deckung bringen.  ;)

Gruß, Ansgar.

rudolfkoenig

Ich habe jetzt AssignIoDev umgebaut, damit es statt Attribut ein Reading setzt, wie oben beschrieben.

ZitatAllerdings hast Du die finish_init() Funktion ja (rein auf das IODev Problem bezogen) auch nicht grundlos nicht via InternalTimer aufgerufen, sondern direkt im Init Ablauf
Das hat damit wenig zu tun, sondern damit, dass der Aufruf ueber InternalTimer aufwendiger waere.

Ich kann (wenn immer noch gewuenscht) ein FinalizeInitFn Aufruf einbauen, bitte bestaetigen.
Am liebsten waere es mir in der aktuellen finish_init(), die macht ja bereits eine Schleife ueber alle Geraete.

noansi

Hallo Rudolf,

vielen Dank für die Änderungen.
Ich schau erst mal, ob ich damit alle Probleme erschlagen kann. Ist ja doch deutlich umfangreicher geworden, als ursprünglich auch nur ansatzweise angedacht.  :)

Gruß, Ansgar.

klaus.schauer

Zitat von: rudolfkoenig am 28 April 2021, 18:56:59
Ich habe jetzt AssignIoDev umgebaut, damit es statt Attribut ein Reading setzt, wie oben beschrieben.
Das hat damit wenig zu tun, sondern damit, dass der Aufruf ueber InternalTimer aufwendiger waere.

Ich kann (wenn immer noch gewuenscht) ein FinalizeInitFn Aufruf einbauen, bitte bestaetigen.
Am liebsten waere es mir in der aktuellen finish_init(), die macht ja bereits eine Schleife ueber alle Geraete.
Ich nehme an, die Änderungen wurden in der Routine AssignIoPort vorgenommen.

Für eine Installation mit mehreren EnOcean-Transceivern ist es notwendig, statisch festzulegen, welcher dieser Transceiver als Sender verwendet wird. Diese Festlegung erfolgt nach wie vor - sowie ich das verstehe - über das Attribut IODev. Welche Routine das Attribut IODev auswertet und das Internal IODev entsprechend nachzieht, ist mir noch nicht klar.

Da das Attribut von AssignIoPort das Attribut IODev nicht mehr versorgt wird, ist diese statische Zuordnung nicht mehr gewährleistet.
Wird dies noch angepasst oder muss das Attribut IODev im EnOcean-Modul nun nach dem Aufruf von AssignIoPort beim Anlernen von Devices entsprechend beschrieben werden?

noansi

#19
Hallo Klaus, hallo Rudolf,

ZitatIch nehme an, die Änderungen wurden in der Routine AssignIoPort vorgenommen.
Nicht nur, siehe https://svn.fhem.de/trac/changeset/24351/.
CommandAttr ist zusätzlich ebenso angepasst, wie CommandSetstate.

Dabei geht es darum, die Zuweisung des IOs an das Ende des Inits zu legen (wie bisher auch), damit die IO devices auch definiert sind, die über Attribut oder Reading beim Init gesetzt werden.

In AssignIoPort wird nur noch das Reading IODev gesetzt. Bei Save Config werden die Readings in der fhem.save gespeichert und beim nächsten Start von fhem daraus wieder gelesen.

Das Attribut IODev wird weder angetastet noch seiner Wirkung beraubt. Sprich, wird es gesetzt, dann wird das IO auch daraus eingestellt (was bedeutet, dass das Internal IODev darauf eingestellt wird). Dabei wird auch das Reading IODev gleich gesetzt.
Ist das Attribut nicht gesetzt, dann wird das Reading IODev genutzt, um das IO daraus einzustellen. Also die neue Methode.
Sprich das Attribut kann dann auch gelöscht werden, ohne dass sich was an der IO Zuordnung ändert, so denn das Reading gespeichert wurde. Das Attribut wird aber nicht automatisch gelöscht.

D.h. bei autocreate wird es jetzt vermutlich interessant für Dich. Da wird nicht das IODev Attribut gesetzt, sondern nur das Reading IODev.
Wenn Du das Attribut noch unbedingt setzen möchtest, dann könntest Du es im Undefined Trigger mitgeben, so da bekannt, denke ich.

Sinnvoll ist das, wenn der Modulcode geändert wird und man beim Testen Fehler einbaut, so dass das Modul beim Start nicht mehr
geladen wird. Somit die devices nicht mehr definiert werden und damit das Reading IODev nicht gesetzt wird und somit beim nächsten FHEM Start nach Korrektur des Fehlers das Reading weg ist und eventuell ein anderes IO zugewiesen wird, wenn kein Attribut IODev in der config vorhanden ist.

Gruß, Ansgar.

rudolfkoenig

Wenn man im Modul auf das Vorhandensein des IODev Attributes prueft, dann kann das zu Problemen fuehren.
Ich bin der Meinung, dass das nicht notwendig ist, das Modul soll (wenn ueberhaupt!) nur das IODev Internal anfassen.
Eigentlich sollte die Kommunikation zwischen den beiden Modulen ueber IOWrite() bzw Dispatch laufen.

Beta-User

Weil ich grade "drübergestolpert" bin: Ich habe einen ähnlichen "gedanklichen Hänger" wie klaus.schauer...

Auch wenn das etwas spezielle Modul RHASSPY der Anlass war (siehe
Zitat von: Beta-User am 20 Mai 2021, 08:29:28
[...]
OT-Anmerkung dazu: Das ist vermutlich in allen den Fällen kein Problem, in denen es sowieso nur eine lose Verbindung zwischen IO und Information gibt (wie bei den meisten Funklösungen, bei denen dann fhem.pl Duplikate vorrab aussortiert).
In allen Fällen, in denen es sein kann, dass - vermeintlich - identische Information über unterschiedliche IO's reinkommen kann (vornehmlich MQTT, aber auch MySensors!), muss die Koppelung zwischen IO und Client-Modul im zweistufigen Modulkonzept aber "gehärtet" werden, was bei MySensors z.B. schon länger dadurch erfolgt, dass da das Attribut durch das Modul gesetzt wird, statt auf AssignIOPort zu vertrauen...

Anders gesagt: Wenn (und solange) man z.B. auch bei MQTT_GENERIC_BRIDGE das Attribut gesetzt hat, ist alles fein...

Für die Zukunft wird es vermutlich auch dort (und bei MQTT2_DEVICE?) eine Ergänzung brauchen, die das klarstellt.
[/OT]

Es gibt bestimmte Konstellationen, in denen es erforderlich ist, eine "harte" Zuweisung (mAn. am besten per Attribut) vorzunehmen, und zwar genau auf das IO, über das "neue" Info reingekommen ist. Bei MySensors hatte ich das vor längerem schon via CommandAttr() im (internen) autocreate-Ablauf vercoded, weil die zufällige Zuweisung per AssignIOPort() (das letzte "passende") "falsche" Ergebnisse bringt ("Node 20" auf Kanal 76 ist eben nicht dasselbe wie "Node 20" auf Kanal 75, und MQTT-Messages auf einen bestimmten Topic von (externem) "MQTT-Server 1" sind auch fast immer nicht dieselben Infos wie solche auf denselben Topic von (externem)  "MQTT-Server 2").

Natürlich kann man das den Usern erklären (bzw. das weiter wie im Falle von MYSENSORS_DEVICE - mit dem "verqueren" eigenen dispatch-Mechanismus hart vercoded) so belassen, aber ggf. wäre es hilfreich, wenn ein IO-Modul einen "flag" setzen könnte, dass es zwingend ein IODev-Attribut haben will, und zwar optimalerweise auf genau das IO, über das die Info (zuerst) reingekommen ist?

Oder übersehe ich mal wieder was wichtiges?
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

rudolfkoenig

Zitatwäre es hilfreich, wenn ein IO-Modul einen "flag" setzen könnte, dass es zwingend ein IODev-Attribut haben will, und zwar optimalerweise auf genau das IO, über das die Info (zuerst) reingekommen ist?
AssignIoPort bietet fuer diesen Fall den optionalen Parameter proposed an.
Soweit ich sehe, wird das in MQTT2_DEVICE verwendet.

Die Deduplizierung der Nachrichten ist auch nicht ganz Stumpf: wenn das Modul ein FingerprintFn anbietet, dann wird die Nachricht per Fingerprint verglichen, und nicht verbatim.

Beta-User

Zitat von: rudolfkoenig am 20 Mai 2021, 11:04:35
AssignIoPort bietet fuer diesen Fall den optionalen Parameter proposed an.
Soweit ich sehe, wird das in MQTT2_DEVICE verwendet.
Wenn ich den Code richtig verstehe, setzt dort dann aber ein "hartes" Setzen die Angabe des IODev _in der DEF_ voraus (war mir bisher nicht bewußt, dass man das bei M2D in der DEF unterbringen kann).
Ist halt "noch ein Ort", indem man das (aus Anwendersicht gesehen) "suchen muss", und sicher auch der einfachere Weg, wenn man die (vollständige) Initialisierung nicht nach $init_done zieht (in meinen Modulen erfolgt das in der Regel über die InternalTimer()-Lösung).

Vermutlich ist es die Frage, ob man tendenziell das IODev-Attribut eher abschaffen will oder eben auf die Fälle beschränken, in denen es nach den jüngsten Änderungen noch sinnvoll ist. Spontan _glaube_ ich, dass es aus User-Sicht einfacher  ist (v.a. auch, wenn man "umziehen" will oder muss!), wenn das via Attribut erfolgt - und da habe ich keine Option, AssignIoPort mitzuteilen, dass es nicht das (aus Usersicht "volatile") Reading setzen soll, sondern das ("harte") Attribut.

Zitat
Die Deduplizierung der Nachrichten ist auch nicht ganz Stumpf: wenn das Modul ein FingerprintFn anbietet, dann wird die Nachricht per Fingerprint verglichen, und nicht verbatim.
Danke für den Hinweis, dass meine Formulierung da unscharf war; mit der Deduplizierung hatte ich mich bisher nicht intensiver beschäftigt, war bisher kein Bedarf ::) ...
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

rudolfkoenig

Zitatund da habe ich keine Option, AssignIoPort mitzuteilen, dass es nicht das (aus Usersicht "volatile") Reading setzen soll, sondern das ("harte") Attribut.
Ich bin immer noch der Ansicht, dass Module kein Attribut setzen sollten, das ist auch die Ursache fuer diesen Umbau gewesen. Die aktuelle Loesung haengt von der statefile ab, was vmtl. als "optional" wahrgenommen wird, das ist aber nicht wirklich der Fall, und nicht nur fuer IODev.

Beta-User

Ich bin grundsätzlich bei dir, sehe das aber etwas differenzierter (vermutlich fehlt mir da etwas Erfahrung). Meine Sichtweise:
- Ein Modul sollte Attribute _nie ändern_- sind sie gesetzt, sind sie "für den User", eindeutig. (Gibt Fälle, in denen das ggf. schwierig ist, z.B. die "model"-Diskussion bei CUL_HM)
- Hier geht es (mir) aber um die Frage des "Vorausfüllens" in den Fällen, in denen es (mAn.) sinnvoll erscheint, DASS das _Attribut_ überhaupt gesetzt wird.

Letzteres ist m.E. eher selten der Fall, aber eben in allen Fällen die "härteste" Lösung, in denen man v.a. für Sendeanweisungen sicherstellen muss, dass die an die richtige Adresse gehen. Nur für solche Fälle halte ich es für eine gute Option, AssignIoPort() mitteilen zu können, dass man (ausnahmsweise!) das Attribut haben will (aber nur, falls es nicht irgendwie schon gesetzt ist!)

Also: kein Overwrite, nur sinnhaftes "Vorausfüllen".

Ob das "Vorausfüllen" sinnvoll ist, sollte der Modulautor irgendwie festlegen können (ggf. auch durch ein Internal, mir egal).

Was statefile angeht: hm, ja, schon, vielleicht, oder auch doch nicht?!?
Mein gedankliches Problem: Hin und wieder braucht man zum Testen Hardware.  Das ist am einfachsten am Echtsystem mit der Folge, dass manchmal auch Module nicht geladen werden - was auch dem User nach einem update passieren kann, wenn der Maintainer es verbockt. Dann will ich aber trotzdem die zwischendurch (überall sonst) angefallenen Daten abspeichern bzw. starte FHEM ggf. dann einfach nochmal, nachdem das Problem gefixt ist. Da sind dann aber die Readings der nicht geladenen Module weg, wenn ich das richtig im Kopf habe... (passiert mir zum Glück zwischenzeitlich eher selten ::) ).
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

Prof. Dr. Peter Henning

Könnte man hier mal zusammenfassen, was denn nun genau geändert worden ist?

In dem seit sehr langer Zeit stabil laufenden OWX-Modul wird nämlich, wenn eine Bus-Suche ein neues Gerät gefunden hat, ein neues Device angelegt mit einem IODev-Attribut.

Da man aber durch mehrere (=viele) 1-Wire-Busmaster haben kann, finde ich das mit dem Reading für IODev nicht besonders gut.

LG

pah

noansi

#27
Hallo Peter,

ZitatKönnte man hier mal zusammenfassen, was denn nun genau geändert worden ist?
https://forum.fhem.de/index.php/topic,120603.msg1153918.html#msg1153918
Das umreist es eigentlich.

Wenn Du das 00_OWX.pm Modul meinst, darin wird in Zeile 633 vorbildlich (im Sinne von Nutzung von Systeminterfacefunktionen)
        CommandAttr (undef,"$acname IODev $hash->{NAME}");

genutzt, um das IODev auf den gewünschten Stand zu setzen.
Damit wird das Attribut, das Reading und das Internal IODev gesetzt. Alles gut, denke ich.

Wenn der Nutzer nun dafür sorgt, dass die config auch gespeichert wird, sei es manuell oder sei es automatisch, dann hat er auch das Attribut mit dem nächsten (regulären) FHEM Start noch und es wird als Quelle zur Einstellung des IOs genutzt.
Ansonsten hat er jetzt, und das ist neu, noch das IODev Reading und ihm sollte nichts fehlen, so denn nicht irgendeine Funktion noch meint, das Attribut IODev als Quelle des aktuell genutzten IOs nutzen zu müssen.

Im Sinne von "Attribut ist User Domäne" wäre es natürlich maximal konsequent, wenn der User selbständig immer ein nur gesetztes Reading IODev in das Attribut IODev einträgt, wenn er es denn haben will oder wenn er den Automatismus der Zuweisung überschreiben möchte. In diesem Fall wäre diese Konsequenz aber weder sinnvoll noch wirklich notwendig.

Einen solchen reinen Reading IODev-Automatismus kann man z.B. mit
AssignIoPort($hash, $proposedIODevName);
erreichen, und damit wird das Attribut IODev nicht gesetzt, sondern nur das Reading und das Internal.

Gruß, Ansgar.

Prof. Dr. Peter Henning

Zitatdarin wird in Zeile 633 vorbildlich

Mehr bráuche ich nicht zu wissen - denn wenn darin größere Änderungen fällig gewesen wäre, hätte ich die im Moment nicht unterbringen können.

LG

pah

rudolfkoenig

ZitatKönnte man hier mal zusammenfassen, was denn nun genau geändert worden ist?
Es sollte sich weder fuer den Modulautor, noch was fuer den Endanwender aendern, lediglich in solchen exotischen Faellen, wo im Modul nach AssigIoPort explizit auf das Attribut abgefragt(!) wird.
AssignIoPort setzt ab sofort ein IODev Reading, und kein Attribut mehr.
Da aber die Readings nach dem Attributen reingelesen werden, hat meine Aenderung in bestimmten Faellen (attr IODev noch nicht definiert) nicht funktioniert. Das habe ich gerade gefixt.