From 148fa2a5c6c91bc8eec7931e884ef2fe495e92f2 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 2 Jan 2011 14:45:53 +0000 Subject: [PATCH] CUL_HM: set rewrite. Note: temporarily there is no device ack event. git-svn-id: https://svn.fhem.de/fhem/trunk@788 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_CUL.pm | 11 +- fhem/FHEM/10_CUL_HM.pm | 402 ++++++++++++++++++++------------------ fhem/docs/commandref.html | 34 +++- fhem/fhem.pl | 3 +- 4 files changed, 252 insertions(+), 198 deletions(-) diff --git a/fhem/FHEM/00_CUL.pm b/fhem/FHEM/00_CUL.pm index 4495efc8d..a0d6ddfc2 100755 --- a/fhem/FHEM/00_CUL.pm +++ b/fhem/FHEM/00_CUL.pm @@ -88,7 +88,7 @@ CUL_Initialize($) $hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 " . "showtime:1,0 model:CUL,CUN,CUR loglevel:0,1,2,3,4,5,6 " . "fhtsoftbuffer:1,0 sendpool addvaltrigger " . - "rfmode:SlowRF,HomeMatic"; + "rfmode:SlowRF,HomeMatic hmId hmProtocolEvents"; $hash->{ShutdownFn} = "CUL_Shutdown"; } @@ -215,12 +215,13 @@ CUL_Set($@) InternalTimer(gettimeofday()+$arg, "CUL_RemoveHMPair", $hash, 1); } elsif($type eq "hmPairSerial") { ################################ - return "Usage: set $name hmPairForSec <10-character-serialnumber>" + return "Usage: set $name hmPairSerial <10-character-serialnumber>" if(!$arg || $arg !~ m/^.{10}$/); + my $id = AttrVal($hash->{NAME}, "hmId", "F1".$hash->{FHTID}); $hash->{HM_CMDNR} = $hash->{HM_CMDNR} ? ($hash->{HM_CMDNR}+1)%256 : 1; - CUL_SimpleWrite($hash, sprintf("As15%02x8401F1%s000000010A%s", - $hash->{HM_CMDNR}, $hash->{FHTID}, unpack('H*', $arg))); + CUL_SimpleWrite($hash, sprintf("As15%02x8401%s000000010A%s", + $hash->{HM_CMDNR}, $id, unpack('H*', $arg))); $hash->{hmPairSerial} = $arg; @@ -926,7 +927,7 @@ CUL_SimpleWrite(@) # Prefix $msg with RRBBU and return the corresponding CUL hash. ($hash, $msg) = CUL_RFR_AddPrefix($hash, $msg); } - Log 1, "SW: $msg"; + #Log 1, "SW: $msg"; $msg .= "\n" unless($nonl); $hash->{USBDev}->write($msg . "\n") if($hash->{USBDev}); diff --git a/fhem/FHEM/10_CUL_HM.pm b/fhem/FHEM/10_CUL_HM.pm index eb07da8e0..8b4eba3f3 100755 --- a/fhem/FHEM/10_CUL_HM.pm +++ b/fhem/FHEM/10_CUL_HM.pm @@ -13,7 +13,7 @@ sub CUL_HM_Parse($$); sub CUL_HM_PushCmdStack($$); sub CUL_HM_SendCmd($$$$); sub CUL_HM_Set($@); -sub CUL_HM_DumpBits(@); +sub CUL_HM_DumpProtocol($$@); my %culHmDevProps=( "10" => { st => "switch", cl => "receiver" }, # Parse,Set @@ -162,14 +162,13 @@ CUL_HM_Parse($$) my $id = CUL_HM_Id($iohash); # Msg format: Allnnccttssssssddddddpp... - $msg =~ m/A(..)(..)(..)(..)(......)(......)(.*)/; + $msg =~ m/A(..)(..)(....)(......)(......)(.*)/; my @msgarr = ($1,$2,$3,$4,$5,$6,$7); - my ($len,$msgcnt,$channel,$msgtype,$src,$dst,$p) = @msgarr; - CUL_HM_DumpBits(@msgarr); + my ($len,$msgcnt,$cmd,$src,$dst,$p) = @msgarr; + CUL_HM_DumpProtocol("CUL_HM RCV", $iohash, @msgarr); my $shash = $modules{CUL_HM}{defptr}{$src}; - my $cm = "$channel$msgtype"; - my $lcm = "$len$channel$msgtype"; + my $lcm = "$len$cmd"; my $dhash = $modules{CUL_HM}{defptr}{$dst}; my $dname = $dhash ? $dhash->{NAME} : "unknown"; @@ -205,27 +204,21 @@ CUL_HM_Parse($$) if($lcm eq "1A8400" || $lcm eq "1A8000") { #### Pairing-Request push @event, CUL_HM_Pair($name, $shash, @msgarr); - } elsif($cm =~ m/^A0[01]{2}$/ && $dst eq $id) {#### Pairing-Request-Convers. + } elsif($cmd =~ m/^A0[01]{2}$/ && $dst eq $id) {#### Pairing-Request-Convers. CUL_HM_SendCmd($shash, $msgcnt."8002".$id.$src."00", 1, 0); # Ack push @event, ""; - } elsif($lcm eq "11A002") { # signing experiments - push @event, "signRequest:$p"; + } elsif($cmd eq "8002") { # Ack - } elsif($lcm eq "19A003") { # signing experiments - push @event, "signAnswer:$p"; + if($shash->{cmdStack}) { # Send next msg from the stack + CUL_HM_SendCmd($shash, shift @{$shash->{cmdStack}}, 1, 1); + delete($shash->{cmdStack}) if(!@{$shash->{cmdStack}}); + $shash->{lastStackAck} = 1; - } elsif(!$st) { # Will trigger unknown - ; + } elsif($shash->{lastStackAck}) { # Ack of our last stack msg + delete($shash->{lastStackAck}); - } elsif($cm eq "8002" && $shash->{cmdStack}) { # Send next msg from the stack - CUL_HM_SendCmd($shash, shift @{$shash->{cmdStack}}, 1, 1); - delete($shash->{cmdStack}) if(!@{$shash->{cmdStack}}); - $shash->{lastStackAck} = 1; - push @event, ""; - - } elsif($cm eq "8002" && $shash->{lastStackAck}) { # Ack of our last stack msg - delete($shash->{lastStackAck}); + } push @event, ""; } elsif($st eq "switch" || ############################################ @@ -238,14 +231,13 @@ CUL_HM_Parse($$) $val = ($val == 100 ? "on" : ($val == 0 ? "off" : "$val %")); my $msg = "unknown"; $msg = "deviceMsg" if($lt =~ m/0.01/); - $msg = "powerOn" if($lt =~ m/0600/); push @event, "$msg:$val"; push @event, "state:$val" if(!$isack); } } elsif($st eq "remote") { ############################################ - if($cm =~ m/^..4./ && $p =~ m/^(..)(..)$/) { + if($cmd =~ m/^..4./ && $p =~ m/^(..)(..)$/) { my ($button, $bno) = (hex($1), hex($2)); my $btn = int((($button&0x3f)+1)/2); @@ -258,9 +250,6 @@ CUL_HM_Parse($$) ($state =~ m/on/?"C8":"00")."0028", 1, 0); } - } elsif($p =~ m/0600/) { - push @event, "powerOn:$p"; - } } elsif($st eq "smokeDetector") { ##################################### @@ -310,7 +299,7 @@ CUL_HM_Parse($$) } - push @event, "unknownMsg:$p" if(!@event); + #push @event, "unknownMsg:$p" if(!@event); my $tn = TimeNow(); for(my $i = 0; $i < int(@event); $i++) { @@ -342,6 +331,19 @@ CUL_HM_Parse($$) return $name; } +my %culHmGlobalSets = ( + raw => "data", + reset => 0, + pair => 0, + statusRequest => 0, +); +my %culHmSubTypeSets = ( + switch => { on => 0, off => 0, toggle => 0 }, + dimmer => { on => 0, off => 0, toggle => 0, pct=>0 }, + blindActuator => { on => 0, off => 0, toggle => 0, pct=>0 }, + remote => { text => " [on|off] " }, +); + ################################### sub CUL_HM_Set($@) @@ -352,104 +354,109 @@ CUL_HM_Set($@) return "no set value specified" if(@a < 2); my $name = $hash->{NAME}; - my $st = AttrVal($name, "subType", undef); + my $st = AttrVal($name, "subType", ""); my $cmd = $a[1]; - my $id = CUL_HM_Id($hash->{IODev}); + my $h = $culHmGlobalSets{$cmd}; + $h = $culHmSubTypeSets{$st}{$cmd} if(!defined($h) && $culHmSubTypeSets{$st}); + + if(!defined($h) && $culHmSubTypeSets{$st}{pct} && $cmd =~ m/^\d+/) { + $cmd = "pct"; + + } elsif(!defined($h)) { + my $usg = "Unknown argument $cmd, choose one of " . + join(" ",sort keys %culHmGlobalSets); + $usg .= " ". join(" ",sort keys %{$culHmSubTypeSets{$st}}) + if($culHmSubTypeSets{$st}); + my $pct = join(" ", (0..100)); + $usg =~ s/ pct/ $pct/; + return $usg; + + } + + if($h) { + my @l = split(" ", $h); + my $narg = int(@l); + return "Usage: set $name $cmd $h" if(@a < $narg+2); + + } else { + return "Usage: set $name $cmd (no argument required)" if(@a > 2); + + } + + + my $id = CUL_HM_Id($hash->{IODev}); my $sndcmd; - my $state; if($cmd eq "raw") { ################################################## - return "Usage: set $a[0] $cmd rowdata" if(@a != 3); - CUL_HM_SendCmd($hash, $a[2], 0, 1); - return ""; - - } elsif($cmd eq "rawStack") { ######################################## - return "Usage: set $a[0] $cmd rowdata" if(@a != 3); - CUL_HM_PushCmdStack($hash, $a[2]); - return ""; - - } elsif($st eq "switch") { ############################################ - - my %scmd = (on=>"C8", off=>"00"); - if($scmd{$cmd}) { - $state = $cmd; - $sndcmd = sprintf("++A011%s%s0201%s0000", $id,$hash->{DEF},$scmd{$cmd}); - - } else { - return "Unknown argument $cmd, choose one of " .join(" ",sort keys %scmd); - + return "Usage: set $a[0] $cmd data [data ...]" if(@a < 3); + $sndcmd = $a[2]; + for (my $i = 3; $i < @a; $i++) { + CUL_HM_PushCmdStack($hash, $a[$i]); } - } elsif($st eq "dimmer" || ############################################ - $st eq "blindActuator") { + } elsif($cmd eq "reset") { ############################################ + $sndcmd = sprintf("++A011%s%s0400", $id,$hash->{DEF}); - my %scmd = (on => "C8", off => "00"); - if($scmd{$cmd}) { - $state = $cmd; - $sndcmd = sprintf("++A011%s%s0201%s0000", $id,$hash->{DEF}, $scmd{$cmd}); + } elsif($cmd eq "pair") { ############################################# + my $serialNr = AttrVal($name, "serialNr", undef); + return "serialNr is not set" if(!$serialNr); + $sndcmd = sprintf("++8401%s000000010A%s", $id, unpack("H*",$serialNr)); + $hash->{hmPairSerial} = $serialNr; - } elsif($cmd =~ m/^\d+/ && $cmd >= 0 && $cmd <= 100) { - $state = "$cmd %"; - $sndcmd = sprintf("++A011%s%s0201%02X0000", $id, $hash->{DEF}, $cmd*2); + } elsif($cmd eq "statusRequest") { #################################### + $sndcmd = sprintf("++A001%s%s010E", $id,$hash->{DEF}); - } else { - my @scmd = ("on", "off", 0..100); - return "Unknown argument $cmd, choose one of " .join(" ",@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" ? 0 : 1); - - 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); + } elsif($cmd eq "on") { ############################################### + $sndcmd = sprintf("++A011%s%s0201C80000", $id,$hash->{DEF}); + } elsif($cmd eq "off") { ############################################## + $sndcmd = sprintf("++A011%s%s0201000000", $id,$hash->{DEF}); + + } elsif($cmd eq "toggle") { ########################################### + $hash->{toggleIndex} = 1 if(!$hash->{toggleIndex}); + $hash->{toggleIndex} = (($hash->{toggleIndex}+1) % 128); + $sndcmd = sprintf("++A03E%s%s%s4001%02x", $id, $hash->{DEF}, + $hash->{DEF}, $hash->{toggleIndex}); + + } elsif($st eq "pct") { ############################################## + $a[1] = 100 if ($a[1] > 100); + $sndcmd = sprintf("++A011%s%s0201%02X0000", $id, $hash->{DEF}, $a[1]*2); + + } elsif($st eq "text") { ############################################# + 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" ? 0 : 1); + + CUL_HM_PushCmdStack($hash, + sprintf("++A001%s%s%02d050000000001", $id, $hash->{DEF}, $bn)); + + my ($l1, $l2, $s, $tl); # Create CONFIG_WRITE_INDEX string + $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 "Set your remote in learning mode to transmit the data"; } - return "$name: Unknown device subtype or command" if(!$sndcmd); CUL_HM_SendCmd($hash, $sndcmd, 0, 1); - if($state) { - $hash->{STATE} = $state; - $hash->{READINGS}{state}{TIME} = TimeNow(); - $hash->{READINGS}{state}{VAL} = $state; - } - return $ret; } @@ -475,7 +482,7 @@ CUL_HM_Set($@) sub CUL_HM_Pair(@) { - my ($name, $hash, $len,$msgcnt,$channel,$msgtype,$src,$dst,$p) = @_; + my ($name, $hash, $len,$msgcnt,$cmd,$src,$dst,$p) = @_; my $iohash = $hash->{IODev}; my $id = CUL_HM_Id($iohash); my $l4 = GetLogLevel($name,4); @@ -523,8 +530,8 @@ CUL_HM_Pair(@) return ""; } - $hash->{pairButtons} = substr($p, 30, 4); - if($hash->{pairButtons} eq "0000") { # Sender pair mode, before btn is pressed + my $pairButtons = substr($p, 30, 4); + if($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}}); @@ -540,9 +547,9 @@ CUL_HM_Pair(@) my ($mystc, $mymodel, $mybtn, $myserNr); $mymodel = "0011"; # Emulate a HM-LC-SW1-PL $mystc = "10"; # switch - $mybtn = "010100";# No buttons (?) - $myserNr = unpack('H*', "FHEM$id"); - $hash->{pairButtons} =~ m/(..)(..)/; + $mybtn = "010100";# channel 1/1 + $myserNr = unpack('H*', "FHEM$id"); + $pairButtons =~ m/(..)(..)/; my ($b1, $b2) = ($1, $2); CUL_HM_SendCmd($hash, @@ -570,7 +577,6 @@ CUL_HM_SendCmd($$$$) { my ($hash, $cmd, $sleep, $waitforack) = @_; my $io = $hash->{IODev}; - my $l4 = GetLogLevel($hash->{NAME},4); select(undef, undef, undef, 0.1*$sleep) if($sleep); @@ -588,13 +594,14 @@ CUL_HM_SendCmd($$$$) $io->{HM_CMDNR} = $mn; $cmd = sprintf("As%02X%02x%s", length($cmd2)/2+1, $mn, $cmd2); - Log $l4, "CUL_HM SEND $cmd"; IOWrite($hash, "", $cmd); if($waitforack) { $hash->{ackWaiting} = $cmd; $hash->{ackCmdSent} = 1; InternalTimer(gettimeofday()+0.4, "CUL_HM_Resend", $hash, 0); } + $cmd =~ m/As(..)(..)(....)(......)(......)(.*)/; + CUL_HM_DumpProtocol("CUL_HM SND", $io, ($1,$2,$3,$4,$5,$6)); } ################################### @@ -602,10 +609,8 @@ sub CUL_HM_PushCmdStack($$) { my ($hash, $cmd) = @_; - my $l4 = GetLogLevel($hash->{NAME},4); my @arr = (); $hash->{cmdStack} = \@arr if(!$hash->{cmdStack}); - Log $l4, $cmd; push(@{$hash->{cmdStack}}, $cmd); } @@ -634,101 +639,120 @@ sub CUL_HM_Id($) { my ($io) = @_; - return "123456" if(!$io || !$io->{FHTID}); - return "F1" . $io->{FHTID}; + return "123456" if(!$io || !defined($io->{FHTID})); + return AttrVal($io->{NAME}, "hmId", "F1".$io->{FHTID}); } my %culHmBits = ( - "8002:01:01" => { txt => "ACK_STATUS", params => { - CHANNEL => "02,2", - STATUS => "04,2", - RSSI => "08,2", } }, - "8002" => { txt => "ACK" }, - "A001:11:01" => { txt => "CONFIG_PEER_ADD", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL_A => "10,2", - PEER_CHANNEL_B => "12,2", } }, - "A001:11:03" => { txt => "CONFIG_PEER_LIST_REQ", params => { - CHANNEL => "0,2", } }, - "A001:11:04" => { txt => "CONFIG_PARAM_REQ", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL => "10,2", - PARAM_LIST => "12,2", } }, - "A001:11:05" => { txt => "CONFIG_START", params => { - CHANNEL => "00,2", - PEER_ADDRESS => "04,6", - PEER_CHANNEL => "10,2", - PARAM_LIST => "12,2", } }, - "A001:11:06" => { txt => "CONFIG_END", params => { - CHANNEL => "0,2", } }, - "A001:11:08" => { txt => "CONFIG_WRITE_INDEX", params => { - CHANNEL => "0,2", - DATA => "4,", } }, - "A001:11:0E" => { txt => "CONFIG_STATUS_REQUEST", params => { - CHANNEL => "0,2", } }, - "A010:01:01" => { txt => "INFO_PEER_LIST", params => { - PEER_ADDR1 => "02,6", PEER_CH1 => "08,2", - PEER_ADDR2 => "10,6", PEER_CH2 => "16,2", - PEER_ADDR3 => "18,6", PEER_CH3 => "24,2", - PEER_ADDR4 => "26,6", PEER_CH4 => "32,2", } }, - "A002" => { txt => "Request AES", params => { - DATA => "0," } }, - "A003" => { txt => "AES reply", params => { - DATA => "0," } }, - "A010:01:02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => { - DATA => "2,", } }, - "A010:01:03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => { - OFFSET => "2,2", - DATA => "4,", } }, - "A011:02:0400" => { txt => "RESET" }, - "A03E" => { txt => "SWITCH", params => { - DST => "00,6", - UNKNOWN => "06,2", - CHANNEL => "08,2", - COUNTER => "10,2", } }, - "A410:01:06" => { txt => "INFO_ACTUATOR_STATUS", params => { - CHANNEL => "2,2", - STATUS => "4,2", - UNKNOWN => "6,2", - RSSI => "8,2" } }, + "8000" => { txt => "DEVICE_INFO", params => { + FIRMWARE => '00,2,$val/=10', + TYPE => "02,4", + SERIALNO => '06,20,$val=pack("H*",$val)', + CLASS => "26,2", + PEER_CHANNEL_A => "28,2", + PEER_CHANNEL_B => "30,2", + UNKNOWN => "32,2", } }, + "8002;p01=01" => { txt => "ACK_STATUS", params => { + CHANNEL => "02,2", + STATUS => "04,2", + RSSI => "08,2", } }, + "8002" => { txt => "ACK" }, + "8401;p02=010A" => { txt => "PAIR_SERIAL", params => { + SERIALNO => '04,,$val=pack("H*",$val)', } }, + "A001;p11=01" => { txt => "CONFIG_PEER_ADD", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL_A => "10,2", + PEER_CHANNEL_B => "12,2", } }, + "A001;p11=03" => { txt => "CONFIG_PEER_LIST_REQ", params => { + CHANNEL => "0,2", } }, + "A001;p11=04" => { txt => "CONFIG_PARAM_REQ", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL => "10,2", + PARAM_LIST => "12,2", } }, + "A001;p11=05" => { txt => "CONFIG_START", params => { + CHANNEL => "00,2", + PEER_ADDRESS => "04,6", + PEER_CHANNEL => "10,2", + PARAM_LIST => "12,2", } }, + "A001;p11=06" => { txt => "CONFIG_END", params => { + CHANNEL => "0,2", } }, + "A001;p11=08" => { txt => "CONFIG_WRITE_INDEX", params => { + CHANNEL => "0,2", + DATA => '4,,$val =~ s/(..)(..)/ $1:$2/g', } }, + "A001;p11=0E" => { txt => "CONFIG_STATUS_REQUEST", params => { + CHANNEL => "0,2", } }, + "A002" => { txt => "Request AES", params => { + DATA => "0," } }, + "A003" => { txt => "AES reply", params => { + DATA => "0," } }, + "A010;p01=01" => { txt => "INFO_PEER_LIST", params => { + PEER_ADDR1 => "02,6", PEER_CH1 => "08,2", + PEER_ADDR2 => "10,6", PEER_CH2 => "16,2", + PEER_ADDR3 => "18,6", PEER_CH3 => "24,2", + PEER_ADDR4 => "26,6", PEER_CH4 => "32,2", } }, + "A010;p01=02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => { + DATA => "2,", } }, + "A010;p01=03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => { + OFFSET => "2,2", + DATA => "4,", } }, + "A011;p02=0400" => { txt => "RESET" }, + "A011;p01=02" => { txt => "SET" , params => { + CHANNEL => "02,2", + VALUE => "04,2", + UNKNOWN => "06,4", } }, + "A03E" => { txt => "SWITCH", params => { + DST => "00,6", + UNKNOWN => "06,2", + CHANNEL => "08,2", + COUNTER => "10,2", } }, + "A410;p01=06" => { txt => "INFO_ACTUATOR_STATUS", params => { + CHANNEL => "2,2", + STATUS => '4,2', + UNKNOWN => "6,2", + RSSI => "8,2" } }, ); sub -CUL_HM_DumpBits(@) +CUL_HM_DumpProtocol($$@) { - my ($len,$cnt,$ch,$type,$src,$dst,$p) = @_; + my ($prefix, $iohash, $len,$cnt,$cmd,$src,$dst,$p) = @_; + my $iname = $iohash->{NAME}; + my $ev = AttrVal($iname, "hmProtocolEvents", 0); + my $l4 = GetLogLevel($iname, 4); + return if(!$ev && $attr{global}{verbose} < $l4); + my $p01 = substr($p,0,2); my $p02 = substr($p,0,4); my $p11 = substr($p,2,2); - $ch = "0A" if($ch eq "0B"); - $ch = "A4" if("$ch$type" eq "8410"); + $cmd = "0A$1" if($cmd =~ m/0B(..)/); + $cmd = "A4" if("$cmd" eq "8410"); my $ps; - $ps = $culHmBits{"$ch$type:11:$p11"} if(!$ps); - $ps = $culHmBits{"$ch$type:01:$p01"} if(!$ps); - $ps = $culHmBits{"$ch$type:02:$p02"} if(!$ps); - $ps = $culHmBits{"$ch$type"} if(!$ps); + $ps = $culHmBits{"$cmd;p11=$p11"} if(!$ps); + $ps = $culHmBits{"$cmd;p01=$p01"} if(!$ps); + $ps = $culHmBits{"$cmd;p02=$p02"} if(!$ps); + $ps = $culHmBits{"$cmd"} if(!$ps); my $txt = ""; if($ps) { $txt = $ps->{txt}; if($ps->{params}) { $ps = $ps->{params}; foreach my $k (sort {$ps->{$a} cmp $ps->{$b} } keys %{$ps}) { - my ($o,$l) = split(",", $ps->{$k}); + my ($o,$l,$expr) = split(",", $ps->{$k}, 3); last if(length($p) <= $o); - if($l) { - $txt .= " $k:".substr($p,$o,$l); - } else { - $txt .= " $k:".substr($p,$o); - } + my $val = $l ? substr($p,$o,$l) : substr($p,$o); + eval $expr if($expr); + $txt .= " $k:$val"; } } $txt = " ($txt)" if($txt); } - Log 1, "CUL_HM L:$len N:$cnt C:$ch T:$type SRC:$src DST:$dst $p$txt"; + my $msg = "$prefix L:$len N:$cnt CMD:$cmd SRC:$src DST:$dst $p$txt"; + Log $l4, $msg; + DoTrigger($iname, $msg) if($ev); } my @culHmTimes = ( 0.1, 1, 5, 10, 60, 300, 600, 3600 ); diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index 3156bd0db..709a7e2ba 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -1258,8 +1258,8 @@ A line ending with \ will be concatenated with the next one, so long lines attr store eventMap on:open off:closed
set store open - The code applies to all set commands, events and to the device state, - but not to the other device READINGS. + The attribute applies to all set commands, events and to the device + state, but not to the other device READINGS.
  • do_not_notify

  • @@ -2033,6 +2033,17 @@ A line ending with \ will be concatenated with the next one, so long lines
    +
  • hmId
    + Set the HomeMatic ID of this device. If this attribute is absent, the + ID will be F1<housecode>. Note 1: after setting or changing this + attribute you have to relearn all your HomeMatic devices. Note 2: the + value _must_ be a 6 digit hex number, and 000000 is not valid. fhem + wont complain if it is not correct, but the communication won't work. +

  • + +
  • hmProtocolEvents
    + Generate events for HomeMatic protocol messages. +


  • @@ -2182,7 +2193,23 @@ A line ending with \ will be concatenated with the next one, so long lines Set
      - Depends on the subType (i.e family) of the device. + General commands (available to all hm devices): +
        +
      • raw <data> ...
        + Only needed for experimentation. + send a list of "raw" commands. The first command will be immediately + sent, the next one after the previous one is acked by the target. The + length will be computed automatically, and the message counter will be + incremented if the first tw charcters are ++. + Example (enable AES):
        +         set hm1 raw ++A001F100001234560105000000001\
        +                     ++A001F10000123456010802010AF10B000C00\
        +                     ++A001F1000012345601080801\
        +                     ++A001F100001234560106
        +         
      • +
      + subType (i.e family) dependent commands: +
      • switch
        • on - set the switch on
        • @@ -2207,6 +2234,7 @@ A line ending with \ will be concatenated with the next one, so long lines set 4Dis text 1 off Kitchen Off
      +

    diff --git a/fhem/fhem.pl b/fhem/fhem.pl index 18cd3be74..38a0ce0dc 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -44,6 +44,7 @@ sub AnalyzeCommand($$); sub AnalyzeCommandChain($$); sub AnalyzeInput($); sub AssignIoPort($); +sub AttrVal($$$); sub addToAttrList($); sub CallFn(@); sub CommandChain($$); @@ -163,7 +164,7 @@ my $nextat; # Time when next timer will be triggered. my $intAtCnt=0; my %duplicate; # Pool of received msg for multi-fhz/cul setups my $duplidx=0; # helper for the above pool -my $cvsid = '$Id: fhem.pl,v 1.120 2010-12-27 09:42:16 rudolfkoenig Exp $'; +my $cvsid = '$Id: fhem.pl,v 1.121 2011-01-02 14:45:53 rudolfkoenig Exp $'; my $namedef = "where is either:\n" . "- a single device name\n" .