Dokumentation für Developer - Einsteiger

Begonnen von Elektrolurch, 21 Januar 2014, 17:59:56

Vorheriges Thema - Nächstes Thema

Elektrolurch

Hallo Stefan, hallo Entwicklergemeinde,
Stefan hat ja löblicherweise ein "Einsteiger-Dokument" für Entwickler geschrieben:
http://www.fhemwiki.de/wiki/Kategorie:Development
Der thread hierzu stand allerdings im Bereich "developer", so dass nicht alle Forumsmitglieder darauf antworten können.
Ich mache daher mal hier unter "Sonstiges" einen neuen thread mit vielen Fragen auf.

Da ich derzeit auch an einem Modul herumbaue, habe ich einige Ergänzungen bzw. Fragen, die in das Dokument noch einfließen könnten, wenn die "Heros" mit guten und verständlichen Antworten  ihren Beitrag dazu leisten.

ich merke mal einige Dinge an.

1.   Einleitung
   Namenskonvention für Module:
Frage:   Gibt es eine Regel für die Vergabe der vorangestellten Nummer?
Frage: Wenn das Modul Initialisierungsdateien benötigt, wo sollen die lieben? In einem Unterverzeichnis in FHEM oder in lib?
Frage: Wie kann man es bewerkstelligen, dass die 23_X-Datei auch im Edit-Bereich von fhem erscheint? Arbeitet man nämlich mit einem seperaten Texteditor und speichert, bekommt man keine Fehlermeldungen von perl. Die kommen erst mit reload und stehen dann im fhem-log-File.
Oder gibt es da eine andere Technik?

Noch so ein kleiner Hinweis:
In die fhem-Zeile kann man ja auch perl-Code eingeben und so Modulteile auch testen. Fand ich ziemlich nützlich....


2. $hash
Frage: Wird alles, was in $hash eingehängt wird, auch in die fhem.sav gesichert?
Bei den $hash->{READINGS}... geht das ja wohl noch in die nächste Untersruktur. Geht das generell so?
z.B. $hash->{READINGS}{readingname}{VAL}{meineListe} zeigt auf die Adresse eines arrays.

Frage: Gibt es einen Unterschied szwischen dem "save" - Befehl und "Save config" an der fhem-Oberfläche?

Anmerkung:
Während der Laufzeit erzeuge ich einige Readings, wenn ein bestimmter Zustand der Solaranlage eingetreten ist. Danach lösche ich die Readings wieder mit:
fhem("deletereading $name $rd");
oder alternativ mit
delete ($defs{$name}{READINGS}{$rd});
fhem bestätigt auch das Löschen des Readings.
Nach dem "save" - Befehl sind die gelöschten Readings wieder da und mit "0" initialisiert, obwohl nirgends in dem Modul eine Zuweisung mit "0" programmiert wird.
Frage: Gibt es da ein Geheimnis, bzw. die Readings werden noch wo anders gespeichert?

Zitat: aus der Doku:
Ein Abfrageintervall, das beim define eines Geräts an die define-Funktion im Modul übergeben wird, würde typischerweise als "Internal" in $hash->{INTERVAL} abgelegt.

Ich würde das jetzt eher als ein Attribut implementieren, da der Nutzer es einstellen können soll.
Frage: Wann Internal oder Attribut und welche Unterschiede gibt es?

Readings:
Wenn der Name mit einem ,,." (Punkt) beginnt, wird er in der Liste der Readings nicht angezeigt.
Frage: Wird das Reading denn mit Save trotzdem gesichert?

Zitat:
Internals werden jedoch im Gegensatz zu Readings nicht im statefile zwischengespeichert.
Frage: Stimmt das?
Frage: Wenn per define, wie hier im Beispiel, die Intervallzeit gesetzt wird, wie wird die dann nach einem Neustart wieder gesetzt, wenn sie nicht im Internal gespeichert wurde (per Save)?

Attribute:
Zitat:
Zur Laufzeit werden sie in der globalen Datenstruktur $attr{$name} gespeichert.

Frage: Heißt dass, das man im undefFN diese nicht separat löschen muss?

Frage: Was muss man über die Globale $modules wissen?
X_Initialize?

Zu X_define:

Hier sollten nach Abschluß der Initialisierung der Instanz auch die Readings erstmalig gelesen werden. Wenn das device selber die Daten holen muss (z.B. per LAN-Zugriff), so können hierfür die entsprechenden Timer mit der Funktion internaltimer( ..# habe im Augenblicfk keinen Quellcode zur Verfügung
Gestartet werden.

Frage: Die Routine, die die Daten holt, muss dann, so wie auch im Beispiel in der Doku, den timer wieder neu initialisieren. Wie wird sicher gestellt, dass dies auch nach einem Neustart von fhem funktioniert? Das erstmalige Daten wird ja über "define" ausgelöst. Wird das "define" nach dem Neustart von fhem wieder ausgeführt?

X_Undef
Frage: Um das Löschen von in $attr, $modules eingetragene Werte muss man sich nicht kümmern?
Frage: Aber die timer für das Datenholen müssen gelöscht werden?

Zitat
X_Set
Die Set-Funktion ist das Gegenteil zur Get-Funktion. Sie ist dafür gedacht, Werte zum physischen Gerät zu schicken. Falls nur interne Werte im Modul gesetzt werden sollen, so sollte statt Set die Attr-Funktion verwendet werden. Attribute werden bei Save-Config auch in der Fhem.cfg gesichert. Set-Befehle nicht.
..
Frage: Was macht dann der Aufruf von ,,setreading" aus fhem heraus? Nur das Reading setzen, ohne dass eine Kommu Kommunikation zum Gerät stattfindet?
Das heißt z.B. ja dann folgendes:

Es soll an einem Gerät der Temperaturschwellwert ,,Schwelle" gesetzt werden.

Set meindev Schwelle 22

Dann müsste der set-Befehl den Wert ans Gerät senden und anschliessend wieder auslesen, um zu prüfen, ob das Gerät den Wert akzeptiert hat.
Dann erst mit readingsSingleUpdate das entsprechende Reading in fhem setzen und damit auch das notify auslösen, falls sinnvoll.
Frage: Wäre das so korrekt implementiert?

Zitat:
Das GUI FHEM-Web kann für die einzelnen Set-Optionen, die das Modul versteht auch automatisch Eingabehilfen wie Drop-Down Boxen oder Slider erzeugen. In der Detailansicht des GUI kann der

Frage: Wie lege ich das fest?

Und was ist die ,,($X_sets{$opt}" – Variable?
Global oder über $modules...?


Mir ist nicht ganz klar, wo ich die möglichen Werte für die Eingabeoptionen des Moduls definieren muss. Zuweisung auf? In der X_Initialize?

Zitat:
Wenn Geräte von sich aus keine Informationen senden sondern abgefragt werden müssen, kann man im Modul die Funktion InternalTimer<code> verwenden. Man übergibt ihr den Zeitpunkt für den nächsten Aufruf, den Namen der Funktion, die aufgerufen werden soll, die zu übergebenden Parameter und ein Flag ob der erste Aufruf verzögert werden soll falls die Initialiserung des Geräts noch nicht abgeschlossen ist.

Frage: Wie übergibt man für die aufzurufende Funktion mehrere Parameter?
Ich habe überall nur immer $hash gefunden.
Frage: Ist der letzte Parameter ,,0" die Verzögerung?
Frage: Wenn zweimal für das gleiche $hash und die gleiche Funktion der interne Timer initialisiert wird, wird dann die Funktion auch zweimal aufgerufen? Oder setzt die letzte Initialisierung das bestimmende Zeitinterval?

Frage: Wie und wo wird die Liste für gültige get-Optionen definiert?


Zitat:
Logging / Debugging
Um Innerhalb eines Moduls eine Protokollmeldung in die Fhem-Logdatei zu schreiben, wird die Funktion Log3 aufgerufen:
Tippfehler? Log3?
Unterschied zu Log(3,"?


Was mich auch noch interessieren würde:
1.   Manche Module erzeugen beim ,,define" gleich das zugehörige Logfile. Wie geht das? Und der entsprechende plot? (wie z.B. beim fht)
2.   Wie kommen die fs20 – Glühbirnen oder das fht-Klappmenü für die ,,desired-temp" zu Stande?

Ich hoffe, das war jetzt nicht zuviel

Gruß

Elektrolurch

configDB und Windows befreite Zone!

rudolfkoenig

ZitatFrage:   Gibt es eine Regel für die Vergabe der vorangestellten Nummer?
Nicht wirklich, die fruehere Rolle ist nicht mehr gegeben. Man sollte es am besten Nummern waehlen, die auch andere aehnliche Module gewaehlt haben.

ZitatWenn das Modul Initialisierungsdateien benötigt, wo sollen die lieben?
Im Modul selber. Neue Verzeichnisse sollten nur nach Ruecksprache mit mir angelegt werden, sonst werden sie per update nicht verteilt.

ZitatWie kann man es bewerkstelligen, dass die 23_X-Datei auch im Edit-Bereich von fhem erscheint?

Wenn Du vom FHEMWEB redest: indem Du X durch Util ersetzt. Das ist aber eigentlich nur fuer MyUtils gedacht, und nicht, dass man damit entwickelt. Entwickeln tu ich mit 3 Fenster:
1. Editor
2. Kommandozeile, wo man "perl fhem.pl cfg/fhem.cfg.XXX" wiederholt aufruft
3. Browser oder telnet um die befehle einzugeben

ZitatIn die fhem-Zeile kann man ja auch perl-Code eingeben und so Modulteile auch testen.

Sollte fuer die, die http://fhem.de/commandref.html#perl gelesen haben, keine wirkliche Ueberraschung sein.

ZitatFrage: Wird alles, was in $hash eingehängt wird, auch in die fhem.sav gesichert?
Nein, nur die Readings.

Zitat$hash->{READINGS}{readingname}{VAL}{meineListe}
Das ist nicht zulaessig.

ZitatGibt es einen Unterschied szwischen dem "save" - Befehl und "Save config" an der fhem-Oberfläche?
Nein, wie man das leicht pruefen kann, wenn man den Inhalt des links (== mouseover in den meisten Browsern) prueft.


ZitatFrage: Gibt es da ein Geheimnis, bzw. die Readings werden noch wo anders gespeichert?
Nein, da ist sonst noch ein Bug.

ZitatWann Internal oder Attribut und welche Unterschiede gibt es?
Internal kann vom Benutzer nicht geaendert werden, und wird auch nicht gespeichert.

ZitatFrage: Wird das Reading denn mit Save trotzdem gesichert?
Sowas testet man, wenn man unsicher ist.

ZitatFrage: Stimmt das?
s.o.


Die restlichen Fragen darf jemand anderes beantworten...

StefanStrobel

Hallo,

ich habe ein paar Dinge in der Doku ergänzt bzw. konkretisiert.

Gruss
   Stefan

Prof. Dr. Peter Henning


StefanStrobel

Wenn man die Seite im Wiki auswählt, dann rechts oben auf Versionsgeschichte klickt, dann kann man sehr komfortabel z.B. die Version vom 14. Januar mit der vom 26. Januar vergleichen lassen und bekommt die Änderungen sehr schön nebeneinander dargestellt.
Hier der direkte Link zum Vergleich:
http://www.fhemwiki.de/w/index.php?title=DevelopmentModuleIntro&diff=4682&oldid=4337

Zusammengefasst habe ich ein paar Rechtschreibfehler korrigiert, die Sache mit der Config-Datei und dem Neustart sowie das mit dem Löschen von Variablen klargestellt, die Übergabe von Parametern an den InternalTimer erläutert und ganz unten zwei neue Absätze mit allgemeinen Hinweisen und Verweisen auf weiterführende Infos hinzugefügt.

Wenn ich heute oder morgen noch etwas mehr Zeit finde, möchte ich als nächstes auch noch die NotifyFn beschreiben.

Generell freue ich mich über konstruktives Feedback, am besten in Form von Ergänzungsvorschlägen wie das zum Beispiel Fhemrocks getan hat, als er die Beschreibung der Optionen nach einem ":" ergänzt hat.

Was auch hilft sind Hinweise auf ältere Threats, in denen möglicherweise einzelne Aspekte schon gut erklärt wurden.

Es gibt noch viel zu tun und ich hoffe dass es Einsteiger künftig leichter haben sich in die Entwicklung von Modulen hineinzufinden.

Gruss
   Stefan


Prof. Dr. Peter Henning

Ich glaube nicht, dass ich Nachhilfe in der Bedienung eines Wiki benötige.

Mein Post war nur als Hinweis gemeint, nicht von "der Doku" zu schreiben - deren gibt es nämlich viele.

Darüber hinaus ist ein Seitentitel wie "DevelopmentModuleIntro" nicht sehr erhellend - besser wäre "Einführung in die Programmierung von FHEM-Modulen".

Noch drei weitere konstruktive Tipps:

  • Texte sind besser lesbar, wenn sie stärker strukturiert sind. Besser mit weiteren Unter-Kapiteln arbeiten
  • Ein Wiki lebt von der internen Verlinkung, auch innerhalb einer Seite
  • Besser kürzere Sätze verwenden und mal mit dem Kommastreuer drüber gehen

Ansonsten: Gute Idee.

LG

pah

Gerhard

Hallo Stefan,

wie pah schon geschrieben hat, es ist eine sehr gute Idee diesen "DevelopmentModuleIntro" ins wiki zu schreiben!!

mir wenigstens hift es sehr, da ich selber dabei bin ein paar Module zu schreiben. Ich komme mit der Beschreibung wunderbar zur recht, und vor allem, sind mir jetzt (und hoffentlich in der Zukunft auch, wo ich auf notify warte) viele Zusammenhänge klar.

danke, Gerhard
FB6890LTE, cubietruck, orangePi, raspberry 2/3/4, HM/HMIP, shelly > 50, etc.

Elektrolurch

Hallo Stefan,

die Doku ist wirklich hilfreich, ich habe nicht schlecht gestaunt, als auf der Seite für mein neues Modul neben den set und get - Knöpfen die Listen der Readings mit ev. auch Untermenüs für die Werte auf Anhieb erschienen.
Mir fehlt aber jetz noch eine Info:
Was muss ich tun, um Werte abzuprüfen, die per setreading gesetzt werden, z.B. aus einem Textfeld heraus?
Gibt es da ein Pendant zu X_Attr?

Gruß

Elektrolurch
configDB und Windows befreite Zone!

StefanStrobel

Hallo Elektrolurch,

So wie ich das verstehe ist der Befehl setreading in fhem.pl so implementiert dass er direkt readingsSingleUpdate aufruft. Damit ändert man readings am Modul vorbei. Such einfach mal nach CommandSetReading in der fhem.pl, dann findest Du den Befehl recht schnell.

Gruß
   Stefan

Elektrolurch

Hallo Stefan,

offensichtlich ist es so, dass die Änderung an einem Textfeld sofort sich auf das mit dem Textfeld assoziierte Reading auswirkt, bei Menüs oder Slider aber die set-Funktion des Moduls aufgerufen wird. Daher gibt es demnächst wohl für das Textfeld eine Erweiterung: mein_Reading:textField,set -> damit sendet das Textfeld seine Änderung an die set-Funktion.
Das Verhalten  zwischen dummy und Modulen ist da seitens fhem auch unterschiedlich. Man muss das wissen, wenn man Module schreibt und das in der set-Funktion entsprechend berücksichtigen.
set X-Name Mein_Reading Wert (ohne ":", wie es im notify erscheint)
Hintergrund: Ich habe in einer readingsGroup wahlweise mal Textfelder, mal Menüs verwandt und mich gewundert, dass ich bei Eingabe in Textfeldern nichts davon mitbekommen habe, wenn aber der Wert über ein Menü gesetzt wurde, wurde die set- Funktion aufgerufen, d.h. die Eingabe in einem Textfeld konnte nicht als Steuerparameter an die Heizung gesendet werden. Offensichtlich ist aber noch niemandem diese Diskrepanz aufgefallen, vermutlich auch, weil die Mechanismen von fhem auch nirgends beschrieben sind)
Das wäre doch noch so ein Punkt für Deine Einsteiger-Doku...?

Gruß

Elektrolurch
configDB und Windows befreite Zone!

StefanStrobel

Hallo Elektrolurch,

mir ist nicht ganz klar was genau die Auswirkungen von :textField bei Sets auf ein WebCmd sind und wie oder warum die sich von anderen ":"-Optionen unterscheiden oder bei Modul vs. Dummy anders ist. Ich möchte in die Modul-Einsteiger-Doku keine Sachen reinschreiben, bei denen ich nicht wenigstens ein bischen überzeugt davon bin, dass ich sie auch verstanden habe.

Ob das überhaupt ein Thema für eine Einsteigerdoku ist ist noch mal eine andere Frage.
Falls hier Dinge bisher gar nicht oder nicht korrekt dokumentiert sind, wäre es vielleicht zielführender wenn jemand, der es verstanden hat einen Vorschlag für die Ergänzung der Commandref macht oder?

Gruss
   Stefan

Elektrolurch

Hallo Stefan,

habe heute mal wieder im wiki in die Einsteiger-Doku geschaut und einiges Neues entdeckt. Aber ich habe da auch noch ein paar Anmerkungen / Fragen:

Im Abschnitt X_def verstehe ich folgende Erklärung nicht:
Neu: Zum Aufteilen und Parsen von $def lässt sich parseParams verwenden. Wenn in X_Initialize
$hash->{parseParams} = 1;
gesetzt wurde dann wird parseParams automatisch aufgerufen und X_Define ändert sich wie folgt:
sub X_Define($$$)
{
   my ( $hash, $a, $h ) = @_;
   ...

Was macht die aufgerufene Parse-Funktion? Welche Vorteile hat das Modul davon?
###############
X_get – Funktion
my X_gets = (
Da fehlt ein "%"?
###############
Zu dieser Fragestellung habe ich rein nichts im Forum (trotz google) gefunden -> Behandlung von userattr im Modul

X_attr
Die X_attr – Funktion sollte ja auf die Eingabe von ,,?" eine Liste der möglichen Attribute zurückliefern. ($hash->{attrlist}
Müsste hier nicht auch noch die Liste der Attribute, die ev. im Attribut ,,userattr" hinterlegt wurden, angefügt werden?
Muss ,,userattr" auch zur $hash->{attrlist} bei der Modulinitialisierung hinzugefügt werden?
####################

Viele Grüße

Elektrolurch




configDB und Windows befreite Zone!

dev0


StefanStrobel

Hallo,

das fehlende % hab ich gerade ergänzt. Danke für den Hinweis.

Den Inhalt vom userattr muss man bei ? nicht zurückgeben. Um die Attribute kümmert sich Fhemweb selbst.

Gruss
     Stefan

justme1968

@Elektrolurch: parseParams ist dazu da um modul übergreifend die gleichen regeln zum parsen der kommandozeilen parameter zu haben. das ist so lange egal wie ein modul nur durch leerzeichen getrennte parameter akzeptiert bei denen die bedeutung von der position abhängt.

mit parseParams bekommt man unter anderem zusätzlich:
- die möglichkeit leerzeichen in parameter zu verwenden in dem anführungzeichen verwendet werden
- man kann ' oder " verwenden um leerzeichen zu maskieren. das jeweils andere zeichen ist dann im string noch erlaubt
- die möglichkeit benannte parameter der form name=wert zu verwenden. damit ist dann die reihenfolge egal
- man kann perl ausdrücke {...} so erkennen und parsen um hinterher perlSyntaxCheck zu verwendet. z.b. um
  attribute direkt bei der eingabe auf korrektheit zu prüfen.


hier: http://www.fhemwiki.de/wiki/DevelopmentModuleAPI#parseParams findest du auch noch etwas dazu.

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

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