A physical ECMD device can host any number of logical ECMD devices. Logical devices are defined as ECMDDevices in fhem. ADC 0 to 3 and I/O port 0 to 3 of the above mentioned board are examples of such logical devices. ADC 0 to 3 all belong to the same device class ADC (analog/digital converter). I/O port 0 to 3 belong to the device class I/O port. By means of extension boards you can make your physical device drive as many logical devices as you can imagine, e.g. IR receivers, LC displays, RF receivers/transmitters, 1-wire devices, etc.
Defining one fhem module for any device class would create an unmanageable
number of modules. Thus, an abstraction layer is used. You create a device class
on the fly and assign it to a logical ECMD device. The
class definition
names the parameters of the logical device, e.g. a placeholder for the number
of the ADC or port, as well as the get and set capabilities. Worked examples
are to be found in the documentation of the ECMDDevice device.
Note: this module requires the Device::SerialPort or Win32::SerialPort module
if the module is connected via serial Port or USB.
Character coding
ECMD is suited to process any character including non-printable and control characters.
User input for raw data, e.g. for setting attributes, and the display of raw data, e.g. in the log,
is perl-encoded according to the following table (ooo stands for a three-digit octal number):
character | octal | code |
---|---|---|
Bell | 007 | \a |
Backspace | 008 | \008 |
Escape | 033 | \e |
Formfeed | 014 | \f |
Newline | 012 | \n |
Return | 015 | \r |
Tab | 011 | \t |
backslash | 134 | \134 or \\ |
any | ooo | \ooo |
define <name> ECMD telnet <IPAddress:Port>
define <name> ECMD serial <SerialDevice>[<@BaudRate>]
telnet
or
serial
are fixed.define AVRNETIO ECMD telnet 192.168.0.91:2701
define AVRNETIO ECMD serial /dev/ttyS0
define AVRNETIO ECMD serial /dev/ttyUSB0@38400
set <name> classdef <classname> <filename>
<classname>
for logical devices.
The class definition is in the file <filename>
. You must
create the device class before you create a logical device that adheres to
that definition.
set AVRNETIO classdef /etc/fhem/ADC.classdef
set <name> reopen
get <name> raw <command>
<command>
to the physical ECMD device
<name>
and reads the response. In the likely case that
the command needs to be terminated by a newline character, you have to
resort to a <perl special>.
get AVRNETIO raw { "ip\n" }
attr myECMD classdefs ADC=/etc/fhem/ADC.classdef:GPIO=/etc/fhem/AllInOne.classdef
attr myECMD split \n
splits foo 12\nbar off\n
into
foo 12\n
and bar off\n
.reading ... match ...
in the class definition) or the time in seconds given with the partial attribute has expired. (b) If a spontaneous transmission does not match the regular expression for any reading, the transmission is recorded and prepended to the next transmission. If the line is quiet for longer than the time in seconds given with the partial attribute, the recorded transmission is discarded. Use regular expressions that produce exact matches of the complete response (after combining partials and splitting).
Set the partial
attribute in combination with reading ... match ...
in the class definition, if you receive datagrams with responses which are broken into several transmissions, like resp
followed by onse\r\n
.
Set the split
attribute if you
receive several responses in one transmission, like reply1\r\nreply2\r\n
.
When to use the requestSeparator and responseSeparator attributes?
Set the requestSeparator
attribute, if you want to send several requests in one command, with one transmission per request. The strings sent to the device for set
and get
commands
as defined in the class definition are broken down into several request/response
interactions with the physical device. The request separator is not sent to the physical device.
Set the responseSeparator
attribute to separate the responses received for a command
broken down into several requests by means of a request separator. This is useful for easier postprocessing.
Example: you want to send the requests request1
and request2
in one command. The
physical device would respond with response1
and response2
respectively for each
of the requests. You set the request separator to \000 and the response separator to \001 and you define
the command as request1\000request2\000
. The command is broken down into request1
and request2
. request1
is sent to the physical device and response1
is received, followed by sending request2
and receiving response2
. The final
result is response1\001response2\001
.
You can think of this feature as of a macro. Splitting and partial matching is still done per single request/response within the macro.
Datagram monitoring and matching
Data to and from the physical device is processed as is. In particular, if you need to send a line feed you have to explicitely send a \n control character. On the other hand, control characters like line feeds are not stripped from the data received. This needs to be considered when defining a class definition.
For debugging purposes, especially when designing a class definition, it is advisable to turn traffic logging on. Use attr myECMD logTraffic 3
to log all data to and from the physical device at level 3.
Datagrams and attribute values are logged with non-printable and control characters encoded as here followed by the octal representation in parantheses.
Example: #!foo\r\n (\043\041\146\157\157\015\012)
.
Data received from the physical device is processed as it comes in chunks. If for some reason a datagram from the device is split in transit, pattern matching and processing will most likely fail. You can use the partial
attribute to make FHEM collect and recombine the chunks.
Connection error handling
This modules handles unexpected disconnects of devices as follows (on Windows only for TCP connections):
Disconnects are detected if and only if data from the device in reply to data sent to the device cannot be received with at most two attempts. FHEM waits at most 3 seconds (or the time specified in the timeout
attribute, see Attributes). After the first failed attempt, the connection to the device is closed and reopened again. The state of the device
is failed
. Then the data is sent again to the device. If still no reply is received, the state of the device is disconnected
, otherwise opened
. You will have to fix the problem and then use set myECMD reopen
to reconnect to the device.
Please design your class definitions in such a way that the double sending of data does not bite you in any case.
Class definition
The class definition for a logical ECMD device class is contained in a text file.
The text file is made up of single lines. Empty lines and text beginning with #
(hash) are ignored. Therefore make sure not to use hashes in commands.
The following commands are recognized in the device class definition:
params <parameter1> [<parameter2> [<parameter3> ... ]]
state <reading>
set <commandname> cmd { <perl special> }
get <commandname> cmd { <perl special> }
<commandname>
. If the user invokes the set or get command <commandname>
, the string that results from the execution of the <perl special> is sent to the physical device.
A request separator (see Attributes)
can be used to split the command into chunks. This is required for sending multiple Ethersex commands for one command in the class definition.
The result string for the command is the
concatenation of all responses received from the physical device, optionally with response separators
(see Attributes) in between.
set <commandname> expect "<regex>"
get <commandname> expect "<regex>"
<commandname>
. <regex>
is a Perl regular expression. The double quotes around the regular expression are mandatory and they are not part of the regular expression itself.
<regex>
must match the entire reply, as in m/^<regex>$/
.
Particularly, broken connections can only be detected if something is expected (see Connection error handling).
set <commandname> postproc { <perl special> }
get <commandname> postproc { <perl special> }
<commandname>
. The data received from the physical device in reply to the get or set command <commandname>
is processed by the Perl code <perl command>
. The perl code operates on $_
. Make sure to return the result in $_
as well. The result of the perl command is shown as the result of the get or set command.
set <commandname> params <parameter1> [<parameter2> [<parameter3> ... ]]
get <commandname> params <parameter1> [<parameter2> [<parameter3> ... ]]
<commandname>
. Be careful not to use a parameter name that
is already used in the device definition (see params
above).
reading <reading> match "<regex>"
<reading>
. A spontaneous data transmission from the physical device that matches the Perl regular expression <regex>
is evaluated to become the value of the named reading. All ECMDDevice devices belonging to the ECMD device with readings with matching regular expressions will receive an update of the said readings.
<regex>
must match the entire reply, as in m/^<regex>$/
.
reading <reading> postproc { <perl special> }
<reading>
. The data received for the named reading is processed by the Perl code <perl command>
. This works analogously to the postproc
spec for set and get commands.
%NAME
will expand to the device name.%TYPE
will expand to the device type.%<parameter>
will expand to the
current value of the named parameter. This can be either a parameter
from the device definition or a parameter from the set or get
command.%pin
and %pin1
.<perl command>
in the postprocessor definitions apply.
Note: Beware of undesired side effects from e.g. doubling of semicolons!