IODev Handling durch device

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

Vorheriges Thema - Nächstes Thema

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