diff --git a/FHEM/00_TCM120.pm b/FHEM/00_TCM120.pm index 01d206272..f6ecf5a36 100755 --- a/FHEM/00_TCM120.pm +++ b/FHEM/00_TCM120.pm @@ -29,6 +29,11 @@ TCM120_Initialize($) $hash->{ReadFn} = "TCM120_Read"; $hash->{WriteFn} = "TCM120_Write"; $hash->{ReadyFn} = "TCM120_Ready"; + $hash->{Clients} = ":EnOcean:"; + my %matchList= ( + "1:EnOcean" => "^EnOcean:0B", + ); + $hash->{MatchList} = \%matchList; # Normal devices $hash->{DefFn} = "TCM120_Define"; @@ -134,8 +139,8 @@ TCM120_Read($) Log $ll5, "$name: wrong checksum: got $crc, computed $mycrc" ; return; } - if($net =~ m/^0b/) { # Receive Radio Telegram (RRT) - Dispatch($hash, $net, undef); + if($net =~ m/^0B/) { # Receive Radio Telegram (RRT) + Dispatch($hash, "EnOcean:$net", undef); } else { # Receive Message Telegram (RMT) TCM120_Parse($hash, $net, 0); } @@ -187,7 +192,7 @@ TCM120_Parse($$$) my $cmd = $parsetbl{substr($rawmsg, 0, 4)}; if(!$cmd) { - $msg ="$name, Unknown command: $rawmsg"; + $msg ="Unknown command: $rawmsg"; } else { if($cmd->{expr}) { @@ -198,6 +203,7 @@ TCM120_Parse($$$) $msg .= eval $cmd->{expr}; } else { + return "" if($cmd ->{msg} eq "OK" && !$ret); # SKIP Ok $msg = $cmd->{msg}; } diff --git a/FHEM/10_EnOcean.pm b/FHEM/10_EnOcean.pm new file mode 100755 index 000000000..42a67c67f --- /dev/null +++ b/FHEM/10_EnOcean.pm @@ -0,0 +1,201 @@ +############################################## +# CUL HomeMatic handler +package main; + +use strict; +use warnings; + +sub EnOcean_Define($$); +sub EnOcean_Initialize($); +sub EnOcean_Pair(@); +sub EnOcean_Parse($$); +sub EnOcean_PushCmdStack($$); +sub EnOcean_SendCmd($$$$); +sub EnOcean_Set($@); +sub EnOcean_convTemp($); + +sub +EnOcean_Initialize($) +{ + my ($hash) = @_; + + $hash->{Match} = "^EnOcean:0B"; + $hash->{DefFn} = "EnOcean_Define"; + $hash->{ParseFn} = "EnOcean_Parse"; + $hash->{SetFn} = "EnOcean_Set"; + $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 " . + "showtime:1,0 loglevel:0,1,2,3,4,5,6 model " . + "subType:remote,sensor,modem "; +} + + +############################# +sub +EnOcean_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $name = $hash->{NAME}; + + return "wrong syntax: define EnOcean 8-digit-hex-code" + if(int(@a)!=3 || $a[2] !~ m/^[A-F0-9]{8}$/i); + + $modules{EnOcean}{defptr}{uc($a[2])} = $hash; + AssignIoPort($hash); + # Help FHEMWEB split up davices + $attr{$name}{subType} = $1 if($name =~ m/EnO_(.*)_$a[2]/); + return undef; +} + + +my %sets = ( Btn0=>"10:30", Btn1=>"30:30", Btn2=>"20:30", Btn2=>"70:30", + "Btn0,Btn2"=>"15:30", "Btn1,Btn2"=>"35:30", + "Btn0,Btn3"=>"17:30", "Btn1,Btn3"=>"37:30", + "released"=>"00:20" ); + +############################# +# Simulate a PTM +sub +EnOcean_Set($@) +{ + my ($hash, @a) = @_; + return "no set value specified" if(@a != 2); + + my $cmd = $a[1]; + my $arg = $a[2]; + my $cmdhash = $sets{$cmd}; + return "Unknown argument $cmd, choose one of " . join(" ", sort keys %sets) + if(!defined($cmdhash)); + + my $name = $hash->{NAME}; + my $ll2 = GetLogLevel($name, 2); + Log $ll2, "EnOcean: set $name $cmd"; + + my ($d1, $status) = split(":", $cmdhash, 2); + IOWrite($hash, "", sprintf("6B05%s000000%s%s", $d1, $hash->{DEF}, $status)); + + my $tn = TimeNow(); + $hash->{CHANGED}[0] = $cmd; + $hash->{STATE} = $cmd; + $hash->{READINGS}{state}{TIME} = $tn; + $hash->{READINGS}{state}{VAL} = $cmd; + return undef; +} + +############################# +sub +EnOcean_Parse($$) +{ + my ($iohash, $msg) = @_; + my %ot = ("05"=>"remote", "06"=>"sensor", "07"=>"sensor", + "08"=>"remote", "0A"=>"modem", "0B"=>"modem", ); + + $msg =~ m/^EnOcean:0B(..)(........)(........)(..)/; + my ($org,$data,$id,$status) = ($1,$2,$3,$4,$5); + + my $ot = $ot{$org}; + if(!$ot) { + Log 2, "Unknown EnOcean ORG: $org received from $id"; + return ""; + } + + $id = ($id & 0xffff) if($org eq "0A"); + $id = (($id & 0xffff0000)>>16) if($org eq "0B"); + + my $hash = $modules{EnOcean}{defptr}{$id}; + if(!$hash) { + Log 3, "EnOcean Unknown device with ID $id, please define it"; + return "UNDEFINED EnO_${ot}_$id EnOcean $id"; + } + + my $name = $hash->{NAME}; + my $ll4 = GetLogLevel($name, 4); + Log $ll4, "EnOcean: ORG:$org, DATA:$data, ID:$id, STATUS:$status"; + my @event; + + push @event, "0:rp_counter:".(hex($status)&0xf); + + my $d1 = hex substr($data,0,2); + + ################################# + if($org eq "05") { # PTM remote. Queer reporting methods. + my $nu = ((hex($status)&0x10)>>4); + + push @event, "0:T21:".((hex($status)&0x20)>>5); + push @event, "0:NU:$nu"; + + if($nu) { + $msg = sprintf "Btn%d", ($d1&0xe0)>>5; + $msg .= sprintf ",Btn%d", ($d1&0x0e)>>1 if($d1 & 1); + + } else { + #confusing for normal use + #my $nbu = (($d1&0xe0)>>5); + #$msg = sprintf "Buttons %d", $nbu ? ($nbu+1) : 0; + $msg = "buttons"; + + } + $msg .= ($d1&0x10) ? " pressed" : " released"; + push @event, "1:state:$msg"; + + ################################# + } elsif($org eq "06") { + push @event, "1:state:$d1"; + push @event, "1:sensor1:$d1"; + + ################################# + } elsif($org eq "07") { + my $d2 = hex substr($data,2,2); + my $d3 = hex substr($data,4,2); + my $d4 = hex substr($data,6,2); + push @event, "1:state:$d1"; + push @event, "1:sensor1:$d1"; + push @event, "1:sensor2:$d2"; + push @event, "1:sensor3:$d3"; + push @event, "1:D3:".($d4&0x8)?1:0; + push @event, "1:D2:".($d4&0x4)?1:0; + push @event, "1:D1:".($d4&0x2)?1:0; + push @event, "1:D0:".($d4&0x1)?1:0; + + ################################# + } elsif($org eq "08") { # CTM remote. + # Dont understand the SR bit + $msg = sprintf "Btn%d", ($d1&0xe0)>>5; + $msg .= ($d1&0x10) ? " pressed" : " released"; + push @event, "1:state:$msg"; + + ################################# + } elsif($org eq "0A") { + push @event, "1:state:Modem:".substr($msg, 12, 6); + + ################################# + } elsif($org eq "0B") { + push @event, "1:state:Modem:ACK"; + + } + + my $tn = TimeNow(); + my @changed; + for(my $i = 0; $i < int(@event); $i++) { + my ($dochanged, $vn, $vv) = split(":", $event[$i], 3); + + if($dochanged) { + if($vn eq "state") { + $hash->{STATE} = $vv; + push @changed, $vv; + + } else { + push @changed, "$vn: $vv"; + + } + } + + $hash->{READINGS}{$vn}{TIME} = TimeNow(); + $hash->{READINGS}{$vn}{VAL} = $vv; + } + $hash->{CHANGED} = \@changed; + + return $name; +} + +1; diff --git a/docs/commandref.html b/docs/commandref.html index fe95e1399..3269cbb3f 100644 --- a/docs/commandref.html +++ b/docs/commandref.html @@ -86,6 +86,7 @@ ECMD   ECMDDevice   DS18S20   + EnOcean   EM   EMEM   EMGZ   @@ -2720,6 +2721,84 @@ A line ending with \ will be concatenated with the next one, so long lines
+ +

EnOcean

+ +

EM