IODev Handling durch device

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

Vorheriges Thema - Nächstes Thema

noansi

Hallo Rudolf,

ich hoffe, Du schaust hier mal rein.

Das Attribut IODev erfährt in fhem.pl in CommandAttr($$) (ab derzeit Zeile 3099) eine Sondernachbehandlung, um die Initialisierungsphase mit ungünsiger Definitionsreihenfolge "zu überstehen", so meine Codeinterpretation.

Wenn man das aber sebst handlen möchte/muss, dann stört diese Sonderbehandlung.
Ausweg ist derzeit nur, in der Attribut Funktion eine falsche Fehlermeldung zurück zu liefern, so dass Zeile 3096 mit next dafür sorgt, dass die Sonderbehandlung nicht durchgeführt wird.
    $ret = CallFn($sdev, "AttrFn", "set", $sdev, $attrName, $attrVal);
    delete($defs{$sdev}->{CL});
    if($ret) {
      push @rets, $ret;
      next;
    }

Leider wird dabei die falsche Fehlermeldung auch an den Aufrufer zurück geliefert, was unerwünscht ist. Sowohl beim FHEM Start, als auch beim händischen Setzen den Attributs.

Kannst Du damit leben, einen bestimmten Rückgabestring in der Zeile davor nicht auf das @rets array zu pushen und damit zu unterdrücken? Z.B. "IODev handled" oder "attr handled". Also so z.B.:
    $ret = CallFn($sdev, "AttrFn", "set", $sdev, $attrName, $attrVal);
    delete($defs{$sdev}->{CL});
    if($ret) {
      push @rets, $ret if ($ret ne "attr handled");
      next;
    }

Damit wird die falsche Fehlermeldung unterdrückt und das Handlen des attr Kommandos muss durch das jeweilige Modul erfolgen.

Natürlich gerne auch eine andere Alternative.

Grund ist ein Änderungsvorschlag für 10_CUL_HM.pm mit Bezug auf IODev und den Konflikten mit automatischer Zuweisung des IODev:
  elsif($attrName eq "IODev") {
    if ($cmd eq "set"){
      if ($attrVal) {
        if ($init_done) {
          return 'CUL_HM '.$name.': unknown IODev '.$attrVal.' specified'
              if (!defined($defs{$attrVal})); # noansi: resonable for a defined IO device only, real error to be reported
          $hash->{helper}{io}{restoredIO} = $attrVal; # noansi: first choice on next CUL_HM_assignIO
          CUL_HM_assignIO($hash);                     # noansi: try an assign
          delete($hash->{IODev}{'.clientArray'}) if (defined($hash->{IODev})); # Force a recompute
        }
        else {
          if (!$hash->{helper}{io}{restoredIO}) {                # noansi: do not overwrite restored data from IO, e.g. TSCUL
            $hash->{helper}{io}{restoredIO} = $attrVal;          # noansi: first choice on next CUL_HM_assignIO with vccu set till $init_done==1
            if (defined($defs{$attrVal})) {                        # noansi: resonable for a defined IO device only
              $attr{$name}{IODev}                     = $attrVal;  # noansi: first choice on next CUL_HM_assignIO with vccu not set
              @{$hash->{helper}{mRssi}{io}{$attrVal}} = (100,100); # noansi: set IO high rssi for first autoassign
              CUL_HM_assignIO($hash);                              # noansi: try an assign
              delete($hash->{IODev}{'.clientArray'}) if (defined($hash->{IODev})); # Force a recompute
            }
          }
        }
        if (defined($hash->{IODev}) && $hash->{IODev}{NAME} ne $attrVal) {
          DoTrigger('global', 'ATTR '.$name.' IODev '.$hash->{IODev}{NAME}, 1) if ($init_done);
          return 'attr handled'; # noansi: we return something to avoid fhem.pl to set $hash->{IODev} by it's own
                                 #         fhem.pl needs an adaption, not log/report it as "error"
                                 #         discussion started here https://forum.fhem.de/index.php/topic,120603.msg1151486.html#msg1151486
        }
      }
      else {
        return 'CUL_HM '.$name.': no IODev specified' if ($init_done); # noansi: real error to be reported
      }
    }
  }

Dabei stört die Nachbehandlung inklusive Setzen des Attributwertes durch CommandAttr($$).
Denn
- im CUL_HM Änderungsvorschlag wird während der FHEM Initialisierung ggf. ein notwendigerweise anderes IO bevorzugt (ein vor einem Neustart für das HM device zuständige), als der übergebene $attrval. Dann soll das IODev im device auch nicht auf den unerwünschten Wert gesetzt werden, was aber am Ende des FHEM Starts in finish_init() passiert, denn es stört im Nachgang bei der CUL_HM Nachinitialisierung.
- die für CUL_HM korrekt funktionale IO Zuweisung funktioniert nur mit CUL_HM_assignIO, weil auch dem IO das HM device als eines seiner bekannten devices mitgeteilt werden muss. Nur Setzen des Attributwertes und IODev setzen reicht nicht (betrifft auch HMLAN, HMUARTLGW). Diese Zuweisung macht CUL_HM entweder bei HM device Definition direkt nach dem FHEM Start.
- bei der vorgeschlagen Unterdrückung mittels Rückgabewert wird ein "Fehler" gelogged, der nur im Log verwirrt.
- im anderen Fall nach dem FHEM Start durch Userwunsch wird im Vorschlag bereits das IO durch CUL_HM_assignIO zugewiesen, damit auch das IO entsprechend initialisiert wird und nicht erst bei der ersten Sendenachricht an das device, wie es bisher der Fall war. Das bisherige Setzen des Attributs war (ist noch) noch nicht voll funktional.
- bei der vorgeschlagenen Unterdrückung mittels Rückgabewert wird derzeit eine störende Meldung angezeigt.


Sollte es weitere Anwendungsfälle geben, dann wäre es eventuell noch nötig, sich Gedanken um die Nachbehandlung am Ende zu machen
    addStructChange("attr", $sdev, "$sdev $attrName $attrVal")
        if(!$opt{silent} && (!defined($oVal) || $oVal ne $attrVal));
    DoTrigger("global", "ATTR $sdev $attrName $attrVal", 1) if($init_done);

die mit dem Mini Patch von oben mangels $opt{silent} Information nicht vollständig im Modul umgesetzt werden kann.

Gruß und Danke,

Ansgar.

rudolfkoenig

Zitatim CUL_HM Änderungsvorschlag wird während der FHEM Initialisierung ggf. ein notwendigerweise anderes IO bevorzugt, als der übergebene $attrval
Anders formuliert: der Benutzer setzt ein Attribut, dem Modul passt der gesetzte Wert nicht, will was Anderes setzen, und der Benutzer soll diese Manipulation nicht mitkriegen. Wenn ich dabei nichts Wesentliches uebersehen habe(*), dann finde ich das nicht ok, und bin auch nicht bereit, es mit dem Framework zu unterstuetzen.

Ausserhalb des Frameworks kann man das auch jetzt schon machen, indem man nach der Initialisierung den Attributswert ueberbuegelt.

*: Da ich keine Klartext-Begruendung fuer die Notwendigkeit gefunden habe, versuche ich das aus dem 10_CUL_HM.pm Patch abzuleiten, gelingt mir aber nicht. Wenn CUL_HM besser weiss, welches IODev zu einem Geraet gehoert, als der Benutzer, wieso laesst es das Attribut ueberhaupt zu?

noansi

#2
Hallo Rudolf,

ZitatAnders formuliert: der Benutzer setzt ein Attribut, dem Modul passt der gesetzte Wert nicht, will was Anderes setzen, und der Benutzer soll diese Manipulation nicht mitkriegen. Wenn ich dabei nichts Wesentliches uebersehen habe(*), dann finde ich das nicht ok, und bin auch nicht bereit, es mit dem Framework zu unterstuetzen.
Nun,
- der andere Wert wird für den Nutzer schon sichtbar im Attributwert. Natürlich wäre es auch kein Problem an der Stelle noch einen Log Hinweis zu ergänzen.
- mit entsprechendem verbose level gibt es auch Log Einträge, wenn IODev genutzt wird, siehe CUL_HM_assignIO Code
- nur, wenn die Möglichkeiten des automatischen IO Wechsels von CUL_HM mit VCCU genutzt werden, kommt es überhaupt zum Tragen. Und dann ist es gut, wenn nach einem FHEM Restart das zuletzt genutze IO auch wieder verwendet wird, statt des IODev Attributs. Sowohl funktional, als auch für tsculfw CULs mit wenig Speicher schonend für deren EEPROM. Wird vor einem FHEM Neustart "Save config" genutzt, dann wird auch das zuletzt zugewiesene IO im IODev Attribut in der config gespeichert.
- sofern andere IO-Typen für HM ein Rücklesen zugewiesener devices unterstützen, könnten sie den funktionalen Vorteil ebenfalls nutzen
- wenn zusätzlich noch das Attribut IOgrp mit Vorzugs-IO genutzt wird, dann ist das IODev Attribut nicht mehr "Master", sondern das gesetzte Vorzugs-IO (sofern nicht auf Fehlerstatus). Das ist schon lange so. Wenn IODev dazu nicht passend gesetzt ist, führt das derzeit eher zu Problemen.
- "unterstützen" tut es das Framework ja schon großenteils, wenn auch nicht beabsichtigt, störend ist aus bisheriger Sicht nur die u.U. verwirrende Meldung und Log Einträge

Zitatwieso laesst es das Attribut ueberhaupt zu?
Es gibt virtuelle devices, die es benötigen. Die anderen Wege greifen da nicht.
Wird keine VCCU benutzt, dann bestimmt IODev das genutzte IO. Notnagel, wenn auch das nicht verfügbar ist, ist AssignIoPort, siehe CUL_HM_assignIO Code.

Hier der Anlass, das IODev Attribut Thema überhaupt anzupacken -> https://forum.fhem.de/index.php/topic,119853.msg1144425.html#msg1144425

ZitatAusserhalb des Frameworks kann man das auch jetzt schon machen, indem man nach der Initialisierung den Attributswert ueberbuegelt.
Dann müsste das Framework das mit Kapselung verhindern, sonst verstehe ich den Einwand oben nicht so ganz in Konsequenz (nicht das ich das damit herauf beschwören wollte  ;) ).

Gruß, Ansgar.

rudolfkoenig

Soweit ich sehe, wird hier verzweifelt versucht ein Attribut fuer etwas zu missbrauchen, was eigentlich Reading sein sollte.

Attribut ist das, was der Benutzer setzt. Reading ist das, was das Modul setzt, wenn es gepsiechert werden soll. Mir ist bewusst, dass das zunehmend vermischt wird, und das ich auch nicht immer konsequent bin, das ist aber keine Begruendung es weiter zu treiben, eher im Gegenteil.

Ich verstehe schon, dass ein Umbau auf Reading mehr Arbeit bedeutet, ich faende es aber toll, wenn nicht bei jedem Problem sofort eine Ausnahme vom beabsichtigten Architektur gemacht wird.

Wie sehen das die anderen Mitschreiter?

Beta-User

Hallo zusammen,

bin zwar alles andere als ein SW-Architekt, aber ganz allgemein finde ich die Vermischung von Attribut ("gehört dem User") und "allem anderen" nicht glücklich.

Bei CUL_HM ist das Phänomen ziemlich verbreitet, eventuelle Uservorgaben auch schon mal zu "überstimmen" z.B. auch, was "model" angeht. Das "Problem" scheint mir zu sein, dass es eigentlich eine "Klasse" zwischen Readings (fhem.save) und Attributen bräuchte, die dann auch dem Userzugriff entzogen sein sollte und (klassisch) in der fhem.cfg zu verorten wäre. Das Problem ist, dass die Info vorhanden sein "muss", was schiefgeht, wenn es (noch) keine Readings gibt (ok, da kann man dann defaults setzen, die aber falsch/kontraproduktiv sein könnten) oder die fhem.save kaputt, verloren, whatever...

Jedenfalls gibt es zu dem IO-Thema auch eine Diskussion mit martinp876, in der er auch erläutert hat, was er "dann noch" im Nachgang so macht. Ist evtl. hier auch interessant: https://forum.fhem.de/index.php/topic,112302.msg1067739.html#msg1067739.
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

noansi

#5
Hallo Zusammen,

ZitatSoweit ich sehe, wird hier verzweifelt versucht ein Attribut fuer etwas zu missbrauchen, was eigentlich Reading sein sollte.
Darüber habe ich auch schon nachgedacht und denke auch, dass es eigentlich ein guter Weg wäre den Zustand auch über den Restart für alle IO Zuordnungen zu sichern. Da es bei CUL_HM_assignIO schnell gehen muss allerdings mit Sparvariante ohne Zeitstempelaktualisierung.

Zunächst ging es aber um den Fix des Problems, dass das Setzen des Attributes im laufenden Betrieb nicht zu vollwertiger Umstellung auf das gewünschte neue IO führt. Damit eine notwendige Behandlung des Attributs durch das CUL_HM Modul, um die Funktion zu erreichen. Und dabei das kleine Hinderniss der unerwünschten Meldungen.
Daraus haben sich die weiteren Fragestellungen ergeben, dass auch das Setzen beim FHEM Start bisher nicht sauber funktioniert hat.
Das vor dem Zielkonflikt, die Änderungsvorschläge nicht zu umfangreich und abweichend vom bisherigen Stand werden zu lassen. Schließlich besteht der Wunsch, dass sie vom Maintainer zumindest funktional auch übernommen werden.

Die Multi-IO Unterstützung von CUL_HM gepaart mit schnellen Antworttiminganforderung und aktiven IOs stellt etwas andere Anforderungen, als es das Framework derzeit für die IO Zurodnung bietet. Ich hoffe, das ist schon etwas klarer geworden.

Von daher sind meine Fragestellungen
- Wurde es nicht bedacht, in der vorgeschlagenen Art das Attribut allein durch das nutzende Modul behandeln zu lassen?
- Gibt es noch andere Anwendungen in FHEM bezüglich IODev, die von mehr Flexibilität bei Attribut IODev profitieren würden? Es sich somit lohnen würde meine Patchanfrage besser direkt etwas umfangreicher anzugehen, statt des vorgeschlagenen sparsamen Flickwerks?
- Würde es mal noch andere Attribute geben, die eine Sonderbehandlung in fhem.pl erfordern und die gleichfalls von der Lösung betroffen wären, respektive davon profitieren könnten?
- Habe ich eine andere Möglichkeit zur einfachen Lösung unter Nutzung von IODev übersehen, so dass mein Patchvorschlag überhaupt nicht notwendig wird?
- Habe ich Nebenwirkungen auf andere Module durch den Patchvorschlag übersehen (z.B. ist mir der Trigger am Ende erst später aufgefallen, womit Save Config anfangs kein rotes '?' bekam)?
- Oder gibt es im Gegenteil eher einen Konsens dieses spezielle Attribut durch das Framework alleine in der Sonderform verwalten zu lassen? Dann verwerfe ich den ganzen Patchvorschlag bezüglich IODev besser und suche andere Wege.

ZitatAttribut ist das, was der Benutzer setzt. Reading ist das, was das Modul setzt, wenn es gepsiechert werden soll.
Das habe ich verstanden. autosave hat die Grenzen aber aufgeweicht. Ebenso die globale Datenhaltung mit direktem Zugriff (anfangs mit wenig bis keinen Zugriffsmethoden, richtig?), die den "Missbrauch" sehr verführerisch gemacht hat, aber auch performant im Vergleich zu Methodenzugriff.
Zitatdas ist aber keine Begruendung es weiter zu treiben, eher im Gegenteil
Dem stimme ich zu. autosave ist bei mir übrigens aus.

ZitatIch verstehe schon, dass ein Umbau auf Reading mehr Arbeit bedeutet, ich faende es aber toll, wenn nicht bei jedem Problem sofort eine Ausnahme vom beabsichtigten Architektur gemacht wird.
Nicht die Mehrarbeit ist das Problem, sondern den Kompromiss für den Zielkonflikt zu finden.

ZitatBei CUL_HM ist das Phänomen ziemlich verbreitet, eventuelle Uservorgaben auch schon mal zu "überstimmen"
Ist auch durchaus sinnvoll, um historische Einstellung automatisch auf aktuellen Stand umzustellen und auch um offensichtliche Einstellfehler zu korrigieren. Macht dem User das ohnehin schon kompilzierte Einstell-Leben einfacher.

ZitatDas Problem ist, dass die Info vorhanden sein "muss", was schiefgeht, wenn es (noch) keine Readings gibt (ok, da kann man dann defaults setzen, die aber falsch/kontraproduktiv sein könnten)
Im Grunde ist das auch die Begründung für die Sonderbehandlung des IODev Attributs, da die config die Reihenfolge der Definitionen nicht vorschreibt/schreiben möchte -> Verlagerung des Setzens ans Ende der Initialisierung, wenn alle IOs definiert sein sollten.
Da kommt mein IODev Änderungsvorschlag in CUL_HM beim FHEM Init nicht dran, weshalb etwas Disziplin bei der Ordnung in der config für volle Funktionalität erforderlich ist.

Damit wäre es eigentlich besser, einem Modul die Möglichkeit zu geben, eine Funktion bereit zu stellen, die zu diesem Zeitpunkt modulspezifische IO Zuweisung durchführt.
Beispielsweise eine $modulhash->{FinalizeInitFn}, die mit Leben gefüllt werden kann, wenn es benötigt wird. Fehlt sie, werden die FHEM default Aktionen ausgeführt bzw. FHEM default Werte gesetzt. Damit auch offen für andere Problemlösungen.

Gruß, Ansgar.

CoolTux

Zitat
- Gibt es noch andere Anwendungen in FHEM bezüglich IODev, die von mehr Flexibilität bei Attribut IODev profitieren würden? Es sich somit lohnen würde meine Patchanfrage besser direkt etwas umfangreicher anzugehen, statt des vorgeschlagenen sparsamen Flickwerks?

Die Max Modulreihe würde davon profitieren. Ich weiß das Wzut daran mal gearbeitet hatte, habe aber keine Ahnung wie weit er damit gekommen ist.


Grüße
Marko
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

Beta-User

Zitat von: noansi am 24 April 2021, 00:06:13
Von daher sind meine Fragestellungen
- Wurde es nicht bedacht, in der vorgeschlagenen Art das Attribut allein durch das nutzende Modul behandeln zu lassen?
Na ja, nach meiner Erfahrung in MySensors kann es zu Situationen kommen, dass einfach das falsche IO verwendet wird, wenn man sich bei autocreate etc. nicht aktiv kümmert. Weiß nicht, inwieweit das jeweils bei anderen zweistufigen Modulen bedacht wurde bzw. ob es da wegen anderer Matching-(Parse-) Strukturen dieses Problem überhaupt in der Form gab/gibt.

Spätestens dann muss der User eingreifen, ähnliches gilt, wenn er Nodes oder IO's anders platziert. Kann ich bei MySensors bei späteren Änderungen vermutlich nicht automatisiert feststellen (oder nur mit sehr hohem Aufwand), bei der initialen Festlegung ist es seit einiger Zeit gefixt.

Zitat- Oder gibt es im Gegenteil eher einen Konsens dieses spezielle Attribut durch das Framework alleine in der Sonderform verwalten zu lassen?
Aus obigen Grund: Dagegen!
gilt 1:1 auch so z.B. für MQTT2_DEVICE; da kann sich das IO auch schon mal ändern, wenn der User die zugrundeliegende Infrastruktur umbaut.

Zitat
Das habe ich verstanden. autosave hat die Grenzen aber aufgeweicht.
autosave ist mAn. zwischenzeitlich (wieder?) allgemein verpönt.

Ansonsten war das mit dem Hinweis, dass CUL_HM Attributinhalte schreibt ausdrücklich keine wirkliche Kritik! Ich fand es aus Usersicht befremdlich, aus heutiger Sicht ist es klar, dass man als Developer keine andere Option hat.
Der Kritikpunkt beschränkt sich daher lediglich auf den, dass das zugrundeliegende framework den Grundsatz "Attribute gehören dem User" durchbricht. Muss man halt an der einen oder anderen Stelle wissen und akzeptieren, that's all.
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

Ich rate weiter, da ich immer noch keine Ursachenbeschreibung gehoert habe: CUL_HM hat Probleme in Multi-Controller Setups, fuer Geraete wie Fernbedienungen, die herumgetragen werden, und deswegen jeweils von unterschiedlichen Controller angesprochen werden sollten. An sowas habe ich bei der Einfuehrung von IODev sicher nicht gedacht.

Ein Schritt zurueck:
- das IODev Internal wird in IOWrite verwendet, den "offiziellen" Weg der Kommunikation vom logischen Modul (wie CUL_HM) zu physischen (wie CUL).
- das FHEM Framework hilft mit AssignIoPort und weiteren Code, um ein passendes IODev zu finden, der Benutzer kann das mit dem IODev Attribut ueberschreiben.
- etwas ungeschickt ist, dass AssignIoPort das IODev Attribut auch setzt. Das ist notwendig wenn mehr als ein physisches Modul das Geraet theoretisch bedienen koennte, aber nur einer es richtig kann.

Attribute gehoeren dem Benutzer, die sind auch nicht dafuer ausgelegt, dauernd vom Modul geaendert zu werden, das ist die Domaene der Reading.

Vorschlag:
- AssignIoPort setzt statt den IODev Attribut ein IODev Reading
- setstate (der fuer das Setzen der Readings beim Initialisieren zustaendig ist), wird analog zu attr IODev speziell behandeln, und das IODev Reading setzen.
- wenn ein Modul IODev aendert, dann soll es auch das Reading setzen (z.Bsp. mit AssignIoPort).
- der Benutzer kann alles mit dem IODev Attribut ueberschreiben, das ist im Normalfall aber nicht notwendig.
Mir ist noch unklar, wie die Uebergangsphase funktionieren soll, stichwort Kompatibilitaet. Eine Loesung waere dem Benutzer mitzuteilen, im Problemfall bitte das alte IODev Attribut zu loeschen.

ZitatDamit wäre es eigentlich besser, einem Modul die Möglichkeit zu geben, eine Funktion bereit zu stellen, die zu diesem Zeitpunkt modulspezifische IO Zuweisung durchführt.
Ich koennte zwar ein FinalizeInitFn inbauen, aber es gibt bereits zwei Loesungen fuer dieses Problem:
- NotifyFn auf global:INITIALIZED
- im InitializeFn ein InternalTimer mit 0 als Timeout starten. Diese Variante ist deutlich billiger und einfacher als die NotifyFn Variante.


ZitatIch fand es aus Usersicht befremdlich, aus heutiger Sicht ist es klar, dass man als Developer keine andere Option hat.
Dann muss man halt an Optionen arbeiten.
Z.Bsp. indem der Modulautor im Modul- oder Instanz-Hash ein defaultAttr pflegt, was AttrVal() zurueckliefert, falls kein Attribut gesetzt ist.

noansi

#9
Hallo Zusammen,

erst mal Danke für die Beiträge bisher und Deinen Vorschlag, Rudolf.

Zusätzlich ist zu Unterscheiden zwischen FHEM Init und dem laufenden Betrieb.

Initphase:
Noch einen Schritt zurück.
Bei einem Neustart von FHEM (kann auch der harte ohne vorheriges shutdown sein) existiert eine IO Zuordnung.
Die IOs waren aktiv vorbereitet und "kennen" ihre devices auf die sie mit eigenen Automatismen antworten sollen (d.h. nicht nur sende- sondern auch empfangsrelevant) und tun dies auch weiter, wenn ihnen nichts anderes gesagt wird.
Das Attribut IODev kann zu der Zuordnung passen oder auch nicht mehr.

Die auf den IOs ist aber in der Regel die aktuell günstigere und soll möglichst beibehalten werden können. Das ist Modulabhängig und ggf. auch abhängig davon, ob das IO seinen Zuweisungszustand auch wieder zur Verfügung stellen kann.

Damit ist der attr IODev Wert in der FHEM Init Phase zu setzen oder auch anders zu setzen oder auch gar nicht. Wird es gesetzt, dann müssen alle IOs des Multi-IO-Verbundes entspechend gesetzt bzw. zurück gesetzt werden.
Ohne Ordnung in der config kann dies nur nach der kompletten Verarbeitung der config korrekt erfolgen.

Das Framework setzt derzeit sowohl das Attribut IODev, als auch das Internal IODev entweder nach Config-Attribut IODev oder entsprechend einem gefundenen kompatiblen IO.
Im Szenario ist die vom Framework gewählte Einstellung in der Regel daher falsch und die IOs nicht korrekt eingestellt, da das Framework auch diese Einstell-Funktionalität nicht bieten kann.

Bei einem harten Neustart wäre auch ein Reading IODev in der Regel falsch. Bei regulärem Neustart wäre der letzte Zustand vor einem nomalen Restart wieder nutzbar.

Zitat- NotifyFn auf global:INITIALIZED
- im InitializeFn ein InternalTimer mit 0 als Timeout starten. Diese Variante ist deutlich billiger und einfacher als die NotifyFn Variante.
- Haben beide den Nachteil, dass $init_done bereits gesetzt ist. Alle Funktionen sehen ein initialisiertes FHEM.
- Geht an/funktioniert für alle defnierten devices (so weit jeweils genutzt). Diese wiederum können einen set ausführen. Dieser set kann auf eines der devices abgesetzt werden, die eines der falsch vorbereiteten IOs nutzen, bevor deren INITIALIZED oder Init Timer durchlaufen ist.
- ReadAnswer Funktionen der IOs können bereits Empfangsdaten bekommen, die geparst und Dispatched werden und ggf. Antworten generieren, die wiederum auf die falsch vorbereiteten IOs treffen können.

Die NotifyFn Variante wird genutzt. Und leidet unter dem $init_done=1 und dass Internal IODev bereits u.U. falsch gesetzt ist. Eventuell kann man aber hier ansetzen und ein modulspezifisches init_done statt dem globalen noch nutzen.


Laufender Betrieb FHEM:
Wenn der User das Attribut IODev setzt, dann soll das Modul das Setzen des Internals IODev überschreiben und die IOs entsprechend einstellen können.
Denn wenn das Attribut IOgrp gesetzt ist und die Verwaltungsinstanz (bei CUL_HM eine VCCU) aktiv ist, dann ist automatische Zuweisung aktiv. Ggf. muss dann von der Verwaltungsinstanz ein Ausweich IO gewählt werden können. IODev habe ich für meinen Vorschlag in dem Fall nur als temporären Vorzugsvorschlag gewählt, weil damit eine Umschaltung darauf möglich ist (nicht muss) und es zu Testzwecken nützlich ist.

Das Widerspricht natürlich Deiner Vorstellung von IODev Userkontrolle.
Auf jedenfall darf das Framework nicht das Internal IODev falsch einstellen, schon gar nicht, ohne die Verbund-IOs richtig umzustellen und das ist bisher der Fall, wenn der User das Attribut im laufenden Betrieb setzt (nur das gerade aktive kann ohne Probleme gesetzt werden), denn das Attribut wird im aktuellen Modul-Code gar nicht behandelt.

Außerdem gibt es im Homematic Forum auch haufenweise User Unverständniss zur Nutzung der Attribute. Wenn IOgrp gesetzt ist und die Verwaltungsinstanz aktiv und zuständig ist, dann ist IODev nun mal nicht mehr Master bei der Zuweisung, sondern nur noch ein Notnagel.
Bei IOgrp kann man auch VorzugsIOs setzen, die bei Nutzbarkeit bevorzugt gewählt werden.
Konsequent wäre dann sogar eigentlich User setzt IODev, aber -> Attribut IOgrp VorzugsIO wird gewählt -> VCCU Attribut IOList IO wird gewählt -> Attribut IODev IO wird gewählt -> Framework AssignIO Zuweisung findet noch ein passendes IO zur Wahl, welches nutzbar ist (operabel meldet).

IOgrp alleine ist auch kein Indikator für die IODev Priorität, denn wenn die Verwaltungsinstanz nicht aktiv ist (z.B. gar nicht definiert), dann ist wieder IODev der Master und IOgrp bedeutungslos.

D.h. das Framework könnte das Internal IODev setzen, dann das Reading IODev mit Trigger und den Trigger müsste das Modul verarbeiten um die Internal Umstellung auf einen funktionalen Zustand einzustellen, wobei ihm aber gerade die Information entzogen wurde, welches IO gerade eigentlich aktiv war (und darf dabei aber nicht auf die Idee kommen CommandAttr zu nutzen um das IODev Attribut selbst zu setzen).

Gruß, Ansgar.

PS: Bezüglich Userverständnis muss ich sicherlich noch eine Prüfung auf einen geeigneten IO Typ einbauen, damit nicht irgendwas als IO gewählt wird.

rudolfkoenig

Ich bin der Ansicht, dass der Programmierer nicht immer klueger ist, als der Benutzer.
Wenn das Modul anderer Ansicht ist, dann schlage ich vor das Attribut nicht mehr anzubieten, dann muss man auch nicht gegen dem Benutzer kaempfen.
IOWrite kann man weiterhin verwenden, das Modul muss nur IODev selbst setzen.

Zitat- Haben beide den Nachteil, dass $init_done bereits gesetzt ist. Alle Funktionen sehen ein initialisiertes FHEM.
Habs noch nicht verstanden, warum das ein Nachteil ist.

Zitat- ReadAnswer Funktionen der IOs können bereits Empfangsdaten bekommen, die geparst und Dispatched werden und ggf. Antworten generieren, die wiederum auf die falsch vorbereiteten IOs treffen können.
Das gilt weder fuer die InternalTimer, noch fuer die NotifyFn Variante.

noansi

Hallo Rudolf,

ZitatHabs noch nicht verstanden, warum das ein Nachteil ist.
Weil mit $init_done üblicherweise ggf. anderer Code in Funktionen ausgeführt wird, als ohne.
Bei $init_done==0 oder undef ist klar, dass man noch im Initialiserungsbereich von FHEM unterwegs ist. Derzeit sagt es, dass noch nicht alle devices definiert und noch nicht alle Attribute und Readings gesetzt sind.

ZitatDas gilt weder fuer die InternalTimer, noch fuer die NotifyFn Variante.
Aus ReadAnswer von CUL.
$init_done ist gesetzt, wenn InternalTimer oder NotifyFn verwendet wird:
    # Dispatch data in the buffer before the proper answer.
    while(($mculdata =~ m/^([^\n]*\n)(.*)/s) || $anydata) {
      my $line = ($anydata ? $mculdata : $1);
      $mculdata = $2;
      $hash->{PARTIAL} = $mculdata; # for recursive calls
      (undef, $line) = CUL_prefix(0, $ohash, $line); # Delete prefix
      if($regexp && $line !~ m/$regexp/) {
        $line =~ s/[\n\r]+//g;
        CUL_Parse($ohash, $hash, $ohash->{NAME}, $line) if($init_done);
        $mculdata = $hash->{PARTIAL};
      } else {
        return (undef, $line);
      }
    }

Wenn die regexp nicht matched, weil schon Empfangsdaten rein kommen, dann wird geparsed, oder übersehe ich was?

Gruß, Ansgar.

rudolfkoenig

ZitatWeil mit $init_done üblicherweise ggf. anderer Code in Funktionen ausgeführt wird, als ohne.
Ok, aber wieso ist das ein Nachteil?

ZitatWenn die regexp nicht matched, weil schon Empfangsdaten rein kommen, dann wird geparsed, oder übersehe ich was?
Nein, aber das ist kein Argument fuer ein Framework-Umbau, sondern eher eins fuer CUL_ReadAnswer bzw. CUL_DoInit Umbau.
Ich gehe davon aus, dass CUL_ReadAnswer bei dem urspruenglichen Problem nur eine theoretische Rolle spielt.

noansi

Hallo Rudolf,

ZitatOk, aber wieso ist das ein Nachteil?
Weil andere Module, die ebenfalls eine NotifyFn oder InternalTimer eben schon Aktionen mit sets auslösen können. Und das bevor das CUL_HM Modul mit seiner NotifyFn dran war, um seine IOs richtig vorzubereiten. Mit Modul eigenem initDone kann man dem begegnen, die Baustelle wird nur wieder größer, weil es derzeit nicht so ist.
Daher der Vorschlag einer FinalizeInitFn, die vor $init_done=1 eingebaut werden könnte. Womit klar wäre, dass alle devices definiert, Attribute und Readings gesetzt sind, aber kein vollständiger Init auch der Module durchgelaufen ist.

ZitatIch gehe davon aus, dass CUL_ReadAnswer bei dem urspruenglichen Problem nur eine theoretische Rolle spielt.
Ein konkreter von vielen Fallstricken. Ich findes es bedenkenswert bezüglich einfach oder kompliziert auch für den Anwender des Frameworks.
Rein praktisch sehe ich beim FHEM start schon mal Log Einträge, die mir klar sagen, dass Empfangsdaten aus den IOs zu früh verarbeitet werden und Aktionen auslösen. Nicht nur im Bezug auf das ursprüngliche Problem.

ZitatIch bin der Ansicht, dass der Programmierer nicht immer klueger ist, als der Benutzer.
Wenn das Modul anderer Ansicht ist, dann schlage ich vor das Attribut nicht mehr anzubieten, dann muss man auch nicht gegen dem Benutzer kaempfen.
IOWrite kann man weiterhin verwenden, das Modul muss nur IODev selbst setzen.
Wenn der erste Satz nicht mit Bezug auf IODev flexibler im Sinne unterschiedlicher Anwendungsszenarien betrachtet werden kann, stimme ich dem zweiten zu und möchte zusätzlich nochmal präzisierend Internal IODev als zu setzend in Erinnerung rufen (weil es dazu schon mal Missverständnisse gab).

Gruß, Ansgar.

rudolfkoenig

Ich fange an deine Vorbehalte gegen InternalTimer zu verstehen, allerdings ist FinalizeInitFn prinzipiell auch nicht anders.
Wenn wir dafuer eine sinnvolle Reihenfolge erfinden koennten, dann waere das womoeglich auch fuer InternalTimer anzuwenden.

Zitatund möchte zusätzlich nochmal präzisierend Internal IODev als zu setzend in Erinnerung rufen (weil es dazu schon mal Missverständnisse gab).
Ich fuerchte da musst Du weiter ausholen, oder an die passende Stelle verweisen, da meine Erinnerung mich im Stich gelassen hat.

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.

martinp876

Ich sehe nicht, dass sich nichts ändert. Auf die Schnelle verstehe ich es nicht und sehe keine Dokumentation, was da geschehen soll in Bezug auf IODev.
Es gibt weiter ein Attr IODev, Reading IODev und Internal IODev

IsIoDummy() : welche funktion hat das?
IOWrite(): hier wird das Internal IODev genutzt.
=> das Internal ist also das operationell relevante Datum

fhem_setIoDev(): diese Funktion ist zu nutzen, um das IO zusetzen. Bedient werden das Internal und das Reading.
=> interessant: sollte man ein "falsches" device setzen wird das Internal "IODevMissing" gesetzt.
=> existiert das Attr IODev  und passt es nicht zum "Wunsch" wird die Aktion abgebrochen (hä?)
=> wenn alles klappt wird das Reading gesetzt und das Internal gelöscht

Ich vermute, fhem_setIoDev() sol genutzt werden, das IO zu aktivieren. Ich muss nun aber erst das Arrtibut löschen oder es passend zu setzen. Ehrlich, was ist der Hintergrund hierzu?

Erwartet hätte ich, dass wenn ich "val" nicht sende, ein IO gesucht wird. Dann wäre es eine wirklich funktionale Methode.
Ich hätte mir gewünscht:
- wenn !init_done => merken und bei/mit/nach init_done aufräumen
- wenn init_done weise das IO zu gemäß: 1) wunsche(val), 2) best-effort (entsprechend AssignIOPort)
- return könnte das IO device sein.

AssignIoPort: hier reden wir nun von einem "port", und nicht mehr von einem "Device" - ist aber wohl identisch - ok.
  Prio 1 ist das Attribut, prio2 das Reading. Wirklich sauber ist es nicht implementiert. Wenn das Attribut auf ein disabled device zeigt wird ein potentiell mögliches Reading nicht berücksichtigt.


Warum wird hier nicht aufgeräumt und eine klare Linie verfolgt? Definitionen sind hilfreich - insbesondere wenn sie auch niedergeschrieben werden! Ich haben einige Abfragen zu "Clients" gefunden - aber bei mir keine Implementierung  gesehen. Doku ebensowenig.


IODev handling - wie ich es sehe
1) capabilites: Clients soll wohl in irgend einer Form die Möglichkeiten abbilden, bspw welche IOs ein Device nutzen könnte. Das wäre cool, aber nicht hinreichend. Zum einen haben wir schlechte und gut IOs. Eine CUL kann HM unterstützen, aber sehr schlecht. tscul ist hier angesagt. Wie also soll das funktionieren, wo kann ich es lesen?
2) possible: das finde ich garnicht - CUL_HM hat etwas implementiert. Man hat mehrere IOs und diese werden den Devices zugewiesen (Stichwirt vccu) - nach Prio, settings werden geprüft, bereitschaft wird geprüft. So etwas könnte man zentral machen... gibt nichts.

3) wunsch Realisierung (meine Meinung)
Attribut IODev ist Anwender Initial Value. Wenn es gesetzt wird, wird es geprüft und, wenn möglich aktiv gesetzt. Weiter ist es default wenn kein "Wunsch" geäussert wird. Operationell ist das Reading relevant, was mit den Internal identisch sein MUSS (warum man das auch immer 2-mal braucht - sollte aufgeräumt werden)

AssignIoPort ist als methode nur kernal-intern notwendig

fhem_setIoDev() Ablauf
IO-wunsch wird auf funktionalität geprüft (vorhanden/enabled<>dummy/aktiv<>error<>temporary inactive) . Aktionen müssen definiert werden.
wenn Io-Wunsch gültig und es mit den current (Internal) identisch => do nothing
wenn Io-Wunsch gültig und änderung zu current (Internal) setze IO in reading und internal
wenn Io-Wunsch ungültig prüfe current. Wenn gültig => do nothing
wenn Io-Wunsch ungültig prüfe current. Wenn ungültig prüfe Attribut. Wenn gültig => setze IO auf Attribut
wenn Io-Wunsch ungültig prüfe current. Wenn ungültig prüfe Attribut. Wenn ungültig suche Optionen. Wenn gültige Option gefunden, setze diese. Wenn keine gefunden wurde disbale IO. Setze current auf "not available".

=> im Reading kann ich dann immer sehen -und nachverfolgen - welches IO gesetzt ist und auch wenn keines zu verfügung steht.

Das ist eine Umwidmung der Semantic von attr IODev - und m.E. eine klare definition: ein initial value.





rudolfkoenig

ZitatIch sehe nicht, dass sich nichts ändert.
Woran siehst Du das?

ZitatIsIoDummy() : welche funktion hat das?
Prueft, ob das IO-Device dummy ist, um zu wissen, ob das Senden eine Auswirkung haben wird. Wird bisher von drei uralten EM*.pm Modulen verwendet, damit bei get sofort eine Fehlermeldung zurueckgeliefert wird. Kann ich gerne entfernen, es verwirrt offensichtlich.

Zitatfhem_setIoDev(): diese Funktion ist zu nutzen, um das IO zusetzen. Bedient werden das Internal und das Reading.
Ich weiss nicht, von wem diese Nachricht stammt, von mir nicht. Sie ist eine fhem.pl Hilfsroutine.

Wie geschrieben: Weder fuer den Modulautor, noch fuer den Benutzer soll sich was aendern.
Es sei denn, man macht als Modulautor komische Sachen, wie AssignIoPort aufrufen, und erwarten, dass ein Attribut gesetzt wird.

Ich verstehe, dass man schlechte Laune hat, und den Aerger auf dem Erstbesten auslassen will, fuehrt aber in diesem Fall nicht weit..
Falls man mir ein konkretes Problem schildert, dann werde ich versuchen eine Loesung zu finden.

noansi

Hallo Martin, hallo Rudolf,

ZitatReading relevant, was mit den Internal identisch sein MUSS (warum man das auch immer 2-mal braucht - sollte aufgeräumt werden)
Das neue Reading wird gebraucht, da es beim fhem Neustart gespeichert wird und ermöglicht, das letzte vor dem Neustart genutzte IO wieder einzustellen.

Für ein z.B. VCCU Autoassign eine sinnvolle Methode, da sich über einen Neustart die Umgebungsbedingung (Stichwort RSSI basierte IO Zuweisung) in der Regel nicht großartig ändern und "intelligente" IOs mit gleicher Einstellung ihrer zugewiesen Clienten weiter arbeiten können.

Für das Attribut ist das Speichern eine Option und stellt den vorherigen Stand daher nur optional wieder ein.

Für die Verarbeitungsgeschwindigkeit und Kompatibilität zu bestehendem Code ist das Internal weiterhin sinnvoll.


Aus meiner Sicht ist das Reading derzeit eine nutzbare Hilfskrücke, damit bei einem fhem Neustart die gleiche Einstellung durch fhem.pl wieder eingestellt wird, wie sie zuvor im IO eingestellt war (so denn der User das Attribut IODev gelöscht hat!).

Eigentlich wollte ich nur den im IO gespeicherten Zustand wiederherstellen (,der ja eigentlich durch vorherige Wahl von Attributeinstellungen durch den User mehr oder minder direkt zustande gekommen ist), bevor fhem IO Empfangsdaten zu verarbeiten beginnt, aber schon alle HM devices und HM IOs definiert sind.


ZitatIODev handling - wie ich es sehe
...
Nebenbei habe ich mir andere CUL sendend nutzende Module um ein Attribut 'IODevList' erweitert, um bei Ausfall des ursprünglich via IODev gesetzten IOs eine (funktechnisch, empirisch) nutzbare automatische Ersatz-IO Wahl zu ermöglichen. Damit wird bei IO Ausfall das erste verfügbare IO aus dieser IODevList eingestellt.
Die von fhem.pl bereit gestellten Möglichkeiten haben dazu nicht gereicht, da AssignIoPort in automatischer Form nur Modulkompatibilität nutzt, aber die funktechnische Erreichbarkeit damit nicht abgedeckt wird. Ging in den Fällen auch nur nach Liste, weil die entsprechenden Clientgeräte keine Rückmeldung geben und damit kein RSSI als Entscheidungshilfe verfügbar ist. Würde es eine Qualitätsinformation, wie RSSI, geben, dann hätte ich die auch mit genutzt.
Die gedankliche Anregung dazu war CUL_HM mit VCCU IOList.

Das wäre ein Anregung zur Erweiterung von AssignIoPort (oder eine alternative Funktion). Einmal eine IO Liste zu nutzender IOs (inklusive des VorzugsIOs) und dann ein Standardinternal/-reading /-helper (z.B. ein Internal IOq_<IOName>), dass das anfordernde device bereit stellen kann, um die "Qualität" eines nutzbaren IOs im Vergleich zu anderen IOs anzugeben. Zusätzlich müssten IOs auf standardisiertem Wege ihre tatsächliche Nutzbarkeit bekannt geben können.
Derzeit ist es ein Abenteuer, die zu ermitteln, wenn mehrere unterschiedliche IOs (unterschiedliche Module) nutzbar sind.

Gruß, Ansgar.

martinp876

Hallo Ansgar,
ZitatDas neue Reading wird gebraucht, da es beim fhem Neustart gespeichert
sehe ich nicht so.
Wenn das io statisch eingestellt wird ist es statisch. Punkt. Das muss das Reading nichts speichern, was wiederhergestellt werden müsste.
Wenn das IO dynamisch vergeben wird kann die Ermittlung nach einem Neustart gestartet werden. Das muss funktionieren.
Man kann es auch in einem Reading speichern - nötig darf es nicht sein.

ZitatFür das Attribut ist das Speichern eine Option und stellt den vorherigen Stand daher nur optional wieder ein.
Das ist Sache von Rudi, es festzulegen. Das sollte bei CUL_HM und dessen IOs nicht anders ein als bei allen anderen.

Die aktuelle Implementierung und die von Rudi bereitgestellten Methoden/Funktionen sind nicht schlüssig. Ich kann über Assignments ein IO einstellen, aber nur wenn es kein Attribut gibt. By all means... wie soll man das nutzen? Indem du in CUL_HM readings manuell und unter Umgehung aller Kernal-methoden setzt? Wozu dann die Kernal-methoden?

ZitatEigentlich wollte ich nur den im IO gespeicherten Zustand ....aber schon alle HM devices und HM IOs definiert sind.
Es macht Sinn, nach dem Init "aufzuräumen". Es gibt einige Consitancy-checks welche nach dem einlesen aller *.cfg und aller Readings ausgeführt werden müssen. Das muss eigentlich JEDES Modul machen. CUL_HM macht das schon geraume Zeit - eine Funktion nach "KernelInit" triggern und dann Attribute und zuordnungen prüfen, bearbeiten, ggf updaten oder löschen. Du kennst die Funktion und ich würde sie bei jedem Modul fordern, welches Abkängigkeiten prüfen muss.

Was also sind meine Probleme:
1) wenn man ein Reading betreibt, sollte es den üblichen Methoden und verhalten unterliegen. Also die Kernel Methoden nutzen und die Notifcation unterstützen.
2) die Kernel methode muss genutzt werden können zum IO setzen. Kann sie nicht, da das Attribut Prio1 hat und nicht angepasst wird. Entweder setze ich das Attribut vorher oder ich lösche es.
3) Für CUL_HM gelten dann 3 Regeln
3a) für devices welche kein "auto-IO" eingestellt haben wird das Attribut genutzt. Period.
3b) für devices welche eine vccu nutzen (auto-IO) wird das Attribut IODev gelöscht. Das IO wird durch die VCCU und deren Methoden geregelt
=> IOgrp löscht IODev!
3c) bei Devices ohne IOgrp und ohne IODev suchen sich ein Device gemäß den aktuellen Regeln (Assign-IO oder beim pairen das Device, welches es meldet.

Die Funktion fhem_setIoDev ist dann nutzbar. Bei "statischen IOs" beim Setzen des Attribut, bei dynamischen bei jeder Änderung.

wirklich sinnvoll wäre es, wenn der Kernel solche Verhalten implementiert so dass es einheitlich im System ist. Also bei fhem_setIoDev alle 3 Attribute setzen. Wie kann man annehmen dass der Programmierer ein "gewünschtes" IO aussucht welches eigentlich nicht  gültig ist. Das ist doch ein internes Interface, keine User-Methode!!!




noansi

#34
Hallo Martin,

ZitatWenn das IO dynamisch vergeben wird kann die Ermittlung nach einem Neustart gestartet werden. Das muss funktionieren.
Man kann es auch in einem Reading speichern - nötig darf es nicht sein.
Ja, wenn das Attribut IODev und jetzt auch das Reading IODev entfernt sind, somit die IO Assignment Mechanismen fhem.pl nicht angesprochen werden.
Weiterhin darf dem User dann das Attribut IODev nicht mehr angeboten werden, denn damit setzt er wieder die Funktionen von fhem.pl in Gang, ohne das die IOs selbst was davon mitbekommen.
Auch darf beim Autoassign nicht mehr auf AssignIOPort als "letzten Rettungversuch" zurück gegriffen werden. Die Funktion ist auch zu langsam, um falls sie zufällig ein funktechnisch sinnvolles IO gewählt hat, noch rechtzeitg senden zu können.

Außerdem darf kein IO vorzeitg geparste Daten in die Parse Funktion schieben und damit über die Verarbeitung/Eventverarbeitung eventuell IO-Aktonen anstoßen, die ihreseits wieder ein Assignment erfordern/anstoßen, bevor die Wiederherstellung abgeschlossen ist.

ZitatIch kann über Assignments ein IO einstellen, aber nur wenn es kein Attribut gibt. By all means... wie soll man das nutzen? Indem du in CUL_HM readings manuell und unter Umgehung aller Kernal-methoden setzt? Wozu dann die Kernal-methoden?
Die Umgehung der Kernel-methoden dient der Geschwindigkeit, da beim Autoassign vor dem Senden trödeln sicher nicht die beste Beschäftigung der CPU ist.

Es ist Rudolfs Vorgabe (und ich habe auch entsprechende Uservorstellung in anderem Zusammenhang gelesen), das ein gesetztes Attribut als Userwille Vorang hat. Sich damit auch das einstellt, was der User sich da vorgestellt hat. Wenn er die Blockade nicht duch das Löschen des (angebotenen) Attributs aufhebt, soll es eben nicht automatisch funktionieren.

Wenn der User gleichzeitig Attribute für die Automatik setzt, dann wir es mit dieser "Regel" spannend (bisher ist das ja Nomalzustand).
Will er IODev starr oder will er IOgrp Automatik? Oder hat er nur nicht begriffen, wofür was wie gut ist (was nach allem Lesen im Forum die wahrscheinlich zutreffende Variante ist).

Zitat1) wenn man ein Reading betreibt, sollte es den üblichen Methoden und verhalten unterliegen. Also die Kernel Methoden nutzen und die Notifcation unterstützen.
Muss nicht, denn Readings kann man auch unter Nutzung der Kernel Methoden setzen, ohne dass Events ausgelöst werden. Das legt der Programmierer fest.
Allerdings wird ja noch mehr dabei gemacht, z.B. Datum/Uhrzeit des Readings setzen. In diesem Fall nicht wirklich von Interesse.
Würde es Events auslösen käme sicher jemand auf die Idee, dass es doch ganz toll wäre, das zu loggen oder noch anderes damit anzustellen.

Zitat3b) für devices welche eine vccu nutzen (auto-IO) wird das Attribut IODev gelöscht. Das IO wird durch die VCCU und deren Methoden geregelt
=> IOgrp löscht IODev!
Jeah. Attribut und Reading?! Und auch aus der Attributsliste?! :) Automatisch und nur geschützt durch entsprechende Hinweise in der Attributs Commandref?  :)
Ich hoffe, das geht hier durch den "TÜV", denn automatisches Löschen ist ja zunächst wiederum ein Eingriff in den User Willen. Und speichern muss er die so gänderte Config auch noch. Sonst nimmt das Drama mit dem nächsten Neustart wieder seinen Lauf.

Und wie bei den virtuellen devices? Eigentlich IODev richtig, aber es gibt noch Möglichkeiten, den RSSI von Zieldevices anzuzapfen, sofern gepeered.

ZitatDie Funktion fhem_setIoDev ist dann nutzbar.
Achtung, nur dann, wenn Rudolf sie zu einer Kernel Methode umdefiniert!
Derzeit ist sie nur eine interne Hilfsfunktion und kann sich ändern, auch im Verhalten/Umfang.

Gruß, Ansgar.

martinp876

Mein Vorgehen:
Ich werden anhand der Vorgaben des Kernel (Dokumentation = code) eine Implementierung finden. Ich denke Rudi hat Zeit bis Ende der Woche. Wenn es so bleibt wie es ist bin ich unzufrieden, aber der Kernel entscheidet. Punkt.

Meine Gedanken:
Die Implementierung von Rudi hat mich massiv enttäuscht. Es gibt nun 3 (DREI) stellen an denen das IODev abgelegt wird. Und man kann sich aussuchen, wo man es abholt. Das ist Bastelei - sorry.
Die Methoden prüfen aus meiner Sicht auf seltsame Weise die Daten. Hier fehlt ganz klar der rote Faden eines Architekten. In der SW prüft man nicht in jeder Prozedur alles - die Verantwortung liegt schon bei dem Entsprechenden Anwender. Also sind erst einmal Anwenderklassen der Funktionen zu definieren.
1) User: Alles was der User ausführen darf sollte sehr genau auf sinnhaltigkeit geparst werden
2) Anwenderentwickler: es wird noch grob geprüft - die Verantwortung steigt gewalting. Hier geht es um Funktionen/Methoden, welche ein User bswp in User-readings o.ä nutzt
3) Moduleentwickler: haben ganz klar eine große Verantwortung, die kernel methoden korrekt aufzurufen. Der Kernel muss sicherstellen, dass es nicht zum Absturz kommt - mehr eigentlich nicht.
4) kernel: nun, der code wird geprüft - intern ist wenig zu prüfen

Beispiel: fhem_setIoDev prüft ob das IO definiert ist. kann man - aber das ist nicht komplett. Wird es auch geprüft, wenn das IO gelöscht oder umbenannt wird? Wird das löschen verhindert oder die IO vergabe neu verhandelt?
Aber gut - ist eben unvollständig.

Jetzt wird beim Setzen des Readings durch den User IODev fhem_setIoDev ausgeführt - aber nur wenn das Attribut entsprechend steht. Da fehlen mir schon die Worte - ehrlich.

Es könnte so einfach sein - einfach lassen, wie es war.

Performance ist mir unklar.
Warum ist InternalVal(<dev>,"IODev","") schneller als AttrVal(<dev>,"IODev","") oder ReadingsVal(<dev>,"IODev","")
ok, direktzugriff. dann ,
warum ist $dev{<dev>}{IODev} schneller als $attr{<dev>}{IODev} oder  $dev{<dev>}{READINGS}{IODev}{val}
=> rechtfertigt das die Duplizierung des Parameters - im anwendersichtbaren Bereich? Dann sollte ich noch weitere Attribute dahin duplizieren.
==> ich bin nicht einverstanden.

Wiederherstellen nach reboot:
Bisher habe ich das Attribut IODev ungesetzt - voll automatisch. Das geht - aber es wird nur über einen restart gesichert, wenn man ein save macht. Na und? Der Mechanismus zur Errechnung des IO muss robust sein. Nach reboot wird es errechnet - fertig. Es kann sein, dass ein andere der mögliche IOs gewählt wird. Das muss übrigens funktionieren - und wird sich schnell wieder einrenken.
Wenn man es retten will - dann mache ich das dich nicht so.
Ich würde, wenn es für mich notwendig ist, ein Reading ".IODev" anlegen (unsichtbar). Der Anwender muss es nicht merken. Auch keine Implementierung im Kernel. Es gibt auch kein notify,... es wird nur die Speicheroption genutzt. Ich muss noch nicht einmal die Zeit setzen...
Nach reboot im "cleanup after boot" wird dann das Reading mit den Attributen abgeglichen. Einmalig. Wenn das Reading einen sinnvollen und gültigen Wert enthält wird er gesetzt. Ansonsten wird das Reading ignoriert. DAS IST KEINE KERNEL FUNKTION!

ZitatDie Umgehung der Kernal-methoden dient der Geschwindigkeit, da beim Autoassign vor dem Senden trödeln sicher nicht die beste Beschäftigung der CPU ist.
schlecht. Kernel funktionen sind nicht zum umgehen da. Wenn du kernal support willst, nutze ihn. wenn nicht, fordere ihn nicht. Es wird so viel Zeit für notifies verbraucht - wie oft änderst du das IODev? Das ist nicht relevant hier zeit zu sparen. Addiere einmal die Zeiten!!!

ZitatEs ist Rudolfs Vorgabe (und ich habe auch entsprechende Uservorstellung in anderem Zusammenhang gelesen), das ein gesetztes Attribut als Userwille Vorang hat
Dem stimme ich nicht zu und kann es nicht einhalten. Es gibt attribute welche ich (schon lange) automatisch setze, da sie sich aus Sachzwängen ergeben. Rudi hatte die Sereinnummer als Attribut in CUL_HM definiert - der User darf diese nicht setzen.
Ich habe "interne Attribtute" in CUL_HM definiert (model-id) welche der User nicht mit legalen Mitteln ändern kann. Braucht er es biete ich eine Methode an, es zu überschreiben.
=> hier kann ich wirklich nicht zustimmen.
=> wenn ein User das Attribut IOgrp setzt KANN das Attribut IODev nicht mehr von ihm verwaltet werden.
=> Rudis vorgaben ist tendentiell korrekt - hat aber klare Grenzen. In diesem Fall stelle ich dem Anwender klare Fallen... was sollte das helfen - und wem?  no go!


ZitatMuss nicht, denn Readings kann man auch unter Nutzung der Kernal Methoden setzen
ich weiss, was man kann. Mir fehlt dennoch die klare Linie, wenn ich es bei jeden Reading anders mache. Nogo.

ZitatUnd auch aus der Attributsliste?!
habe ich nicht gesagt, geht auch nicht. Löschen ist, das gesetzte Attribut löschen - ein Setzen verhindern.
Attributlisten kann man leider nicht je device sondern nur je Modul setzen. Daher haben wir unangenehm lange Attributlisten. Leider.


ZitatAchtung, nur dann, wenn Rudolf sie zu einer Kernal Methode umdefiniert!
Derzeit ist sie nur eine interne Hilfsfunktion und kann sich ändern, auch im Verhalten/Umfang.
na hoffentlich!
Ich bin für löschen!
Wenn sie blebt sollte es zwingend eine kernalmethode werden - schliesslich wird hier das Verhalten definiert welches nur hier dokumentiert ist.

rudolfkoenig

Ihr schreibt ja Romane. Ich habe alles gelesen, hoffentlich auch alle Punkte behalten, die angesprochen wurden.

Zu der IODev "Theorie":
- das IODev Internal wird nur vom IOWrite() verwendet, diese Funktion sollte das alleinige Interface von einem logischen Modul zum physischen sein. Die andere Richtung ist Dispatch.
- das IODev Internal wird durch AssignIoPort() vom logischen Modul gesetzt, dabei kann man einen Vorschlag unterbreiten. Dieser Wert wird fuer den Neustart in einem Reading mit dem gleichen Namen gespeichert, da die automatische Zuordnung bei mehreren physischen Geraeten sich aendern kann.
- der Benutzer hat die Moeglichkeit, die automatische Zuordnung durch ein Attribut mit dem Namen IODev zu beeinflussen.

Was sich geaendert hat: IODev wird in AssignIoPort nicht im Attribut, sondern im Reading gespeichert. Sollte weder fuer den Modulentwickler (der ja nur AssignIoPort, IOWrite und Dispatch verwendet), noch fuer den Anwender eine Aenderung bedeuten.

Ein Attribut gehoert aus Prinzip dem Benutzer. Dass ich selbst Fehler mache, soll nicht als Ausrede verwendet werden, sondern als Grund zum Aendern, wie hier gerade. Manchmal landet ein Datum im Attribut, weil ich am Anfang der Modulprogrammierung nicht weiss, ob das vom Benutzer geaendert werden soll. Wenn man spaeter sicher ist, kann man das aendern.

Der Programmierer kann nicht absehen, wie sein Programm verwendet wird (FHEM ist das beste Beispiel dafuer), deswegen soll der Wille des Benutzers respektiert werden. Wenn ich als Benutzer einen Fehler mache (d.h. ich setzte den Attribut falsch), dann muss ich mit den Konsequenzen leben. Keiner zwingt mich, den Attribut zu setzen.


Zu den einzelnen Punkten:
ZitatDas wäre ein Anregung zur Erweiterung von AssignIoPort (oder eine alternative Funktion).
Theoretisch muesste vor dem Senden jedes Ausgabegeraet geprueft werden, auf welchem Wege das aktuelle Ziel am besten erreichbar ist. Koennen die Ausgabegeraete das zuverlaessig? Gibt es einen tatsaechlichen Bedarf dafuer, oder ist das eine akademische Diskussion? Ich will mich nicht wehren, aber z.Zt. bin ich noch nicht ueberzeugt, dass es den Aufwand wert ist, da es die Sache fuer viele Beteiligte (Programmierer und Endanwender) verkompliziert.

ZitatWas also sind meine Probleme: [...]
1) und 3) habe ich nicht als Problem verstanden, sondern als Luft abassen.
2) kann ich nicht nachvollziehen, bzw. wenn es ein Problem ist, dass der "ahnungslose" Benutzer die Vorgaben der Programmierers ueberschreiben kann, und damit womoeglich das Programm unbenutzbar macht, dann ist das mAn kein Problem, sondern Absicht.

ZitatEs gibt nun 3 (DREI) stellen an denen das IODev abgelegt wird. Und man kann sich aussuchen, wo man es abholt.
Der erste Satz ist richtig, der Zweite nicht: man "holt" IODev nicht ab, man verwendet IOWrite.
Ein logisches Modul sollte keine Kenntnisse ueber die drunterligende IODevs haben, diese haben die gleiche Funktionen anzubieten, oder (wenn sie es nicht koennen), zu ignorieren. Sonst kann man nicht ohne Weiteres ein neues physisches Modul hinzufuegen, oder Hilfsmodule wie CUL_RFR oder FHEM2FHEM implementieren. Wenn man die Schnittstellen aufgibt, dann kann man auch alles in einem Modul implementieren.

ZitatIch habe "interne Attribtute" in CUL_HM definiert (model-id) welche der User nicht mit legalen Mitteln ändern kann. Braucht er es biete ich eine Methode an, es zu überschreiben.
Das kann man so machen, bedeutet aber eine Abweichung vom normal, und man darf sich nicht wundern, wenn das Modul zunehmend weniger zum Rest passt.

ZitatAttributlisten kann man leider nicht je device sondern nur je Modul setzen.
Das ist nicht richtig: wenn $defs{NAME}{.AttrList} definiert ist, dann wird sie anstatt $modules{TYPE}{AttrList} verwendet.
Diese Moeglichkeit ist jetzt etwas ueber drei Jahre alt.

herrmannj

Ehrlich gesagt finde ich das ebenfalls suboptimal. Die Logik ist total quer und vor allem die kruecke dafür ein Reading zu erzeugen ist daneben. Drei Mal io (Attribut, internal, Reading), völliger Unsinn. Wenn hier als Einzelschicksal das benötigt wird, dann speichert das doch bitte im KV Store und gebt fhem die Möglichkeit das der dev das unabhängig vom Attribut per Funktion aus seinem Modul explizit setzen kann.

noansi

#38
Hallo Rudolf,

ZitatDamit wird bei IO Ausfall das erste verfügbare IO aus dieser IODevList eingestellt.
ZitatGibt es einen tatsaechlichen Bedarf dafuer
Für die Funktion "Ersatz-IO" ja. Es ist schon beruhigend, wenn ein IO Ausfall nicht gleich einen Totalzusammbruch im System bedeuted.
Bei HM Nutzern ist dieses Einsatzgebiet häufiger zu sehen. Vermutlich auch, weil es geht.

Zitat, oder ist das eine akademische Diskussion?
Nun, Du hast das IODev Reading eingeführt, warum also nicht weiter denken?
- Wenn ein IO Ausfall per Event signalisiert wird, kann über Eventverarbeitung auch was auf Userebene gemacht werden. Die zu sendende Information ist dann aber meist verloren.
- Lösbar natürlich auf Modulebene. In dem Fall geht es zunächst um eine Ersatz Liste mit Userdefinierter Prorität, also Reihenfolge in der Liste. Damit ist dann auch eine ggf. notwendige IO  Vorbereitung erschlagbar.
Würdest Du was ins Kernel integrieren,
- würdest Du auf den IODev Attributskonflikt stoßen. Sprich, die Frage klären müssen, ob es sinnvoll ist ein gesetztes Attribut automatisch zu übergehen, wenn der User via anderem Attribut Automatik festgelegt hat. (Der Fehler des nicht Löschens des Automatikhemmers fällt nach Murphy sicher in eine Abwesenheitsphase).
- versuchen, eine standardisierten Weg für IO Ausfallsignalisierung zu etablieren

Für eine Funktion "bestes IO wählen" ist die Frage, in wieweit die IO Eignung über einen Qualitätswert ausreichend gut abbildbar ist.
Auf Modulebene vermutlich geeigneter lösbar. Der Qualitätswert wäre ohnehin schon auf Mudulebene geeignet bereit zu stellen. Das ist nicht mehr weit weg auch das IO zuzuweisen.

Gruß, Ansgar.

martinp876

Hallo Rudi,

Ich für meinen Teil sehe hier - neben dem eigentlichen Problem - architektonische und semantische Probleme. Ich kann das leider nicht in einem Satz ausdrücken - und wundere mich eigentlich, dass ich das überhaupt darlegen muss.

IOWrite ist der einzige nutzer des IO. Warum das nun nicht mehr aus den Attribut kommen soll ist mir unklar.

Ich bin nicht einverstanden, was du implementiert hast. Das ist sehr eingeschränkt und auch sehr fragwürdig.  AssignIoPort() kann ich gerne zum Setzen des IO nutzen.
Dein AssignIoPort ist aber schwach! Es mag hienreichend sein für einfache Anwendungen. CUL_HM bietet eine Möglichkeit für automatische Ersatzschaltungen von IOs. AssignIoPort bietet nur das Setzen und macht prüfungen welche ich sowieso schon mache(n muss).
AssignIoPort setzt nur das System-interface. Das IO wird nicht vorgereitet - was bei HM notwendig ist.
Faktisch bietet mir AssginIoPort fast keinen Service, ist recht aufwendig für den geringen benefit,... aber gut - ich bin für Standards und werden es endsprchend nutzen. AssingIoPort prüft nicht die Auslastung, den Zustand(overload), den rssi.

"Attribute welcher der Anwender setzt sind beizubehalten". Sehe ich eigenltich auch so. Aber der Anwender muss nicht alle Attribute setzen - und kann das bei CUL_HM auch nicht (mit User-Methoden!). Es gibt attribute welche CUL_HM gehören. Die meinsten habe ich verriegelt  - eventuell könnte ich stringenter sein. IODev darf der Anwender setzen - wenn er nicht den Auto-Mode IOgrp gewählt hat. Das ist schlüssig - der Anwender wird IODev nicht mehr ändern können und somit kann ich seine Entscheidung auch nicht überschreiben.
Zitat
der Benutzer hat die Moeglichkeit, die automatische Zuordnung durch ein Attribut mit dem Namen IODev zu beeinflussen.
Die Aussage ist quatsch. Der User - in deiner Implementierung hat die Möglichkeit jede Automatik abzuschalten. Ehrlich - CUL_HM ist hier meilen weiter! Der User kann bestimmte IOs zulassen, automatik einschalten, preferd-IOs definieren. Alles wie ich meine schlank und effizient. AssingIoPort ist hier eigentlich hinderlich.

In deiner Implementierung kann der User das IO über setReading setzen. Das ist schlicht eine Kathastrophe. Das geht ja garnicht. Das IO wird geändert -aber CUL_HM bekommt es nicht mit. Das IO wird nicht eingerichtet -geht also nur bedingt.

ZitatEin Attribut gehoert aus Prinzip dem Benutzer.
widerspruch.  Warum? Wenn der User es nicht setzen kann - un dich das verhindere  - gehört es mir. Punkt. Bedenke das einmal in deiner Philosophie - das ist schlüssig und wird seit Jahren in CUL_HM erfolgreich praktiziert. Die User sind zufrieden (zumindest traut sich keiner etwas zu sagen).

ZitatDass ich selbst Fehler mache...
ich jedenfalls rede nicht von coding fehlern - ich mache selbst genug. Ich reden von Grundsatzentscheidungen.

ZitatTheoretisch muesste vor dem Senden jedes Ausgabegeraet geprueft werden, auf welchem Wege das aktuelle Ziel am besten erreichbar ist. Koennen die Ausgabegeraete das zuverlaessig?
falsche Frage. Nicht das Ausgabegerät entscheidet, sondern die "vccu". Ich müsste schon wieder weiter ausholen... für CUL_HM (und für jedes Multi-Entity modul) fehlt die "modul Instanz" welche das Modul koordiniert. In CUL_HM habe ich einst den ActionDetector erstellt, dann das externe hmInfo und nun noch die "vccu" als interne, aber doch übergreifenden Entity. Das alles gehört eigentlich in die "modul-übergreifend-koordinierende Entity" - etwas was fhem schmerzlich vermissen lässt, weil das Desing strict flat sein soll.
Die vccu definiert zulässige IOs. Die IOs melden ihren Zustand - oder besser man kann ihn abfragen. Die Modul-Instanz entschiedet dann, welches IO am besten geeignet ist. Ist seit jahren am laufen. Der User kann - je Device (kanäle können das natürlich nicht - auch ein Hierarchiestufe welche FHEM eigentlich nicht kennt) die Automatik einschalten/prefered listen einrichten,...

ZitatGibt es einen tatsaechlichen Bedarf dafuer, oder ist das eine akademische Diskussion?
aber hallo!!! wo kommst du her? Mehr als natürlich. Ein Anwender von homematik kann mehrere IOs haben. Zur Redundanz, für Erreichbarkeit,... Ein IO kann überlastet sein (nach Funk-Vorscrift darf ein IO nur eine bestimmte Dauer je Stunden aktiv funken - eine Regelung über welche du dich mit deinen CULs hinwegsetzt). Und wenn ein IO keine "credits" mehr hat kann ich evtl ein andere nutzen (ohne Gesetzesbruch). Es gibt hand-helds welche sich bewegen. Auch das kann die vccu bedienen - automatisch

ZitatIch will mich nicht wehren, aber z.Zt. bin ich noch nicht ueberzeugt, dass es den Aufwand wert ist, da es die Sache fuer viele Beteiligte (Programmierer und Endanwender) verkompliziert.
Leider hast du dich nicht gewehrt. Die ursprüngliche Implementierung was nahezu perfekt. Nun ist es (sorry) ein Chaos aus meiner Sicht.
Ersatzschaltung ist essentiell. Ich sehe nicht, wie der kernel das machen sollte. das Modul sollte entscheiden, wie das zu machen ist. Übrigens sind dynamische IOs auch bei bluetooth in Presence ein Thema.
=> aus meiner Sicht solle der kernel sich auf sein Kerngeschäft beschränken. Die Alternative ist, es richtig zu machen. Dann ist aber deutlich mehr zu machen. Und ob das bei FHEM und dem Zoo am Module und Entwicklern durchsetzbar ist überlasse ich dir.


Zitat1) und 3) habe ich nicht als Problem verstanden, sondern als Luft abassen.
Ich lasse nicht wirklich Luft ab - ich engargiere mich um etwas zu retten. Luft ablassen ist etwas anders bei mir :)
1) ist mit sicherheit ein Problem, insbesonderen deine User-Implementierung. Bitte ersatzlos löschen. Dringend.
3) der Automode hat nichts mit Luft ablassen zu tun. Das ist Realität und funktional. Wenn eine User einen Automode einstellt hat er die Kontrolle über Attr IODev an mich abgegeben. Ok, mein strategischer Fehler - ich sollte ihm das kalr machen, indem ich ihm das setzen von diesem Zeitpunkt an verbiete oder zumindest einschränke. Das werde ich nun auch tun.

Zu 2) habe ich eine andere Ansicht. Ein Nutzer will das System sicher nutzen. Man sollte ihn for Fehlern bewaren (was auch du an einigen Stellen schon tust). User sind zu schützen.  Hacker und Freaks haben in fhem jede möglichkeit und können alles überschreiben. sowieso - das System ist offen.
Aus meiner Erfahrung wissen nur (sehr!) wenigen nutzer, was wirklich zu machen ist, ein homematik IO umzuschalten. Müsse sie auch nicht, macht der Modulentwickler.

ZitatDas ist nicht richtig: wenn $defs{NAME}{.AttrList} definiert ist, dann wird sie anstatt $modules{TYPE}{AttrList} verwendet.
Diese Moeglichkeit ist jetzt etwas ueber drei Jahre alt.
sehr!  cool. Habe ich nicht meit bekommen - und werden das nnun intensiv nutzen, im aufzuräumen.

Resumee: so wie es ist wird es typisch funktionieren. Ein Anwender wird wohl kaum die Methode setReading IODev nutzen (zum Glück). Schon das macht setReading zu einem Steuer-element - bei dem nun wirklich alles fehlt. Sollte es genutzt werden geht es bein CUL_HM schief. Sollte es nicht genutzt werden ist es sinnlos.
Mit fehlt hier das wie bei Attributen übliche
- user-interface
- auswahl-liste
- Modul-option eines Konsistenz-checks
- Modul-support das IO einzurichten
Hoffentlich nutzt es keiner

martinp876

Hallo Ansgar,
IO Ersatzschaltungen sind NOTWENDIG, realität und werden von mir nicht diskutiert. Sie sind gefordert und Anwender hatten sich eh gewundert, warum das nicht standard ist. Allein die Frage, ob man es braucht ist seltsam. Rein die Art der Implementierung kann diskutiert werden.

rudolfkoenig

ZitatSprich, die Frage klären müssen, ob es sinnvoll ist ein gesetztes Attribut automatisch zu übergehen, wenn der User via anderem Attribut Automatik festgelegt hat. (Der Fehler des nicht Löschens des Automatikhemmers fällt nach Murphy sicher in eine Abwesenheitsphase).
Ich habe nichts dagegen, wenn jemand das Denken dem Programm ueberlaesst, werde aber allergisch, wenn die Maschine meine Wuensche ignoriert. Wenn ich Fehler mache, dann sind das meine Fehler, daran kann ich was aendern. Wenn das Programm meine Wuensche ignoriert, dann brauche ich ein anderes Programm. Es bleibt euch frei, Attribute zu ignorieren, das ist aber nicht mehr FHEM, wie ich das fuer mich haben will.

ZitatAuf Modulebene vermutlich geeigneter lösbar. Der Qualitätswert wäre ohnehin schon auf Mudulebene geeignet bereit zu stellen. Das ist nicht mehr weit weg auch das IO zuzuweisen.
Sehe ich auch so, und ich weiss nicht, warum hier so ein Theater darum gemacht wird. Man muss weder AssignIoPort aufrufen, noch ein IODev Attribut anbieten, es reicht, wenn man das IODev Internal setzt, und sich auf IOWrite/Dispatch fuer die Kommunikation beschraenkt: die Schnittstelle ist damit weiterhin gewahrt, und man kann die IO-Module austauschen oder die IO-Kette erweitern.

noansi

Hallo Rudolf,

Zitatwerde aber allergisch, wenn die Maschine meine Wuensche ignoriert
Dein Standpunkt ist verstanden.
Die Implementierung mit Reading passt auch besser dazu, denn das Attribut manuell zu löschen ist auch ein User-Wunsch. Trotzdem bekommt man ein möglicherweise ungeeignetes IO beim nächsten Neustart "aufgezwungen", nur weil das IODev Attribut in der Attributliste des Moduls steht.  ;)
Eine Art Plug&Play. Für den Anfang mit fhem auch hilfreich. Von daher auch nicht wirklich zu kritisieren.

In der alten Attributsimplementierung hätte IODev bei Fehlen auch direkt mit einer Liste aller in Frage kommender IOs gefüllt werden können, mit Prio für das erste in der Liste. Dann hätte der User eine Lösch- oder Umsortierliste vorgefertigt bekommen. Und Martin schon eine IO Liste als mögliche Basis zum Attribut IOList bei der VCCU. (die VCCU benötigt aber auch noch ein eigenes IO, von daher hat IOList noch seine Berechtigung)

Wenn man nur mit diesem einen Attribut IODev die IO-Wahl kontrolliert ist Dein Kontroll-Standpunkt auch richtig.
Und auch CUL_HM kennt Fälle, wo eine automatische Wahl des IOs nicht möglich ist. Das betrifft virtuelle HM devices, die nur Broadcasts senden. Da muss der User ein IODev festlegen, so dass die Wunschempfänger den Broadcast auch empfangen können.
Auch wenn er die Automatik nicht wünscht, dann muss er ein jeweils passendes IODev setzen können.
Das vom Kernal angebotene IODev Attribut hat somit auch seine grundsätzliche Anwendungsberechtigung. Und wenn der User es nur so fahren will, muss er nicht umdenken, wenn er das gleiche Attribut nutzen kann.

Will er Automatik, dann sind mehr Einstellungen richtig zu wählen, VCCU einrichten und mit IOList versehen, HM devices mit IOgrp versehen, darüber wird dann auch eine Liste von VorzugsIOs angegeben.
Das Dogma, dass das Attribut IODev nicht Modulseitig anzutasten ist, sondern zwingend den vorgegebenen Wert einzustellen ist, wird nun hinderlich. Um den neuen Userwunsch zu respektieren, darf es nicht da sein. Damit wäre es in gleicher Logik sinnvoll, das Attribut mit der Umstellung automatisch zu löschen, denn sonst gehorscht das System dem User auch nicht! Ein Dilemma!
Ist es gelöscht, kommt auch keine Verwirrung bezüglich "falscher" Einstellung des IOs auf.
In der geänderten Automatik-Einstellung ist das Vorzugs-IO die Stelle, an der nun zur Wahl eines Wunsch-IO umzustellem ist. Die Dir vorschwebende Kontrollmöglichkeit ist also vorhanden, nun aber an anderer Stelle.
Von daher sollte das IODev Attribut dann bei Automatikwahl auch nicht mehr angeboten werden.

ZitatAssignIoPort setzt nur das System-interface. Das IO wird nicht vorgereitet - was bei HM notwendig ist.
Ja, da fehlt eine Moduleingriffsmöglichkeit, auch zum Verhindern in Automatikeinstellung. Nicht nur für HM.

Gruß, Ansgar.

martinp876

Hallo Rudi,

ich gehe nicht konform mit deiner Einstellung zu Attributen. Am Ende wiederspricht deine Implementierung deinen Aussagen. Sinnvoll ist es eh nicht.

Aber zurück: User Einstellungen sind zu beachten und haben Hoheit. So gut es eben geht. Daher:
vom User gesetzte Attribute haben Prio
   - das ist eine wichtige Richtlinie
   - das ist KEIN Dogma
   => User Attribute werden, wenn möglich, beachtet.

Ich habe auch "system Attribute". Diese lasse ich den User nicht ändern - hier kann er also auch keine Einstellungen (legal) vornehmen.

Aber zu fhem. Wie ich gestern gelernt haben kann man Attribute Entity-spezifisch definieren. Das ist wirklich prima und ich bin mal wieder etwas spät. Aber damit definierst du selbst, dass das vorhanden sein von Attributen volatil ist - und natürlich auch dessen Inhalt. Die Attribute ändern sich also, je nach dem, as mit der Entity passiert (sonst macht es ja keinen Sinn!!!). Um das ganze Konsistent zu halten muss (MUSS) der ordentliche Modul-programmierer aufräumen, kontrollieren,.... Ändert sich also der Zustand und es kommt eine Attribut-option hinzu und wird diese von User gesetzt hat der User seinen Wunsch geäußert. Attr <entity> OptAttr1 = OptAttrValXXX. Nun ändert sich die Entity, die Attribut-Optionen lassen hier OptAttr1 nicht mehr zu. Was machst du?
1) Ich lasse das Attribut stehen - ist ungültig, unzulässig, aber egal Der User wollte es so. Beim Reboot löscht es der kernel - oder?
2) ich lasse das Umstellen der Entity nicht zu so lange Attribute existieren, welche nach der Umstellung nicht mehr zulässig wären
3) ich lasse die Umstellung der Entity zu und bringen die Attribute auf Stand. Maximal schonend um die Richtlinie einzuhalten - logisch.

Welchen Tot wirst du sterben?
Für mich gibt es nur eine Lösung das ist 3). Alles andere destabilisiert das System. Der User kann möglicherweise garnicht übersehen, was er tut. Ich als Anwender von Modulen anderer Entickler wünsche mir dringend! dass diese die Standart Konfiguration auf Stand halten und ebenso initialisieren. Leider ist das nicht immer der Fall und ich muss mich sogar mit tirvialen Einstellungen rumschlagen und einarbeiten um einen Schalter zu bedienen. Weil der Programmierer den Default nicht automatisch anbietet.

Wie sieht es nun mit IODev aus. Einst hatte ich das Problem, dass ein IO Automatismus notwendig wurde. Die Semantik sit gewachsen und unterliegt der Methodik: Wähle einen IO Controller (vccu) und legen eine mögliche prio liste fest. => <vccu>:[<prefIO1>[,<prefIO2>[,<prefIO3>,...]]]
Es wäre nun cool gewesen, wenn der Anwender das in attr IODev hinterlegen hätte können. Aber die Semantic des Attributs forderte genau ein IO.
Daher habe ich ein IOgrp eingeführt mit welcher der Anwender (aktiv!) den Wunsch äussert, IOs nach (seinen!) Regeln automatisch gesetzt werden. Natürlich kann ich im Sagen - nun ja, lieben User, hättest du mal besser attr IODev gelöscht, dann würde auch IOgrp funktionieren. Obendrein hat fhem.pl aber ein attr IODev gefordert. Dead-lock.

Hier sollte man eben kein Dogma anwenden (auch wenn es schwer fällt) sondern den kurzen Dienstweg gehen und nach der "Richtlinen methode" vorgehen.
=> User wüchscht IO Automatik => Attr IODev wird vom Modul übernommen, IOgrp gehört dem User
Modul-Attribtute sind vom User nicht mehr Änderbar (muss ich an dieser Stelle noch realisieren)

De-Fakto ist es nicht sinnvoll möglich, dem User die uneingeschränkte Hoheit über Attribute zu geben. Bestmöglich, ja. Uneingeschränkt, nein!
Ich kann gerne noch Warnungen ausgeben, wenn ich eingreife - in User Attribute. Modul-Attribute gehören mir, die hat der User nie gesetzt und kann es auch nicht.


martinp876

Noch mal für Rudi,
über den Umgang mit Attributen habe ich nun referriert und zumindest versucht klar zu machen, dass es (nahezu) unauflösbare Konflikt beim Umgang mit dem "Userwillen" gibt,welche das Userinterface, macht man es richtig - SEHR umständlich macht. Rudi hat keine Stellung bezogen, auch gut.

Nun einmal zu AssignIoPort. Keine Diskussion, ob es nun ein Port oder ein Device ist - oder nur ein IO. Und ALLE meine kommentare sollen weder persönlich noch irgendwie reines gemecker sein. Ich habe ein paar Erfahrungen und CUL_HM hat Anforderungen. Ich hoffe, die Anmerkungen werden als Anregung verstanden, als solche reviewed und evtl sogar angenommen.
Also AssignIO:
Rudis konzept ist gut - aus der Ferne betrachtet. Funktions-Entitys (also bspw ein CUL_HM Aktor) - ich kürze einmal "FE" ab - welche ein IO benötigen kommnizieren - objektorientierter Ansatz - über die Zentrale (fhem.pl) miteinander. Dabei werden alle möglichen FM mit den passenden IOs verbunden. Cool .

Nun, tritt man näher funtioniert es vorne und hinten nicht - und auch nicht in der Mitte. Es funktionsfähig zu machen wäre ein erheblicher Eingriff!! Möglich, ja. Gewünscht?

Vorne: Die IO Auswahl.
Um ein IO zu proglamieren muss man prüfen
- ist es ein IO
- unterützt es das Modul (CUL_HM)
- ist es konfiguriert auf das Modul - oder schon von konträren Module allokiert
- ist es enabled
=> nun haben wir eine Liste möglicher IOs nach statischen Kriterien
- ist das IO auf die Addresse geprägt, welche das FM benötigt?
=> IO config check
- Ist das IO erreichbar
- besteht ein Oberload zustand
- besteht ein sonstiger Error
=> nun sind die dynamischen Zustände der IOs eingegrenzt
- ist das FM in reichweite
- welches IO hat den besten Empfang?
=> nun sind die FM berücksichtigt.
- sind wir gerade am abarbeiten eines Auftrags? Kein Umschalten des IOs mitten im "job"
=> der Operational-state der FM/IO beziehung ist berücksichtigt
- hat der User präferenzen, umschaltungen einzuschränken oder priorisieren?
=> der User-wille

Alles aus der obigen Liste ist notwendig
==> AssignIo bietet hier so gut wie nichts. Wäre auch schwer, klar. Besser, das Modul macht dies
==> wäre SEHR schön, wenn die internen Schnittstellen standartisert würden. Hier habe ich aber wenig Hoffnung, in endlicher Zeit irgendetwas zu erreichen.  Ich erinnere daran, dass Rudi schon verhindert hat, dass der homematic mode von der CUL hinreichend unterstützt werden kann. Daher hat Ansgar das Modul TSCUL ins rennen schicken müssen. leider.


Hinten:
Ist ein IO vorne ausgesucht muss es hinten eingerichtet werden. Bei einer Änderung der IO<>FM Zuordnung muss das FM aus dem alten IO gestrichen werden und im neuen IO zugewiesen werden.
==> AssignIo bietet hier wiedrum nichts.


Und die Mitte: Performance
AssignIo ist als statische Zuordnung erdacht. Dabei ist Performance ein kleines Problem. Da wir aber dynamische Zurordnungen machen ist Performance bei der Prüfung ein erhebliches Thema. Ein Paradigmen-shift wäre hier notwendig. CUL_HM versucht Prüfungen auf die Konfigurationsebenen zu heben und die operationelle Ebene (welche performance-relevant ist) von allem zu entlasten, was hier sinnvoll vermieden werden kann.


Wie also geht es, wenn doch nichts passt? nun, CUL_HM prüft das IO (leider  kein einheitliches Interface - sehr schade) und das FM sowieso. Der User kann seine Wünsche doch recht detailliert in einem einzigen Attribut artikulieren.
Um dem System genüge zu tun wird AssignIo befriedigt. Beitragen tut AssignIo eigentlich nichts, bietet ja nichts. Eigentlich behindert es in diesem Zustand nur.


So lange AssignIo Anforderungen nicht beachtet - oder sogar unterstützt - bleibt CUL_HM gar nichts anderes übrig, es faktisch zu umgehen und formal zu befriedigen.


Schaue ich mir den Code in fhem.pl im IO umfeld an komme ich schon zum nächsten Thema. init_done wird schon vor finish_init() gesetzt. Ok, der Trigger kommt erst danach, was bei rereadCfg in einer andern Reihenfolge passiert. Hier wird leider auch der Trigger REREADCFG ausgelöst, bevor init_done gesetzt ist.
Neue Frage: wie ist "init_done" definiert? hart? Ich würde erwarten, dass init_done dann gesetzt wird, wenn der kernel init erledigt hat. Final. Danach erwarte ich einen Trigger
welchen die Module nutzen können (und müssen!) um die Konfiguration zu prüfen. Ach da gibt es auch noch ein reread_active. Sollte so etwas nicht zusammen mit init_done schon beim ersten booten initialisiert werden? Wäre sauber.

Wie gesagt, ich warte bis zum Wochenende. Und noch einmal - das sind Anregungen - kritik am Code (weniger - Rudi ist hier deutlich besser als ich!!) und der Architektur (deutlich mehr) - aber alles hoffentlich konstruktiv.
CUL_HM wird auch in Zukunft den kernel befriedigen. Sollte der Kernal hilfreich sein wird diese Hilfe entgegen genommen - gerne.



noansi

#45
Hallo Rudolf und andere interessierte Mitleser.

da es einen Blumenstrauß an IOs und IO Eigenschaften in fhem gibt, sehe ich spontan folgende Punkte, die das Framework auf standardisiertem Weg mit Systemfunktionen unterstützen kann:

- welche IOs sind registriert (IO Modul Unterstützung erforderlich)
- welche IOs für das Modul sind registriert (IO Modul Unterstützung erforderlich)
- ist das IO konfiguriert auf das Modul - oder schon von konträren Module allokiert (IO Modul Unterstützung erforderlich)
- ist das IO enabled/nutzbar (disabled/dummy...)
- ist das IO sendefähig (oder ist es ein listen only IO für das anfordernde Modul) (IO Modul Unterstützung erforderlich)
- ist das IO erreichbar (ggf. IO Modul Unterstützung erforderlich)
- besteht ein sonstiger Error (IO Modul Unterstützung erforderlich)
- besteht ein Overload Zustand (Pufferlimits, Funkkontingent ausgeschöpft) (IO Modul Unterstützung erforderlich)
- wieviel vom maximalen Sendekontingent (Funkkontingent) ist verfügbar (IO Modul Unterstützung erforderlich)

Es geht dabei um Standardmethoden, die ein Modul, welches mehrere mögliche IO Module nutzen kann, aufrufen kann, um die Informationen zu bekommen. Derzeit muss man die Informationen aus dem System/den Modulen/den IOs individuell extrahieren.
Das bedeutet natürlich auch, dass die IO Module entsprechend angepasst werden müssen, um die Informationen passend zu liefern. 00_CUL.pm ist mit dabei.

Hier https://forum.fhem.de/index.php/topic,120268.msg1160889.html#msg1160889 übrigens noch Verbesserungen an 00_CUL.pm auch als diff, wie in dem Thread entstanden.
Es verbessert das Timing für Folgesendemessages, die zuvor beim User zu früh gesendet wurden, außerdem das Message Logging für den HM Support.

Gruß, Ansgar.

martinp876

Hallo Ansgar,

das ist alles rightig, hört sich komplex an und wird am Ende vereinfacht sein.
Wir haben configState und operState (die Namen könnt ihr gerne anpassen)

Config State
Das Modul meldet den Config state an den Kernel -also alle Modultypen, welche es zu unterstützen gedenkt. Wird es auf einen Typ geprägt muss der Kernel informiert werden, die Liste wird upgedated.
=> ein IO kann mehrere Typen parallel unterstützen. Der IO-Modul entwickler muss die angebotenen Optionen natürlich erfüllen können
=> ein Dummy-modul liefert eine leere Liste (kann ja nix)
=> ein Modul kann anfragen, welche IOs möglich sind.
=> das Modul kann (muss) sich über Änderungen informieren lassen (können) - Kernel funktion.

Schön wäre, wenn sich ein Modul beim IO enrolen könnte - direkt oder über den Kernel, egal. Damit kann man sicherstellen, dass ein besetztes IO nicht gekapert wird. Es ist also möglich, dass mehrere Module enrolt sind, wenn das IO dies zulässt.

OperState:
=> Der Oper-State des Modul kann abgefragt werden. Das sollte direkt gehen - hier geht es um Performance.
=> bei Oper-state handelt es sich um dynamiche Änderungen jenseits der Configuration
Wenn das Enrolement genutzt wird informiert das IO das Modul, ansonsten kann man es abfragen (eine Standart-variable würden reichen).
Die states sind zu definieren
- operational|highLoad|noTransmition
noTransmission beinhaltelt alles, wenn das IO nicht senden wird. Der Grund ist egal, könnte sich aber schnell ändern
Alternativ kann man auch schlicht die Sendekapazität zurückgeben. Error entspricht "0% kapazität"
=> immer daran denken: Das Modul muss nicht über details informiert werden, das macht das IO schon selbst. Nur ein Wert welcher eine Entscheidung ermöglicht ist notwendig.

Wie du siehst und sicherlich weisst sind Interworking und Architektur zu definieren.
So kommen wir der Sache langsam näher.

Wieder einmal lege ich eine ModulInstanz nahe bspw eine "CUL_HM Entity".


Nebenbei: Wenn ihr alles so lasst wie es ist (nun, war) sind in CUL_HM schon genug "arbeite-herum" um die Misstände eingebaut. Entferne ich gerne, aber nur wenn es ein sinnhaltiges Konzept gibt



noansi

Hallo Martin,

Zitatdas ist alles rightig, hört sich komplex an und wird am Ende vereinfacht sein.
Das ist nur ein Versuch, etwas abzugrenzen, damit sich hoffentlich auch andere Entwickler ein Stück weit darin wieder finden.
Schließlich würden Änderungen in Richtung von Standardmethoden einige betreffen, nicht nur Rudolf als Bereitsteller von Interfaces.

Nur CUL_HM spezifisch macht es wenig Sinn und es wird sich dazu sicherlich kein Konsens finden lassen.

Deine Aufstellung der letzten Beiträge macht aber schon deutlich, was CUL_HM im Optimalfall brauchen könnte.

Wäre schön, wenn andere ähnliches aus ihrer Sicht darlegen würden, was gebraucht wird/werden kann oder derzeit stört (und damit meine ich nicht das Reading IODev, das ist zunächst nur Gewohnheitssache und ein zusätzliches Feature zur Wiederherstellung eines letzten Zustandes bei Neustart. Braucht auch nicht jedes Modul, aber auch nicht jedes Modul braucht z.B. ein Write).

Sonst bleibt es sicherlich beim Stand, der von der Basis her auf Rudolfs Module zugeschnitten ist.
Der Baukasten ist ja auch nicht schlecht, nur einige sehr ähnliche und öfter gebrauchte Legosteine muss ein Modul überall zusammensuchen und kann sie hoffentlich dauerhaft in der einmal vorgefunden Form weiter benutzen.

Was mir auch nicht so gefällt, ist Kommandos an das IO-device (das logische in FHEM) ebenfalls über das Write Interface zu realisieren.
Da sammelt sich mit der Zeit ein Christbaum an Abfragen im IO-Modul (insbesondere bei Multifunktions-IOs) an, die das Senden von Nutzinformation ausbremsen bzw. jedes mal Zeit kosten. Dafür halte ich es für sinnvoll ein zusätzliches IOCommand Funktionsinterface als Alternative zu etablieren.

Gruß, Ansgar.

justme1968

beim überfliegen des thread verstehe ich denn sinn des iodev reading nicht so ganz.

und zu attributen: ja. attribute sind für den anwender. aber ich bin der meinung das ein modul durchaus die möglichkeit haben soll am anfang attribute sinnvoll vorzubelegen und dem anwender einen hinweis über die möglichkeiten zu geben. wenn der anwender ein attribut ein mal gesetzt oder geändert hat darf ein modul nicht mehr 'dazwischen pfuschen'. schade ist hier das es keine möglichkeit gibt zwischen nicht gesetztem und leerem attribut zu unterscheiden.

wenn es dinge gibt die ein modul sich selber über einen neustart 'merken' muss sollte es das in den unsichtbaren .readings tun. wenn es als reading sichtbar ist verführt das nur dazu mit setrading zu spielen.

dinge die nur zur laufzeit relevant sind wären dann in den internals aufgehoben.

das wäre dann ein iodev attribut das sinnvoll vorbelegt werden kann vom modul, das ein anwender dann ändern kann und das dann geändert bleibt. in iodev könnte auch eine (priorisiere) liste stehen. das aktuell tatsächlich verwendete iodev wäre dann im internal sichtbar. ein modul das sich zwingen sein iodev selber merken muss und dem user keine änderung erlaubt würde ein .iodev reading verwenden.

zu keiner zeit taucht ein iodev reading auf das nur zu zweideutigkeiten führt.

in fhem ganz allgemein mehrerer iodevs im iodev attribut ablegen und verwenden zu können wäre schön der als modul spezifische sonder wege.

hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

noansi

#49
Hallo Andre,

Zitatbeim überfliegen des thread verstehe ich denn sinn des iodev reading nicht so ganz.
Wenn der User das Attribut IODev löscht, dann kann ein Automatismus darin den letzten Zuweisungsstand ablegen, der beim nächsten Start denn wiederhergestellt werden kann.
So lange das Attribut existiert, hat das Attribut die Macht, so hat es Rudolf festgelegt.

Gruß, Ansgar.

justme1968

das klingt nach etwas internem und nach etwas das unsichtbar sein sollte also ein reading mit punkt. oder noch besser ein attribut mit punkt. es sollte jedenfalls nicht sichtbar sein.

andererseits: wenn ein anwender etwas löscht dann hat er das doch mit absicht gemacht und es sollte nicht hinter seinem rücken wieder geändert werden. andere attribute werden ja auch nicht gesichert und nach dem löschen wieder repariert. das gleiche argument würde ja auch für readings gelten und die werden nach dem löschen nicht 'repariert'. oder ist der nächste schritte dann ein backup vom backup reading?

was ist wenn der anwender durch das löschen erreichen möchte das das system automatisch neu nach einem passenden iodev sucht und nicht das alte wieder herstellt?
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

noansi

Hallo Andre,

ob mit oder ohne Punkt ist eigentlich egal, denn jeder kann sich auch die versteckten Daten sichtbar machen.

Zitatwenn ein anwender etwas löscht dann hat er das doch mit absicht gemacht und es sollte nicht hinter seinem rücken wieder geändert werden.
Zitatwas ist wenn der anwender durch das löschen erreichen möchte das das system automatisch neu nach einem passenden iodev sucht und nicht das alte wieder herstellt?
Wenn der Anwender sich so viel Systemverständniss angeeignet hat, dass er den Zusammenhang versteht, dann ist es dem Anwender ein leichtes, auch noch das Reading zu löschen.  ;)

Zitatandere attribute werden ja auch nicht gesichert und nach dem löschen wieder repariert.
Es geht auch nicht darum, das Attribut zu sichern, es geht darum, den letzten Zustand der IO Zuordnung über den FHEM Neustart zu erhalten und der steht im Reading.
Attr IODev == Reading IODev -> Attr == Reading IODev wird zu Internal IODev nach FHEM Neustart (effektiv)
Attr NULL != Reading IODev -> Reading IODev wird zu Internal IODev nach FHEM Neustart
Attr NULL && Reading NULL -> Neuzuordnungsversuch seitens FHEM bei Neustart (konkret, letztes definierte geeignete IO-device aus der config, das nicht disabled ist)

Attr NULL während des FHEM Betriebs -> Modulautomatik kann ein anderes IODev wählen, so Rudolfs Vorstellung
Attr IODev gesetzt während des FHEM Betriebs -> Modulautomatik soll durch Attribut überstimmt werden

Gruß, Ansgar.

justme1968

ah. ok. die zusammenfassung ist hilfreich.

es klingt für mich aber immer noch eher nach einem versteckten reading. oder besser verstecktem attribut. es sollte nicht sichtbar sein. iodev enthält ein oder mehrere einträge, .iodev enthält das aktuell tatsächlich ausgewählte damit es beim neustart nicht verloren geht. das iodev internal enhält sichtbar das aktuell relevante iodev.

natürlich kann ein anwender im prinzip alles löschen. verstecke readings oder attribute sieht er aber erst al nicht. auch nicht per list. es ist also nicht 'mal so' passiert.

warum das letzte iodev zu verwenden besser ist als neu zu suchen ist mit aber nicht klar. durch den neustart kann sich ja alles mögliche geändert haben. vielleicht war ja sogar fas genau der sinn des neustarts.

vielleicht kommt das aber auch von der arbeitsweise. mein fhem läuft monatelang ohne neustart durch.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

noansi

#53
Hallo Andre,

da Du ja gerade raus gearbeitet hast, dass der User sowohl Attribut, als auch Reading löschen können muss, ist es schon sinnvoller, beide nicht zu verstecken. Zumindest sieht man dann, was man im ersten Anlauf eventuell vergessen hat...

Zitatwarum das letzte iodev zu verwenden besser ist als neu zu suchen ist mit aber nicht klar. durch den neustart kann sich ja alles mögliche geändert haben.
CUL_HM bietet dynamische IO-Zuweisung auf Basis des RSSI mit dem das jeweilige device beim jeweiligen IO empfangen wird.
Die dabei entstehende Zuweisung ist somit umgebungsabhängig, bei den meisten devices aber doch eher statisch (ständiger Umbau des Heimes ist eher unüblichl).
D.h. die Zuordnung nach dem Neustart passt am ehesten zu der vor dem Neustart -> die Kommunikation sollte damit am besten wieder anlaufen.
Das würde auch für andere Funkprotokolle gelten, so sie eine solche empfangsqualitätsabhängige IO-Zuordnung in FHEM implementiert bekommen.
Auch Protokolle mit dynamischem Routing würden davon profitieren können.
Und dann gibt es noch einen Grund die IOs betreffend. Sofern der Zuordnungszustand im IO in nicht flüchtigem Speicher abgelegt ist, ist es für den IO Zuordnungsspeicher am schonendsten, die gleiche Einstellung weiter nutzen zu können, statt alle Zuordnungen neu einzurichten. Wie sich gerade heraus kristallisiert https://forum.fhem.de/index.php/topic,121139.msg1160404.html#msg1160404, gibt es nicht nur tsculfw (nur die mit wenig RAM) IOs mit Zuordnungsinformation in nichtflüchtigem Speicher.

Zitatvielleicht war ja sogar fas genau der sinn des neustarts.
Das statische (via Attribut) bleibt statisch, das dynamische wird entsprechend Optimierungsziel dynamisch verändert.
Wenn es um's Testen der Dynamik geht kann man auch
- vorher Reading (und Attribut IODev) löschen
- oder (bei CUL_HM) gleich mal eine andere Zuordnung via IOgrp Vorzugs-IO einstellen und dann schauen, wie sich das bei Rücknahme des Vorzugs-IO entwickelt, auch ohne Neustart

Gruß, Ansgar.

rudolfkoenig

Ich bin erstaunt ueber die heftigen Reaktionen als Konsequenz einer Aenderung, die mAn keine Auswirkungen haben sollte.
 
Zitates klingt für mich aber immer noch eher nach einem versteckten reading. oder besser verstecktem attribut.
IODev sollte nicht versteckt werden, man will schliesslich als Benutzer sehen, wie die automatische Zuordnung erfolgt ist, um Fehler korrigieren zu koennen. Und Reading ist es, weil es damit offensichtlich ist, dass es vom System gesetzt ist.

Zitatda es einen Blumenstrauß an IOs und IO Eigenschaften in fhem gibt, sehe ich spontan folgende Punkte, die das Framework auf standardisiertem Weg mit Systemfunktionen unterstützen kann:
Eigentlich(TM) muss ein Virtuelles IO Interface (wie es in HM implementiert ist) diese Aufgaben uebernehmen, und wie man es an dern "Problemen" (Erreichbarkeit, Sendezeit, Pufferoverflow) sieht, ist es stark Protokoll abhaengig.
Die Liste der verfuegbaren IO-Instanzen, und was diese gerade uenterstuetzen ist auch jetzt verfuegbar, eine Reservierung waere Sache der virtuellen Schicht (wenn ueberhaupt, manche Protokolle erfordern keine Reservierung, bei anderen ist Multi-IO nicht vorgesehen).

Ich bin nicht ueberzeugt, dass es sich lohnt dynamisches(!) Multi-IO Steuerung zu implementieren, sowohl wegen Aufwand fuer den Programmierer, Komplexitaet fuer den Benutzer und Haeufigkeit der fuer FHEM relevanten Faelle. Heisst nicht, dass ich was gegen Module habe, die das selbst implementieren, aber eine Generalisierung sehe ich z.Zt. nicht.

justme1968

als benutzer sieht man es aber doch in den internals. die sind dazu da informationen zu zeigen die nur zur laufzeit relevant sind.

so wie die attribute eigentlich dem anwender gehören gehören die readings eigentlich dem modul und die internals dem system.
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

noansi

#56
Hallo Rudolf,

ZitatIch bin nicht ueberzeugt, dass es sich lohnt dynamisches(!) Multi-IO Steuerung zu implementieren
Kann ich verstehen, die Beiträge hier lassen bisher nur bei einem Modul Bedarfswünsche erkennen. Schade.

Deswegen vielleicht noch einmal etwas konkreter am Beispiel von einem SlowRf Sendemodul mit 'IODevList' Implementierung (und es unterstützt kein Attribut IODev mehr):

# erstes aktives IODev ermitteln
  my @ionames = split(/,/, AttrVal($name, 'IODevList', ''));
  my $ioh;
  foreach my $ioname (@ionames) {
    $ioh = $defs{$ioname};
    if (   defined($ioh)
        && defined($ioh->{STATE})
        && $ioh->{STATE} ne 'disconnected'
        && !IsDummy($ioname)) {
      AssignIoPort($hash, $ioname) if (   !defined($hash->{IODev})
                                       || ($hash->{IODev}->{NAME} ne $ioname));
      last if (   defined($hash->{IODev})
               && defined($hash->{IODev}->{CMDS})
               && ($hash->{IODev}->{CMDS} =~ m/G/) );
    }
  }

  return 'no IO available, adapt attribute IODevList' if (!defined($hash->{IODev}));


Da steckt viel Vorwissen drin, dass das in dem Fall spezielle IO Modul (hmm, eigentlich sind es zwei) eigentlich beantworten sollte.
Zunächst sollte schon der User das Vorwissen einbringen, dass das IO, welches er in das Attribut eingetragen hat, überhaupt ein 'G' fähiges Modul ist. Sonst ist nicht sicher, dass die Prüfungen nicht falsch positive Aussagen liefern. Eine Prüfung auf den Modultyp des IOs möchte ich vermeiden, das hält es offener für neue IO-Module.

Dann weiter im Code
1. Frage: ist das IO verfügbar?
Nach einigem Code Studium bin ich zur Erkenntniss gekommen, dass STATE eq disconnected diese Frage bei den in Frage kommenden IOs verneint. Ist das immer so? Bei allen IOs?

2. Frage: ist das IO irgendwie disabled?
Wiederum nach einigem Code Studium bin ich zur Erkenntnis gekommen, das IsDummy diese Frage hinreichend für die in Frage kommenden IOs beantwortet. Ist das immer so? Bei allen IOs? Gibt es noch andere nicht in Erwägung gezogene Attribute/Readings/Internals, die auf disabled schließen lassen?

3. Frage: unterstützt das IO den CULG 'G' Befehl?
Das ist in diesem Fall speziell auf die beiden (mir bekannten) IO Module zugeschnitten, die CULG unterstützen (sofern in die Firmware compiliert).
Die Frage wird durch die Dispatcherseitig verfügbare Information zu CULG Unterstützung durch das jeweilige IO nur bezüglich Empfang beantwortet. In diesem Fall falsch, da nur Senden unterstützt wird, nicht aber Empfang. Das CMDS Internal ist auch kein IO-Modulübergreifender Standard, denke ich. Außerdem kann ein unterstützendes anderes IO Modul auch ein anderes Befehlskürzel nutzen.

Wie schön wäre es, beim Kernel mit IsIOUseable($ioname) die erste und zweite Frage beantwortet zu bekommen. Das Kernel muß die Frage auch nicht zwingend selbst beantworten, sondern seinerseits beim IO die Anfrage stellen, weil es eine IsIOUseableFn Modulfunktion hat, die via Modul Initialize Funktion bekannt gemacht wird, damit das Kernel nicht alle speziellen Funktionsnamen der Module kennen muss.

Die dritte Frage wäre schön durch eine Kernel Funktion IOSendSupportForModule($ioname,$hash->{TYPE}) beantwortet und könnte als Zusatzinfo auch den zu nutzenden Befehlscode liefern. Wiederum seitens Kernel Anfrage beim IO.

Bei beiden Funktionen wäre eine Rückabe 'undef' eine sinnvolle Rückmeldung dafür, dass das IO die Anfragefunktion (noch) nicht unterstützt und auch das Kernel die Anfrage nicht beantworten kann.

In diesem Sinne ist meine Auflistung zu verstehen und damit auch nicht begrenzt auf dynamische MultiIO Unterstützung.

Gruß, Ansgar.

martinp876

Das die Diskussion so weit geht liegt daran, dass die Philosophie, wie mit Elementen umzugehen ist nicht niedergeschrieben ist sondern sich in den Köpfen, primär Rudis befinden. Startet man die Diskussion werden die Probleme sichtbar. Und das sind einige.

Ich bin zwar nicht einverstanden - und eure Felstlegung ist per eurer Definition  nicht haltbar, aber so verstehe ich eure Aussagen:
Dogmen:
D1) Attribute gehören dem User- Er kann einstellen was er will und bekommt recht
D2) Readings sind ... unklar. Der Programmierer kann sich hier Werte Merken - die kommen und gehen. Speichern und Recover ist deutlich schwächer
D3) Internals werden sowieso nicht gemerkt - was der einzige Unterschied zu Attributen ist. Ausnahme ist das Define.
D4) Dynamische IO Zuordnung braucht es nicht.


Stellungnahmen - Unsortiert:
D4) ist ok - im Allgemeinen. CUL_HM wird es machen (hat schon) - es ist ZWINGEND notwendig. Sollte sich Rudis Aussage auf den kernel beziehen ist das vollkommen ok. Würde ich auch so sehen. Es generell zu unterbinden ist nicht tragbar und werden/kann ich nicht unterstützen

D1) Ich sehe keine Notwendigkeit der starren Abgrenzung. Es hat schon seinen Sinn, dass Attribute beim Setzen geprüft werden. Der Modulschreiben kann bestimmte Werte ablehnen. Das geht bis dabin, dass einige Attribute vom User garnicht gesetzt werden können. Damit hat der User  hier auch nicht seinen Wunsch äussern dürfen - damit kann er es auch nicht einfordern.
2. Punkt: Attribute und deren Prüfung hängen von einander ab - FAKT! Rudi hat eingeführt (sehr gut!) dass Attribute je Entity erlaubt sein können. Das bedeutet, dass eine Entity einige Attribute manchmal unterstützt und manchmal nicht. Ich kennen jetzt die Beispiele nicht, wer das gebraucht hat - aber es kann ja nur sein, dass durch Einstellung eben attribute freigeschaltet werden und eliminiert werden. Damit ist es die Aufgabe!!! des Modulentwicklers dies konsistent zu halten. Das geht nur auf 2 Wegen: Entweder wird die Änderung verweigert, welche ein vorhandenes Attribut obsolet macht oder das obsolete Attribut wird gelöcht.
Ersteres geht nur, wenn der Anwender die Änderung initiiert. 2teres geht immer.
Obsoleten Attribute stehen lassen geht garnicht. Ein Reboot würde es sowieso löschen!
Sich in die Tasche lüge ist bspw:
Ein User stellt Attr IODev ein, fhem prüft (wie auch immer) ob es sich um ein gültiges IO handelt. => gut
Das IO wird gelöscht. Würde man das Attribut nun setzen, würde es verboten. Das ist also Quatsch. Entweder wird das Löschen verhindert oder das Attribut gelöscht. Oder das IO gegen ein gültiges ausgetauscht. Lässt man das Löschen (oder umbenennen ) eines IOs zu ist es Programmer-pflicht!!! die Attribute (bestmöglich) zu prüfen.
MD1) mein Dogma: wenn der Developer eine Prüfung beim Eintragen eines Attributs mache ist es SEINE Aufgabe, dies konsistent zu halten. Das Attribut muss eingeltich zu jedem Zeitpunkt der Prüfung genügen! Voll automatisch, best-möglich.
=> jetzt seid ihr dran.
Macht das CUL_HM? Nun ja, es gibt sicher Lücken. Bei einem "rename" bspw habe ich mich eingehängt und passe alles an, was ich identifizieren kann - innerhalb CUL_HM


D2) Readings werden nur schwach gespeichert. Das ist störend - aber gut. Um Konfigurationen zu speichern war es lange nicht stabil genug. Evtl. muss ich es noch einmal prüfen, ob es nun hinreichend ist. Mir sind hier schon einige Werte verloren gegangen - leider oft. Mein Vertrauen ist leider gering - aus Erfahrung.
Readings löschen... ist unbedingt notwendig. Readings stellen den Zustand der Entity dar. Es sollten(dürfen!!!!!!!) nur gültige und verlässliche Readings sichtbar sein. Die Liste der Beispiele ist endlos.
CUL_HM: wenn eine Entity gepeert ist sind register-readings vorhanden. Wird das peering entfernt sind diese nicht mehr vorhanden. Selbstverständlich muss ich diese Löschen. Die sind schliesslich WEG!
YAMAHA_NP: hier schalte ich die modi ständig um: Radio, Server, CD. Ich sehe Senderlisten, DAB+ Infos,... je nach Source. NATÜRLICH ist es meine Aufgabe, ungültige Readings zu löschen. Die sind ungültig und das ist bekannt.
=> nichts schlechter als falsche Information. Besser keine Information

Anderes Thema: ihr habe auch über Sichtbarkeit von Parametern gesprochen. FHEM hat hier eine sehr schwache Implementierung - mehr hat Rudi mir nicht zugestanden.
Statements von mir
+ natürlich darf der User alles sehen
+ das einfache Frontent sollte in Sachen Sichtbarkeit einstellbar sein. Typisch will ich nur wenig sehen, manchmal alles. Die Listen aller Readings (oder auch Attribute ) ist unleserlich.
? Frage:Ist die "einfache" native Darstellung als Programmer-darstellung gedacht? Dann ist es egal, was dargestellt wird. Ist es als primary-User-Frontend gedacht gebe ich eine schlechte Note. Das macht keinen Spass, wenn man nicht nachbessert!
+ In CUL_HM habe ich ein "get list" eingebaut - das sollte Standart sein. Hier kann der User schnell und einfach alle (ALLE) Parameter ansehen. Über die Option "normal/full" kann man hidden parameter darstellen oder nicht.
+ Sichtbarkeit  von Parametern sollte der Übersichtlichkeit der Darstellung dienen. Diese sollte per entity einstellbar/umschaltbar sein - schnell und einfach.
+ CUL_HM hat einen mAn tragbaren, wenn auch sub-optimalen und programmtechnisch leider komplexen Weg implementiert, die Sichtbarkeit von Readings (primär Registern) zu steuern. Es nähert sich für meine Ansprüche eine User-Frontend an. Wirklich freundlich ist es an allen Ecken nicht, intern wie extern. Rudi hat damit allerdings den kernel einfach halten können.


Ich mache hier einmal ein schluss-statement:
Hier sind einige Themen angesprochen welche von einander unabhängig sind. Faktisch ist es ein Durcheinander und die Themen sollten eines nach dem Anderen besprochen werden. Die aktuellen Aussagen ALLER beteiligten geht nur von Sunny-Day Szenarien aus - Problemfälle werden noch nicht einmal angesprochen. So kann es nicht funktionieren.
Die Definition von Attribut sollte einmal KNALLHART! definiert werden, diskutiert und alle (ALLE) Konsequenzen besprochen werden. Insbesondere Problemfälle!!!
Was macht es für Sinn über die Nutzung von Attr IODev zu sprechen, wenn Attr selbst nicht auch für Regentage definiert ist und in sich zusammenfällt. Man muss vorne anfangen.

Typisch kenne ich es nicht, dass Rudi meine Eingaben wirklich diskutiert. Wenn etwas nicht mit einem Einwurf und einer Antwort erledigt ist wird es ignoriert.  Rudi sind jetzt schon die Mendungen wieder zu lang und ausschweifend, wir er hat durchblicken lassen.

Ich finde es schade wie schon häufiger, werde mich aber nicht daran aufarbeiten und bleiben bei meiner Aussage Eingangs: Gerne Kommentieren ich, werde mir das Ergebnis ansehen und CUL_HM auf Basis der Ergebnisse CUL_HM weiterhin Userfreundlich und Nutzbar halten.




noansi

#58
Hallo Martin und interessierte Mitleser,

Zitateure Felstlegung ist per eurer Definition
? wer ist eure

Die Vorstellung von Rudolf ist in fhem.pl bezüglich Attributen in CommandAttr($$) festgehalten:

ZitatD1) Attribute gehören dem User- Er kann einstellen was er will und bekommt recht
    $ret = CallFn($sdev, "AttrFn", "set", $sdev, $attrName, $attrVal);
    delete($defs{$sdev}->{CL});
    if($ret) {
      push @rets, $ret;
      next;
    }

    $attr{$sdev}{$attrName} = $attrVal;

D.h. der Modulprogrammierer kann den Attributwert nicht verändern, aber eine Fehlerrückmeldung geben, wenn er ein Problem erkennt und damit verhindern, dass er gesetzt wird.
Das war der Aufhänger des Threads und Rudolf beharrt, aus durchaus nachvollziehbaren Gründen, auf diesem System. Ohne Ausnahme (was ich nicht nachvollziehen, aber aktzeptieren kann).

Während des FHEM Starts gibt es dabei nur das Problem, dass noch nicht alle devices definiert sind und nicht alle Attribute und noch gar keine Readings bereit stehen. D.h. sollte es da Abhängigkeiten geben, dann kann eine Fehlerrückmeldung nicht sinnvoll während des FHEM Inits gegeben werden.
Also kann der Modulprogrammierer nur nach dem FHEM Init eine Prüfung vornehmen und ggf. das Attribut (tja, hier wird dann zwar alles möglich, aber) nicht auf den neuen Wert setzen (so entspricht es der fhem.pl Logik).
Um sich als Programmierer diese Logik aufzuwingen, wäre es eine Möglichkeit, das jeweilige Attribut neu über die Systemfunktion zu setzen und die Prüfungen innerhalb der Modul Attributsfunktion abhängig vom fhem Initzustand auszuführen. Wenn der alte Attributwert schon Käse ist, dann muss der Modulprogrammierer das anderweitig abfangen.

Ohne Ausnahme? Im Grunde nicht ganz, denn in CommandAttr gibt es davor auch noch diese Codeteile:
    if($opt{a} && $attr{$sdev} && $attr{$sdev}{$attrName}) {
      $attrVal = $attr{$sdev}{$attrName} .
                        ($attrVal =~ m/^,/ ? $attrVal : " $attrVal");
    }
    if($opt{r} && $attr{$sdev} && $attr{$sdev}{$attrName}) {
      my $v = $attr{$sdev}{$attrName};
      $v =~ s/\b$attrVal\b//;
      $attrVal = $v;
    }

    if($attrName eq 'disable' && $attrVal eq 'toggle') {
       $attrVal = IsDisabled($sdev) ? 0 : 1;
    }
...
    if($fhemdebug && $sdev eq "global") {
      $attrVal = "-" if($attrName eq "logfile");
      $attrVal = 5   if($attrName eq "verbose");
    }

Warum dem Kernel Modifikationen des Attributwertes erlaubt sind aber dem Modul nicht ... . Ok steckt ein Nutzerwille dahinter..., war einfach umzusetzen, egal, Schwamm drüber.

Dafür gibt es jetzt eine alternative Möglichkeit, einen IODev Ist-Zustand über den FHEM Neustart zu erhalten (so der User-Wille dem nicht widerspricht) und das hilft schon mal beim ursprünglichen Problem.

ZitatD2) ... Speichern und Recover ist deutlich schwächer
Ja, vier Gründe fallen mir ein, warum dies passiert.
1. Der User löscht das Reading
2. Das Modul löscht das Reading
3. Zugriffsrechte im Filesystem verhindern das Speichern der Sicherungsdaten
4. Bugs im Modul, die einen Modulstart verhindern -> Readings verloren, so denn keine Sicherungskopie der Readingdaten vor einem regulären Stop von fhem angelegt wird.
@Rudolf: hier wäre es ein willkommenes Feature, beim Schreiben der Readingdaten vorher automatisch ein Backup zu erzeugen. Z.B. alte fhem.save in fhem.save.last umbennen und dann neue fhem.save schreiben.

Gruß, Ansgar.

rudolfkoenig

Zitat@Rudolf: hier wäre es ein willkommenes Feature, beim Schreiben der Readingdaten vorher automatisch ein Backup zu erzeugen. Z.B. alte fhem.save in fhem.save.last umbennen und dann neue fhem.save schreiben.
Beim vom Benutzer ausgeloesten Schreiben der Konfiguration wird per Voreinstellung auch eine Sicherung von fhem.save erzeugt.
fhem.save.last kann ich einbauen, allerdings sehe ich z.Zt. genausoviele neue Probleme wegen Erstellen eines weiteren Backups, wie es diese loest. Ich lass mich aber gerne umstimmen.

noansi

Hallo Rudolf,

ZitatBeim vom Benutzer ausgeloesten Schreiben der Konfiguration wird per Voreinstellung auch eine Sicherung von fhem.save erzeugt.
Ist schon veraltet. Und dabei soll dieses Backup auch nicht erstellt werden.

Zitatfhem.save.last kann ich einbauen, allerdings sehe ich z.Zt. genausoviele neue Probleme wegen Erstellen eines weiteren Backups, wie es diese loest. Ich lass mich aber gerne umstimmen.
Es geht nur um den Fall, dass ein Modul nicht geladen werden kann. (Tippfehler des Programmierers, Tastatur mal wieder kaputt...)
Dann startet fhem durch und die Readings des Moduls sind weg. Dann hat man noch die Chance, ein Backup der Datei zu erstellen, bevor man fhem stoppt.
Mache ich derzeit dann manuell, aber manchmal vergesse ich es. Und ein älteres Backup lässt sich dann auch noch finden.
Wenn ein Modul fhem abschießt, besteht das Problem nicht, da dann die fhem.save nicht angetastet wird.

Muss nicht zwingend sein. Kann hilfreich sein. Kann auch nur per global Attribut aktivierbar sein.

Gruß, Ansgar.

rudolfkoenig

ZitatDann startet fhem durch und die Readings des Moduls sind weg. Dann hat man noch die Chance, ein Backup der Datei zu erstellen, bevor man fhem stoppt.
fhem.last ist eine Hilfe, wenn man das Problem nicht sofort merkt, aber nach dem naechsten FHEM-Restart, und man kein save vorher gemacht hat. Nach zwei Restarts ist es schon wieder zu spaet. Dafuer verursacht es Probleme, wenn die Festplatte fast voll ist.

Bin noch nicht ganz ueberzeugt, aber wenn das von Anderen auch gewuenscht wird, baue ich das ein.

martinp876

Hallo Ansgar, Rudi,

Dokumentation per Code enthält NULL Semantik. Das ist schlicht keine Dokumentation.
"Der User kann Attribute setzen, welche nicht mehr verändert werden. ". Nun, macht man einen reboot lösche Rudi ungefragt alle Attribute, welche nun nicht mehr passen. Es ist also nur manchmal Userwille. Und das ist gut so.

ZitatWährend des FHEM Starts gibt es dabei nur das Problem, dass noch nicht alle devices definiert sind und nicht alle Attribute und noch gar keine Readings bereit stehen
CUL_HM verlässt sich schon lange nicht mehr darauf. Die Konsistenz wird NACH init_done geprüft. Nur so geht das, alles andere ist Quatch. Es ist am Modulentwickler den Init-Status zuerst zu prüfen.
ZitatWarum dem Kernel Modifikationen des Attributwertes erlaubt sind aber dem Modul nicht ... . Ok steckt ein Nutzerwille dahinter..., war einfach umzusetzen, egal, Schwamm drüber.
Bisher hat es recht gut funktioniert, dass CUL_HM attribute angepasst hat. Ich sehe keinen Grund, das zu ändern. Es sind auch nur sehr wenige. Weiter kann der User diese typisch auch nicht ändern, da es gesperrt ist. Ich wiederhole mich.

ZitatJa, vier Gründe fallen mir ein, warum dies passiert.
Ich habe keinen Grund, mich auf Readings zu verlassen. Möglich, dass es klappt... da ich es nicht brauche ist es egal.

ZitatUm sich als Programmierer diese Logik aufzuwingen,....
leute... komplizierter geht es nicht mehr? Ein Programmierer hat Verantwortung. Wenn er mist baut muss er nachbessern. Es wäre ganz einfach und braucht keinerlei weitere Attribute. Während "init" lasse tendentiell alle Attribute zu (einfache prüfungen sind möglich). Mit "Init_done" gehe einmalig über die Parameter und räume auf. Es kann so einfach sein.
User hatten anfänglich jede Menge Probleme mit der Reihenfolge in den Config files. Das ist schon jahrelang Geschichte für CUL_HM.

Und noch einmal: Bei der Eingabe wird das Attribut geprüft. Danach ist es egal? Das ist definitv ein schlechtes, inakzeptables Vorgehen. Wenn bei Eingabe geprüft wird sollte man auch weiterhin auf Kosistenz achten. Beispiele gibt es genug. Wir sind doch nicht in den 80ern und die User sind nicht ausschliesslich Hacker. Etwas service des Systems sollte schon sein.

Zitat@Rudolf: hier wäre es ein willkommenes Feature, beim Schreiben der Readingdaten vorher automatisch ein Backup zu erzeugen
Ich will keine Backups einspielen müssen - schon garnicht von Readings - das sind leicht veränderliche Daten.

CUL_HM fährt hervorragend mit dem Umgang mit Attributen. Bisher habe ich kein einzigens konsistentes Bild oder durchgängiges Konzept gesehen oder gehört. Dass Attribute dem User gehören, nur weil es Attribute sind kann ich nicht nachvollzeihen - steht auch nirgendwo. Auch mit dem "kann nicht verändert werden" nimmt es keiner so genau. Je genauer man hinsieht desto inkonsistenter wird es.
Warum also die letzt endlich seltsame Diskussion?

Daraus folgt - zurück zum IODev:
Ist es des User's wille, ein IO festzulegen,keine Dynamik, kann schreibt er es in Attr IODev.
Entschiedet sich der User für eine Automatik setzt er ein entsprechendes Attribut (IOgrp in CUL_HM). Damit hat er seinen Willen kund getan, dem Modul das IO aus einer Liste suchen zu lassen. Damit hat er das Recht verwirkt, IODev zu setzen aus freiem Willen. Es gehört ihm nicht mehr. 

Wenn gewünscht kann man es in zig andere Parameter kopieren, ist mir egal. Den Sinn sehe ich nicht, aber wenn es sein muss...

Und für alle, welche das IO statisch definieren (warum auch immer) gilt eh das Attribut IODef.  Hier braucht es kein Reading, es ist unveränderlich und singulär.

Und zuletzt: Ich kann fhem.pl die Auswahl des IO nie und nimmer überlassen. Ich werde es IMMER selbst suchen/definieren und prüfen - auch die User-eingabe so diese erfolgt.

Somit erledigt sich die Diskussion von selbst. Ich bitte aber, die Sinnhaltigkeit der Schwemme der IODev zu überdenken. Es wäre schlicht schade, so etwas grundlos zu implementieren.


noansi

Hallo Rudolf,

Zitatfhem.last ist eine Hilfe, wenn man das Problem nicht sofort merkt, aber nach dem naechsten FHEM-Restart, und man kein save vorher gemacht hat. Nach zwei Restarts ist es schon wieder zu spaet. Dafuer verursacht es Probleme, wenn die Festplatte fast voll ist.

Da WriteStatefile() ein guter Punkt wäre, so was einzubauen hab ich mir den Wunsch schon mal selbst erfüllt:  ;)
  my $ofx = AttrVal('global','statefilebck',0);
  $ofx = 0 if ($ofx !~ m/^\d+$/);
  $ofx = 5 if ($ofx > 5);
  if ($ofx > 0) {
    my $bckFile = $stateFile.'.last';
    my $ofu = 5;
    do {
      unlink($bckFile.$ofu);
    } while (--$ofu >= $ofx);
    while (--$ofx) {
      rename($bckFile.$ofx, $bckFile.($ofx+1));
    }
    rename($stateFile, $bckFile.($ofx+1));
  }


Passiert so natürlich auch bei Save Config, aber der Zweck bleibt erfüllt (sonst wäre noch ein Parameter für WriteStatefile eine Möglichkeit). Und wenn ich mal schwer von Begriff bin, kann der Attributwert was höher ausfallen.

Gruß, Ansgar.

martinp876

Ich haben einmal AssignIoPort angesehen - und verstehe die Logik nicht. Aus meiner sicht nicht Wasserdicht - wasserdicht wäre sogar einfacher.

fhem_setIoDev ist eininterner Aufruf  undmuss nicht alles prüfen, was der caller schon macht.
Der Aufruf  aus setReadings ist eigentlich sinnlos, es sollte AssignIoPort aufgerufen werden.
Eigentlich braucht man fhem_setIoDev überhaupt nicht.

In AssignIoPort wird nach Prio "proposed->attr->reading" geprüft, später noch gesucht.
1) warum hat nun proposed vorrang for Attr? Wenn es dann doch in fhem_setIoDev  geschlachtet wird?
2) warum wird nur auf das Vorhanden sein priorisiert - die Gültigkeit erst später geprüft. Wenn es dann nicht gültig ist, werden die nachrangigen nicht mehr geprüft
3) "Clients " wird nur bei der Suche betrachtet. Soll das so sein? Abwärts-Kompatiblität?

In meinem Vorschlag werden unnötige Abfragen gelöscht. Weiter werden die Priorisierungen  nur dann eingehalten, wenn diese auch nach den Vorgabengültig sind.
Die Prio von Proposed an erste Stelle zu setzen halte ich für falsch. Attr war doch nummer 1. proposed 2 und Reading 3.

Und bei der Gelegenkeit wird gleich geprüft, ob das IO auch eine WriteFn zu Verfügung stellt. Das geht evtl auch effizienter.

Was meint ihr?

sub
fhem_setIoDev($$)
{
  my ($hash, $val) = @_;

#  if(!$val || !defined($defs{$val})) { # check not required - already done by caller.
    if(!$init_done) {
      $hash->{IODevMissing} = 1;
      $hash->{IODevName} = $val;
    }
#    return "unknown IODev $val specified";
#  }
#
#  my $av = AttrVal($hash->{NAME}, "IODev", "");
#  return "$hash->{NAME}: not setting IODev to $val, as different attr exists"
#        if($av && $av ne $val);
   
  $hash->{IODev} = $defs{$val};
  setReadingsVal($hash, "IODev", $val, TimeNow()); # 120603
  delete($defs{$val}{".clientArray"}); # Force a recompute
  delete($hash->{IODevMissing});
  delete($hash->{IODevName});
  return undef;
}


sub
AssignIoPort($;$)
{
  # IO prio: 1) proposed, 2) attribut 3) reading 4) best guess
  # internalVal "Clients" required for IO.
  my ($hash, $proposed) = @_;
  my $hn = $hash->{NAME};
 
  # Set the I/O device, search for the last compatible one.
  for my $p ($proposed
            ,AttrVal($hn,     "IODev", undef)
            ,ReadingsVal($hn, "IODev", undef)
            ,sort { $defs{$b}{NR} <=> $defs{$a}{NR} }
             grep/./
            ,map{($defs{$_}{TYPE}
                  && $modules{$defs{$_}{TYPE}}
                  && $modules{$defs{$_}{TYPE}}{WriteFn}?$_:'')}
            keys %defs) {
    next if (  !$p
            || !$defs{$proposed}
            || IsDisabled($p) == 1
            || $defs{$p}{TEMPORARY}); # e.g. server clients

    my $cl = ($defs{$p}{Clients} ? $defs{$p}{Clients}
                                 : $modules{$defs{$p}{TYPE}}{Clients});
    if(   $cl
       && $defs{$p}{NAME} ne $hn
       && $cl =~ m/:$hash->{TYPE}:/) {
        fhem_setIoDev($hash, $p);
        last;
      }
    }
  }

  return if($hash->{IODev});

  if($init_done) {
    Log 3, "No I/O device found for $hn";
  } else {
    $hash->{IODevMissing} = 1;
  }
  return undef;
}

noansi

#65
Hallo Martin, hallo Rudolf, hallo interessierte Mitleser,

fhem_setIoDev ist wohl bezüglich Attribut IODev Übergehen ein Torwächter und zugleich Hinweisgeber, was der User tun kann, um die verhinderte Manipulation zuzulassen. -> Attribut IODev löschen.

Zitat1) warum hat nun proposed vorrang for Attr? Wenn es dann doch in fhem_setIoDev  geschlachtet wird?
Ich denke, weil proposed eigentlich nur dazu gedacht ist, bei neuen devices eine "Empfehlung" mitzugeben, nicht jedoch es in jedem Fall zu erzwingen.

Zitat2) warum wird nur auf das Vorhanden sein priorisiert - die Gültigkeit erst später geprüft. Wenn es dann nicht gültig ist, werden die nachrangigen nicht mehr geprüft
Die Funktion wird bei Rudolfs Modulen am Ende der jeweiligen DefineFn aufgerufen. Damit ist zu erwarten, dass sie zwar gültig sind, aber erst nach $init_done=1 auch wirklich verfügbar sind.

Zitat3) "Clients " wird nur bei der Suche betrachtet. Soll das so sein? Abwärts-Kompatiblität?
Systemveränderungen werden hier in der Tat nicht ausreichend berücksichtigt, insbesondere, da CUL bezüglich Clients auch mit Attribut rfmode wandelbar ist. Sich somit auch einstmals passende IODev Einstellungen zu unpassenden entwickeln können. Hier spielt es keine Rolle, ob das durch User Eingriff oder Automatik passiert.

Ich fände es auch besser, wenn bei einer ungültigen IODev Vorgabe auf was potentiell funktionsfähiges geschwenkt wird. Das ist aber Ansichtssache.

Bei gültigen Vorgabedaten ist die Aufbereitung der Suche über alle Definitionen ein Bremsschuh. In der Regel dürfte man von gültigen Vorgabedaten zu IODev ausgehen dürfen.

Gruß, Ansgar.

martinp876

Hallo Ansgar
mir ist schon klar, wie man "proposed" übersetzt. Das ist kein User Interface - komplett unklar, wer es wie einsetzen soll. aus meiner Sicht alles nicht durchdacht - zumindest nicht umfassend. Ich kann die Methoden verstehen, die Linie nicht.

Hallo Rudi - wie versteht sich fhem nun eigentlich? Ich dringe mit meinen Fragen bislang nicht durch und mache es hier einmal am Attr IODev und einfachen Use-cases fest.

Szenario: eine Entity ENT1 ist definiert
User-Aktion: attr ENT1 IODev IO1
fhem (das modul) prüft die Eingabe nach einem der PrüfRegeln (PR)
  PR0: nix prüfen, alles zulassen. Das Attribut wird bei Nutzung geprüft
  PR1: reject wenn IO1 nicht instanziiert ist
  PR2: reject wenn IO1 kein IO ist (impliziert PR1)
  PR3: reject wenn IO1 kein IO und der Typ von ENT1 nicht unterstützt wird (impliziert PR2)
  PR4: reject wenn IO1 disabled ist (impliziert PR1, kann mit 2 oder 3 kombiniert werden)

=> meine Wahl: PR3, min PR2
+ "Disable" ist ein (hat die Semanik eines) administrativen Attributs. Man kann "mal disablen" und "mal enablen" Daher ist es beim Attribut setzen nicht zu berücksichtigen

Haben wir uns entschieden >PR0 zu implementieren ist es nun naheliegend, den Status der Attribute immer auf Stand zu halten. Das gehört sich und zeiht sich durch das gesamte System.

Szenario: eine Entity ENT1 ist definiert, attr ENT1 IODev IO1 gesetzt, IO1 existiert
User Aktion: rename IO1 IO1new
fhem Reaktion bei ENT1
   R0: wir machen nix - was schert mich die Prüfung PR1. Hierzu passt dann nur PR0. Vielleicht wird ja alles wieder gut und der User definiert ein neues IO1. Die Hoffnung stirbt zu letzt.
   R1: rename wird rejected, da IO1 genutzt ist
   R2: attr ENT1 IODev IO1new wird ausgeführt, zumindest sinngemäß
   R3: R2 wird durchgeführt und eine Info wird nach dem Kommando ausgegeben, dass IODev implizit geändert wurde.

Meine Wahl: Da R3 nicht unterstützt wird (keine Ausgabe von Info oder Warning nach Kommando Ausführung vorgesehen) ist meine Wahl klar R2.

Szenario: eine Entity ENT1 ist definiert, attr ENT1 IODev IO1 gesetzt, IO1 existiert
User Aktion: delete IO1
fhem Reaktion bei ENT1
  R10: nix machen, still halten. Siehe R0
  R11: reject delete so lange es assoziiert ist.
  R12: delattr ENT1 IODev : Das Attribut kann nicht aufrecht erhalten werden.
  R13: R12 + eine Info ausgabe an Ende. Wie R3

Szenario: eine Entity ENT1 ist definiert, attr ENT1 IODev IO1 gesetzt, IO1 existiert, attr IO1 disable 0
User Aktion: attr IO1 disable 1
fhem Reaktion bei ENT1 und Operationelle Reaktion ( also beim senden)
  R20: nichts machen
  R21: Info ausgeben, welche Entites nun nicht mehr senden können  - oder beieinflusst sind.
  R22: deleteattr ENT1 IODev
  OR20: ENT1 kann nicht mehr senden. Das exklusiv vom User eingestellte IO ist disabled, der User hat damit das Senden unterbunden
  OR21: IO1 empfängt nichts mehr, besser: empfangene Messages werden nicht mehr geroutet.
  OR22: fhem ignoriert die User-Einstellungen und sendet über irgend ein anderes IO, wenn es gefunden wird
  OR23: Es wird nicht mehr gesendet, die messages werden gequeued
  OR24: Es wird nicht mehr gesendet, die messages werden gedropped

Ich sehe R21, min R20. R22 ist nicht sinnvoll.
OR24 ist das geradlinige Vorgehen. FHEM macht OR22 - keine Zustimmung von mir. Der User hat mit den Attributen seinen KLAREN!!! Willen eingegeben. IODev ist demnach nur ein "preferred"
Die Definition von IODev kann man interpretieren. "shall be used" lässt bei Profis keine Option zum Ausweichen, bei Normalos sicherlich schon. "which can receive data" - das ist sicher "which supports the entity type". Senden sollte schon auch gehen. Wichtiger aber: Eine CUL kann unterschiedliche Typen unterstützen - aber nicht parallel. Somit muss dies auch behandelt werden. Hier müssen wir dann noch einen Usecase erstellen.

Wie immer gilt auch ind insbesonderen für opensource: wenn wir das Verhalten nichtklar und verständlich definieren wird es der Modulentwickler nicht umsetzen können und der Anwender keine Linie erkennen.

Mein Grundsatz: Was bei der Eingabe gefordert wird muss über die gesamte Laufzeit sichergestellt werden.
Anmerkung: Probleme bei der Sequenz in der fhem-init phase muss der Modulentwickler abfangen. Prüfungen können erst an Ende durchgeführt werden.

martinp876

keine Antwort, kein Interesse, keine Klärung, kein Hinweis auf Doku welche ich nicht gelesen habe. Noch nicht einmal eine Diskussion. Schade.
Also "jeder für sich - HURRA".

Dann ist das Thema also geschlossen. Danke.


noansi

Hallo Martin,

da ich auch User bin, stimme ich Dir bei den Prüfungen begrüßend zu.

Ein rename oder delete eines devices (generell) sauber durch das System zu ziehen, scheitert leider an der ausgiebigen Nutzung von user matches, um an diversen Stellen etwas auf das device zutreffendes zu prüfen.
Was auf der einen Seite eine hohe Flexibilität ermöglicht verhindert in diesen Punkten einen durchgängigen Automatismus.

Als User möchte ich lieber möglichst früh (direkt) auf die Nase fallen, als das es deutlich nach einer Änderung zu einem Fehlverhalten führt.
Daher nutze ich rename oder delete nicht, sondern adaptiere (ja bekennend und überzeugt) meine fhem.cfg, da dabei die Chancen am besten sind, Nebenwirkungen auch zu sehen. Auch modulübergreifende.

Rename und delete müssen nach meiner Meinung immer mit einer Warnmeldung enden, auf welche weiteren Systemfunktionen diese Änderungen Auswirkungen haben können. Am liebsten eine konkrete Liste, nach welchen Einstellungen man noch schauen müsste.

Auch CUL_HM kann ein funktionierendes rename und delete nur auf CUL_HM Ebene leisten, nicht aber modulübergreifend.

ZitatAlso "jeder für sich - HURRA".
Da sich weiteres konkretes Interesse bezüglich Multi-IO Unterstützung nicht unter Entwicklern gezeigt hat, sieht es leider danach aus.
Immerhin, das Reading IODev bietet einen gewisses Supportbausteinchen dafür, wenn es auch nicht durchgehend so begrüßt wurde.

@Martin: Als Fazit wäre mein Vorschlag, in CUL_HM nur noch das essentielle Internal IODev zu nutzen. IO Festlegungen nur durch CUL_HM eigene Funktionen und und CUL_HM eigene IO-Attribute. Eine automatische Umsetzung von Attribut IODev auf neuen Stand wäre dann auch möglich (das sollte konform sein, da damit der alte User Wille nur in eine neue Form übersetzt würde).

Vom Kernel würde ich für diesen Fall erwarten, dass das Reading IODev und damit auch das Internal IODev nur via CommandSetReading gesetzt werden kann, wenn auch das Attribut IODev vom Modul unterstützt wird.

@Rudolf: Das ist derzeit nicht abgefangen, wenn ich es nicht übersehen habe. Nur CommandAttr enthält eine entsprechende Prüfung auf zulässiges Attribut.

Gruß, Ansgar.

rudolfkoenig

Zitat@Rudolf: Das ist derzeit nicht abgefangen, wenn ich es nicht übersehen habe. Nur CommandAttr enthält eine entsprechende Prüfung auf zulässiges Attribut.
Ohne Komplettumbau kann ich mW nichts "abfangen", ich kann hoechstens bei der Benutzung bestimmter Routinen was pruefen.
Aber ich verstehe noch nicht genau, was genau geprueft werden soll. Und das "warum" wuerde mir auch viel helfen.

noansi

Hallo Rudolf,

ZitatAber ich verstehe noch nicht genau, was genau geprueft werden soll. Und das "warum" wuerde mir auch viel helfen.
Das Attribut IODev wird abgewiesen, wenn das Modul es nicht unterstützt. Das ist ok.

Wenn ein Modulentwickler sich entschließen sollte, vom Attribut IODev und dessen Behandlungs-Features durch fhem.pl Abstand zu nehmen (was Du ja als erlaubte Alterantive in den Raum gestellt hast, um in einem Modul IO-Automatismen zu implementieren), dann existiert das Reading IODev noch.
Ein Neustart des Systems führt dann zu einem Setzen des Readings IODev, aber zusätzlich auch automatisch zu einem Setzen des Internals IODev via fhem_setIoDev($$), ob der Modulentwickler das will oder auch nicht.

Auch wenn ein User meint, das Reading IODev manuell setzen zu müssen, wird das Internal IODev via fhem_setIoDev($$) mit gesetzt, was dann massiv stören kann, wenn das Modul das nicht unterstützt. (Warum der User das tun sollte? Z.B. weil er die Änderung der IODev Behandlung nicht mitbekommen/verstanden hat und was glaubt korrigieren zu müssen).

Es geht also um das zusätzliche Setzen des Internals IODev durch das Kernel, wenn das Modul es aber nicht wünscht/unterstützt (nicht um das Setzen des Readings selbst).
Die derzeit einzige Möglichkeit für ein Modul, dies kenntlich zu machen, ist das Attribut nicht in seiner Attributsliste zu führen. Sinngemäß war diese Attribut ja Aufhänger für die ergänzte Readingbehandlung des Readings IODev.

Der Modulentwickler kann nur via notifiyFn feststellen, dass das Reading gesetzt wurde, dann ist aber das Internal IODev bereits überschrieben (eventuell auch via Trigger genutzt). Effizient abfangen kann er es also auf keinem mir bekannten Weg.

Wie Martin ja deutlich gemacht hat, müssen IOs auch vorbereitet werden, nur das Setzen des Internals IODev macht es noch nicht funktional, sondern erlaubt zunächst nur die Nutzung von Write und Dispatch.

Das ist mir nur aufgefallen.

Gruß, Ansgar.

rudolfkoenig

Ich kann das Problem nicht nachvollziehen, bzw. nicht verstehen warum das relevant ist.

Readings gehoeren eigentlich nicht dem Benutzer, genauso wie Attribute nicht dem Modul. Wenn ein Benutzer diese trotzdem setzt, dann ist er selber Schuld, er kann ja auch ohne Weiteres Internals setzen, oder FHEM anderweitig zerstoeren.

Wenn ein Modul Probleme damit hat, dass das Framework IODev merkt, dann soll es IODev nicht mit fhem_setIoDev setzen und kein IODev Attribut anbieten, sondern das IODev Internal selbst setzen. Man kann auch ein Kombi-Modell fahren: wenn das IODev Attribut gesetzt ist, dann verwendet man das Framework, ansonsten sucht das Modul ein IODev aus.

Man muss nichtmal IODev oder Dispatch verwenden, das ist nur ein Angebot, womit man meiner Ansicht nach alle Faelle sinnvoll abdecken kann. Das ist aber nur meine Meinung, und was sinnvoll ist, ist auch subjektiv.

noansi

#72
Hallo Rudolf,

ZitatWenn ein Modul Probleme damit hat, dass das Framework IODev merkt, dann soll es IODev nicht mit fhem_setIoDev setzen
Es ist bei der Umstellung alt mit Attribut IODev auf neu ohne Attribut IODev beim FHEM Start doch so, dass erst die fhem.cfg inklusive darin enthaltener Attribute und dann das Statefile mit Readings gelesen wird.
Beim Einlesen des IODev Attributs wird mit neuem Modul es als unzulässig abgewiesen, ok und kein Problem, hat der Modulprogrammierer durch Weglassen des IODev Atrributs so festgelegt.

Das Reading IODev jedoch nicht und es wird mit CommandSetstate gesetzt, erfährt damit auch die Sonderbehandlung des Setzens des Internals IODev.
Hat der Modulprogrammierer aber anderes im Sinn, z.B. Setzen des Internals bereits beim define, dann wird es überschrieben.
Oder möchte er das Internal erst in seiner INITIALIZED notify Funktion oder seinem Initialize Timer setzen, um z.B. definitv auszuschließen, dass vorher IO stattfindet, dann würde das bereits gesetzte Internal stören können.

Erst mit dem nächsten Shutdown kann der Modulprogrammierer effizient über eine shutdownFn störende Readings, damit auch IODev, löschen.
An vielen Stellen im Code noch Sonderbahndlungen bzgl. existierendem Reading einzubauen ist nicht effizient, eine notifyFn nur zum Zweck des Abfangens des Setztens dieses einen Readings einzurichten, auch nicht wirklich und zudem für den FHEM Start auch nicht nutzbar.

Bezüglich User Eingriff hast Du ja bereits deutlich gemacht, dass Du das über eine Verhaltensänderung des Users lösbar siehst. Ist nach Umgewöhnung auch sicherlich so. Martin hatte aber ebenfalls zu recht angemerkt, dass eine saubere Lösung stets das Abfangen von User Fehleingaben (nebst verständlichem Fehlerhinweis) bedeutet.

Natürlich kannst Du auch das Reading IODev als künftig stets sonderbahndelt mit Setzen des Internals definieren, wie es der Code jetzt macht und eine Modulumstellung hat ggf. dadurch Umstellungsstolpersteine.
Jetzt wäre meiner Ansicht nach der Zeitpunkt der Festlegung. Noch bei Setzen des Reading IODev vor Setzen des Internals zusätzlich zu prüfen, ob das Modul das Attribut unterstützt wäre nicht sehr aufwändig, analog zu CommandAttr($$).
Wenn mal ein Modulprogrammierer das Reading IODev mit dieser Funktion des Setzen des Internals verwendet hat (ohne dass das Modul das Attribut unterstützt), wird eine Umwidmung jedenfalls künftig u.U. schwierig.

ZitatMan muss nichtmal IODev oder Dispatch verwenden, das ist nur ein Angebot
Ein für seinen Einsatzzweck grundsätzlich gutes, wie ich finde. Deswegen wäre es auch Quatsch, es komplett durch was zusätzliches zu ersetzten, wenn nur die IO Verwaltung nicht zum Modulprogrammiererwunsch passt.

Gruß, Ansgar.

martinp876

Ich werden weiter verfahren wie bisher was meine Grundsätze betrifft. Die Diskussion hat mich weiter gebracht und es muss einigen umstellen.
Rudi hat recht, dass es im Kernel schwierig ist, die Dependancies bei delete oder rename aufzulösen.  Dennoch
=> könnte man in "guidelines"  einmal definieren, was die Pflicht des Modul-Autors ist?
Fakt 1) Rudi muss deutlich mehr prüfen, ob bei einem Aufruf die Entites überhaupt existieren - und ähnliches. Der Kernel muss stabil sein und schlampereien in den Modulen überstehen
Vorschlag 1) Die Module sollten bei Änderungen and dependancies diese  automatisch nachgezogen werden und alles notwendige (bspw Attribute ) korrigiert werden. Das betrifft Rename/Delete und ggf Attr...

Ich musste hier einiges nachziehen. Auch die Entity-spezifischen Attribute und Attribut-werte waren zu korrigieren.
Fakt 2) Wenn Vorschlag 1) beachtet wird und Funktionen genutzt werden (commandAttr...) müssen deutlich weniger Konsistenzprüfungen im operationellen Teil code gemacht werden (was der Performance zu Gute kommen sollte). Konfigurations-Kommandos könnten länger dauern - das sollte ok sein.

Beispiel: Wenn ich ein IO lösche welches in Attr IODev genutzt wird werden alle Attribute gelöscht, welche dieses Attribut nutzen. Bei Rename wird der Attributwert ersetzt.

Fakt 3) Ein Modul muss die Konsistenz der Attribute seiner Schützlinge nach Reload/init prüfen - vollständig. Und zwar nachdem "init_done". Nur wer keine Abhängigkeiten hat kann sich das sparen.

Ich haben die erste Version CUL_HM fertig und werde sie zum Testen bald bereitstellen.

Fakt4) der User bekommt ein anderes Verhalten. Abhängigkeiten kann man nicht durch Namenstausch wechseln! Es ist wichtig, dass FHEM hier einheitlich funktioniert oder zumindest Grundsätze festlegt.

=> wieder fehlt ein Dokument.
=> der Kernel stellt alles bereit, was notwendig ist, es zu realisieren
=> Attribute verändern sich indirekt, unterliegen ständiger Prüfung und Anpassung (nicht so dramatisch wie es sich anhört - aberimmerhin)

martinp876

und Rudi,klar müsste auch der Kernel seine Attribute kontrollieren.
IODev ist eine Kernel Erfindung.  Also.
Unzulässig ist: nicht existente device und devices welche den typ nicht unterstützen.  Natürlich muss es ein io sein.
Der Zustand muss beibehalten werden. Wird das io umbenannt sind die Attribute nachzuziehen. Wird das io gelöscht so auch das Attribut, wo auch immer das io genutzt ist.
Sowohl beim init wie beim reload ist das zu kontrollieren. Also erst ALLES laden dann prüfe dann korrigieren.

Aktuell habe ich es eingebaut.  Noch lokal, funktioniert aber schon. Demnächst live.
Eigentlich ein Kernel Attribute also eigentlich ein Kernel job

rudolfkoenig

ZitatNoch bei Setzen des Reading IODev vor Setzen des Internals zusätzlich zu prüfen, ob das Modul das Attribut unterstützt wäre nicht sehr aufwändig, analog zu CommandAttr($$).
Ich finde zwar die Begruendung sehr speziell, ich will aber weder unsere Zeit mit weiteren Diskussionen vergeuden, noch Euer Wunsch ignorieren, habe also den Vorschlag implementiert. Bin unsicher, ob es alle Sonderfaelle so abfaengt, wie Du dir das vorgestellt hast, bitte also um Feedback.

noansi

Hallo Rudolf,

danke für's drüber schauen und den Umsetzungsversuch.

In CommandSetstate wird mit
    if($b1 eq "IODev") {
      my $ret = fhem_setIoDev($hash, $b[2]);
      push @rets, $ret if($ret);
      next;
    }

über fhem_setIoDev
  $hash->{IODev} = $defs{$val};
  setReadingsVal($hash, 'IODev', $val, TimeNow()); # 120603

weiterhin das Internal IODev als Sonderbehandlung gesetzt.
Nur das Setzen des Readings wird nun unterbunden (so weit ich den Code verstehe), wenn das Attribut vom Modul nicht unterstützt wird.

Was ich meinte
ZitatDas Reading IODev jedoch nicht und es wird mit CommandSetstate gesetzt, erfährt damit auch die Sonderbehandlung des Setzens des Internals IODev.
Hat der Modulprogrammierer aber anderes im Sinn, z.B. Setzen des Internals bereits beim define, dann wird es überschrieben.
sehe ich im Code daher noch nicht umgesetzt.
Das Setzen des Readings hat mich nicht gestört, sondern das Setzen des Internals.

D.h. ich vermute aus Deinem Zitat noch ein Missverständnis und ich hoffe, das klärt es nun.

Weiterhin interpretiere ich Deine Änderung derzeit dahingehend, dass Du das Reading IODev in jedem Fall gerne für fhem.pl reservieren möchtest.

Müsste nicht sein, ich meine primär nur Sonderbehandlungen, wenn das Attribut IODev vom Modul in der Attributsliste geführt wird. Andererseits würde eine klare Exklusiviität auch für das Reading natürlich auch künftige IODev Stolperfallen für Modulprogrammierer und unglückliche Userfehlinterpretation verhindern helfen.
Sprich, ein Modul, das die IO Zurodnungsverwaltung selbst übernehmen möchte, lasst die Finger sowohl vom Attribut, als auch vom Reading IODev.
ZitatReadings gehoeren eigentlich nicht dem Benutzer, genauso wie Attribute nicht dem Modul.
Nicht dem Benutzer ist klar, aber noch nicht so recht, unter welchen Bedingungen des Reading IODev dem Modul oder dem Kernel "gehört".

Gruß, Ansgar.

rudolfkoenig

Naechste Runde, bitte um Feedback.

noansi

Hallo Rudolf,

danke! :-)

Damit steht nun fest:
- das Reading IODev steht grundsätzlich unter der exklusiven Kontrolle von fhem.pl
- das Reading IODev wird nur gesetzt, wenn das Attribut IODev vom Modul unterstützt wird
- das Internal IODev wird nicht nach Reading IODev gesetzt, wenn das das Attribut IODev vom Modul nicht unterstützt wird
- sollte ein Modul dynamisch die Attribut IODev Unterstützung ab-/zuschalten wollen, dann gibt es dafür keine Kernel Unterstützung. Ein entsprechender Feature Request mit Diskussion der Funktionalität wäre dann erforderlich.

Der letzte Punkt entspringt den variablen HM-Device Eigenschaften.

Gruß, Ansgar.

Beta-User

Hallo zusammen,

nachdem ich jetzt schon eine Weile das - aus meiner Sicht eher zweifelhafte - Vergnügen hatte, behelfsweise alles mögliche rund um die aktuellen Probleme bei CUL_HM zu sammeln, möchte ich nochmal auf die Anregung von noansi hier zurückkommen:
Zitat von: noansi am 24 April 2021, 00:06:13
Im Grunde ist das auch die Begründung für die Sonderbehandlung des IODev Attributs, da die config die Reihenfolge der Definitionen nicht vorschreibt/schreiben möchte -> Verlagerung des Setzens ans Ende der Initialisierung, wenn alle IOs definiert sein sollten.
Da kommt mein IODev Änderungsvorschlag in CUL_HM beim FHEM Init nicht dran, weshalb etwas Disziplin bei der Ordnung in der config für volle Funktionalität erforderlich ist.

Damit wäre es eigentlich besser, einem Modul die Möglichkeit zu geben, eine Funktion bereit zu stellen, die zu diesem Zeitpunkt modulspezifische IO Zuweisung durchführt.
Beispielsweise eine $modulhash->{FinalizeInitFn}, die mit Leben gefüllt werden kann, wenn es benötigt wird.

Mit vorhandenen Bordmitteln ($hash->{NotifyOrderPrefix}) scheint es jetzt zwar zu funktionieren, dass die Initialisierungen von HMLAN und CUL_HM im Verhältnis zueinander und auch im Verhältnis zu anderen INITIALIZED-Eventhandlern in der richtigen Reihenfolge abgearbeitet werden, aber irgendwie fühlt sich das wie ein workaround an, und wenn das weitere Verbreitung findet, wird das ganze vermutlich komplett unübersichtlich.

Was - warum auch immer - bei CUL_HM gar nicht mehr funktioniert ist rereadcfg. Evtl. könnte man das dann auch in dem Zuge wieder reparieren...? (oder ganz ausbauen!)

Na jedenfalls: Falls sowas doch angegangen wird, sollte es m.E. auch die Möglichkeit geben, die Reihenfolge innerhalb der Aufrufe per Modul zu manipulieren.

(Hier OT, aber ansonsten wäre ich sehr glücklich, wenn sich wieder ein wirklich Wissender die Zeit nähme, die hoffentlich einigermaßen strukturiert eingesammelten Problemchen rund um CUL_HM eine Lösung im svn zuführen würde. Danke vorab!)
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

Beta-User

Nachdem wir heute wieder einen User hatten, der mit at/computeAfterInit ein Verständnisproblem hatte, greife ich das mit dem Vorschlag einer FinalizeInitFn hier nochmal auf:
Zitat von: rudolfkoenig am 22 November 2021, 13:19:27
Ich kann InitFn() einbauen, aber nur, damit ich nicht immer wieder erklaeren muss, dass es nicht hilft.

Wäre für weitere Rückmeldungen dazu dankbar...

Klar ist:
ZitatWenn Astro gettimeofday()+5 fuer die Initialisierung verwendet, dann wird das mit InitFn nicht besser. Um die richtige Reihenfolge zu berechnen, muessten alle Instanzen (und nicht nur die Module) angeben, von welchen Anderen sie abhaengen. Das ist Konfigurations und damit Benutzer abhaengig, und kann nicht ernsthaft von einem Benutzer verlangt werden. Mit etwas "Glueck" darf man auch eine zyklische Abhaengigkeit aufloesen.
Diese Argumentation ist m.E. zwar berechtigt, was den Hinweis betrifft, dass man dadurch nicht alle möglichen Abhängigkeiten beseitigt, sondern "nur" dafür sorgt, dass zumindest ReadingsVal()-Abfragen usw. nicht ins Leere gehen, nur weil die Devices halt - aus welchen Gründen auch immer - in der cfg an der "falschen Stelle" steht.
Diese FinishInitFn() kann nur dafür sorgen, dass der betreffende Code erst dann ausgeführt wird, wenn zwar alle Devices geladen sind und die alten Reading-Werte geladen (soweit überhaupt bekannt) und dabei "nebenbei" bekannte Abhängigkeiten beachten (indem es die Option gibt, eine Reihenfolge vorzugeben).

Events dürfen übrigens m.E. zu diesem Zeitpunkt keine generiert werden.

Zitat
Und das steht wo genau ? :)
:o
Aber im Ergebnis ändert es wenig daran, dass eine getimerte Initialisierung, z.B. mit "-10000000" immer erst nach den global:INITIALIZED-Eventhandlern drankommt, oder übersehe ich da wieder was?
Jedenfalls für CUL_HM war der Zeitpunkt "0" mind. in einem Fall zu spät, sonst wäre nicht der jetzige Vorschlag der Lösung mit NotifyFn() und niedrigem Präfix entstanden...
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

ZitatIch kann InitFn() einbauen, aber nur, damit ich nicht immer wieder erklaeren muss, dass es nicht hilft.
Ich baue was ein, wenn mindestens zwei Modulautoren ernsthaft beabsichtigen sie zu verwenden.
Bitte spezifizieren:
- wann genau sollen die Funktionen aufgerufen werden
- nach welcher Reihenfolge sollen die Aufrufe erfolgen


Zitatdass eine getimerte Initialisierung, z.B. mit "-10000000" immer erst nach den global:INITIALIZED-Eventhandlern drankommt...
Das ist richtig.
Die Aufrufreihenfolge kann der Maintainer fuer die Instanzen der eigenen Module festlegen, das geht aber sowohl mit der notify wie auch mit der InternalTimer Methode.
Wenn man von Instanzen fremder Modulen abhaengt, dann muessten diese jeweils ein INITIALIZED Event generieren, das kann vom abhaengigen Modulinstanz ausgewertet werden. Dazu ist "nur" das Wissen notwendig, wer von wem abhaengt.

Beta-User

Zitat von: rudolfkoenig am 22 November 2021, 14:33:21
Ich baue was ein, wenn mindestens zwei Modulautoren ernsthaft beabsichtigen sie zu verwenden.
Ich würde einen Vorschlag für CUL_HM/HMLAN/etc. liefern, vorausgesetzt, Martin würde sich dazu (positiv) äußern. Für meine eigenen Module brauche ich es nicht.

Aufgegriffen hatte ich das Thema, weil ich annehme, dass sich manche Initialisierungs-Probleme damit besser lösen lassen, mit denen sich grade zap bei HMCCU.* rumschlägt bzw. die mir als potentielle Probleme bei der ersten Durchsicht über eines der Module aufgefallen waren (ich habe das aber nicht näher untersucht, ist nur ziemlich von ferne). Auch insoweit würde ich ggf. Unterstützung anbieten.

Zitat
Bitte spezifizieren:
- wann genau sollen die Funktionen aufgerufen werden
- nach welcher Reihenfolge sollen die Aufrufe erfolgen
Meine Vorstellung:
- Aufruf vor dem global:INITIALIZED-Event, also: Alle Devices mit allen Attributen geladen, alle Readings aus der statefile geladen.
- Reihenfolge beeinflussbar durch ein Internal, analog zu NotifyOrderPrefix, hilfsweise könnte automatisch auch der Modul-Namenspräfix verwendet werden, also 00_HMLAN ergäbe "00" vor 10_CUL_HM (=> 10).

Einzuhaltende Regel durch die Module wäre: Es werden in diesem Stadium keine Events erzeugt! (Oder es wird irgendwie anders verhindert, dass irgendeine NotifyFn() dazwischengrätscht).

Zitat
Wenn man von Instanzen fremder Modulen abhaengt, dann muessten diese jeweils ein INITIALIZED Event generieren, das kann vom abhaengigen Modulinstanz ausgewertet werden. Dazu ist "nur" das Wissen notwendig, wer von wem abhaengt.
Das wäre auch eine Variante. Hat halt den Nachteil, dass man überhaupt eine NotifyFn() braucht. In einem Gutteil der Module scheint die nur drin zu sein, um die Initialisierung zu machen, und es erfordert in diesen Fällen etwas "Beiwerk", um das auf "global" zu begrenzen usw.. Ergo würde das auch ein klein wenig Overhead sparen, wenn man es insgesamt so macht (in den meisten Fällen kann man vermutlich auch einen InternalTimer alternativ verwenden; so war das jedenfalls bei den Modulen, die ich bisher in diese Richtung in der Hand hatte).
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

M.Schulze

Hallo,

nur das ich das richtig verstehe:

Ich habe hier eine Installation mit > 200 Geräten, und bei allen ist das

Reading:
IODev NAMEIODEV 2022-02-21 22:24:12

hinzugekommen. Es war früher nicht da. Und ist jetzt immer da???


Das geht so nicht weil es sich nie ändern wird, und bläht, und die Hausfrau nicht interessiert. Wie bekomme ich das Reading weg?

Ausgangslage: Eigenes Modul, ich setze das Reading aber nicht!!!

Bin ich hier im richtigen Thread? Muss ich mein Modul anpassen?

MfG
Muss ich das Licht aus machen?

rudolfkoenig

ZitatEs war früher nicht da. Und ist jetzt immer da???
Haengt vermutlich damit zusammen, dass das Modul das FHEM Framework verwendet, und hier ein update durchgefuehrt wurde.

ZitatDas geht so nicht weil es sich nie ändern wird, und bläht, und die Hausfrau nicht interessiert. Wie bekomme ich das Reading weg?
Einfach eine alte FHEM-Version installieren, z.Bsp. aus dem SVN.