CUL_HM: set rewrite. Note: temporarily there is no device ack event.

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@788 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2011-01-02 14:45:53 +00:00
parent 010857723c
commit 7d9dd7a94f
4 changed files with 252 additions and 198 deletions

View File

@ -88,7 +88,7 @@ CUL_Initialize($)
$hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 " . $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 " . "showtime:1,0 model:CUL,CUN,CUR loglevel:0,1,2,3,4,5,6 " .
"fhtsoftbuffer:1,0 sendpool addvaltrigger " . "fhtsoftbuffer:1,0 sendpool addvaltrigger " .
"rfmode:SlowRF,HomeMatic"; "rfmode:SlowRF,HomeMatic hmId hmProtocolEvents";
$hash->{ShutdownFn} = "CUL_Shutdown"; $hash->{ShutdownFn} = "CUL_Shutdown";
} }
@ -215,12 +215,13 @@ CUL_Set($@)
InternalTimer(gettimeofday()+$arg, "CUL_RemoveHMPair", $hash, 1); InternalTimer(gettimeofday()+$arg, "CUL_RemoveHMPair", $hash, 1);
} elsif($type eq "hmPairSerial") { ################################ } 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}$/); 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; $hash->{HM_CMDNR} = $hash->{HM_CMDNR} ? ($hash->{HM_CMDNR}+1)%256 : 1;
CUL_SimpleWrite($hash, sprintf("As15%02x8401F1%s000000010A%s", CUL_SimpleWrite($hash, sprintf("As15%02x8401%s000000010A%s",
$hash->{HM_CMDNR}, $hash->{FHTID}, unpack('H*', $arg))); $hash->{HM_CMDNR}, $id, unpack('H*', $arg)));
$hash->{hmPairSerial} = $arg; $hash->{hmPairSerial} = $arg;
@ -926,7 +927,7 @@ CUL_SimpleWrite(@)
# Prefix $msg with RRBBU and return the corresponding CUL hash. # Prefix $msg with RRBBU and return the corresponding CUL hash.
($hash, $msg) = CUL_RFR_AddPrefix($hash, $msg); ($hash, $msg) = CUL_RFR_AddPrefix($hash, $msg);
} }
Log 1, "SW: $msg"; #Log 1, "SW: $msg";
$msg .= "\n" unless($nonl); $msg .= "\n" unless($nonl);
$hash->{USBDev}->write($msg . "\n") if($hash->{USBDev}); $hash->{USBDev}->write($msg . "\n") if($hash->{USBDev});

View File

@ -13,7 +13,7 @@ sub CUL_HM_Parse($$);
sub CUL_HM_PushCmdStack($$); sub CUL_HM_PushCmdStack($$);
sub CUL_HM_SendCmd($$$$); sub CUL_HM_SendCmd($$$$);
sub CUL_HM_Set($@); sub CUL_HM_Set($@);
sub CUL_HM_DumpBits(@); sub CUL_HM_DumpProtocol($$@);
my %culHmDevProps=( my %culHmDevProps=(
"10" => { st => "switch", cl => "receiver" }, # Parse,Set "10" => { st => "switch", cl => "receiver" }, # Parse,Set
@ -162,14 +162,13 @@ CUL_HM_Parse($$)
my $id = CUL_HM_Id($iohash); my $id = CUL_HM_Id($iohash);
# Msg format: Allnnccttssssssddddddpp... # Msg format: Allnnccttssssssddddddpp...
$msg =~ m/A(..)(..)(..)(..)(......)(......)(.*)/; $msg =~ m/A(..)(..)(....)(......)(......)(.*)/;
my @msgarr = ($1,$2,$3,$4,$5,$6,$7); my @msgarr = ($1,$2,$3,$4,$5,$6,$7);
my ($len,$msgcnt,$channel,$msgtype,$src,$dst,$p) = @msgarr; my ($len,$msgcnt,$cmd,$src,$dst,$p) = @msgarr;
CUL_HM_DumpBits(@msgarr); CUL_HM_DumpProtocol("CUL_HM RCV", $iohash, @msgarr);
my $shash = $modules{CUL_HM}{defptr}{$src}; my $shash = $modules{CUL_HM}{defptr}{$src};
my $cm = "$channel$msgtype"; my $lcm = "$len$cmd";
my $lcm = "$len$channel$msgtype";
my $dhash = $modules{CUL_HM}{defptr}{$dst}; my $dhash = $modules{CUL_HM}{defptr}{$dst};
my $dname = $dhash ? $dhash->{NAME} : "unknown"; my $dname = $dhash ? $dhash->{NAME} : "unknown";
@ -205,27 +204,21 @@ CUL_HM_Parse($$)
if($lcm eq "1A8400" || $lcm eq "1A8000") { #### Pairing-Request if($lcm eq "1A8400" || $lcm eq "1A8000") { #### Pairing-Request
push @event, CUL_HM_Pair($name, $shash, @msgarr); 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 CUL_HM_SendCmd($shash, $msgcnt."8002".$id.$src."00", 1, 0); # Ack
push @event, ""; push @event, "";
} elsif($lcm eq "11A002") { # signing experiments } elsif($cmd eq "8002") { # Ack
push @event, "signRequest:$p";
} elsif($lcm eq "19A003") { # signing experiments if($shash->{cmdStack}) { # Send next msg from the stack
push @event, "signAnswer:$p"; 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, ""; push @event, "";
} elsif($st eq "switch" || ############################################ } elsif($st eq "switch" || ############################################
@ -238,14 +231,13 @@ CUL_HM_Parse($$)
$val = ($val == 100 ? "on" : ($val == 0 ? "off" : "$val %")); $val = ($val == 100 ? "on" : ($val == 0 ? "off" : "$val %"));
my $msg = "unknown"; my $msg = "unknown";
$msg = "deviceMsg" if($lt =~ m/0.01/); $msg = "deviceMsg" if($lt =~ m/0.01/);
$msg = "powerOn" if($lt =~ m/0600/);
push @event, "$msg:$val"; push @event, "$msg:$val";
push @event, "state:$val" if(!$isack); push @event, "state:$val" if(!$isack);
} }
} elsif($st eq "remote") { ############################################ } elsif($st eq "remote") { ############################################
if($cm =~ m/^..4./ && $p =~ m/^(..)(..)$/) { if($cmd =~ m/^..4./ && $p =~ m/^(..)(..)$/) {
my ($button, $bno) = (hex($1), hex($2)); my ($button, $bno) = (hex($1), hex($2));
my $btn = int((($button&0x3f)+1)/2); my $btn = int((($button&0x3f)+1)/2);
@ -258,9 +250,6 @@ CUL_HM_Parse($$)
($state =~ m/on/?"C8":"00")."0028", 1, 0); ($state =~ m/on/?"C8":"00")."0028", 1, 0);
} }
} elsif($p =~ m/0600/) {
push @event, "powerOn:$p";
} }
} elsif($st eq "smokeDetector") { ##################################### } 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(); my $tn = TimeNow();
for(my $i = 0; $i < int(@event); $i++) { for(my $i = 0; $i < int(@event); $i++) {
@ -342,6 +331,19 @@ CUL_HM_Parse($$)
return $name; 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 => "<btn> [on|off] <txt1> <txt2>" },
);
################################### ###################################
sub sub
CUL_HM_Set($@) CUL_HM_Set($@)
@ -352,104 +354,109 @@ CUL_HM_Set($@)
return "no set value specified" if(@a < 2); return "no set value specified" if(@a < 2);
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $st = AttrVal($name, "subType", undef); my $st = AttrVal($name, "subType", "");
my $cmd = $a[1]; 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 $sndcmd;
my $state;
if($cmd eq "raw") { ################################################## if($cmd eq "raw") { ##################################################
return "Usage: set $a[0] $cmd rowdata" if(@a != 3); return "Usage: set $a[0] $cmd data [data ...]" if(@a < 3);
CUL_HM_SendCmd($hash, $a[2], 0, 1); $sndcmd = $a[2];
return ""; for (my $i = 3; $i < @a; $i++) {
CUL_HM_PushCmdStack($hash, $a[$i]);
} 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);
} }
} elsif($st eq "dimmer" || ############################################ } elsif($cmd eq "reset") { ############################################
$st eq "blindActuator") { $sndcmd = sprintf("++A011%s%s0400", $id,$hash->{DEF});
my %scmd = (on => "C8", off => "00"); } elsif($cmd eq "pair") { #############################################
if($scmd{$cmd}) { my $serialNr = AttrVal($name, "serialNr", undef);
$state = $cmd; return "serialNr is not set" if(!$serialNr);
$sndcmd = sprintf("++A011%s%s0201%s0000", $id,$hash->{DEF}, $scmd{$cmd}); $sndcmd = sprintf("++8401%s000000010A%s", $id, unpack("H*",$serialNr));
$hash->{hmPairSerial} = $serialNr;
} elsif($cmd =~ m/^\d+/ && $cmd >= 0 && $cmd <= 100) { } elsif($cmd eq "statusRequest") { ####################################
$state = "$cmd %"; $sndcmd = sprintf("++A001%s%s010E", $id,$hash->{DEF});
$sndcmd = sprintf("++A011%s%s0201%02X0000", $id, $hash->{DEF}, $cmd*2);
} else { } elsif($cmd eq "on") { ###############################################
my @scmd = ("on", "off", 0..100); $sndcmd = sprintf("++A011%s%s0201C80000", $id,$hash->{DEF});
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 <btn> [on|off] <txt1> <txt2>" 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 "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); CUL_HM_SendCmd($hash, $sndcmd, 0, 1);
if($state) {
$hash->{STATE} = $state;
$hash->{READINGS}{state}{TIME} = TimeNow();
$hash->{READINGS}{state}{VAL} = $state;
}
return $ret; return $ret;
} }
@ -475,7 +482,7 @@ CUL_HM_Set($@)
sub sub
CUL_HM_Pair(@) 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 $iohash = $hash->{IODev};
my $id = CUL_HM_Id($iohash); my $id = CUL_HM_Id($iohash);
my $l4 = GetLogLevel($name,4); my $l4 = GetLogLevel($name,4);
@ -523,8 +530,8 @@ CUL_HM_Pair(@)
return ""; return "";
} }
$hash->{pairButtons} = substr($p, 30, 4); my $pairButtons = substr($p, 30, 4);
if($hash->{pairButtons} eq "0000") { # Sender pair mode, before btn is pressed if($pairButtons eq "0000") { # Sender pair mode, before btn is pressed
if($hash->{cmdStack}) { if($hash->{cmdStack}) {
CUL_HM_SendCmd($hash, shift @{$hash->{cmdStack}}, 1, 1); CUL_HM_SendCmd($hash, shift @{$hash->{cmdStack}}, 1, 1);
delete($hash->{cmdStack}) if(!@{$hash->{cmdStack}}); delete($hash->{cmdStack}) if(!@{$hash->{cmdStack}});
@ -540,9 +547,9 @@ CUL_HM_Pair(@)
my ($mystc, $mymodel, $mybtn, $myserNr); my ($mystc, $mymodel, $mybtn, $myserNr);
$mymodel = "0011"; # Emulate a HM-LC-SW1-PL $mymodel = "0011"; # Emulate a HM-LC-SW1-PL
$mystc = "10"; # switch $mystc = "10"; # switch
$mybtn = "010100";# No buttons (?) $mybtn = "010100";# channel 1/1
$myserNr = unpack('H*', "FHEM$id"); $myserNr = unpack('H*', "FHEM$id");
$hash->{pairButtons} =~ m/(..)(..)/; $pairButtons =~ m/(..)(..)/;
my ($b1, $b2) = ($1, $2); my ($b1, $b2) = ($1, $2);
CUL_HM_SendCmd($hash, CUL_HM_SendCmd($hash,
@ -570,7 +577,6 @@ CUL_HM_SendCmd($$$$)
{ {
my ($hash, $cmd, $sleep, $waitforack) = @_; my ($hash, $cmd, $sleep, $waitforack) = @_;
my $io = $hash->{IODev}; my $io = $hash->{IODev};
my $l4 = GetLogLevel($hash->{NAME},4);
select(undef, undef, undef, 0.1*$sleep) if($sleep); select(undef, undef, undef, 0.1*$sleep) if($sleep);
@ -588,13 +594,14 @@ CUL_HM_SendCmd($$$$)
$io->{HM_CMDNR} = $mn; $io->{HM_CMDNR} = $mn;
$cmd = sprintf("As%02X%02x%s", length($cmd2)/2+1, $mn, $cmd2); $cmd = sprintf("As%02X%02x%s", length($cmd2)/2+1, $mn, $cmd2);
Log $l4, "CUL_HM SEND $cmd";
IOWrite($hash, "", $cmd); IOWrite($hash, "", $cmd);
if($waitforack) { if($waitforack) {
$hash->{ackWaiting} = $cmd; $hash->{ackWaiting} = $cmd;
$hash->{ackCmdSent} = 1; $hash->{ackCmdSent} = 1;
InternalTimer(gettimeofday()+0.4, "CUL_HM_Resend", $hash, 0); 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($$) CUL_HM_PushCmdStack($$)
{ {
my ($hash, $cmd) = @_; my ($hash, $cmd) = @_;
my $l4 = GetLogLevel($hash->{NAME},4);
my @arr = (); my @arr = ();
$hash->{cmdStack} = \@arr if(!$hash->{cmdStack}); $hash->{cmdStack} = \@arr if(!$hash->{cmdStack});
Log $l4, $cmd;
push(@{$hash->{cmdStack}}, $cmd); push(@{$hash->{cmdStack}}, $cmd);
} }
@ -634,101 +639,120 @@ sub
CUL_HM_Id($) CUL_HM_Id($)
{ {
my ($io) = @_; my ($io) = @_;
return "123456" if(!$io || !$io->{FHTID}); return "123456" if(!$io || !defined($io->{FHTID}));
return "F1" . $io->{FHTID}; return AttrVal($io->{NAME}, "hmId", "F1".$io->{FHTID});
} }
my %culHmBits = ( my %culHmBits = (
"8002:01:01" => { txt => "ACK_STATUS", params => { "8000" => { txt => "DEVICE_INFO", params => {
CHANNEL => "02,2", FIRMWARE => '00,2,$val/=10',
STATUS => "04,2", TYPE => "02,4",
RSSI => "08,2", } }, SERIALNO => '06,20,$val=pack("H*",$val)',
"8002" => { txt => "ACK" }, CLASS => "26,2",
"A001:11:01" => { txt => "CONFIG_PEER_ADD", params => { PEER_CHANNEL_A => "28,2",
CHANNEL => "00,2", PEER_CHANNEL_B => "30,2",
PEER_ADDRESS => "04,6", UNKNOWN => "32,2", } },
PEER_CHANNEL_A => "10,2", "8002;p01=01" => { txt => "ACK_STATUS", params => {
PEER_CHANNEL_B => "12,2", } }, CHANNEL => "02,2",
"A001:11:03" => { txt => "CONFIG_PEER_LIST_REQ", params => { STATUS => "04,2",
CHANNEL => "0,2", } }, RSSI => "08,2", } },
"A001:11:04" => { txt => "CONFIG_PARAM_REQ", params => { "8002" => { txt => "ACK" },
CHANNEL => "00,2", "8401;p02=010A" => { txt => "PAIR_SERIAL", params => {
PEER_ADDRESS => "04,6", SERIALNO => '04,,$val=pack("H*",$val)', } },
PEER_CHANNEL => "10,2", "A001;p11=01" => { txt => "CONFIG_PEER_ADD", params => {
PARAM_LIST => "12,2", } }, CHANNEL => "00,2",
"A001:11:05" => { txt => "CONFIG_START", params => { PEER_ADDRESS => "04,6",
CHANNEL => "00,2", PEER_CHANNEL_A => "10,2",
PEER_ADDRESS => "04,6", PEER_CHANNEL_B => "12,2", } },
PEER_CHANNEL => "10,2", "A001;p11=03" => { txt => "CONFIG_PEER_LIST_REQ", params => {
PARAM_LIST => "12,2", } }, CHANNEL => "0,2", } },
"A001:11:06" => { txt => "CONFIG_END", params => { "A001;p11=04" => { txt => "CONFIG_PARAM_REQ", params => {
CHANNEL => "0,2", } }, CHANNEL => "00,2",
"A001:11:08" => { txt => "CONFIG_WRITE_INDEX", params => { PEER_ADDRESS => "04,6",
CHANNEL => "0,2", PEER_CHANNEL => "10,2",
DATA => "4,", } }, PARAM_LIST => "12,2", } },
"A001:11:0E" => { txt => "CONFIG_STATUS_REQUEST", params => { "A001;p11=05" => { txt => "CONFIG_START", params => {
CHANNEL => "0,2", } }, CHANNEL => "00,2",
"A010:01:01" => { txt => "INFO_PEER_LIST", params => { PEER_ADDRESS => "04,6",
PEER_ADDR1 => "02,6", PEER_CH1 => "08,2", PEER_CHANNEL => "10,2",
PEER_ADDR2 => "10,6", PEER_CH2 => "16,2", PARAM_LIST => "12,2", } },
PEER_ADDR3 => "18,6", PEER_CH3 => "24,2", "A001;p11=06" => { txt => "CONFIG_END", params => {
PEER_ADDR4 => "26,6", PEER_CH4 => "32,2", } }, CHANNEL => "0,2", } },
"A002" => { txt => "Request AES", params => { "A001;p11=08" => { txt => "CONFIG_WRITE_INDEX", params => {
DATA => "0," } }, CHANNEL => "0,2",
"A003" => { txt => "AES reply", params => { DATA => '4,,$val =~ s/(..)(..)/ $1:$2/g', } },
DATA => "0," } }, "A001;p11=0E" => { txt => "CONFIG_STATUS_REQUEST", params => {
"A010:01:02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => { CHANNEL => "0,2", } },
DATA => "2,", } }, "A002" => { txt => "Request AES", params => {
"A010:01:03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => { DATA => "0," } },
OFFSET => "2,2", "A003" => { txt => "AES reply", params => {
DATA => "4,", } }, DATA => "0," } },
"A011:02:0400" => { txt => "RESET" }, "A010;p01=01" => { txt => "INFO_PEER_LIST", params => {
"A03E" => { txt => "SWITCH", params => { PEER_ADDR1 => "02,6", PEER_CH1 => "08,2",
DST => "00,6", PEER_ADDR2 => "10,6", PEER_CH2 => "16,2",
UNKNOWN => "06,2", PEER_ADDR3 => "18,6", PEER_CH3 => "24,2",
CHANNEL => "08,2", PEER_ADDR4 => "26,6", PEER_CH4 => "32,2", } },
COUNTER => "10,2", } }, "A010;p01=02" => { txt => "INFO_PARAM_RESPONSE_PAIRS", params => {
"A410:01:06" => { txt => "INFO_ACTUATOR_STATUS", params => { DATA => "2,", } },
CHANNEL => "2,2", "A010;p01=03" => { txt => "INFO_PARAM_RESPONSE_SEQ", params => {
STATUS => "4,2", OFFSET => "2,2",
UNKNOWN => "6,2", DATA => "4,", } },
RSSI => "8,2" } }, "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 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 $p01 = substr($p,0,2);
my $p02 = substr($p,0,4); my $p02 = substr($p,0,4);
my $p11 = substr($p,2,2); my $p11 = substr($p,2,2);
$ch = "0A" if($ch eq "0B"); $cmd = "0A$1" if($cmd =~ m/0B(..)/);
$ch = "A4" if("$ch$type" eq "8410"); $cmd = "A4" if("$cmd" eq "8410");
my $ps; my $ps;
$ps = $culHmBits{"$ch$type:11:$p11"} if(!$ps); $ps = $culHmBits{"$cmd;p11=$p11"} if(!$ps);
$ps = $culHmBits{"$ch$type:01:$p01"} if(!$ps); $ps = $culHmBits{"$cmd;p01=$p01"} if(!$ps);
$ps = $culHmBits{"$ch$type:02:$p02"} if(!$ps); $ps = $culHmBits{"$cmd;p02=$p02"} if(!$ps);
$ps = $culHmBits{"$ch$type"} if(!$ps); $ps = $culHmBits{"$cmd"} if(!$ps);
my $txt = ""; my $txt = "";
if($ps) { if($ps) {
$txt = $ps->{txt}; $txt = $ps->{txt};
if($ps->{params}) { if($ps->{params}) {
$ps = $ps->{params}; $ps = $ps->{params};
foreach my $k (sort {$ps->{$a} cmp $ps->{$b} } keys %{$ps}) { 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); last if(length($p) <= $o);
if($l) { my $val = $l ? substr($p,$o,$l) : substr($p,$o);
$txt .= " $k:".substr($p,$o,$l); eval $expr if($expr);
} else { $txt .= " $k:$val";
$txt .= " $k:".substr($p,$o);
}
} }
} }
$txt = " ($txt)" if($txt); $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 ); my @culHmTimes = ( 0.1, 1, 5, 10, 60, 300, 600, 3600 );

View File

@ -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<br> attr store eventMap on:open off:closed<br>
set store open set store open
</code></ul> </code></ul>
The code applies to all set commands, events and to the device state, The attribute applies to all set commands, events and to the device
but not to the other device READINGS. state, but not to the other device READINGS.
</li><br> </li><br>
<li><a href="#do_not_notify">do_not_notify</a></li><br> <li><a href="#do_not_notify">do_not_notify</a></li><br>
@ -2033,6 +2033,17 @@ A line ending with \ will be concatenated with the next one, so long lines
</ul> </ul>
</li><br> </li><br>
<li><a name="hmId">hmId</a><br>
Set the HomeMatic ID of this device. If this attribute is absent, the
ID will be F1&lt;housecode&gt;. 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.
</li><br>
<li><a name="hmProtocolEvents">hmProtocolEvents</a><br>
Generate events for HomeMatic protocol messages.
</li><br>
</ul> </ul>
<br> <br>
</ul> </ul>
@ -2182,7 +2193,23 @@ A line ending with \ will be concatenated with the next one, so long lines
<a name="CUL_HMset"></a> <a name="CUL_HMset"></a>
<b>Set</b> <b>Set</b>
<ul> <ul>
Depends on the subType (i.e family) of the device. General commands (available to all hm devices):
<ul>
<li>raw &lt;data&gt; ...<br>
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):<pre>
set hm1 raw ++A001F100001234560105000000001\
++A001F10000123456010802010AF10B000C00\
++A001F1000012345601080801\
++A001F100001234560106<pre>
</li>
</ul>
subType (i.e family) dependent commands:
<ul>
<li>switch <li>switch
<ul> <ul>
<li>on - set the switch on</li> <li>on - set the switch on</li>
@ -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<br> set 4Dis text 1 off Kitchen Off<br>
</ul> </ul>
</ul></li> </ul></li>
</ul>
</ul><br> </ul><br>
<a name="CUL_HMget"></a> <a name="CUL_HMget"></a>

View File

@ -44,6 +44,7 @@ sub AnalyzeCommand($$);
sub AnalyzeCommandChain($$); sub AnalyzeCommandChain($$);
sub AnalyzeInput($); sub AnalyzeInput($);
sub AssignIoPort($); sub AssignIoPort($);
sub AttrVal($$$);
sub addToAttrList($); sub addToAttrList($);
sub CallFn(@); sub CallFn(@);
sub CommandChain($$); sub CommandChain($$);
@ -163,7 +164,7 @@ my $nextat; # Time when next timer will be triggered.
my $intAtCnt=0; my $intAtCnt=0;
my %duplicate; # Pool of received msg for multi-fhz/cul setups my %duplicate; # Pool of received msg for multi-fhz/cul setups
my $duplidx=0; # helper for the above pool 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 = my $namedef =
"where <name> is either:\n" . "where <name> is either:\n" .
"- a single device name\n" . "- a single device name\n" .