Entwicklung eines eigenen Module

Begonnen von Brun, 30 Oktober 2013, 08:34:00

Vorheriges Thema - Nächstes Thema

Brun

Wo kann ich denn mal Fragen zur Modulentwicklung stellen?

Ich bin gerade dabei und schreibe ein Modul. Da habe ich noch ein paar Fragen zu bestimmten Funktionen.
Als Developer bin ich allerdings nicht registriert.

Wohin nun mit meinen Fragen?


Gruß Brun

cotecmania

Das Thema habe ich nun schon mehrmals gefunden aber keine Lösung.

Wie erstellt man selbst Module.
Warum gibts kein Skelett-Modul, in dem alle notwendigen Funktionen, etc.  leer oder mit Beispiel drin sind.
Umgang mit Variablen etc.
Oder ein kleines Beispielmodul, an dem man sich orientieren kann.

Was soll man als Beginner als Ausgangspunkt nehmen um einen gewissen Standart zu schaffen ?

Gruss
Joe
FHEM auf RaspberryPI B (buster)
2xCUL868 für MAX/Slow_RF, HM-LAN, JeeLink
MAX!/HM-Thermostate, FS20/HM-Rolladenschalter, FS20-EM, LevelJet-Ölstandsmessung, PCA301, IT, KM271, IPCAM, FireTAB10 FTUI

bugster_de

#2
Hallo Leute,

das würde mich auch interessieren. Vielleicht kann man dazu einen Wiki Artikel verfassen?

Ich habe mir das angehängte Modul mal als Spielwiese erstellt. Es realisiert einen einfachen Counter. Den Code habe ich aus verschiedenen Modulen zusammen kopiert und ihn an den Stellen, wo ich nicht ganz genau verstehe, was passiert mit Fragezeichen versehen.
- vielleicht spielt hier auch mal damit rum und teilt eure Erkenntnisse hier mit?
- vielleicht schaut einer der FHEM Entwickler mal drüber und kommentiert?

Auf dieser Basis habe ich mir einige eigene Module geschrieben, die auch im produktiven Einsatz bei mir sind. Die funktionieren zwar zuverlässig, aber ich habe eigentlich keine Ahnung warum (ich bin da mal ehrlich...:-))

Dieses Modul ist erstmal nur für logische Devices. Ein physikalisches Device habe ich noch nicht erstellt und ich habe auch keinen Dunst, wie das gehen soll.


bugster_de

#3
und hier mal meine Erkenntnisse, die so nicht aus meinem Code ablesbar sind. Bitte nicht schlagen, falls die falsch sind sondern lieber korrigieren.

- FHEM ist "flach" organisiert. Jeder kann auf alles zugreifen
- jedes Modul kann Attribute, Readings und Internal readings haben
- Readings und internal Readings haben dabei einen Wert und einen Zeitstempel.
- Attribute haben nur einen Wert
- es gibt einen Unterschied zwischen state und STATE. Man sollte wohl nur auf state arbeiten. Wann aber STATE durch FHEM aktualisiert wird ist mir nicht klar
- in der Struktur defs sind alle Elemente von FHEM gelistet. Über diese kann man z.B. per foreach drüber iterieren um alle Elemente in FHEM zu finden
- sollte man Aufgaben im Modul haben, die entsprechend lange Ausführungszeit haben, dann sollte man dieses auslagern und via BlockingCall starten

betateilchen

Zitat von: cotecmania am 10 Dezember 2013, 11:48:09Warum gibts kein Skelett-Modul, in dem alle notwendigen Funktionen, etc.  leer oder mit Beispiel drin sind.
Umgang mit Variablen etc.
Oder ein kleines Beispielmodul, an dem man sich orientieren kann

Gibts doch.

Im Unterverzeichnis ./contrib das Modul 00_TAHR.pm

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

hexenmeister

Hallo,

vor dieser Frage stand ich vor kurzem auch.
Am Ende habe ich irgendein halbwegs ähnliches Modul als Vorlage genommen.
Das ist dann rausgekommen: https://github.com/hexenmeister/MyFHEM/blob/master/FHEM/42_SYSMON.pm

00_TAHR.pm kannte ich noch nicht. Gut zu wissen ;)

Weiteres Erkenntnis:
- Wenn ein Modul abstürzt - geht FHEM mit kaputt => kein Schutz, keine Trennung
- Die Methoden für GET und SET prüfen die übergebenen Werte (get XYZ) und liefern ein String, wenn sie den gewünschten Befehl nicht kennen. Die Rückgabe wird durch FHEMWEB geparst und daraus die Comboboxen mit den möglichen Werten generiert:
return "Unknown argument $cmd, choose one of list:noArg update:noArg interval_base:noArg interval_multipliers:noArg version:noArg";
- Die Commandref ist nicht automatisch da, wenn man ins Modull die Texte schreibt. Es gibt in contrib ein Script zum Generieren.
...

Gruß,

Alexander
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

bugster_de

die 00_TAH.pm kannte ich auch noch nicht. Scheint für ein physikalisches Modul zu sein, oder?

ZitatDie Rückgabe wird durch FHEMWEB geparst
hier habe ich noch nicht genau verstanden, was FHEM im Falle von i.O. als Rückgabe erwartet. Wenn ich z.B. in der Define Funktion einen String mit einer fehlerbeschreibung zurück liefere, dann wird dieser String angezeigt und mein Element nicht angelegt. FHEM interpretiert offensichtlich den String als Fehlermeldung.
Aber was muss ich denn zurück geben um FHEM zu signalisieren, dass alles gut ist?
Und was macht return(undef);?

aus deinem Code
#SYSMON_Update($hash); #-> so nicht. hat im Startvorgang gelegentlich (oft) den Server 'aufgehaengt'
kann ich so bestätigen. Ging bei mir auch nicht; oder besser der Startvorgang dauert dann bis zu 20 Minuten. FHEM kommt irgendwann mal hoch. Somit also alles was Readings via readingsBulkupdate oder readingsSingleUpdate beschreibt nicht während des defines machen, sonst gibt das schiefe Schuhe.

ZitatWenn ein Modul abstürzt - geht FHEM mit kaputt => kein Schutz, keine Trennung
kann ich so auch bestätigen. Deshalb habe ich bei neuen Modulen in den ersten Versionen immer jede Menge checks drin. Sobald ich alle möglichen Situationen gesehen habe, nehme ich die Checks sukzessive raus um Laufzeit zu sparen.

hexenmeister

Hi!

ZitatUnd was macht return(undef);?

return undef;
oder
return;

veranlasst FHEM die Seite so stehen zu lassen und keine Meldung anzuzeigen.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

bugster_de

sprich wenn ich in der Define Funktion return(); oder return( undef ); zurück gebe ist alles i.O. und das Element wird angelegt.

Wenn ich return( "dies ist ein Fehler" ) zurück gebe ist das für FHEM ein Fehler und das Modul wird nicht angelegt?


hexenmeister

Ich habe zwar von den Funktionen get und set gesprochen, aber das könnte auch für define so gelten. Muss ich mal ausprobieren.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

bugster_de

habe ich schon auch so für get und set gelesen  :)

Momentan habe ich den Code in der define so, dass im Fehlerfall ein text zurück gegeben wird. Im i.O. Fall habe ich aber gar kein return drin, was ich sehr unschön finde.
Im Fehlerfall erhalte ich zumindest kein in der Web Oberfläche sichtbares Modul; aber ich wieß auch nicht, ob FHEM dann die bis zum Fehlerzeitpunkt angelegten Variablen (z.B. Readings) wieder abbaut oder ob ich mir dann den Speicher zu mülle.

betateilchen

Zitat von: bugster_de am 10 Dezember 2013, 18:25:34Wenn ich return( "dies ist ein Fehler" ) zurück gebe ist das für FHEM ein Fehler und das Modul wird nicht angelegt?

Genau so ist es. Wenn IRGENDWAS zurückkommt, das man als "nicht null" interpretieren könnte, interpretiert fhem das als 1 - und dann knallts.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

hobbynaut

Habe mich auch dran versucht ein eigenes Modul zu schreiben, bin dann aber immer an der Fehlermeldung "Unknown module FooBar, choose one ..." gescheitert. Selbst mein "minimales" Modul FooBar wollte nicht laufen:

package main;

#####################################
sub
FooBar_Initialize($)
{
  my ($hash) = @_;

  $hash->{DefFn}   = "FooBar_Define";
}

###################################
sub
FooBar_Define($$)
{
  my ($hash, $def) = @_;
  return undef;
}

Dann sah ich den Tipp mit dem 00_THAR.pm und dort als letzte Zeile diese:

1;

Und siehe da die Fehlermeldung ist weg! Diese zwei letzten unscheinbaren zwei Zeichen haben mich einige graue Haare und Stunden des Rumprobierens gekostet  :'(
Mögen alle Anfänger wie ich bei ihrer Suche nach "Unknown module" diesen Beitrag schnell finden.

bugster_de

Nebenbemerkung: das ist auch bei 99_Utils.pm so (oder generell bei Perl). Hat mit Modulen nichts zu tun.