| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- ##############################################
- # $Id: 16_STACKABLE.pm 14018 2017-04-17 16:33:06Z rudolfkoenig $
- package main;
- use strict;
- use warnings;
- #####################################
- sub
- STACKABLE_Initialize($)
- {
- my ($hash) = @_;
- $hash->{Match} = "^\\*";
- $hash->{DefFn} = "STACKABLE_Define";
- $hash->{UndefFn} = "STACKABLE_Undef";
- $hash->{ParseFn} = "STACKABLE_Parse";
- $hash->{NotifyFn} = "STACKABLE_Notify";
- $hash->{AttrList} = "IODev ignore:1,0 binary:1,0 writePrefix";
- $hash->{noRawInform} = 1; # Our message was already sent as raw.
- $hash->{noAutocreatedFilelog} = 1;
- $hash->{IOOpenFn} = "STACKABLE_IOOpenFn";
- $hash->{IOReadFn} = "STACKABLE_IOReadFn";
- $hash->{IOWriteFn} = "STACKABLE_IOWriteFn";
- }
- #####################################
- sub
- STACKABLE_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- return "wrong syntax: define <name> STACKABLE baseDevice"
- if(int(@a) != 3);
- my $io = $defs{$a[2]};
- return "$a[2] is not a valid device"
- if(!$io);
- return "$io->{NAME} already has a stacked device: $io->{STACKED}"
- if($io->{STACKED});
- $io->{STACKED} = $hash->{NAME};
- $hash->{IODev} = $io;
- delete($io->{".clientArray"}); # Force a recompute
- $hash->{STATE} = "Defined";
- notifyRegexpChanged($hash, $a[2]);
- return undef;
- }
- #####################################
- sub
- STACKABLE_Parse($$)
- {
- my ($iohash,$msg) = @_;
- return "UNDEFINED $iohash->{NAME}_STACKABLE STACKABLE $iohash->{NAME}"
- if(!$iohash->{STACKED});
- my $name = $iohash->{STACKED};
- return "" if(IsIgnored($name));
- $msg =~ s/^.//; # Cut off prefix *
- my $sh = $defs{$name};
- my $ch = $sh->{".clientHash"};
- if($ch) {
- delete $ch->{IOReadFn};
- $ch->{IODevRxBuffer} = (AttrVal($name,"binary",0) ?
- pack("H*",$msg) : $msg."\n");
- CallFn($ch->{NAME}, "ReadFn", $ch);
- $ch->{IOReadFn} = "STACKABLE_IOReadFn";
- } else {
- Log 1, "$name: no client device assigned";
- }
- return "";
- }
- sub
- STACKABLE_Undef($$)
- {
- my ($hash, $arg) = @_;
- delete $hash->{IODev}{STACKED};
- return undef;
- }
- sub
- STACKABLE_Notify($$)
- {
- my ($me, $src) = @_;
- my $eva = deviceEvents($src,0);
- return undef if(!$eva || !@$eva);
- my $evt = $eva->[0];
- my $tgt = $me->{".clientHash"};
- if($evt eq "DISCONNECTED") {
- DevIo_Disconnected($tgt);
- my ($dev, undef) = split("@", $tgt->{DeviceName});
- delete $readyfnlist{"$tgt->{NAME}.$dev"}; # no polling by child devices
- delete $tgt->{DevIoJustClosed};
- } elsif($evt eq "CONNECTED") {
- CallFn($tgt->{NAME}, "ReadyFn", $tgt);
- }
- return undef;
- }
- sub
- STACKABLE_IOOpenFn($)
- {
- my ($hash) = @_;
- $hash->{FD} = $hash->{IODev}{IODev}{FD}; # Lets fool the client
- $hash->{IODev}{".clientHash"} = $hash;
- $hash->{IOReadFn} = "STACKABLE_IOReadFn";
- return 1;
- }
- sub
- STACKABLE_IOReadFn($) # used by synchronuous get
- {
- my ($hash) = @_;
- my $me = $hash->{IODev};
- my $buf = "";
- if($me->{IODev} && $me->{IODev}{PARTIAL}) {
- $buf = $me->{IODev}{PARTIAL};
- $me->{IODev}{PARTIAL} = "";
- }
- while($buf !~ m/\n/) {
- my $ret = DevIo_SimpleReadWithTimeout($me->{IODev}, 1); # may block
- return undef if(!defined($ret));
- $buf .= $ret;
- }
- my $mName = $me->{NAME};
- Log3 $mName, 5, "$mName read: $buf";
- my @l = split("\n", $buf);
- $buf = join("\n", grep { $_ =~ m/^\*/ } @l)."\n";
- $buf =~ s/^\*//gsm;
- if(AttrVal($me->{NAME},"binary",0)) {
- $buf =~ s/[\r\n]//g;
- return pack("H*",$buf);
- } else {
- return $buf;
- }
- }
- sub
- STACKABLE_IOWriteFn($$)
- {
- my ($hash, $msg) = @_;
- my $myhash = $hash->{IODev};
- my $myname = $myhash->{NAME};
- my $prf = AttrVal($myname,"writePrefix","*");
- if(AttrVal($myname,"binary",0)) {
- return IOWrite($myhash, "", $prf.unpack("H*",$msg));
- } else {
- $msg =~ s/[\r\n]//g;
- return IOWrite($myhash, "", $prf.$msg);
- }
- }
- 1;
- =pod
- =item summary Module for stacked IO devices like the Busware SCC
- =item summary_DE Modul fuer gestapelte IO Geräte wie das Busware SCC
- =begin html
- <a name="STACKABLE"></a>
- <h3>STACKABLE</h3>
- <ul>
- This module is a more generic version of the STACKABLE_CC module, and is used
- for stacked IO devices like the Busware SCC. It works by adding/removing a
- prefix (default is *) to the command, and redirecting the output to the
- module, which is using it.
- <a name="STACKABLEdefine"></a>
- <b>Define</b>
- <ul>
- <code>define <name> STACKABLE <baseDevice></code> <br>
- <br>
- <baseDevice> is the name of the unterlying device.<br>
- Example:
- <ul><code>
- define CUL_1 CUL /dev/ttyAMA0@38400<br>
- attr CUL_1 rfmode SlowRF<br><br>
- define CUL_1_SCC STACKABLE CUL1<br>
- define CUL_2 CUL FHEM:DEVIO:CUL_1_SCC:9600 0000<br>
- attr CUL_2 rfmode HomeMatic<br><br>
- define CUL_2_SCC STACKABLE CUL2<br>
- define CUL_3 ZWCUL FHEM:DEVIO:CUL_2_SCC:9600 12345678 01<br>
- </code></ul>
- <b>Note:</b>If you rename the base CUL or a STACKABLE, which is a base for
- another one, the definition of the next one has to be adjusted, and FHEM
- has to be restarted.
- </ul>
- <a name="STACKABLEset"></a>
- <b>Set</b> <ul>N/A</ul><br>
- <a name="STACKABLEget"></a>
- <b>Get</b> <ul>N/A</ul><br>
- <a name="STACKABLEattr"></a>
- <b>Attributes</b>
- <ul>
- <li><a name="#writePrefix">writePrefix</a><br>
- The prefix used when writing data, default is *.
- "readPrefix" is hardcoded to *.
- </li><br>
- <li><a name="#binary">binary</a><br>
- If set to true, read data is converted to binary from hex before offering
- it to the client IO device (e.g. TCM). Default is 0 (off).
- </li><br>
- </ul>
- </ul>
- =end html
- =cut
|