############################################## # $Id$ package main; use strict; use warnings; ##################################### sub STACKABLE_CC_Initialize($) { my ($hash) = @_; LoadModule("CUL"); $hash->{Match} = "^\\*"; $hash->{DefFn} = "STACKABLE_CC_Define"; $hash->{UndefFn} = "STACKABLE_CC_Undef"; $hash->{ParseFn} = "STACKABLE_CC_Parse"; $hash->{NotifyFn} = "STACKABLE_CC_Notify"; $hash->{AttrFn} = "CUL_Attr"; $hash->{AttrList} = "IODev ignore:0,1 ".$modules{CUL}{AttrList}; $hash->{WriteFn} = "STACKABLE_CC_Write"; $hash->{GetFn} = "CUL_Get"; $hash->{SetFn} = "CUL_Set"; $hash->{AddPrefix} = "STACKABLE_CC_AddPrefix"; $hash->{DelPrefix} = "STACKABLE_CC_DelPrefix"; $hash->{noRawInform} = 1; # Our message was already sent as raw. $hash->{noAutocreatedFilelog} = 1; $hash->{IOOpenFn} = "STACKABLE_CC_IOOpenFn"; $hash->{IOReadFn} = "STACKABLE_CC_IOReadFn"; $hash->{IOWriteFn} = "STACKABLE_CC_IOWriteFn"; } ##################################### sub STACKABLE_CC_Define($$) { my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); $hash->{TCM} = pop @a if(int(@a) == 4 && $a[3] eq "TCM"); return "wrong syntax: define STACKABLE_CC [CUL|SCC] [TCM]" if(int(@a) != 3); my $io = $defs{$a[2]}; return "$a[2] is not a CUL/STACKABLE_CC" if(!$io || $io->{TYPE} !~ m/^(CUL|TSCUL|STACKABLE_CC|TSSTACKED)$/); return "$io->{NAME} has alread a stacked device: $io->{STACKED}" if($io->{STACKED}); $io->{STACKED} = $hash->{NAME}; $hash->{IODev} = $io; delete($io->{".clientArray"}); # Force a recompute if(!$hash->{TCM}) { $hash->{initString} = $io->{initString}; $hash->{CMDS} = ""; $hash->{Clients} = $io->{Clients}; $hash->{MatchList} = $io->{MatchList}; CUL_DoInit($hash); } $hash->{StackLevel} = $io->{StackLevel} ? $io->{StackLevel}+1 : 1; $hash->{STATE} = "Defined"; notifyRegexpChanged($hash, $a[2]); return undef; } sub STACKABLE_CC_DoNotify($) { my ($ntfy) = @_; DoTrigger($ntfy->{NAME}, $ntfy->{TriggerText}); delete $ntfy->{TriggerText}; } sub STACKABLE_CC_Notify($$) { my ($ntfy, $dev) = @_; my $events = deviceEvents($dev, 0); for(my $i = 0; $i < @{$events}; $i++) { if($events->[$i] eq "DISCONNECTED") { $ntfy->{STATE} = "disconnected"; setReadingsVal($ntfy, "state", "disconnected", TimeNow()); $ntfy->{TriggerText} = $events->[$i]; InternalTimer(gettimeofday()+0.1, "STACKABLE_CC_DoNotify", $ntfy, 0); } elsif($events->[$i] eq "CONNECTED") { CUL_DoInit($ntfy); $ntfy->{TriggerText} = $events->[$i]; InternalTimer(gettimeofday()+0.001, "STACKABLE_CC_DoNotify", $ntfy, 0); } } } ##################################### sub STACKABLE_CC_Write($$) { my ($hash,$fn,$msg) = @_; ($fn, $msg) = CUL_WriteTranslate($hash, $fn, $msg); return if(!defined($fn)); IOWrite($hash, "", ($hash->{TCM} ? "%":"*")."$fn$msg"); # No more translations } ##################################### sub STACKABLE_CC_Parse($$) { my ($iohash,$msg) = @_; $msg =~ s/^.//; # Cut off prefix * my $name = $iohash->{STACKED} ? $iohash->{STACKED} : ""; my $id = $iohash->{StackLevel} ? $iohash->{StackLevel}+1 : 1; return "UNDEFINED STACKABLE_CC_$id STACKABLE_CC $iohash->{NAME}" if(!$name); return "" if(IsIgnored($name)); my $sh = $defs{$name}; if($sh && $sh->{TCM}) { my $th = $sh->{TCMHash}; if($th) { delete $th->{IOReadFn}; $th->{IODevRxBuffer} = pack("H*", $msg); CallFn($th->{NAME}, "ReadFn", $th); $th->{IOReadFn} = "STACKABLE_CC_IOReadFn"; } else { Log 1, "$name: no TCM device assigned"; } } else { CUL_Parse($defs{$name}, $iohash, $name, $msg); } return ""; } sub STACKABLE_CC_DelPrefix($$) { my ($hash, $msg) = @_; $msg =~ s/^[^A-Z0-9]//i; return $msg; } sub STACKABLE_CC_AddPrefix($$) { my ($hash, $msg) = @_; return "*$msg"; } sub STACKABLE_CC_Undef($$) { my ($hash, $arg) = @_; CUL_SimpleWrite($hash, "X00"); delete $hash->{IODev}{STACKED}; return undef; } sub STACKABLE_CC_IOOpenFn($) { my ($hash) = @_; $hash->{FD} = $hash->{IODev}{IODev}{FD}; # Lets fool the TCM $hash->{IODev}{TCMHash} = $hash; $hash->{IOReadFn} = "STACKABLE_CC_IOReadFn"; return 1; } sub STACKABLE_CC_IOReadFn($) { my ($hash) = @_; my $me = $hash->{IODev}; my $buf = ""; while($buf !~ m/\n/) { $buf .= DevIo_SimpleRead($me->{IODev}); # may block } $buf =~ s/[\r\n]//g; $buf = STACKABLE_CC_DelPrefix($me, $buf); return pack("H*",$buf); } sub STACKABLE_CC_IOWriteFn($$) { my ($hash, $msg) = @_; return IOWrite($hash, "", unpack("H*",$msg)); } 1; =pod =item summary Busware Stackable CC (SCC) base module =item summary_DE Busware Stackabble CC (SCC) basis Modul =begin html

STACKABLE_CC

=end html =begin html_DE

STACKABLE_CC

=end html_DE =cut