DevelopmentIntroduction: Unterschied zwischen den Versionen
Yfhem (Diskussion | Beiträge) K (→Application Lifecycle: Improved list.) |
Krikan (Diskussion | Beiträge) K (Kategorie:Development (Archive) zugeordnet) |
||
(2 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt) | |||
Zeile 26: | Zeile 26: | ||
## For FHZ devices, the FHZ_CheckCRC method is used to validate the received data | ## For FHZ devices, the FHZ_CheckCRC method is used to validate the received data | ||
## Call the Dispatch method in FHEM.pl to pass the message onto the correct device and corresponding module (Parse function) | ## Call the Dispatch method in FHEM.pl to pass the message onto the correct device and corresponding module (Parse function) | ||
$server->fileno() is used to check for and accept new connections to the server | |||
For each connected client: | |||
# Read data from the client using sysread | # Read data from the client using sysread | ||
# Pass the received input into the AnalyzeInput method to execute the command | # Pass the received input into the AnalyzeInput method to execute the command | ||
== Configuration and State Files == | == Configuration and State Files == | ||
Note that these are just lists of commands to execute in a text file! So anything in these files will be interpreted by FHEM in the exact same way if a user keys the commands manually into a client application, eg a telnet connection. | Note that these are just lists of commands to execute in a text file! So anything in these files will be interpreted by FHEM in the exact same way if a user keys the commands manually into a client application, eg a telnet connection. | ||
Zeile 62: | Zeile 62: | ||
Die Funktion '''readingsEndUpdate'''aktualisiert $hash->{STATE} grundsätzlich immer bei jedem Aufruf nach folgendem Algorithmus: | Die Funktion '''readingsEndUpdate''' aktualisiert $hash->{STATE} grundsätzlich immer bei jedem Aufruf nach folgendem Algorithmus: | ||
Falls $sr= $attr{$name}{stateReading} gesetzt ist: | Falls $sr= $attr{$name}{stateReading} gesetzt ist: | ||
Zeile 80: | Zeile 80: | ||
Aus '''DoTrigger'''werden | Aus '''DoTrigger''' werden | ||
<nowiki>$defs{$dev}{STATE} = ReplaceEventMap($dev, $defs{$dev}{STATE}, 1);</nowiki> | <nowiki>$defs{$dev}{STATE} = ReplaceEventMap($dev, $defs{$dev}{STATE}, 1);</nowiki> | ||
Zeile 89: | Zeile 89: | ||
$r->{state}{VAL} = $defs{$dev}{STATE} if($r && $r->{state});</nowiki> | $r->{state}{VAL} = $defs{$dev}{STATE} if($r && $r->{state});</nowiki> | ||
entfernt. | entfernt. | ||
== Global Attributes == | == Global Attributes == | ||
Zeile 101: | Zeile 97: | ||
global userattr hinzufuegen. | global userattr hinzufuegen. | ||
[[Kategorie:Development]] | [[Kategorie:Development (Archive)]] |
Aktuelle Version vom 19. Oktober 2016, 13:14 Uhr
Developer's Introduction to FHEM
Introduction
This page is intended to give an introduction to the FHEM application from a developer's perspective. If you're interested in extending, modifying or reusing the FHEM code, then hopefully you will find this a useful document. Note that this document is a work in progress! I myself at the time of writing this have only a few hours of experience under my belt, but I'm documenting things I learn as I learn them.
Application Lifecycle
When you first launch the FHEM server, the following activities take place:
- Application variables are initialised
- The valid application commands are loaded into a structure (%cmds) with the corresponding function name to call
- Do the job, either act as client or server. One of the following applies:
- If the application has been called as a FHEM client (eg perl fhem.pl 127.0.0.1:7072 commandToExecute)
- Connect to the FHEM server
- Execute the command
- Exit the program
- Otherwise (the application has been started as a server)
- Execute each of the commands listed in the configuration file to initialise the server (see the CommandInclude and then the AnalyzeCommandChain methods)
- Execute each of the commands in the state file if configured to restore the devices to the last state recorded when the server last ran
- Start the main application loop
- If the application has been called as a FHEM client (eg perl fhem.pl 127.0.0.1:7072 commandToExecute)
Main Application Loop
The following code is repeated until the application ends:
- For each input device (eg FHZ1000 / FHZ1300 / CUL):
- Use that device module's Ready and Read functions to read data from the device
- For CUL devices, the data is read and parsed at this point
- For FHZ devices, the FHZ_CheckCRC method is used to validate the received data
- Call the Dispatch method in FHEM.pl to pass the message onto the correct device and corresponding module (Parse function)
$server->fileno() is used to check for and accept new connections to the server For each connected client:
- Read data from the client using sysread
- Pass the received input into the AnalyzeInput method to execute the command
Configuration and State Files
Note that these are just lists of commands to execute in a text file! So anything in these files will be interpreted by FHEM in the exact same way if a user keys the commands manually into a client application, eg a telnet connection.
Readings
The following mechanism is recommended for updating readings. It saves lines of codes and automatically makes your module honor the event-on-update-reading and event-on-change-reading attributes.
Before you start updating readings, write (in case $hash = $defs{<device>})
readingsBeginUpdate($hash);
For every reading you update, write
readingsBulkUpdate($hash,$reading,$value);
Terminate with
readingsEndUpdate($hash, $dotrigger);
The $dotrigger parameter should be 0 for updates initiated by fhem message dispatcher as the dispatcher already calls DoTrigger on its behalf. $dotrigger should be 1 for updates initiated by internal timers, e.g. for polling devices.
As a shorthand notation for updating just one reading write
readingsSingleUpdate($hash,$reading,$value,$dotrigger);
which is the same as
readingsBeginUpdate($hash); readingsBulkUpdate($hash,$reading,$value); readingsEndUpdate($hash, $dotrigger);
STATE
Vorschlag zur Umsetzung, diskutiert hier.
In den DevelopmentGuidelines, Kapselung, Standardisierung der Vorgehensweise.
Die Funktion readingsEndUpdate aktualisiert $hash->{STATE} grundsätzlich immer bei jedem Aufruf nach folgendem Algorithmus:
Falls $sr= $attr{$name}{stateReading} gesetzt ist:
Fall 1: wenn $sr =~ "^{.*}$" dann eval "\$hash->{STATE} = $sr"; Fall 2: sonst $hash->{STATE}= $hash->{READINGS}{$sr}{VAL}
sonst
Falls es $hash->{READINGS}{state} gibt, $hash->{STATE}= $hash->{READINGS}{state}{VAL}
sonst
Tue nichts (das Modul hat sich gekuemmert).
Ausserdem wird
ReplaceEventMap()
losgelassen, um die EventMaps des Anwenders auch im STATE zur Anwendung zu bringen.
Aus DoTrigger werden
$defs{$dev}{STATE} = ReplaceEventMap($dev, $defs{$dev}{STATE}, 1);
und
# STATE && {READINGS}{state} should be the same my $r = $defs{$dev}{READINGS}; $r->{state}{VAL} = $defs{$dev}{STATE} if($r && $r->{state});
entfernt.
Global Attributes
In fhem.pl existiert ein
my $AttrList = "room comment alias ...";
Weiterhin kann jedes Modul im Initialize mit addToAttrList eigene Attribute zu global userattr hinzufuegen.