From f05d84c2bd70034bb323d175bb487ad2d6844ecd Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 21 Nov 2010 17:57:24 +0000 Subject: [PATCH] Weekly progress git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@757 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/10_CUL_HM.pm | 247 ++++++++++++++++++++++++++++------------------ 1 file changed, 149 insertions(+), 98 deletions(-) diff --git a/FHEM/10_CUL_HM.pm b/FHEM/10_CUL_HM.pm index 23c21f22b..278ad9796 100755 --- a/FHEM/10_CUL_HM.pm +++ b/FHEM/10_CUL_HM.pm @@ -10,6 +10,7 @@ sub CUL_HM_Id($); sub CUL_HM_Initialize($); sub CUL_HM_Pair(@); sub CUL_HM_Parse($$); +sub CUL_HM_PushCmdStack($$); sub CUL_HM_SendCmd($$$$); sub CUL_HM_Set($@); @@ -122,7 +123,7 @@ CUL_HM_Initialize($) "subType:switch,dimmer,blindActuator,remote,sensor,". "swi,pushButton,threeStateSensor,motionDetector,". "keyMatic,winMatic,smokeDetector " . - "hmClass:receiver,sender"; + "hmClass:receiver,sender serialNr"; } @@ -152,8 +153,8 @@ CUL_HM_Define($$) sub CUL_HM_Parse($$) { - my ($hash, $msg) = @_; - my $id = CUL_HM_Id($hash); + my ($iohash, $msg) = @_; + my $id = CUL_HM_Id($iohash); # Msg format: Allnnccttssssssddddddpp... $msg =~ m/A(..)(..)(..)(..)(......)(......)(.*)/; @@ -165,7 +166,7 @@ CUL_HM_Parse($$) my $dhash = $modules{CUL_HM}{defptr}{$dst}; my $dname = $dhash ? $dhash->{NAME} : "unknown"; $dname = "broadcast" if($dst eq "000000"); - $dname = $hash->{NAME} if($dst eq $id); + $dname = $iohash->{NAME} if($dst eq $id); if(!$shash) { my $sname = "CUL_HM_$src"; @@ -192,16 +193,25 @@ CUL_HM_Parse($$) my $st = AttrVal($name, "subType", undef); - if("$channel$msgtype" =~ m/(8400|A000|A001)/) { # Pairing-Request + if("$len$channel$msgtype" eq "1A8400") { #### Pairing-Request push @event, CUL_HM_Pair($name, $shash, @msgarr); + + } elsif("$channel$msgtype" =~ m/A00[012]/ && #### Pairing-Request-Conversation + $dst eq $id) { + CUL_HM_SendCmd($shash, $msgcnt."8002".$id.$src."00", 1, 0); # Ack + push @event, ""; } elsif(!$st) { # Will trigger unknown ; - } elsif("$channel$msgtype" eq "8002" && - $shash->{pairingStep} && - $len eq "0A") { # Ack Pair - push @event, CUL_HM_Pair($name, $shash, @msgarr); + } elsif("$channel$msgtype" eq "8002") { #### Ack + + if($shash->{cmdStack}) { + CUL_HM_SendCmd($shash, shift @{$shash->{cmdStack}}, 1, 1); + delete($shash->{cmdStack}) if(!@{$shash->{cmdStack}}); + } + + push @event, ""; } elsif($st eq "switch") { ############################################ @@ -220,13 +230,15 @@ CUL_HM_Parse($$) } elsif($st eq "remote") { ############################################ if("$channel$msgtype" =~ m/A.4./ && $p =~ m/^(..)(..)$/) { - my $btn = int(($1+1)/2); - my $state = $1&1 ? "off" : "on"; + my ($button, $bno) = (hex($1), hex($2)); + + my $btn = int((($button&0x3f)+1)/2); + my $state = ($button&1 ? "off" : "on") . ($button & 0x40 ? "Long" : ""); my $add = ($dst eq $id) ? "" : " (to $dname)"; push @event, "state:Btn$btn:$state$add"; if($id eq $dst) { CUL_HM_SendCmd($shash, "++8002".$id.$src."0101". # Send Ack. - ($state eq "on"?"C8":"00")."0028", 1, 0); + ($state =~ m/on/?"C8":"00")."0028", 1, 0); } } @@ -273,10 +285,8 @@ sub CUL_HM_Set($@) { my ($hash, @a) = @_; - my $ret = undef; - my $na = int(@a); - return "no set value specified" if($na < 2 || $na > 3); + return "no set value specified" if(@a < 2); my $name = $hash->{NAME}; my $st = AttrVal($name, "subType", undef); @@ -286,13 +296,63 @@ CUL_HM_Set($@) my $sndcmd; my $state; - if($st eq "switch") { - if($cmd eq "on" || $cmd eq "off") { + if($cmd eq "raw") { ################################################## + return "Usage: set $a[0] $cmd rowdata" if(@a != 3); + CUL_HM_PushCmdStack($hash, $a[2]); + return ""; + + } elsif($st eq "switch") {############################################# + my %scmd = (on => "02", off => "01", onLong => "42", offLong => "41") ; + if($scmd{$cmd}) { $state = $cmd; - $sndcmd = sprintf("++A440%s%s%02d%02d", $id, $hash->{DEF}, - $cmd eq "on" ? 2: 1, $hash->{"${cmd}MsgNr"}++); + $sndcmd = sprintf("++A440%s%s%s%02d", $id, $hash->{DEF}, + $scmd{$cmd}, $hash->{"${cmd}MsgNr"}++); + + } else { + return "Unknown argument $cmd, choose one " . join(" ", sort keys %scmd); + } + } elsif($st eq "remote") {############################################# + my %scmd = (text => "01"); + if($cmd eq "text") { + return "Usage: set $a[0] $cmd [on|off] " if(@a != 6); + return "$a[2] is not a button number" if($a[2] !~ m/^\d$/); + return "$a[3] is not on or off" if($a[3] !~ m/^(on|off)$/); + my $bn = $a[2]*2-($a[3] eq "on" ? 1 : 0); + + CUL_HM_PushCmdStack($hash, + sprintf("++A001%s%s%02d050000000001", $id, $hash->{DEF}, $bn)); + + my ($l1, $l2, $s, $tl); + $l1 = $a[4] . "\x00"; + $l1 = substr($l1, 0, 13); + $s = 54; + $l1 =~ s/(.)/sprintf("%02X%02X",$s++,ord($1))/ge; + + $l2 = $a[5] . "\x00"; + $l2 = substr($l2, 0, 13); + $s = 70; + $l2 =~ s/(.)/sprintf("%02X%02X",$s++,ord($1))/ge; + $l1 .= $l2; + + $tl = length($l1); + for(my $l = 0; $l < $tl; $l+=28) { + my $ml = $tl-$l < 28 ? $tl-$l : 28; + CUL_HM_PushCmdStack($hash, + sprintf("++A001%s%s%02d08%s", $id, $hash->{DEF}, $bn, substr($l1,$l,$ml))); + } + + CUL_HM_PushCmdStack($hash, + sprintf("++A001%s%s%02d06", $id, $hash->{DEF}, $bn)); + return; + + } else { + return "Unknown argument $cmd, choose one " . join(" ", sort keys %scmd); + + } + + } return "$name: Unknown device subtype or command" if(!$sndcmd); @@ -310,9 +370,9 @@ CUL_HM_Set($@) ################################### # A pairing between rrrrrr (remote) and ssssss (switch) looks like the # following (nn and ff is the index of the on and off button): -# 1A 66 84 00 ssssss 000000 19 0011 46 4551303 03831363537 10 01 0100 -# 1A CF 84 00 rrrrrr ssssss 12 0035 47 4551303 03333333633 40 04 nnff -# 0A D0 80 02 ssssss rrrrrr 00 +# 1A CF 84 00 rrrrrr 000000 10 0060 serialnumberxxxxxxxx 40 04 nnff +# 1A 66 A0 00 ssssss rrrrrr 19 0011 serialnumberxxxxxxxx 10 01 0100 +# 0A D0 80 02 rrrrrr ssssss 00 # 10 D0 A0 01 ssssss rrrrrr nn05 ssssss 0104 # 0A D0 80 02 rrrrrr ssssss 00 # 0E D0 A0 01 ssssss rrrrrr nn07 020201 @@ -328,99 +388,79 @@ CUL_HM_Set($@) sub CUL_HM_Pair(@) { - my ($name, $def, $len,$msgcnt,$channel,$msgtype,$src,$dst,$p) = @_; - my $id = CUL_HM_Id($def->{IODev}); + my ($name, $hash, $len,$msgcnt,$channel,$msgtype,$src,$dst,$p) = @_; + my $iohash = $hash->{IODev}; + my $id = CUL_HM_Id($iohash); my $l4 = GetLogLevel($name,4); - my $ps = $def->{pairingStep} ? $def->{pairingStep} : ""; + my $stc = substr($p, 26, 2); # subTypeCode + my $model = substr($p, 2, 4); + my $dp = $culHmDevProps{$stc}; - # Starting pair message with everything we need - if($len eq "1A") { - my $stc = substr($p, 26, 2); # subTypeCode - my $model = substr($p, 2, 4); - my $dp = $culHmDevProps{$stc}; + $attr{$name}{model} = $culHmModel{$model}? $culHmModel{$model} :"unknown"; + $attr{$name}{subType} = $dp ? $dp->{st} : "unknown"; + $attr{$name}{hmClass} = $dp ? $dp->{cl} : "unknown"; + $attr{$name}{serialNr} = pack('H*', substr($p, 6, 20)); + my $isSender = (AttrVal($name,"hmClass","") eq "sender"); - $attr{$name}{model} = $culHmModel{$model}? $culHmModel{$model} :"unknown"; - $attr{$name}{subType} = $dp ? $dp->{st} : "unknown"; - $attr{$name}{hmClass} = $dp ? $dp->{cl} : "unknown"; + my $stn = $attr{$name}{subType}; # subTypeName + my $stt = $stn eq "unknown" ? "subType unknown" : "is a $stn"; - my $stn = $attr{$name}{subType}; # subTypeName - my $stt = $stn eq "unknown" ? "subType unknown" : "is a $stn"; + Log GetLogLevel($name,2), "CUL_HM pair: $name $stt, model $attr{$name}{model} ". + "serialNr $attr{$name}{serialNr}"; - # First message - if(!$ps) { - Log GetLogLevel($name,2), "CUL_HM $name $stt, model $attr{$name}{model}"; + # Abort if we are not authorized + if($dst eq "000000") { + return if(!$iohash->{HM_PAIR} && !AttrVal($iohash->{NAME}, "hm_autopair", 0)); - if($stn eq "unknown") { - Log GetLogLevel($name,1), "CUL_HM unknown subType $stc, cannot pair"; - return ""; - } + } elsif($dst ne $id) { + return "" ; - # Abort if we are not authorized - my $ion = $def->{IODev}->{NAME}; - return "" - if(!($dst eq "000000" && AttrVal($ion, "hm_autopair", 1) || - $dst eq $id)); + } - # Sender pair mode, before btn is pressed - $def->{pairButtons} = substr($p, 30, 4); - return "" if($def->{pairButtons} eq "0000"); + if($stn eq "unknown") { + Log GetLogLevel($name,1), "CUL_HM unknown subType $stc, cannot pair"; + return ""; + } - my ($mystc, $mymodel, $mybtn, $myunknown); - if(AttrVal($name,"hmClass","") eq "sender") { - $mymodel = "0011"; # Emulate a HM-LC-SW1-PL - $mystc = "10"; # switch - $mybtn = "010100";# No buttons (?) - $myunknown = "46455130303831363537" - - } else { - $mymodel = "0060"; # Emulate a HM-PB-4DIS-WM - $mystc = "40"; # remote - $mybtn = "940201";# Buttons 02 (on) & 01 (off) - $myunknown = "48455130303634393136"; - } - - if($dst eq "000000") { - Log $l4, "CUL_HM Pairing Step 1"; - CUL_HM_SendCmd($def, - $msgcnt."A000".$id.$src."19".$mymodel.$myunknown.$mystc.$mybtn, 1, 0); - } - - $ps = $def->{pairingStep} = 1; - return "" if(AttrVal($name,"hmClass","") eq "receiver"); + $hash->{pairButtons} = substr($p, 30, 4); + if($hash->{pairButtons} eq "0000") { # Sender pair mode, before btn is pressed + if($hash->{cmdStack}) { + CUL_HM_SendCmd($hash, shift @{$hash->{cmdStack}}, 1, 1); + delete($hash->{cmdStack}) if(!@{$hash->{cmdStack}}); } - } - - if(!$ps || $dst ne $id) { - Log 4, "CUL_HM $name pairing step with other device"; return ""; } - # If the partner is a receiver, then we only have to ack every message - # after the first. - if($ps && AttrVal($name,"hmClass","") eq "receiver") { - CUL_HM_SendCmd($def, $msgcnt."8002".$id.$src."00", 1, 0); - return ""; - } + my ($mystc, $mymodel, $mybtn, $myserNr); + if($isSender) { + $mymodel = "0011"; # Emulate a HM-LC-SW1-PL + $mystc = "10"; # switch + $mybtn = "010100";# No buttons (?) - # switch emulation (sender is ack only and handled above); - $def->{pairButtons} =~ m/(..)(..)/; - my ($b1, $b2, $cmd) = ($1, $2, ""); - $cmd = "++A001$id$src${b1}05$src${b1}04" if($ps == 1); - $cmd = "++A001$id$src${b1}07020201" if($ps == 2); - $cmd = "++A001$id$src${b1}06" if($ps == 3); - $cmd = "++A001$id$src${b2}05$src${b1}04" if($ps == 4); - $cmd = "++A001$id$src${b2}07020201" if($ps == 5); - $cmd = "++A001$id$src${b2}06" if($ps == 6); - if($ps == 7) { - delete($def->{pairingStep}); - return ""; + } else { + $mymodel = "0060"; # Emulate a HM-PB-4DIS-WM + $mystc = "40"; # remote + $mybtn = "940201";# Buttons 02 (on) & 01 (off) } - CUL_HM_SendCmd($def, $cmd, 1, 1); - $def->{pairingStep} = ++$ps; - Log $l4, "CUL_HM Pairing Step $ps ($cmd)"; + $myserNr = unpack('H*', "FHEM$id"); + CUL_HM_SendCmd($hash, + $msgcnt."A000".$id.$src."19".$mymodel.$myserNr.$mystc.$mybtn, 1, 0); + + # switch emulation (actor/receiver is ack only); + if($isSender) { + $hash->{pairButtons} =~ m/(..)(..)/; + my ($b1, $b2, $cmd) = ($1, $2, ""); + CUL_HM_SendCmd($hash, "++A001$id$src${b1}05$src${b1}04", 1, 1); + CUL_HM_PushCmdStack($hash, "++A001$id$src${b1}07020201"); + CUL_HM_PushCmdStack($hash, "++A001$id$src${b1}06"); + CUL_HM_PushCmdStack($hash, "++A001$id$src${b2}05$src${b1}04"); + CUL_HM_PushCmdStack($hash, "++A001$id$src${b2}07020201"); + CUL_HM_PushCmdStack($hash, "++A001$id$src${b2}06"); + } return ""; + } ################################### @@ -447,7 +487,7 @@ CUL_HM_SendCmd($$$$) $io->{HM_CMDNR} = $mn; $cmd = sprintf("As%02X%02x%s", length($cmd2)/2+1, $mn, $cmd2); - Log $l4, "CUL_HM $cmd"; + Log $l4, "CUL_HM SEND $cmd"; IOWrite($hash, "", $cmd); if($waitforack) { $hash->{ackWaiting} = $cmd; @@ -456,6 +496,17 @@ CUL_HM_SendCmd($$$$) } } +################################### +sub +CUL_HM_PushCmdStack($$) +{ + my ($hash, $cmd) = @_; + my @arr = (); + $hash->{cmdStack} = \@arr if(!$hash->{cmdStack}); + #Log 1, $cmd; + push(@{$hash->{cmdStack}}, $cmd); +} + ################################### sub CUL_HM_Resend($)