DevIo

Aus FHEMWiki


Clock - Under Construction.svg An dieser Seite wird momentan noch gearbeitet.


DevIo
Zweck / Funktion
Dienstfunktionen für die Kommunikation per serieller Schnittstelle (USB/RS232), TCP/IP-Verbindung oder UNIX-Socket
Allgemein
Typ Utilities
Details
Dokumentation siehe Forum
Support (Forum) FHEM Development
Modulname DevIo.pm
Ersteller rudolfkoenig (Forum / Wiki)
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref!


Das Modul DevIo(.pm) ist für Modulentwickler gedacht, um Daten zwischen einem FHEM-Modul und bspw. einer seriellen Schnittstelle, einer TCP/IP-Verbindung oder einem UNIX-Socket auszutauschen. Es übernimmt dabei die gesamte Verbindungsverwaltung und Aufrechterhaltung innerhalb von FHEM und nimmt dem Modulentwickler daher die gesamte Verbindungsverwaltung (Aufbau, Initialisierung, Neu-Verbindung bei Abbruch, etc.) ab. Es berücksichtigt dabei Besonderheiten zwischen Unix-basierten Betriebssystemen und Windows.

Es dient dabei lediglich dem Zweck einen Kommunikationskanal für eine Definition in FHEM zu etablieren und Daten darüber auszutauschen. Die Interpretation der empfangenen Daten obliegt dem Modul, welches die Verbindung via DevIo geöffnet hat. Die ausgetauschten Daten werden durch DevIo nicht verändert.

Allgemeine Funktionsweise

DevIo hat das Ziel eine besonders einfache Möglichkeit für Modulentwickler zu schaffen, um einen dauerhaften Kommunikationskanal mit einem Hardware- oder Netzwerk-Gerät bzw. Service zu etablieren. Um eine Verbindung aufzubauen muss zunächst die Gegenstelle bekannt sein. Dazu muss vor dem Verbindungsaufbau in dem Internal $hash->{DeviceName} der jeweiligen Definition das Ziel hinterlegt werden. Dies kann bspw. eine serielle Schnittstelle sein (z.B. "/dev/ttyUSB0" oder "COM1" unter Windows) oder eine TCP/IP-Gegenstelle (z.B. "192.168.1.100:1012") sein. Eine detaillierte Aufstellung der möglichen Verbindungsarten und deren Angabe in $hash->{DeviceName} gibt es im folgenden Kapitel Unterstützte Verbindungsarten.

Die Funktion DevIo_OpenDev() baut dabei die entsprechende Verbindung für eine einzelne Definition in Form eines Filedeskriptors auf und registriert diesen in dem globalen Hash %selectlist[1]. Sobald die Verbindung erfolgreich aufgebaut wurde, kann beim eine durch den Modulautor mitgelieferte Initialisierungs-Funktion ausgeführt werden, um die Kommunikation zu initialiseren (bspw. das Senden einer Authentifizierungs-/Loginsequenz oder aktivieren der Hardware, etc.).

FHEM (respektive fhem.pl) prüft nun regelmäßig, ob Daten zum Lesen bereitstehen (also Daten empfangen wurden). Ist dies der Fall, so wird die X_Read()-Funktion des zugehörigen Moduls für die hinterlegte Definition aufgerufen. Hier können die Daten durch den Aufruf von DevIo_SimpleRead() nun eingelesen und verarbeitet werden. Das Senden von Daten ist durch den Aufruf von DevIo_SimpleWrite() sehr einfach möglich.

Sollte die Verbindung zusammenbrechen (USB-Gerät abgezogen, Gerät per Netzwerk nicht mehr erreichbar, etc.), so erkennt dies fhem.pl und führt die X_Ready()-Funktion des zugehörigen Moduls aus um zu prüfen, ob die Verbindung wieder aufgebaut werden kann. Hier wird nun erneut DevIo_OpenDev() ausgeführt um die Verbindung wieder herzustellen.

Sobald die Verbindung nicht mehr benötigt wird, oder FHEM bspw. beendet wird, kann die Verbindung via DevIo_Close() sauber geschlossen werden.

Unterstützte Verbindungsarten

Die folgenden Verbindungsarten können via DevIo realisiert werden.

Verbindungsart Beispielangabe in
$hash->{DeviceName}
Beschreibung
Serielle Schnittstelle
  • /dev/ttyUSB0
  • /dev/ttyUSB0@9600
  • /dev/ttyUSB0@9600,7,E,2
  • /dev/ttyUSB0@directio
  • COM1@9600

Durch Angabe eines Geräts in Form eines Gerätepfad (UNIX-basierte Betriebssysteme) oder der Schnittstellenbezeichnung aus Windows kann eine serielle Verbindung geöffnet werden. Der Gerätename kann zusätzliche Angaben zu Baudrate, Datenbits, Parität und Stoppbits enthalten um die Verbindung entsprechend zu konfiguieren. Diese Angaben sind durch ein "@" getrennt an die Gerätebezeichnung angehangen:

Schematische Syntax: <Gerät>@<Baudrate>,<Datenbits>,<Parität>,<Stopbits>

  • <Baudrate> - Eine gültige Taktfrequenz (Symbole pro Sekunde) mit der die Schnittstelle geöffnet werden soll (Beispiel: 9600, 14400, 115200, ...)
  • <Datenbits> - Die Anzahl an Datenbits (7 oder 8 Datenbits). Standardwert sofern nicht angegeben sind 8 Datenbits.
  • <Parität> - Die zu verwendende Parität, sofern benötigt. Dabei bedeutet der Wert N keine Parität, O bedeutet ungleiche Parität (odd) und E bedeutet gleiche Parität (even) Standardwert sofern nicht angegeben ist N (keine Parität).
  • <Stopbits> - Die Anzahl an zu verwendenden Stopbits (0, 1 oder 2 Stopbits). Standardwert sofern nicht angegeben sind 0 Stopbits.

Wenn man unter Unix-basierten Betriebssystemen die Schnittstelle nicht explizit konfiguriert öffnen möchte, sondern das Gerät direkt öffnen möchte (und damit die OS-Einstellungen verwendet), kann man durch Angabe von @directio die Konfiguration der Schnittstelle umgehen und das Gerät direkt öffnen:

Bsp: /dev/ttyUSB0@directio

Unter Windows verwendet man als Gerätename die entsprechende Schnittstellenbezeichung wie bspw. COM1, COM2, usw.

TCP/IP-Verbindung
  • 192.168.1.2:1012
  • raspberry:5000

Durch Angabe eines Hostnamen oder IP-Adresse und einem Port, kann eine TCP-Verbindung aufgebaut werden. Dazu muss Hostname/IP-Adresse und Port in folgendem Schema angegeben werden:

Schematische Syntax: <Hostname/IP-Adresse>:<Port>

  • <Hostname/IP-Adresse> - Der Hostname oder die IP-Adresse des zu verbindenden Gerätes/Server.
  • <Port> - Der Zielport zu dem sich verbunden werden soll (0-65535).

Die Verbindung kann optional verschlüsselt via SSL/TLS aufgebaut werden. Dazu muss das Internal $hash->{SSL} auf 1 gesetzt werden.

UNIX-Socket
  • UNIX:SEQPACKET:/var/tmp/me_avm_home_external.ctl
  • UNIX:STREAM:/var/socket/con

TODO

FHEM IO-Modul
  • FHEM:DEVIO:Firmata_SerielleSchnittstelle@9600

TODO: Beschreibung nach Thema

Wichtige Internals zur Konfiguration

Da DevIo ausschließlich definitionsbezogen arbeitet, erfolgt eine Konfiguration von DevIo über Internals, die im übergebenen $hash gesetzt werden müssen (oder können). Hiermit lässt sich das Verhalten von DevIo entsprechend beeinflussen.

Hier eine Auflistung von allen Internals, die DevIo beeinflussen:

Internal Beschreibung
$hash->{DeviceName}

mandatory

Die Gegenstelle zu der eine Verbindung aufgebaut werden soll. Die möglichen Werte und deren Syntax ist im Kapitel Unterstützte Verbindungsarten genauer beschrieben.
$hash->{nextOpenDelay}

optional

Die Zeit in Sekunden, welche im Falle eines Verbindungsabbruchs gewartet werden soll, bevor ein erneuter Verbindungsversuch stattfindet.

Standardwert: 60 Sekunden

$hash->{TIMEOUT}

optional

Die maximale Zeit in Sekunden für den Aufbau einer TCP/IP-Verbindung. Sollte diese Zeit überschritten werden, bricht der Verbindungsaufbau mit einer Fehlermeldung ab.

WICHTIG: Sollte beim Aufruf von DevIo_OpenDev() keine Callback-Funktion parametrisiert sein und die Gegenstelle antwortet beim Verbindungsaufbau nicht, so wird FHEM für die Dauer von $hash->{TIMEOUT} blockiert.

Standardwert: 3 Sekunden

$hash->{SSL}

optional

Flag (0 oder 1), ob eine TCP/IP-Verbindung verschlüsselt (via SSL/TLS) aufgebaut werden soll. Wenn dieses Flag auf 1 gesetzt ist, wird nach erfolgtem Verbindungsaufbau eine SSL-Session initiiert.

Standardwert: 0 (keine Verschlüsselung)

$hash->{devioLoglevel}

optional

Das Loglevel in dem disconnected/reappeared Meldungen geloggt werden sollen. Standardmäßig werden solche Verbindungsabbrüche (disconnected/reappeared) im Loglevel 1 geloggt. Die erfolgreiche Erstverbindung wird standardmäßig im Loglevel 3 geloggt. Durch das Setzen von $hash->{devioLoglevel} werden diese Meldungen allesamt in dem gesetzten Loglevel ausgegeben. Details dazu siehe Thema.

Standardwert: [leer]

Die Funktionen

DevIo_OpenDev

$error = DevIo_OpenDev($hash, $reopen, $initfn);
$error = DevIo_OpenDev($hash, $reopen, $initfn, $callback);

Die Funktion DevIo_OpenDev() öffnet eine Verbindung zu dem Endpunkt der in $hash->{DeviceName} hinterlegt ist. Sobald die Verbindung erfolgreich hergestellt wurde, wird die Funktion $initfn ausgeführt, sofern gesetzt, um die Verbindung zu initialisieren. Sofern eine TCP/IP-Verbindung hergestellt wird, kann eine optionale Callback-Funktion $callback übergeben werden um den Verbindungsaufbau non-blocking durchzuführen.

Der Rückgabewert enthält im Fehlerfall eine entsprechende Fehlermeldung. Im Erfolgsfall wird undef zurückgegeben. Sofern eine TCP/IP-Verbindung hergestellt wird und eine Callback-Funktion $callback übergeben wurde, wird immer undef zurückgegeben, da ein evtl. Fehler an diese Callback-Funktion nach dem erfolgten Verbindungsversuch mitgeteilt wird.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, für die eine Verbindung geöffnet werden soll
$reopen

mandatory
can be undef

Flag (0 oder 1), ob es sich um einen erneuten Verbindungsversuch handelt (im Rahmen der X_Ready()-Funktion). Sollte es der erste Verbindungsversuch sein, so muss dieser Parameter den Wert 0 besitzen.
$initfn

mandatory
can be undef

Der Name (als Zeichenkette) oder die Referenz auf eine Modulfunktion, welche optional nach dem erfolgreichen Aufbau/Wiederaufbau der Verbindung ausgeführt werden soll. Im Rahmen dieser Funktion kann weiterführende Kommunikation über die aufgebaute Verbindung erfolgen um zum Beispiel eine Loginsequenz oder eine Konfiguration der Gegenseite vorzunehmen, bevor die Verbindung allgemein benutzt werden kann.

Die Funktion welche in $initfn angegeben wurde, wird mit folgenden Parametern aufgerufen:

$ret = MYMODULE_InitFn($hash)

Wenn der Rückgabewert $ret einen Inhalt zurückliefert, wird die Initialisierung als fehlgeschlagen bewertet und die Verbindung wieder geschlossen um einen neuen Verbindungsversuch zu einem späteren Zeitpunkt zu versuchen. Der genaue Inhalt von $ret ist dabei unerheblich, da er nicht weiterverwendet wird. Die Rückgabewerte 0 oder undef signalisieren dabei eine erfolgreiche Initialisierung.

Beispiel:

  • "MYMODULE_InitFn"
  • \&MYMODULE_InitFn
$callback

optional

Der Name (als Zeichenkette) oder die Referenz auf eine Modulfunktion, welche aufgerufen werden soll um evtl. Fehlermeldungen beim Verbindungsaufbau einer TCP/IP-Verbindung an das Modul zurückzuliefern. Wenn eine Callback-Funktion gesetzt ist, erfolgt der Verbindungsaufbau non-blocking. Andernfalls wartet DevIo_OpenDev() bis die Verbindung steht bzw. ein Fehler auftritt (z.B. Timeout).

Die Funktion welche in $callback angegeben wurde, wird mit folgenden Parametern aufgerufen:

MYMODULE_ConnectCallbackFn($hash, $error)

Das Argument $error enthält dabei eine Fehlermeldung als Zeichenkette welche die aufgetretene Fehlermeldung enthält. Der Rückgabewert der Callback-Funktion wird nicht ausgewertet und ist daher irrelevant.

Beispiel:

  • "MYMODULE_ConnectCallbackFn"
  • \&MYMODULE_ConnectCallbackFn

Rückgabewert:

Rückgabe Bedeutung
$error Eine Fehlermeldung als Zeichenkette, sollte der Verbindungsaufbau fehlschlagen. Im Erfolgsfall wird undef zurückgegeben.

Wenn es sich um eine TCP/IP-Verbindung handelt und eine Callback-Funktion als Parameter $callback angegeben wurde, wird immer undef zurückgegeben, andernfalls erfolgt der Verbindungsaufbau blocking und eine evtl. Fehlermeldung wird als Rückgabewert zurückgegeben. Im Erfolgsfall wird undef zurückgegeben.

DevIo_IsOpen

$status = DevIo_IsOpen($hash);

Die Funktion DevIo_IsOpen() prüft, ob eine Verbindung für $hash geöffnet ist. Falls ja, wird das zugehörige IO-Objekt zurückgegeben, andernfalls undef.

Diese Funktion kann dabei direkt in typischen if-Konstrukten verwendet werden um zu prüfen, ob eine Verbindung für die jeweilige Definition geöffnet oder geschlossen ist.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, deren Verbindung geprüft werden soll.

Rückgabewerte:

Rückgabewert Bedeutung
$status Der Status der Verbindung. Wenn eine Verbindung besteht, wird das zugehörige IO-Objekt zurückgegeben. Falls keine Verbindung besteht, wird undef zurückgegeben.

DevIo_SimpleRead

$buf = DevIo_SimpleRead($hash);

Die Funktion DevIo_SimpleRead() liest anstehende Daten für die Verbindung von $hash ein und gibt diese zurück.

Sollte beim Versuch Daten zu lesen eine geschlossene Verbindung erkannt werden, so wird undef zurückgegeben und die Verbindung geschlossen. Es erfolgt zu einem späteren Zeitpunkt (siehe Internal $hash->{nextOpenDelay} aus Kapitel Wichtige Internals zur Konfiguration) ein neuer Verbindungsversuch.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, für deren Verbindung aktuell anstehende Daten gelesen werden sollen.

Rückgabewert:

Rückgabe Bedeutung
$buf Die zu lesenden Daten als Zeichenkette. Im Falle eines Verbindungsabruchs wird undef zurückgegeben.

DevIo_SimpleReadWithTimeout

Emblem-question-yellow.svgACHTUNG: Bei der Benutzung von DevIo_SimpleReadWithTimeout() wird FHEM für die Dauer von bis zu $timeout Sekunden blockiert, sollten keine Daten bis dahin zum Lesen bereitstehen.
$buf = DevIo_SimpleReadWithTimeout($hash, $timeout);

Die Funktion DevIo_SimpleReadWithTimeout() wartet maximal $timeout Sekunden bis die Verbindung von $hash Daten zum einlesen bereitstellt und gibt diese zurück. Sollte nach dem Warten von $timeout noch immer keine Daten zum Lesen bereitstehen, so wird ein Leerstring zurückgegeben.

Sollte beim Versuch Daten zu lesen eine geschlossene Verbindung erkannt werden, so wird undef zurückgegeben und die Verbindung geschlossen. Es erfolgt zu einem späteren Zeitpunkt (siehe Internal $hash->{nextOpenDelay} aus Kapitel Wichtige Internals zur Konfiguration) ein neuer Verbindungsversuch.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, für deren Verbindung aktuell anstehende Daten gelesen werden sollen.
$timeout

mandatory

Die maximale Wartezeit in Sekunden.

Rückgabewert:

Rückgabe Bedeutung
$buf Die zu lesenden Daten als Zeichenkette. Im Falle eines Verbindungsabruchs wird undef zurückgegeben.

DevIo_TimeoutRead

Emblem-question-yellow.svgACHTUNG: Bei der Benutzung von DevIo_TimeoutRead() wird FHEM für die Dauer von $timeout Sekunden blockiert.
$buf = DevIo_TimeoutRead($hash, $timeout);

Die Funktion DevIo_SimpleReadWithTimeout() wartet $timeout Sekunden und liest sämtliche Daten für die Verbindung von $hash ein, die in dieser Zeit eintreffen. Sollten keinerlei Daten während der Wartezeit eintreffen, so wird ein Leerstring zurückgegeben.

Sollte beim Versuch Daten zu lesen eine geschlossene Verbindung erkannt werden, so wird undef zurückgegeben und die Verbindung geschlossen. Es erfolgt zu einem späteren Zeitpunkt (siehe Internal $hash->{nextOpenDelay} aus Kapitel Wichtige Internals zur Konfiguration) ein neuer Verbindungsversuch.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, für deren Verbindung Daten eingelesen werden sollen.
$timeout

mandatory

Die Wartezeit in Sekunden.

Rückgabewert:

Rückgabe Bedeutung
$buf Die eingelesenen Daten als Zeichenkette. Im Falle eines Verbindungsabruchs wird undef zurückgegeben.

DevIo_SimpleWrite

DevIo_SimpleWrite($hash, $msg, $type);
DevIo_SimpleWrite($hash, $msg, $type, $addnl);

Die Funktion DevIo_SimpleWrite() sendet den Inhalt von $msg über die Verbindung von $hash. Mit den beiden Argumenten $type und $addnl kann die Formatierung von $msg beeinflusst werden bevor die Daten tatsächlich gesendet werden.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, über deren Verbindung die Daten gesendet werden sollen.
$msg

mandatory

Die zu schreibenden Daten als Zeichenkette. Abhängig von $type kann $msg Byte-Characters, HEX-Darstellungen oder normale ASCII-Zeichen enthalten.
$type

mandatory

Die Art des Inhalts von $msg. Abhängig von dem Inhalt von $type wird $msg entsprechend geändert oder nicht. Desweiteren werden die Daten für Logausgaben evtl. leserlich gemacht.

Folgende Werte sind möglich:

  • 0 - $msg enthält Daten in Byteform. Der Inhalt von $msg wird 1:1 gesendet. Zur besseren Lesbarkeit werden die Daten bei Logausgaben in HEX-Darstellung umgewandelt.
  • 1 - $msg enthält Binärdaten in HEX-Darstellung (0-9/A-F). Der Inhalt von $msg wird vorher in Byteform umgewandelt und anschließend gesendet. In Logausgaben wird die HEX-Darstellung wie übergeben verwendet.
  • 2 - $msg enthält normale ASCII-Textzeichen. Der Inhalt von $msg wird 1:1 gesendet. In Logausgaben wird $msg wie übergeben ausgegeben.
$addnl

optional

Ein Flag (0/1) welches, sofern aktiviert, einen Zeilenumbruch an $msg anfügt, bevor es gesendet wird.

Standardwert: 0

DevIo_Expect

TBD

DevIo_CloseDev

DevIo_CloseDev($hash);
DevIo_CloseDev($hash, $isFork);

Die Funktion DevIo_CloseDev() schließt eine evtl. geöffnete Verbindung für die Defintion $hash.

Optional kann man mit dem Flag $isFork angeben, dass man sich aktuell in einem Fork vom Hauptprozess befindet. Dadurch wird beim Schließen von seriellen Verbindungen die Kommunikationsparameter nicht zurückgesetzt. Dies verhindert einen Ausfall der nachwievor bestehenden Verbindung im Hauptprozess.

Parameter:

Parameter Bedeutung
$hash

mandatory

Die Hash-Referenz der Definition, deren Verbindung geschlossen werden soll.
$isFork

optional

Ein Flag (0 oder 1), welches angibt, dass DevIo_CloseDev() innerhalb eines geforkten Kindprozess ausgeführt wird. Dadurch werden serielle Verbindung so geschlossen, dass dabei die Kommunikationsparameter (Baudrate, Datenbits, Parität, etc.) nicht zurückgesetzt werden.

Standardwert: 0 (Verbindung wird im Hauptprozess geschlossen)

Beispiel

TBD

Referenzen

  1. Development Module Introduction - Wichtige globale Variablen aus fhem.pl