99 myUtils anlegen

Aus FHEMWiki
Version vom 3. Oktober 2018, 18:28 Uhr von Trelle (Diskussion | Beiträge) (Typenangaben durch Veralgemeinerung erweitert)

Mit wachsender Anzahl von eigenen Helfer-Programmen wird die Speicherung von Perl-Code in Eventhandlern, Timehandlern oder anderen Geräten in denen Perl-Ausdrücke angegeben werden können, unübersichtlich. Es besteht die Möglichkeit, eine eigene Programmdatei zu erzeugen, in der mehrere kleine Programme gesammelt und dann aus entsprechenden Geräten aufgerufen werden.

Eine neue Programmdatei erzeugen

FHEM enthält seit Updatestand 01/2015 eine Vorlage 'myUtilsTemplate.pm', die zur Erzeugung der Programmdatei genutzt werden sollte. Vorgehensweise:

  • FHEM-Menüpunkt Edit files anklicken
  • Weblink 'myUtilsTemplate.pm' anklicken
  • Im Textfeld hinter 'Save as' den Dateinamen '99_myUtils.pm' für die Programmdatei eintragen
Hinweis: Wenn ein anderer Dateiname angegeben wird, muss der Name Initialize-Routine entsprechend angepasst werden (siehe nachfolgende Erläuterung zur Grundstruktur unter Nr. 3)
  • Save as anklicken

Nun ist die eigene Programmdatei '99_myUtils.pm' mit der notwendigen Grundstruktur unter dem Menüpunkt 'Edit files' zur Bearbeitung mit dem Integrierter Editor zu finden. Für eine einfache und fehlerminimierende Bearbeitung sollten die Syntaxhervorhebungs-, Befehlsauswahl- und Befehlsvervollständigungsfunktionen im Integrierten Editor eingeschaltet sein.

Für Experten ist auch die Nutzung eines Externen Editors zur Bearbeitung möglich, aber nicht empfohlen.

Eine ‚leere‘ Programmdatei muss grundsätzlich folgenden Grundstruktur besitzen:

 package main;
 use strict;
 use warnings;
 use POSIX;
 sub
 myUtils_Initialize($$)
 {
   my ($hash) = @_;
 }
 1;

Folgende Dinge sind für die Programmdatei besonders zu beachten:

  1. Der Dateiname muss mit 99_ beginnen. FHEM lädt beim Start alle Programmdateien mit dem prefix 99_. Andere Programmdateien werden erst dann geladen, wenn sie durch eine define-Anweisung in der Konfiguration angefordert werden. So wird z.B. 10_FS20.pm erst geladen, wenn beim Einlesen der Konfiguration das erste define für ein FS20-device abgearbeitet wird. Da Ihre eigene Programmsammlung wahrscheinlich kein neues Gerät mit einem zugehörigen define-Befehl implementiert, würde sie also nie geladen, wenn ihr Name nicht mit 99_ beginnt.
  2. Damit die neue Datei bei 'Edit files' angezeigt wird, muss sie mit Utils.pm enden. Also zum Beispiel 99_meineUtils.pm
  3. Der Name der Programmdatei muss mit dem Namen der Initialize-Routine übereinstimmen. Wenn Sie Ihr Programm also 99_Werkzeugkasten.pm nennen, muss die im code dargestellte initialize-Routine sub Werkzeugkasten_Initialize heißen.
  4. Die Zeile 1; muss immer die letzte Programmzeile sein. Wenn Sie also eigene Routinen in Ihre Programmsammlung einfügen, tragen Sie diese zwischen dem Ende der Initialize-Routine und der abschließenden Zeile 1; ein.

Eigene Routinen einfügen

Als Beispiel dient das Umsetzen von FS20 toggle-Events aus dem Artikel "FS20 Toggle Events auf On/Off umsetzen". Das gesamte Programm sieht dann folgendermaßen aus:

package main;
use strict;
use warnings;
use POSIX;
sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}
##########################################################
# Untoggle
# toggle-Vorgänge in den Status on/off umsetzen
sub Untoggle($) {
  my ($obj) = @_;

  if( Value($obj) eq "toggle" ){
    if( OldValue($obj) eq "off" ) {
      fhem( "setstate $obj on" );
    }
    else {
      fhem( "setstate $obj off" );
    }
  }
  else {
    fhem( "setstate $obj ".Value($obj) );
  } 
}
1;

Der Aufruf erfolgt dann z.B. so:

#fhem.cfg
define lampe_untoggle notify lampe {Untoggle(„$NAME“)}

Der Aufruf aus einem notify (oder at) erfolgt als Perl-code, muss also in geschweiften Klammern stehen. Der Aufruf erfolgt durch Angabe des Namens der Routine (Untoggle) unter Angabe der zu übergebenden Parameter (hier "$NAME"). Im Programm wurde die Routine Untoggle mit einem Parameter definiert ( Untoggle($) , die Anzahl der $-Zeichen bestimmt die Anzahl der zu übergebenden Parameter). Der Wert des übergebenen Parameters wird in der ersten Programmzeile in die Variable $obj übernommen (my ($obj) = @_; ). Der Aufruf erfolgt mit Untoggle(„$NAME“) . Der Platzhalter $NAME in fhem steht für den Namen des Geräts. Im o.g. Beispiel erfolgt der Aufruf also eigentlich mit Untoggle(„lampe“). Natürlich können beim Aufruf auch feste Werte ( „lampe1“ ) oder Variablen ( $hour ) übergeben werden.

Routinen mit mehreren Parametern

In der Definition der Routine geben Sie außerdem an, wieviele Parameter übergeben werden sollen, für 2 Parameter z.B. so:

define test at *09:00 { wakeup($we, Schlafzimmerlampe) }

Die Deklaration der Routine in Ihrer Programmdatei muss dann so beginnen:

#Nur am Wochenende eingeschaltet
sub wakeup($$) {
  my ($wochenende, $device) = @_;
  if ($wochenende) {
    fhem( "set $device on" );
  }
  else {
    fhem( "set $device off" );
  }
}

Durch die Anzahl der $-Zeichen in der Routinen-Deklaration wird also die Anzahl der Parameter festgelegt. In der ersten Programmzeile Ihrer Routine übernehmen Sie dann die übergebenen Parameterwerte in lokale Variablen. Wie beim Routinen-Aufruf muss auch hierbei die Anzahl der Parameter mit der Routinen-Deklaration (also Anzahl der $-Zeichen) übereinstimmen.

Routinen ohne Parameter

Auch Routinen ohne Parameter sind natürlich möglich. Definition und Aufruf sehen dann folgendermassen aus:

sub parameterlos() {
  ...
}
{ parameterlos() }

Eigene Programmdatei laden

Die Programmdatei wird beim FHEM-Start immer automatisch geladen.

Bei Änderungen an der Programmdatei bei laufendem FHEM ist bezüglich Neuladen ohne FHEM-Neustart zwischen den verschiedenen Bearbeitungsvarianten der Progammdatei zu unterscheiden.

Bei der Bearbeitung über den Integrierten Editor wird die Programmdatei beim Abspeichern automatisch mit den Änderungen neu geladen.

Bei der nicht empfohlenen Bearbeitung der Programmdatei mit einem externen Editor muss FHEM manuell angewiesen werden, die Programmdatei mit den Änderungen zu laden. Also bearbeiten Sie Ihr Programm, speichern die Programmdatei, und weisen FHEM dann explizit an, die Programmdatei erneut zu laden. Der Befehl dazu, der in das Befehls-Eingabefeld eingegeben wird, lautet: reload 99_myUtils.pm

Treten beim Laden (Syntax)fehler auf, werden diese am Bildschirm wie auch im Log angezeigt. Da der Ladevorgang fehlgeschlagen ist, stehen Ihre eigenen Routinen nun nicht zur Verfügung (bzw. in der zuletzt erfolgreich geladenen Version).

Eigene Programmdatei dokumentieren

In der lokalen Commandref kann man die eigenen Routinen auch dokumentieren. Dazu muss am Ende der 99_myUtils folgender Codeblock eingefügt werden

=pod
=begin html

<a name="myUtils"></a>
<h3>myUtils</h3>
<ul>
  <b>Name</b>
  <br>
  Text<br>
  Examples:
  <ul>
   <code>Example Code </code><br>
  </ul>
</ul>

=end html
=begin html_DE

<a name="myUtils"></a>
<h3>myUtils</h3>

=end html_DE
=cut

Der a Tag stellt einen Verweis dar, der h3 Tag kennzeichnet die Überschrift. Beide Tags müssen sein, ansonsten kann FHEM die Doku nicht in die commandref einbinden. Der Abschnitt für die deutsche Doku kann komplett fehlen. Die Beschreibungen der einzelnen Routinen werden mit ul Tags geklammert und eventuell mit ul Tags weiter untergliedert. Dabei entsteht ein eingerückter Text. Beispiele können mit dem code Tag formatiert werden.

Mit diesem Befehl kann die Erzeugung des Commandrefeintrages initiiert und getestet werden:

{system("/usr/bin/perl ./contrib/commandref_join.pl")}

Links