diff --git a/fhem/FHEM/10_EnOcean.pm b/fhem/FHEM/10_EnOcean.pm index df056ce66..8ec0053bd 100755 --- a/fhem/FHEM/10_EnOcean.pm +++ b/fhem/FHEM/10_EnOcean.pm @@ -1,10 +1,5 @@ ############################################## # $Id$ -# 2013-02-12 klaus.schauer -# new attr switchMode: released will sent after switch if attr set to pushbutton -# Eltako FSG70: only commands on|off possible, special query inserted -# Eltako FTN14: switch type "Staircase off-delay timer" defined [Eltako FTN14] -# commandref: further explanations added and text reorganized. package main; @@ -18,15 +13,15 @@ sub EnOcean_Parse($$); sub EnOcean_Set($@); sub EnOcean_MD15Cmd($$$); -my %EnO_rorgname = ("F6"=>"switch", # RPS - "D5"=>"contact", # 1BS - "A5"=>"sensor", # 4BS +my %EnO_rorgname = ("F6"=>"switch", # org 05, RPS + "D5"=>"contact", # org 06, 1BS + "A5"=>"sensor", # org 07, 4BS ); my @EnO_ptm200btn = ("AI", "A0", "BI", "B0", "CI", "C0", "DI", "D0"); my %EnO_ptm200btn; # Some Manufacturers (e.g. Jaeger Direkt) also sell EnOcean products without an -# intry in the table below. This table is only needed for A5 category devices +# entry in the table below. This table is only needed for A5 category devices. my %EnO_manuf = ( "001" => "Peha", "002" => "Thermokon", @@ -56,10 +51,80 @@ my %EnO_manuf = ( "01A" => "Res.", "01B" => "Lutuo Technology", "01C" => "CAN2GO", + "7FF" => "Multi user Manufacturer ID", ); my %EnO_subType = ( + "A5.02.01" => "tempSensor.01", + "A5.02.02" => "tempSensor.02", + "A5.02.03" => "tempSensor.03", + "A5.02.04" => "tempSensor.04", + "A5.02.05" => "tempSensor.05", + "A5.02.06" => "tempSensor.06", + "A5.02.07" => "tempSensor.07", + "A5.02.08" => "tempSensor.08", + "A5.02.09" => "tempSensor.09", + "A5.02.0A" => "tempSensor.0A", + "A5.02.0B" => "tempSensor.0B", + "A5.02.10" => "tempSensor.10", + "A5.02.11" => "tempSensor.11", + "A5.02.12" => "tempSensor.12", + "A5.02.13" => "tempSensor.13", + "A5.02.14" => "tempSensor.14", + "A5.02.15" => "tempSensor.15", + "A5.02.16" => "tempSensor.16", + "A5.02.17" => "tempSensor.17", + "A5.02.18" => "tempSensor.18", + "A5.02.19" => "tempSensor.19", + "A5.02.1A" => "tempSensor.1A", + "A5.02.1B" => "tempSensor.1B", + "A5.02.20" => "tempSensor.20", + "A5.02.30" => "tempSensor.30", + "A5.04.01" => "roomSensorControl.01", + "A5.04.02" => "tempHumiSensor.02", + "A5.06.01" => "lightSensor.01", + "A5.06.02" => "lightSensor.02", + "A5.07.01" => "occupSensor.01", + "A5.08.01" => "lightTempOccupSensor.01", + "A5.08.02" => "lightTempOccupSensor.02", + "A5.08.03" => "lightTempOccupSensor.03", + "A5.09.01" => "COSensor.01", + "A5.09.04" => "tempHumiCO2Sensor.01", + "A5.10.01" => "roomSensorControl.05", + "A5.10.02" => "roomSensorControl.05", + "A5.10.03" => "roomSensorControl.05", + "A5.10.04" => "roomSensorControl.05", + "A5.10.05" => "roomSensorControl.05", + "A5.10.06" => "roomSensorControl.05", + "A5.10.07" => "roomSensorControl.05", + "A5.10.08" => "roomSensorControl.05", + "A5.10.09" => "roomSensorControl.05", + "A5.10.0A" => "roomSensorControl.05", + "A5.10.0B" => "roomSensorControl.05", + "A5.10.0C" => "roomSensorControl.05", + "A5.10.0D" => "roomSensorControl.05", + "A5.10.10" => "roomSensorControl.01", + "A5.10.11" => "roomSensorControl.01", + "A5.10.12" => "roomSensorControl.01", + "A5.10.13" => "roomSensorControl.01", + "A5.10.14" => "roomSensorControl.01", + "A5.10.15" => "roomSensorControl.02", + "A5.10.16" => "roomSensorControl.02", + "A5.10.17" => "roomSensorControl.02", + "A5.12.00" => "autoMeterReading.00", + "A5.12.01" => "autoMeterReading.01", + "A5.12.02" => "autoMeterReading.02", + "A5.12.03" => "autoMeterReading.03", + "A5.13.01" => "weatherStation", + "A5.13.02" => "weatherStation", + "A5.13.03" => "weatherStation", + "A5.13.04" => "weatherStation", + "A5.13.05" => "weatherStation", + "A5.13.06" => "weatherStation", "A5.20.01" => "MD15", + "A5.30.01" => "digitalInput.01", + "A5.30.02" => "digitalInput.02", + "A5.3F.7F" => "manufProfile", 1 => "switch", 2 => "contact", 3 => "sensor", @@ -70,24 +135,31 @@ my %EnO_subType = ( 8 => "FBH", 9 => "FTF", 10 => "SR04", + 11 => "FRW", + 12 => "keycard", ); my @EnO_models = qw ( other MD15-FtL-HE - SR04 SR04P SR04PT SR04PST SR04PMS + SR04 SR04P SR04T SR04PT SR04PMS SR04PS SR04PST + FT55 FAH60 FAH63 FIH63 FABH63 FBH63 FIBH63 - PM101 + FAFT60 FIFT63AP + FMS14 FMS61 FSB12 FSB14 FSB61 FSB70 FSG70 FSM12 FSM61 + FSR14 FSR61 FTF55 FTN14 FTS12 FUD12 FUD14 FUD61 FUD70 + PM101 ); +# Initialize sub EnOcean_Initialize($) { @@ -102,7 +174,9 @@ EnOcean_Initialize($) "showtime:1,0 loglevel:0,1,2,3,4,5,6 ". "model:".join(",",@EnO_models)." ". "subType:".join(",",values %EnO_subType)." ". - "actualTemp dimTime shutTime subDef switchMode ". + "actualTemp dimTime dimValueOn manufID shutTime ". + "subDef subDef0 subDefI ". + "switchMode switchType ". $readingFnAttributes; for(my $i=0; $i<@EnO_ptm200btn;$i++) { @@ -112,7 +186,7 @@ EnOcean_Initialize($) return undef; } -############################# +# Define sub EnOcean_Define($$) { @@ -129,8 +203,7 @@ EnOcean_Define($$) return undef; } - -############################# +# Set sub EnOcean_Set($@) { @@ -142,6 +215,7 @@ EnOcean_Set($@) my $st = AttrVal($name, "subType", ""); my $model = AttrVal($name, "model", ""); my $ll2 = GetLogLevel($name, 2); + my $sendCmd = "yes"; shift @a; my $tn = TimeNow(); @@ -149,9 +223,10 @@ EnOcean_Set($@) for(my $i = 0; $i < @a; $i++) { my $cmd = $a[$i]; - ##################### - # See also http://www.oscat.de/community/index.php/topic,985.30.html if($st eq "MD15") { + # Battery Powered Actuator (EEP A5-20-01) + # [Kieback&Peter MD15-FTL-xx] + # See also http://www.oscat.de/community/index.php/topic,985.30.html my %sets = ( "desired-temp" => "\\d+(\\.\\d)?", "actuator" => "\\d+", @@ -161,9 +236,9 @@ EnOcean_Set($@) my $re = $sets{$a[0]}; return "Unknown argument $cmd, choose one of ".join(" ", sort keys %sets) if(!defined($re)); - return "Need a parameter" if($re && @a < 2); + return "Need a parameter" if ($re && @a < 2); return "Argument $a[1] is incorrect (expect $re)" - if($re && $a[1] !~ m/^$re$/); + if ($re && $a[1] !~ m/^$re$/); $hash->{CMD} = $cmd; $hash->{READINGS}{CMD}{TIME} = $tn; @@ -178,9 +253,8 @@ EnOcean_Set($@) $hash->{READINGS}{$cmd}{TIME} = $tn; $hash->{READINGS}{$cmd}{VAL} = $arg; - ########################### } elsif($st eq "eltakoDimmer" && $model ne "FSG70") { - + # Dimmer my $sendDimCmd=0; my $dimTime=AttrVal($name, "dimTime", 0); my $onoff=1; @@ -198,6 +272,7 @@ EnOcean_Set($@) # for eltako relative (0-100) (but not compliant to EEP because DB0.2 # is 0) $dimVal=$a[1]; + readingsSingleUpdate($hash,"dimValueStored",$dimVal,1); shift(@a); if(defined($a[1])) { $dimTime=sprintf("%X",(($a[1]*2.55)-255)*-1); @@ -208,6 +283,7 @@ EnOcean_Set($@) } elsif($cmd eq "dimup") { return "Usage: $cmd percent [dimspeed 1-100]" if(@a<2 or $a[1]>100); $dimVal+=$a[1]; + readingsSingleUpdate($hash,"dimValueStored",$dimVal,1); shift(@a); if(defined($a[1])) { $dimTime=sprintf("%X",(($a[1]*2.55)-255)*-1); @@ -218,6 +294,7 @@ EnOcean_Set($@) } elsif($cmd eq "dimdown") { return "Usage: $cmd percent [dimspeed 1-100]" if(@a<2 or $a[1]>100); $dimVal-=$a[1]; + readingsSingleUpdate($hash,"dimValueStored",$dimVal,1); shift(@a); if(defined($a[1])) { $dimTime=sprintf("%X",(($a[1]*2.55)-255)*-1); @@ -228,7 +305,23 @@ EnOcean_Set($@) } elsif($cmd eq "on" || $cmd eq "B0") { $dimTime=1; $sendDimCmd=1; - $dimVal=100; + my $dimValueOn = AttrVal($name, "dimValueOn", 100); + if ($dimValueOn eq "stored") { + $dimVal = ReadingsVal($name, "dimValueStored", 100); + if ($dimVal < 1) { + $dimVal = 100; + readingsSingleUpdate($hash, "dimValueStored", $dimVal, 1); + } + } elsif ($dimValueOn eq "last") { + $dimVal = ReadingsVal($name, "dimValueLast", 100); + if ($dimVal < 1) { + $dimVal = 100; + } + } else { + $dimVal = $dimValueOn; + if($dimValueOn > 100) { $dimVal = 100; } + if($dimValueOn < 1) { $dimVal = 1; } + } } elsif($cmd eq "off" || $cmd eq "BI") { $dimTime=1; @@ -240,23 +333,21 @@ EnOcean_Set($@) my $list = "dim:slider,0,1,100 dimup:slider,0,1,100 ". "dimdown:slider,0,1,100 on off teach"; return SetExtensions($hash, $list, $name, @a); - } if($sendDimCmd) { $updateState = 0; $a[0]="on"; - if($dimVal > 100) { $dimVal=100; } - if($dimVal <= 0) { $dimVal=0; $onoff=0; $a[0]="off" } - ReadingsVal($name, "dimValue", $dimVal); + if($dimVal > 100) { $dimVal=100; } + if($dimVal <= 0) { $dimVal=0; $onoff=0; $a[0]="off"; } my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $dimTime, $onoff|0x08, $subDef); IOWrite($hash, "000A0001", $data); Log $ll2, "EnOcean: set $name $cmd $dimVal"; } - ########################### } elsif($st eq "eltakoShutter") { + # Shutter my $shutTime=AttrVal($name, "shutTime", 0); my $subDef = AttrVal($name, "subDef", "$hash->{DEF}"); my $shutCmd = 0x00; @@ -296,50 +387,100 @@ EnOcean_Set($@) shift(@a); if($shutCmd || ($cmd eq "stop")) { $updateState = 0; - # EEP: A5/3F/7F Universal ??? my $data = sprintf("A5%02X%02X%02X%02X%s00", 0x00, $shutTime, $shutCmd, 0x08, $subDef); IOWrite($hash, "000A0001", $data); Log $ll2, "EnOcean: set $name $cmd"; } - ########################### - # Rocker Switch, simulate a PTM200 switch module } else { + # Rocker Switch, simulate a PTM200 switch module + # separate first and second action my ($c1,$c2) = split(",", $cmd, 2); + # check values if(!defined($EnO_ptm200btn{$c1}) || ($c2 && !defined($EnO_ptm200btn{$c2}))) { my $list = join(" ", sort keys %EnO_ptm200btn); return SetExtensions($hash, $list, $name, @a); } + my $channelA = ReadingsVal($name, "channelA", undef); + my $channelB = ReadingsVal($name, "channelB", undef); + my $channelC = ReadingsVal($name, "channelC", undef); + my $channelD = ReadingsVal($name, "channelD", undef); + my $subDef = AttrVal($name, "subDef", "$hash->{DEF}"); + my $subDef0 = AttrVal($name, "subDef0", "$hash->{DEF}"); + my $subDefI = AttrVal($name, "subDefI", "$hash->{DEF}"); + my $switchMode = AttrVal($name, "switchMode", "switch"); + my $switchType = AttrVal($name, "switchType", "direction"); + # first action + if ($switchType eq "central") { + if ($c1 =~ m/.0/ || $c1 eq "released") { + $subDef = $subDef0; + } else { + $subDef = $subDefI; + } + } + if ($switchType eq "universal") { + if ($c1 =~ m/A0|AI/ && (!$channelA || ($c1 ne $channelA))) { + $c1 = "A0"; + } elsif ($c1 =~ m/B0|BI/ && (!$channelB || $c1 ne $channelB)) { + $c1 = "B0"; + } elsif ($c1 =~ m/C0|CI/ && (!$channelC || ($c1 ne $channelC))) { + $c1 = "C0"; + } elsif ($c1 =~ m/D0|DI/ && (!$channelD || ($c1 ne $channelD))) { + $c1 = "D0"; + } elsif ($c1 eq "released") { + + } else { + $sendCmd = "no"; + } + } + # second action + if ($c2 && $switchType eq "universal") { + if ($c2 =~ m/A0|AI/ && (!$channelA || ($c2 ne $channelA))) { + $c2 = "A0"; + } elsif ($c2 =~ m/B0|BI/ && (!$channelB || $c2 ne $channelB)) { + $c2 = "B0"; + } elsif ($c2 =~ m/C0|CI/ && (!$channelC || ($c2 ne $channelC))) { + $c2 = "C0"; + } elsif ($c2 =~ m/D0|DI/ && (!$channelD || ($c2 ne $channelD))) { + $c2 = "D0"; + } else { + $c2 = undef; + } + if ($c2 && $sendCmd eq "no") { + # only second action has changed, send as first action + $c1 = $c2; + $c2 = undef; + $sendCmd = "yes"; + } + } + # convert and send first and second command my ($db_3, $status) = split(":", $EnO_ptm200btn{$c1}, 2); $db_3 <<= 5; $db_3 |= 0x10 if($c1 ne "released"); # set the pressed flag - if($c2) { + if($c2 && $switchType ne "central") { my ($d2, undef) = split(":", $EnO_ptm200btn{$c2}, 2); $db_3 |= ($d2<<1) | 0x01; } - my $subDef = AttrVal($name, "subDef", "$hash->{DEF}"); - my $switchMode = AttrVal($name, "switchMode", "switch"); - IOWrite($hash, "", sprintf("6B05%02X000000%s%s", $db_3, $subDef, $status)); - Log $ll2, "EnOcean: set $name $cmd"; - if ($switchMode eq "pushbutton") { - IOWrite($hash, "", sprintf("6B0500000000%s20", $subDef)); - Log $ll2, "EnOcean: set $name released"; + if ($sendCmd ne "no") { + IOWrite($hash, "", sprintf("6B05%02X000000%s%s", $db_3, $subDef, $status)); + Log $ll2, "EnOcean: set $name $cmd"; + if ($switchMode eq "pushbutton") { + IOWrite($hash, "", sprintf("6B0500000000%s20", $subDef)); + Log $ll2, "EnOcean: set $name released"; + } } } - select(undef, undef, undef, 0.2); # Tested by joerg. He prefers 0.3 :) } - if($updateState == 1) { readingsSingleUpdate($hash, "state", join(" ", @a), 1); return undef; } } -############################# -# "EnOcean:F6:50000000:0011C8D4:FF" -> EnO_switch on (BI) +# Parse sub EnOcean_Parse($$) { @@ -363,7 +504,6 @@ EnOcean_Parse($$) Log $ll4, "$name: ORG:$rorg DATA:$data ID:$id STATUS:$status"; my @event; - #push @event, "1:rp_counter:".(hex($status)&0xf); my $dl = length($data); my $db_3 = hex substr($data,0,2); @@ -371,19 +511,21 @@ EnOcean_Parse($$) my $db_1 = hex substr($data,4,2) if($dl > 4); my $db_0 = hex substr($data,6,2) if($dl > 6); my $st = AttrVal($name, "subType", ""); + my $manufID = AttrVal($name, "manufID", ""); my $model = AttrVal($name, "model", ""); - ################################# - # RPS: PTM200 based switch/remote or a windowHandle if($rorg eq "F6") { + # RPS Telegram (PTM200) + # Rocker Switch (EEP F6-02-01 ... F6-03-02) + # Position Switch, Home and Office Application (EEP F6-04-01) + # Mechanical Handle (EEP F6-10-00) + my $event = "state"; my $nu = ((hex($status)&0x10)>>4); - # unused flags (AFAIK) #push @event, "1:T21:".((hex($status)&0x20)>>5); #push @event, "1:NU:$nu"; if($nu) { - # Theoretically there can be a released event with some of the A0,BI # pins set, but with the plastic cover on this wont happen. $msg = $EnO_ptm200btn[($db_3&0xe0)>>5]; @@ -391,12 +533,12 @@ EnOcean_Parse($$) $msg .= " released" if(!($db_3 & 0x10)); } else { - - if($db_3 == 112) { # KeyCard, not tested + if($db_3 == 112) { + # Key Card, not tested $msg = "keycard inserted"; - # Only the windowHandle is setting these bits when nu=0 } elsif($db_3 & 0xC0) { + # Only a Mechanical Handle is setting these bits when nu=0 $msg = "closed" if($db_3 == 0xF0); $msg = "open" if($db_3 == 0xE0); $msg = "tilted" if($db_3 == 0xD0); @@ -411,34 +553,69 @@ EnOcean_Parse($$) } } } - + if ($st eq "FRW") { + # smoke detector Eltako FRW, untested + if ($msg =~ m/A0$/) { + push @event, "3:battery:low"; + } elsif ($msg =~ m/AI$/) { + push @event, "3:alarm:smoke-alarm"; + $msg = "smoke-alarm"; + } elsif ($msg =~ m/released$/) { + push @event, "3:alarm:off"; + push @event, "3:battery:ok"; + $msg = "off"; + } + } else { + if ($msg =~ m/A0$/) { + push @event, "3:channelA:A0"; + } elsif ($msg =~ m/AI$/) { + push @event, "3:channelA:AI"; + } elsif ($msg =~ m/B0$/) { + push @event, "3:channelB:B0"; + } elsif ($msg =~ m/BI$/) { + push @event, "3:channelB:BI"; + } elsif ($msg =~ m/C0$/) { + push @event, "3:channelC:C0"; + } elsif ($msg =~ m/CI$/) { + push @event, "3:channelC:CI"; + } elsif ($msg =~ m/D0$/) { + push @event, "3:channelD:D0"; + } elsif ($msg =~ m/DI$/) { + push @event, "3:channelD:DI"; + } # released events are disturbing when using a remote, since it overwrites - # the "real" state immediately. - # In the case of an Eltako FSB14, FSB61 the state should remain released (by Thomas) - my $event = "state"; - $event = "buttons" if($msg =~ m/released$/ && - $model ne "FSB14" && - $model ne "FSB61" && $model ne "FSB70" && - $model ne "FSM12" && $model ne "FSM61" && - $model ne "FTS12"); - + # the "real" state immediately. In the case of an Eltako FSB14, FSB61 + # the state should remain released. (by Thomas) + $event = "buttons" if ($msg =~ m/released$/ && + $model ne "FT55" && $model ne "FSB14" && + $model ne "FSB61" && $model ne "FSB70" && + $model ne "FSM12" && $model ne "FSM61" && + $model ne "FTS12"); + } push @event, "3:$event:$msg"; - ################################# - # 1BS. Only contact is defined in the EEP2.1 for 1BS } elsif($rorg eq "D5") { - push @event, "3:state:" . ($db_3&1 ? "closed" : "open"); - push @event, "3:learnBtn:on" if(!($db_3&0x8)); + # 1BS Telegram + # Single Input Contact (EEP D5-00-01) + # [Eltako FTK (untested), STM-250] + push @event, "3:state:" . ($db_3 & 1 ? "closed" : "open"); + push @event, "3:learnBtn:on" if (!($db_3 & 0x8)); - ################################# } elsif($rorg eq "A5") { + # 4BS Telegram if(($db_0 & 0x08) == 0) { + # teach-in telegram if($db_0 & 0x80) { - my $fn = sprintf "%02x", ($db_3>>2); - my $tp = sprintf "%02X", ((($db_3&3) << 5) | ($db_2 >> 3)); - my $mf = sprintf "%03X", ((($db_2&7) << 8) | $db_1); - $mf = $EnO_manuf{$mf} if($EnO_manuf{$mf}); - my $m = "teach-in:class A5.$fn.$tp (manufacturer: $mf)"; + # teach-in telegram with EEP and Manufacturer ID + my $fn = sprintf "%02x", ($db_3 >> 2); + my $tp = sprintf "%02X", ((($db_3 & 3) << 5) | ($db_2 >> 3)); + my $mf = sprintf "%03X", ((($db_2 & 7) << 8) | $db_1); + + # manufID to account for vendor-specific features + $attr{$name}{manufID} = $mf; + + $mf = $EnO_manuf{$mf} if($EnO_manuf{$mf}); + my $m = "teach-in:EEP A5-$fn-$tp Manufacturer: $mf"; Log 1, $m; push @event, "3:$m"; my $st = "A5.$fn.$tp"; @@ -453,29 +630,12 @@ EnOcean_Parse($$) } } else { - push @event, "3:teach-in:no type/manuf. data transmitted"; - + push @event, "3:teach-in:No EEP profile identifier and no Manufacturer ID"; } - } elsif($model =~ m/^SR04/ || $st eq "SR04") { - my ($fspeed, $temp, $present, $solltemp); - $fspeed = 3; - $fspeed = 2 if($db_3 >= 145); - $fspeed = 1 if($db_3 >= 165); - $fspeed = 0 if($db_3 >= 190); - $fspeed = "Auto" if($db_3 >= 210); - $temp = sprintf("%0.1f", 40-$db_1/6.375); # 40..0 - $present= $db_0&0x1 ? "no" : "yes"; - $solltemp= sprintf("%0.1f", $db_2/6.375); - - push @event, "3:state:temperature $temp"; - push @event, "3:set_point: $solltemp"; - push @event, "3:fan:$fspeed"; - push @event, "3:present:$present" if($present eq "yes"); - push @event, "3:learnBtn:on" if(!($db_0&0x8)); - push @event, "3:T:$temp SP: $db_3 F: $fspeed P: $present"; - } elsif($st eq "MD15") { + # Battery Powered Actuator (EEP A5-20-01) + # [Kieback&Peter MD15-FTL-xx] push @event, "3:state:$db_3 %"; push @event, "3:currentValue:$db_3"; push @event, "3:serviceOn:" . (($db_2 & 0x80) ? "yes" : "no"); @@ -490,22 +650,23 @@ EnOcean_Parse($$) EnOcean_MD15Cmd($hash, $name, $db_1); } elsif($model eq "PM101") { - #################################### - # Ratio Presence Sensor Eagle PM101, code by aicgazi - #################################### + # Light and Presence Sensor [Omnio Ratio eagle-PM101] + # The sensor also sends switching commands (RORG F6) with the senderID-1 + # code by aicgazi + # $db_2 is the illuminance where max value 0xFF stands for 1000 lx my $lux = sprintf "%3d", $db_2; - # content of $db_2 is the illuminance where max value 0xFF stands for 1000 lx $lux = sprintf "%04.2f", ( $lux * 1000 / 255 ) ; push @event, "3:brightness:$lux"; push @event, "3:channel1:" . ($db_0 & 0x01 ? "off" : "on"); push @event, "3:channel2:" . ($db_0 & 0x02 ? "off" : "on"); + push @event, "3:motion:" . ($db_0 & 0x02 ? "off" : "on"); + push @event, "3:state:" . ($db_0 & 0x02 ? "off" : "on"); } elsif($st eq "FAH" || $model =~ /^(FAH60|FAH63|FIH63)$/) { - #################################### - # Eltako FAH60, FAH63, FIH63 (EEP: 07-06-01 plus Data_byte3) - # $db_3 is the illuminance where min 0x00 = 0 lx, max 0xFF = 100 lx; + # Light Sensor + # [Eltako FAH60, FAH63, FIH63] (EEP A5-06-01 plus Data_byte3) + # $db_3 is the illuminance where min 0x00 = 0 lx, max 0xFF = 100 lx # $db_2 must be 0x00 - if($db_2 eq 0x00) { my $luxlow = sprintf "%3d", $db_3; $luxlow = sprintf "%d", ( $luxlow * 100 / 255 ) ; @@ -520,11 +681,10 @@ EnOcean_Parse($$) } } elsif($st eq "FBH" || $model =~ /^(FABH63|FBH55|FBH63|FIBH63)$/) { - #################################### - # Eltako FABH63, FBH55, FBH63, FIBH63 (EEP: similar 07-08-01) + # Light and Occupancy Sensor (no Temperature) + # [Eltako FABH63, FBH55, FBH63, FIBH63] (EEP similar A5-08-01) # $db_0 motion detection where 0x0D = motion and 0x0F = no motion # (DB0_Bit1 = 1 or 0) - if($db_0 eq 0x0D) { push @event, "3:motion:yes"; push @event, "3:state:yes"; @@ -537,25 +697,488 @@ EnOcean_Parse($$) my $lux = sprintf "%3d", $db_2; $lux = sprintf "%d", ( $lux * 2048 / 255 ) ; push @event, "3:brightness:$lux"; - # $db_3 is voltage in EEP 07-08-01 but not used by Eltako !? + # $db_3 is voltage in EEP A5-08-01 but not used by Eltako !? # push @event, "3:voltage:$db_3"; } elsif($st eq "FTF" || $model eq "FTF55") { - #################################### - # Eltako FTF55 (EEP: 07-02-05) - # $db_1 is the temperature where 0x00 = 40?C and 0xFF 0?C + # Temperature Sensor (EEP A5-02-05) + # [Eltako FTF55, Thermokon SR04] + # $db_1 is the temperature where 0x00 = 40°C and 0xFF = 0°C my $temp = sprintf "%3d", $db_1; $temp = sprintf "%0.1f", ( 40 - $temp * 40 / 255 ) ; + push @event, "3:state:$temp"; + push @event, "3:temperature:$temp"; + + } elsif($model =~ m/^SR04/ || $st eq "SR04") { + # Room Sensor and Control Unit + # [Thermokon SR04 *] + my ($fspeed, $temp, $present, $solltemp); + $fspeed = 3; + $fspeed = 2 if($db_3 >= 145); + $fspeed = 1 if($db_3 >= 165); + $fspeed = 0 if($db_3 >= 190); + $fspeed = "Auto" if($db_3 >= 210); + $temp = sprintf("%0.1f", 40-$db_1/6.375); # 40..0 + $present= $db_0&0x1 ? "no" : "yes"; + $solltemp= sprintf("%0.1f", $db_2/6.375); + push @event, "3:state:temperature $temp"; + push @event, "3:set_point: $solltemp"; + push @event, "3:setpoint:$db_2"; + push @event, "3:fan:$fspeed"; + push @event, "3:present:$present" if($present eq "yes"); + push @event, "3:learnBtn:on" if(!($db_0&0x8)); + push @event, "3:T:$temp SP: $db_3 F: $fspeed P: $present"; + + } elsif ($st =~ m/^tempSensor/) { + # Temperature Sensor with with different ranges (EEP A5-02-01 ... A5-02-1B) + # $db_1 is the temperature where 0x00 = max °C ... 0xFF = min °C + my $temp; + $temp = sprintf "%0.1f", -40 - $db_1 / 6.375 if ($st eq "tempSensor.01"); + $temp = sprintf "%0.1f", -30 - $db_1 / 6.375 if ($st eq "tempSensor.02"); + $temp = sprintf "%0.1f", -20 - $db_1 / 6.375 if ($st eq "tempSensor.03"); + $temp = sprintf "%0.1f", -10 - $db_1 / 6.375 if ($st eq "tempSensor.04"); + $temp = sprintf "%0.1f", 0 - $db_1 / 6.375 if ($st eq "tempSensor.05"); + $temp = sprintf "%0.1f", 10 - $db_1 / 6.375 if ($st eq "tempSensor.06"); + $temp = sprintf "%0.1f", 20 - $db_1 / 6.375 if ($st eq "tempSensor.07"); + $temp = sprintf "%0.1f", 30 - $db_1 / 6.375 if ($st eq "tempSensor.08"); + $temp = sprintf "%0.1f", 40 - $db_1 / 6.375 if ($st eq "tempSensor.09"); + $temp = sprintf "%0.1f", 50 - $db_1 / 6.375 if ($st eq "tempSensor.0A"); + $temp = sprintf "%0.1f", 60 - $db_1 / 6.375 if ($st eq "tempSensor.0B"); + $temp = sprintf "%0.1f", -60 - $db_1 / 3.1875 if ($st eq "tempSensor.10"); + $temp = sprintf "%0.1f", -50 - $db_1 / 3.1875 if ($st eq "tempSensor.11"); + $temp = sprintf "%0.1f", -40 - $db_1 / 3.1875 if ($st eq "tempSensor.12"); + $temp = sprintf "%0.1f", -30 - $db_1 / 3.1875 if ($st eq "tempSensor.13"); + $temp = sprintf "%0.1f", -20 - $db_1 / 3.1875 if ($st eq "tempSensor.14"); + $temp = sprintf "%0.1f", -10 - $db_1 / 3.1875 if ($st eq "tempSensor.15"); + $temp = sprintf "%0.1f", 0 - $db_1 / 3.1875 if ($st eq "tempSensor.16"); + $temp = sprintf "%0.1f", 10 - $db_1 / 3.1875 if ($st eq "tempSensor.17"); + $temp = sprintf "%0.1f", 20 - $db_1 / 3.1875 if ($st eq "tempSensor.18"); + $temp = sprintf "%0.1f", 30 - $db_1 / 3.1875 if ($st eq "tempSensor.19"); + $temp = sprintf "%0.1f", 40 - $db_1 / 3.1875 if ($st eq "tempSensor.1A"); + $temp = sprintf "%0.1f", 50 - $db_1 / 3.1875 if ($st eq "tempSensor.1B"); + $temp = sprintf "%0.2f", -10 - (($db_2 << 8) | $db_1) / 19.98 if ($st eq "tempSensor.20"); + $temp = sprintf "%0.1f", -40 - (($db_2 << 8) | $db_1) / 6.3 if ($st eq "tempSensor.30"); push @event, "3:temperature:$temp"; push @event, "3:state:$temp"; - - } elsif($st eq "eltakoDimmer") { + + } elsif($st eq "COSensor.01") { + # Gas Sensor, CO Sensor (EEP A5-09-01) + # [untested] + # $db_3 is the CO concentration where 0x00 = 0 ppm ... 0xFF = 255 ppm + # $db_2 is the CO concentration where 0x00 = 0 ppm ... 0xFF = 255 ppm + # $db_1 is the temperature where 0x00 = 0 °C ... 0xFF = 255 °C + # $db_0 bit D1 temperature sensor available 0 = no, 1 = yes + my $coChannel1 = $db_3; + my $coChannel2 = $db_2; + push @event, "3:Channel1:$coChannel1"; + push @event, "3:Channel2:$coChannel2"; + if ($coChannel1 == $coChannel2) { + push @event, "3:state:$coChannel1"; + } else { + push @event, "3:state:measuring error"; + } + if ($db_0 & 2) { + my $temp = $db_1; + push @event, "3:temperature:$temp"; + } + + } elsif($st eq "tempHumiCO2Sensor.01") { + # Gas Sensor, CO2 Sensor (EEP A5-09-04) + # [Thermokon SR04 CO2 *, untested] + # $db_3 is the humidity where 0x00 = 0 %rH ... 0xC8 = 100 %rH + # $db_2 is the CO2 concentration where 0x00 = 0 ppm ... 0xFF = 2500 ppm + # $db_1 is the temperature where 0x00 = 0°C ... 0xFF = +51 °C + # $db_0 bit D2 humidity sensor available 0 = no, 1 = yes + # $db_0 bit D1 temperature sensor available 0 = no, 1 = yes + my $humi = "unknown"; + my $temp = "unknown"; + my $airQuality; + if ($db_0 & 4) { + $humi = $db_3 >> 1; + push @event, "3:humidity:$humi"; + } + my $co2 = sprintf "%d", $db_2 * 2550 / 255; + push @event, "3:CO2:$co2"; + if ($db_0 & 2) { + $temp = sprintf "%0.1f", $db_1 * 51 / 255 ; + push @event, "3:temperature:$temp"; + } + if ($co2 <= 400) { + $airQuality = "high"; + } elsif ($co2 <= 600) { + $airQuality = "mean"; + } elsif ($co2 <= 1000) { + $airQuality = "moderate"; + } else { + $airQuality = "low"; + } + push @event, "3:airQuality:$airQuality"; + push @event, "3:state:CO2 $co2 AQ: $airQuality T: $temp H: $humi"; + + } elsif ($st eq "roomSensorControl.05") { + # Room Sensor and Control Unit (EEP A5-10-01 ... A5-10-0D) + # [Eltako FTF55D, FTF55H, Thermokon SR04 *, Thanos SR *, untested] + # $db_3 is the fan speed or night reduction for Eltako + # $db_2 is the setpoint where 0x00 = min ... 0xFF = max or + # reference temperature for Eltako whre 0x00 = 0°C ... 0xFF = 40°C + # $db_1 is the temperature where 0x00 = +40°C ... 0xFF = 0°C + # $db_0 bit D0 is the occupy button, pushbutton or slide switch + my $temp = sprintf "%0.1f", 40 - $db_1 / 6.375; + if ($manufID eq "00D") { + my $nightReduction = 0; + $nightReduction = 1 if ($db_3 == 0x06); + $nightReduction = 2 if ($db_3 == 0x0c); + $nightReduction = 3 if ($db_3 == 0x13); + $nightReduction = 4 if ($db_3 == 0x19); + $nightReduction = 5 if ($db_3 == 0x1f); + my $setpointTemp = sprintf "%0.1f", $db_2 / 6.375; + push @event, "3:state:T: $temp SPT: $setpointTemp NR: $nightReduction"; + push @event, "3:nightReduction:$nightReduction"; + push @event, "3:setpointTemp:$setpointTemp"; + } else { + my $fspeed = 3; + $fspeed = 2 if ($db_3 >= 145); + $fspeed = 1 if ($db_3 >= 165); + $fspeed = 0 if ($db_3 >= 190); + $fspeed = "Auto" if ($db_3 >= 210); + my $switch = $db_0 & 1; + push @event, "3:state:T: $temp SP: $db_2 F: $fspeed SW: $switch"; + push @event, "3:fan:$fspeed"; + push @event, "3:switch:$switch"; + push @event, "3:setpoint:$db_2"; + } + push @event, "3:temperature:$temp"; + + } elsif($st eq "roomSensorControl.01") { + # Room Sensor and Control Unit (EEP A5-04-01, A5-10-10 ... A5-10-14) + # [Thermokon SR04 * rH, Thanus SR *, untested] + # $db_3 is the setpoint where 0x00 = min ... 0xFF = max + # $db_2 is the humidity where 0x00 = 0%rH ... 0xFA = 100%rH + # $db_1 is the temperature where 0x00 = 0°C ... 0xFA = +40°C + # $db_0 bit D0 is the occupy button, pushbutton or slide switch + my $temp = sprintf "%0.1f", $db_1 * 40 / 250; + my $humi = sprintf "%d", $db_2 / 2.5; + my $switch = $db_0 & 1; + push @event, "3:state:T: $temp H: $humi SP: $db_2 SW: $switch"; + push @event, "3:humidity:$humi"; + push @event, "3:switch:$switch"; + push @event, "3:setpoint:$db_2"; + push @event, "3:temperature:$temp"; + + } elsif($st eq "roomSensorControl.02") { + # Room Sensor and Control Unit (A5-10-15 ... A5-10-17) + # [untested] + # $db_2 bit D7 ... D2 is the setpoint where 0 = min ... 63 = max + # $db_2 bit D1 ... $db_1 bit D0 is the temperature where 0 = -10°C ... 1023 = +41.2°C + # $db_0_bit_0 is Occupany Button where 0 = pressed, 1 = released + my $temp = sprintf "%0.2f", -10 + ((($db_2 & 3) << 8) | $db_1) / 19.98; + my $setpoint = ($db_2 & 0xFC) >> 2; + my $presence = $db_0 & 1 ? "present" : "absent"; + push @event, "3:state:T: $temp P: $presence SP: $setpoint "; + push @event, "3:presence:$presence"; + push @event, "3:setpoint:$setpoint"; + push @event, "3:temperature:$temp"; + + } elsif($st eq "tempHumiSensor.02") { + # Temperatur and Humidity Sensor(EEP A5-04-02) + # [Eltako FAFT60, FIFT63AP] + # $db_3 is the voltage where 0x59 = 2.5V ... 0x9B = 4V, only at Eltako + # $db_2 is the humidity where 0x00 = 0%rH ... 0xFA = 100%rH + # $db_1 is the temperature where 0x00 = -20°C ... 0xFA = +60°C + #my $temp = sprintf "%3d", $db_1; + #my $voltage = sprintf "%3d", $db_3; + my $humi = sprintf "%d", $db_2 / 2.5; + my $temp = sprintf "%0.1f", -20 + $db_1 * 80 / 250; + my $battery = "unknown"; + if ($manufID eq "00D") { + # Eltako sensor + my $voltage = sprintf "%0.1f", $db_3 * 6.58 / 255; + my $energyStorage = "unknown"; + if ($db_3 le 0x58) { + $energyStorage = "empty"; + $battery = "low"; + } + elsif ($db_3 le 0xDC) { + $energyStorage = "charged"; + $battery = "ok"; + } + else { + $energyStorage = "full"; + $battery = "ok"; + } + push @event, "3:battery:$battery"; + push @event, "3:energyStorage:$energyStorage"; + push @event, "3:voltage:$voltage"; + } + push @event, "3:state:T: $temp H: $humi B: $battery"; + push @event, "3:humidity:$humi"; + push @event, "3:temperature:$temp"; + + } elsif ($st eq "lightSensor.01") { + # Light Sensor (EEP A5-06-01) + # [Eltako FAH60, FAH63, FIH63, Thermokon SR65 LI, untested] + # $db_3 is the voltage where 0x00 = 0 V ... 0xFF = 5.1 V + # $db_3 is the low illuminance for Eltako devices where + # min 0x00 = 0 lx, max 0xFF = 100 lx, if $db_2 = 0 + # $db_2 is the illuminance (ILL2) where min 0x00 = 300 lx, max 0xFF = 30000 lx + # $db_1 is the illuminance (ILL1) where min 0x00 = 600 lx, max 0xFF = 60000 lx + # $db_0_bit_0 is Range select where 0 = ILL1, 1 = ILL2 + my $lux; + my $voltage = "unknown"; + # operation prüfen + if ($manufID eq "00D") { + if($db_2 == 0) { + $lux = sprintf "%d", $db_3 * 100 / 255; + } else { + $lux = sprintf "%d", $db_2 * 116.48 + 300; + } + } else { + $voltage = sprintf "%d", $db_3 * 0.02; + if($db_0 & 1) { + $lux = sprintf "%d", $db_2 * 116.48 + 300; + } else { + $lux = sprintf "%d", $db_1 * 232.94 + 600; + } + push @event, "3:voltage:$voltage"; + } + push @event, "3:brightness:$lux"; + push @event, "3:state:$lux"; + + } elsif ($st eq "lightSensor.02") { + # Light Sensor (EEP A5-06-02) + # $db_3 is the voltage where 0x00 = 0 V ... 0xFF = 5.1 V + # $db_2 is the illuminance (ILL2) where min 0x00 = 0 lx, max 0xFF = 510 lx + # $db_1 is the illuminance (ILL1) where min 0x00 = 0 lx, max 0xFF = 1020 lx + # $db_0_bit_0 is Range select where 0 = ILL1, 1 = ILL2 + my $lux; + my $voltage = sprintf "%d", $db_3 * 0.02; + if($db_0 & 1) { + $lux = $db_2 << 1; + } else { + $lux = $db_1 << 2; + } + push @event, "3:voltage:$voltage"; + push @event, "3:brightness:$lux"; + push @event, "3:state:$lux"; + + } elsif ($st eq "occupSensor.01") { + # Occupancy Sensor (EEP A5-07-01) + # $db_1 is PIR Status (motion) where 0 ... 127 = off, 128 ... 255 = on + my $motion = "off"; + if ($db_1 >= 128) {$motion = "on";} + push @event, "3:motion:$motion"; + push @event, "3:state:$motion"; + + } elsif ($st =~ m/^lightTempOccupSensor/) { + # Light, Temperatur and Occupancy Sensor (EEP A5-08-01 ... A5-08-03) + # $db_3 is the voltage where 0x00 = 0 V ... 0xFF = 5.1 V + # $db_2 is the illuminance where min 0x00 = 0 lx, max 0xFF = 510 lx, 1020 lx, (2048 lx) + # $db_1 is the temperature whrere 0x00 = 0 °C ... 0xFF = 51 °C or -30 °C ... 50°C + # $db_0_bit_1 is PIR Status (motion) where 0 = on, 1 = off + # $db_0_bit_0 is Occupany Button where 0 = pressed, 1 = released + my $lux; + my $temp; + my $voltage = sprintf "%0.1f", $db_3 * 0.02; + my $motion = $db_0 & 2 ? "off" : "on"; + my $presence = $db_0 & 1 ? "present" : "absent"; + + if ($st eq "lightTempOccupSensor.01") { + # Light, Temperatur and Occupancy Sensor (EEP A5-08-01) + # [Eltako FABH63, FBH55, FBH63, FIBH63] + if ($manufID eq "00D") { + $lux = sprintf "%d", $db_2 * 2048 / 255; + push @event, "3:state:M: $motion E: $lux"; + } else { + $lux = $db_2 << 1; + $temp = sprintf "%0.1f", $db_1 * 0.2; + push @event, "3:state:M: $motion E: $lux P: $presence T: $temp U: $voltage"; + push @event, "3:presence:$presence"; + push @event, "3:temperature:$temp"; + push @event, "3:voltage:$voltage"; + } + } elsif ($st eq "lightTempOccupSensor.02") { + # Light, Temperatur and Occupancy Sensor (EEP A5-08-02) + $lux = $db_2 << 2; + $temp = sprintf "%0.1f", $db_1 * 0.2; + push @event, "3:state:M: $motion E: $lux P: $presence T: $temp U: $voltage"; + push @event, "3:presence:$presence"; + push @event, "3:temperature:$temp"; + push @event, "3:voltage:$voltage"; + } elsif ($st eq "lightTempOccupSensor.03") { + # Light, Temperatur and Occupancy Sensor (EEP A5-08-03) + $lux = $db_2 * 6; + $temp = sprintf "%0.1f", -30 + $db_1 * 80 / 255; + push @event, "3:state:M: $motion E: $lux P: $presence T: $temp U: $voltage"; + push @event, "3:presence:$presence"; + push @event, "3:temperature:$temp"; + push @event, "3:voltage:$voltage"; + } + push @event, "3:brightness:$lux"; + push @event, "3:motion:$motion"; + + } elsif ($st =~ m/^autoMeterReading/) { + # Automated meter reading (AMR) (EEP A5-12-00 ... A5-12-03) + # $db_3 (MSB) + $db_2 + $db_1 (LSB) is the Meter reading + # $db_0_bit_7 ... $db_0_bit_4 is the Measurement channel + # $db_0_bit_2 is the Data type where 0 = cumulative value, 1 = current value + # $db_0_bit_1 ... $db_0_bit_0 is the Divisor where 0 = x/1, 1 = x/10, + # 2 = x/100, 3 = x/1000 + # my $meterReading = hex sprintf "%02x%02x%02x", $db_3, $db_2, $db_1; + my $dataType = $db_0 & 4; + my $divisor = $db_0 & 3; + if ($divisor == 3) { + $divisor = 1000; + } elsif ($divisor == 2) { + $divisor = 100; + } elsif ($divisor == 1) { + $divisor = 10; + } else { + $divisor = 1; + } + my $meterReading = sprintf "%0.1f", (($db_3 << 16) | ($db_2 << 8) | $db_1) / $divisor; + my $channel = $db_0 >> 4; + + if ($st eq "autoMeterReading.00") { + # Automated meter reading (AMR), Counter (EEP A5-12-01) + # [Thermokon SR-MI-HS, untested] + if ($dataType == 1) { + # current value + push @event, "3:currentValue:$meterReading"; + push @event, "3:state:$meterReading"; + } else { + # cumulative counter + push @event, "3:counter$channel:$meterReading"; + } + } elsif ($st eq "autoMeterReading.01") { + # Automated meter reading (AMR), Electricity (EEP A5-12-01) + # [Eltako FSS12, FWZ12,DSZ14DRS, DSZ14WDRS] + # $db_0_bit_7 ... $db_0_bit_4 is the Tariff info + # $db_0_bit_2 is the Data type where 0 = cumulative value kWh, + # 1 = current value W + if ($dataType == 1) { + # momentary power + push @event, "3:power:$meterReading"; + push @event, "3:state:$meterReading"; + } elsif ($db_0 == 0x8F && $manufID eq "00D") { + # Eltako, read meter serial number + my $serialNumber; + if ($db_0 == 0) { + # first 2 digits of the serial number + $serialNumber = printf "S-%01x%01x", $db_3 >> 4, $db_3 & 0x0F; + } else { + # last 4 digits of the serial number + $serialNumber = substr (ReadingsVal($name, "serialNumber", "S---"), 0, 4); + $serialNumber = printf "%4c%01x%01x%01x%01x", $serialNumber, + $db_2 >> 4, $db_2 & 0x0F, $db_3 >> 4, $db_3 & 0x0F; + } + push @event, "3:serialNumber:$serialNumber"; + } else { + # power consumption + push @event, "3:energy$channel:$meterReading"; + push @event, "3:currentTariff:$channel"; + } + } elsif ($st eq "autoMeterReading.02" | $st eq "autoMeterReading.03") { + # Automated meter reading (AMR), Gas, Water (EEP A5-12-02, A5-12-03) + if ($dataType == 1) { + # current value + push @event, "3:flowrate:$meterReading"; + push @event, "3:state:$meterReading"; + } else { + # cumulative counter + push @event, "3:consumption$channel:$meterReading"; + push @event, "3:currentTariff:$channel"; + } + } + + } elsif ($st eq "weatherStation") { + # Weather Station (EEP A5-13-01 ... EEP A5-13-06) + # [Eltako FWS61, untested] + # $db_0_bit_7 ... $db_0_bit_4 is the Identifier + my $identifier = $db_0 >> 4; + if ($identifier == 1) { + # EEP A5-13-01 + # $db_3 is the dawn sensor where 0x00 = 0 lx ... 0xFF = 999 lx + # $db_2 is the temperature where 0x00 = -40 °C ... 0xFF = 80 °C + # $db_1 is the wind speed where 0x00 = 0 m/s ... 0xFF = 70 m/s + # $db_0_bit_2 is day / night where 0 = day, 1 = night + # $db_0_bit_1 is rain indication where 0 = no (no rain), 1 = yes (rain) + my $dawn = sprintf "%d", $db_3 * 999 / 255; + my $temp = sprintf "%0.1f", -40 + $db_2 * 120 / 255; + my $windSpeed = sprintf "%0.1f", $db_1 * 70 / 255; + my $dayNight = $db_0 & 2 ? "night" : "day"; + my $isRaining = $db_0 & 1 ? "yes" : "no"; + push @event, "3:brightness:$dawn"; + push @event, "3:dayNight:$dayNight"; + push @event, "3:isRaining:$isRaining"; + push @event, "3:temperature:$temp"; + push @event, "3:windSpeed:$windSpeed"; + push @event, "3:state:T: $temp B: $dawn W: $windSpeed IR: $isRaining"; + } elsif ($identifier == 2) { + # EEP A5-13-02 + # $db_3 is the sun exposure west where 0x00 = 1 lx ... 0xFF = 150 klx + # $db_2 is the sun exposure south where 0x00 = 1 lx ... 0xFF = 150 klx + # $db_1 is the sun exposure east where 0x00 = 1 lx ... 0xFF = 150 klx + my $sunWest = sprintf "%d", 1 + $db_3 * 149999 / 255; + my $sunSouth = sprintf "%d", 1 + $db_2 * 149999 / 255; + my $sunEast = sprintf "%d", 1 + $db_1 * 149999 / 255; + push @event, "3:sunWest:$sunWest"; + push @event, "3:sunSouth:$sunSouth"; + push @event, "3:sunEast:$sunEast"; + } else { + # EEP A5-13-03 ... EEP A5-13-06 not implemented + } + + } elsif ($st =~ m/^digitalInput/) { + # Digital Input (EEP A5-30-01, A5-30-02) + my $contact; + if ($st eq "digtalInput.01") { + # Single Input Contact, Batterie Monitor (EEP A5-30-01) + # [Thermokon SR65 DI, untested] + # $db_2 is the supply voltage, if >= 121 = battery ok + # $db_1 is the input state, if <= 195 = contact closed + my $battery = $db_2 >= 121 ? "ok" : "low"; + $contact = $db_1 <= 195 ? "closed" : "open"; + push @event, "3:battery:$battery"; + } else { + # Single Input Contact (EEP A5-30-01) + # $db_0_bit_0 is the input state where 0 = closed, 1 = open + $contact = $db_0 & 1 ? "open" : "closed"; + } + push @event, "3:contact:$contact"; + push @event, "3:state:$contact"; + + } elsif ($st eq "manufProfile") { + # Manufacturer Specific Applications (EEP A5-3F-7F) + if ($manufID eq "002") { + # [Thermokon SR65 3AI, untested] + # $db_3 is the input 3 where 0x00 = 0 V ... 0xFF = 10 V + # $db_2 is the input 2 where 0x00 = 0 V ... 0xFF = 10 V + # $db_1 is the input 1 where 0x00 = 0 V ... 0xFF = 10 V + my $input3 = sprintf "%0.2f", $db_3 * 10 / 255; + my $input2 = sprintf "%0.2f", $db_2 * 10 / 255; + my $input1 = sprintf "%0.2f", $db_1 * 10 / 255; + push @event, "3:input1:$input1"; + push @event, "3:input2:$input2"; + push @event, "3:input3:$input3"; + push @event, "3:state:I1: $input1 I2: $input2 I3: $input3"; + } else { + # Unknown Application + push @event, "3:state:Manufacturer Specific Application unknown"; + } + + } elsif ($st eq "eltakoDimmer") { + # Dimmer # todo: create a more general solution for the central-command responses - if($db_3 eq 0x02) { # dimm + if($db_3 eq 0x02) { # dim push @event, "3:state:" . ($db_0 & 0x01 ? "on" : "off"); push @event, "3:dimValue:" . $db_2; + if ($db_2 > 0) { + push @event, "3:dimValueLast:" . $db_2; + } } + } else { + # unknown devices push @event, "3:state:$db_3"; push @event, "3:sensor1:$db_3"; push @event, "3:sensor2:$db_2"; @@ -578,6 +1201,7 @@ EnOcean_Parse($$) return $name; } +# MD15Cmd sub EnOcean_MD15Cmd($$$) { @@ -610,6 +1234,7 @@ EnOcean_MD15Cmd($$$) } } +# A5Cmd sub EnOcean_A5Cmd($$$) { @@ -619,7 +1244,7 @@ EnOcean_A5Cmd($$$) # type=A5 msg:4 senderId:4 status=00 subTelNum=01 destId:4 dBm=FF Security=00 } -##################################### +# Undef sub EnOcean_Undef($$) { @@ -636,50 +1261,116 @@ EnOcean_Undef($$)

EnOcean


+ Set attr subType to keycard manually. + +

-
  • Door/Window Contact [STM-250] +
  • Single Input Contact, Door/Window Contact + (EEP D5-00-01, 1BS Telegram)
    + [Eltako FTK, STM-250]
    • closed
    • open
    • learnBtn: on
    • +
    • state: open|closed
  • +

    -
  • Dimmer [Eltako FUD14, FUD61, FUD70, FSG14, FSG70, ...]
    - Set attr subType to eltakoDimmer manually.
    +
  • Dimmer
    + [Eltako FUD14, FUD61, FUD70, FSG14, FSG70, ...]
    • on
    • off
    • -
    • dimValue: %
    • -
    • state: [on|off]
    • -
  • - -
  • Heating/Valve Regulator [MD15-FtL-HE]
    - The attr subType must be MD15. This is done if the device was created by - autocreate.
    -
      -
    • $actuator %
    • -
    • currentValue: $actuator
    • -
    • serviceOn: [yes|no]
    • -
    • energyInput: [enabled|disabled]
    • -
    • energyStorage: [charged|empty]
    • -
    • battery: [ok|empty]
    • -
    • cover: [open|closed]
    • -
    • tempSensor: [failed|ok]
    • -
    • window: [open|closed]
    • -
    • actuator: [ok|obstructed]
    • -
    • temperature: $tmp
    • -
  • - -
  • Brigthness Sensor [Eltako FAH60, FAH63, FIH63]
    - Set attr subType to FAH or attr model to FAH60|FAH63|FIH63 manually.
    -
      -
    • brightness: $lux
    • -
    • state: $lux
    • -
  • - -
  • Motion/Brightness Sensor [Eltako FABH63, FBH55, FBH63, FIBH63]
    - Set attr subType to FBH or attr model to FABH63|FBH55|FBH63|FIBH63 manually.
    -
      -
    • brightness: $lux
    • -
    • motion:[yes|no]
    • -
    • state: [motion: [yes|no]
    • -
  • - -
  • Temperature Sensor [Eltako FTF55]
    - Set attr subType to FTF or attr model to FTF55 manually.
    -
      -
    • temperature: $temp
    • -
    • state: $temp
    • -
  • - -
  • Temprature Sensor / Presence Button / Desired Temp Dial [SR04*]
    - Set attr model to one of SR04 SR04P SR04PT SR04PST SR04PMS or attr - subType to SR04. -
      -
    • temperature: XY.Z
    • -
    • set_point: [0..255]
    • -
    • fan: [0|1|2|3|Auto]
    • -
    • present: yes
    • -
    • learnBtn: on
    • -
    • T: XY.Z SP: [0..255] F: [0|1|2|3|Auto] P: [yes|no]
    • -
  • - -
  • Ratio Presence Sensor [Eagle PM101]
    - Set attr model to PM101 manually.
    -
      -
    • brightness: $lux
    • -
    • channel1: [on|off]
    • -
    • channel2: [on|off]
    • -
  • - -
  • Shutter [Eltako FSB14, FSB61, FSB70]
    - Set attr subType to eltakoShutter and attr model to FSB14|FSB61|FSB70 - manually.
    +
  • dimValue: Dim/% (Sensor Range: Dim = 0 % ... 100 %)
  • +
  • dimValueLast: Dim/%
    + Last value received from the bidirectional dimmer.
  • +
  • dimValueStored: Dim/%
    + Last value saved by set <name> dim <value>.
  • +
  • state: on|off
  • +
    + Set attr subType to eltakoDimmer manually. + +

    + +
  • Shutter (EEP F6-02-01 ... F6-02-02)
    + [Eltako FSB14, FSB61, FSB70]
    • B0
      - The status of the device will become "B0" after the TOP endpoint is - reached, or it has finished an "up %" command.
    • + The status of the device will become "B0" after the TOP endpoint is + reached, or it has finished an "up %" command.
    • BI
      - The status of the device will become "BI" if the BOTTOM endpoint is - reached
    • + The status of the device will become "BI" if the BOTTOM endpoint is + reached
    • released
      - The status of the device become "released" between one of the endpoints.
    • -
  • - -
  • Window Handle [HOPPE SecuSignal]
    - Set attr subType to windowHandle manually. + The status of the device become "released" between one of the endpoints.
  • +
  • state: BO|BI|released +
    + Set attr subType to eltakoShutter and attr model to + FSB14|FSB61|FSB70 manually. +
  • +

    + +
  • Window Handle (EEP F6-10-00)
    + [HOPPE SecuSignal]
    • closed
    • open
    • tilted
    • open from tilted
    • -
  • +
  • state: closed|open|tilted|open from tilted
  • +
    + The device should be created by autocreate. + +

    +
  • Smoke Detector (EEP F6-02-01 ... F6-02-02)
    + [Eltako FRW, untested]
    +
      +
    • smoke-alarm
    • +
    • off
    • +
    • alarm: smoke-alarm|off
    • +
    • battery: low|ok
    • +
    • state: smoke-alarm|off
    • +

    + Set attr subType to FRW. +
  • +

    + +
  • Battery Powered Actuator (EEP A5-20-01)
    + [Kieback&Peter MD15-FTL-xx]
    +
      +
    • Actuator/%
    • +
    • currentValue: Actuator/%
    • +
    • serviceOn: yes|no
    • +
    • energyInput: enabled|disabled
    • +
    • energyStorage: charged|empty
    • +
    • battery: ok|empty
    • +
    • cover: open|closed
    • +
    • tempSensor: failed|ok
    • +
    • window: open|closed
    • +
    • actuator: ok|obstructed
    • +
    • temperature: t/°C
    • +
    • state: Actuator/%
    • +

    + The attr subType must be MD15. This is done if the device was created by + autocreate. +
  • +

    + +
  • Temperature Sensors with with different ranges (EEP A5-02-01 ... A5-02-30)
    + [Thermokon SR65, untested]
    +
      +
    • t/°C
    • +
    • temperature: t/°C (Sensor Range: t = <t min> °C ... <t max> °C)
    • +
    • state: t/°C
    • +

    + The attr subType must be tempSensor.01 ... tempSensor.30. This is done if the device was + created by autocreate. +
  • +

    + +
  • Gas Sensor, CO Sensor (EEP A5-09-01)
    + [untested]
    +
      +
    • Channel1, Channel2: c/ppm (Sensor Range: c = 0 ppm ... 255 ppm)
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 255 °C)
    • +
    • state: c/ppm | measuring error
    • +

    + The attr subType must be COSensor.01. This is done if the device was + created by autocreate. +
  • +

    + +
  • Gas Sensor, CO2 Sensor (EEP A5-09-04)
    + [Thermokon SR04 CO2 *, untested]
    +
      +
    • airQuality: high|mean|moderate|low (Air Quality Classes DIN EN 13779)
    • +
    • CO2: c/ppm (Sensor Range: c = 0 ppm ... 2550 ppm)
    • +
    • humidity: rH/% (Sensor Range: rH = 0 % ... 100 %)
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 51 °C)
    • +
    • state: CO2: c/ppm AQ: high|mean|moderate|low T: t/°C H: rH/%
    • +

    + The attr subType must be tempHumiCO2Sensor.01. This is done if the device was + created by autocreate. +
  • +

    + +
  • Room Sensor and Control Unit (EEP A5-10-01 ... A5-10-0D)
    + [Eltako FTF55, FTR55*, Thermokon SR04 *, Thanos SR *, untested]
    +
      +
    • T: t/°C SP: 0 ... 255 F: 0|1|2|3|Auto SW: 0|1
    • +
    • fan: 0|1|2|3|Auto
    • +
    • switch: 0|1
    • +
    • setpoint: 0 ... 255
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 40 °C)
    • +
    • state: T: t/°C SP: 0 ... 255 F: 0|1|2|3|Auto SW: 0|1

    • + Alternatively for Eltako devices +
    • T: t/°C SPT: t/°C NR: t/°C
    • +
    • nightReduction: t/°C
    • +
    • setpointTemp: t/°C
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 40 °C)
    • +
    • state: T: t/°C SPT: t/°C NR: t/°C

    • +

    + The attr subType must be roomSensorControl.05 and attr + manufID must be 00D for Eltako Devices. This is done if the device was + created by autocreate. +
  • +

    + +
  • Room Sensor and Control Unit (EEP A5-04-01, A5-10-10 ... A5-10-14)
    + [Thermokon SR04 * rH, Thanos SR *, untested]
    +
      +
    • T: t/°C H: rH/% SP: 0 ... 255 SW: 0|1
    • +
    • humidity: rH/% (Sensor Range: rH = 0 % ... 100 %)
    • +
    • switch: 0|1
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 40 °C)
    • +
    • setpoint: 0 ... 255
    • +
    • state: T: t/°C H: rH/% SP: 0 ... 255 SW: 0|1
    • +

    + The attr subType must be roomSensorControl.01. This is + done if the device was created by autocreate. +
  • +

    + +
  • Room Sensor and Control Unit (EEP A5-10-15 - A5-10-17)
    + [untested]
    +
      +
    • T: t/°C P: absent|present SP: 0 ... 63
    • +
    • presence: absent|present
    • +
    • temperature: t/°C (Sensor Range: t = -10 °C ... 41.2 °C)
    • +
    • setpoint: 0 ... 63
    • +
    • state: T: t/°C P: absent|present SP: 0 ... 63
    • +

    + The attr subType must be roomSensorControl.02. This is done if the device was + created by autocreate. +
  • +

    + +
  • Temperatur and Humidity Sensor (EEP A5-04-02)
    + [Eltako FAFT60, FIFT63AP]
    +
      +
    • T: t/°C H: rH/% B: unknown|low|ok
    • +
    • battery: unknown|low|ok
    • +
    • energyStorage: unknown|empty|charged|full
    • +
    • humidity: rH/% (Sensor Range: rH = 0 % ... 100 %)
    • +
    • temperature: t/°C (Sensor Range: t = -20 °C ... 60 °C)
    • +
    • voltage: U/V
    • (Sensor Range: U = 0 V ... 6.6 V) +
    • state: T: t/°C H: rH/% B: unknown|low|ok
    • +

    + The attr subType must be tempHumiSensor.02 and attr + manufID must be 00D for Eltako Devices. This is done if the device was + created by autocreate. +
  • +

    + +
  • Light Sensor (EEP A5-06-01)
    + [Eltako FAH60, FAH63, FIH63, Thermokon SR65 LI, untested]
    +
      +
    • E/lx
    • +
    • brightness: E/lx (Sensor Range: 300 lx ... 30 klx, 600 lx ... 60 klx + , Sensor Range for Eltako: E = 0 lx ... 100 lx, 300 lx ... 30 klx)
    • +
    • voltage: U/V
    • (Sensor Range: U = 0 V ... 5.1 V) +
    • state: E/lx
    • +

    + Eltako devices only support Brightness.
    + The attr subType must be lightSensor.01 and attr manufID must be 00D + for Eltako Devices. This is done if the device was created byr + autocreate. +
  • +

    + +
  • Light Sensor (EEP A5-06-02)
    + [untested]
    +
      +
    • E/lx
    • +
    • brightness: E/lx (Sensor Range: 0 lx ... 1020 lx
    • +
    • voltage: U/V
    • (Sensor Range: U = 0 V ... 5.1 V) +
    • state: E/lx
    • +

    + The attr subType must be lightSensor.02. This is done if the device was + created by autocreate. +
  • +

    + +
  • Occupancy Sensor (EEP A5-07-01)
    + [untested]
    +
      +
    • on|off
    • +
    • motion: on|off
    • +
    • state: on|off
    • +

    + The attr subType must be occupSensor.01. This is done if the device was + created by autocreate. +
  • +

    + +
  • Light, Temperatur and Occupancy Sensor (EEP A5-08-01 ... A5-08-03)
    + [Eltako FABH63, FBH55, FBH63, FIBH6, Thermokon SR-MDS, untested]
    +
      +
    • M: on|off E: E/lx P: absent|present T: t/°C U: U/V
    • +
    • brightness: E/lx (Sensor Range: E = 0 lx ... 510, 1020, 1530 or 2048 lx)
    • +
    • motion: on|off
    • +
    • presence: absent|present
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 51 °C or -30 °C ... 50 °C)
    • +
    • voltage: U/V
    • (Sensor Range: U = 0 V ... 5.1 V) +
    • state: M: on|off E: E/lx P: absent|present T: t/°C U: U/V
    • +

    + Eltako devices only support Brightness and Motion.
    + The attr subType must be lightTempOccupSensor.<01|02|03> and attr + manufID must be 00D for Eltako Devices. This is done if the device was + created by autocreate. +
  • +

    + +
  • Automated meter reading (AMR), Counter (EEP A5-12-00)
    + [Thermokon SR-MI-HS, untested]
    +
      +
    • 1/s
    • +
    • currentValue: 1/s
    • +
    • counter<0 ... 15>: 0 ... 16777215
    • +
    • channel: 0 ... 15
    • +
    • state: 1/s
    • +

    + The attr subType must be autoMeterReading.00. This is done if the device was + created by autocreate. +
  • +

    + +
  • Automated meter reading (AMR), Electricity (EEP A5-12-01)
    + [Eltako FSS12, FWZ12,DSZ14DRS, DSZ14WDRS, Thermokon SR-MI-HS, untested]
    +
      +
    • P/W
    • +
    • power: P/W
    • +
    • energy<0 ... 15>: E/kWh
    • +
    • currentTariff: 0 ... 15
    • +
    • serialNumber: S-<nnnnnn>
    • +
    • state: P/W
    • +

    + The attr subType must be autoMeterReading.01 and attr + manufID must be 00D for Eltako Devices. This is done if the device was + created by autocreate. +
  • +

    + +
  • Automated meter reading (AMR), Gas, Water (EEP A5-12-02, A5-12-03)
    + [untested]
    +
      +
    • Vs/l
    • +
    • flowrate: Vs/l
    • +
    • consumption<0 ... 15>: V/m3
    • +
    • currentTariff: 0 ... 15
    • +
    • state: Vs/l
    • +

    + The attr subType must be autoMeterReading.02|autoMeterReading.02. + This is done if the device was created by autocreate. +
  • +

    + +
  • Weather Station (EEP A5-13-01 ... EEP A5-13-06)
    + [Eltako FWS61, untested]
    +
      +
    • T: t/°C B: E/lx W: Vs/m IR: yes|no
    • +
    • brightness: E/lx (Sensor Range: E = 0 lx ... 999 lx)
    • +
    • temperature: t/°C (Sensor Range: t = -40 °C ... 80 °C)
    • +
    • dayNight: day|night
    • +
    • isRaining: yes|no
    • +
    • sunEast: E/lx (Sensor Range: E = 1 lx ... 150 klx)
    • +
    • sunSouth: E/lx (Sensor Range: E = 1 lx ... 150 klx)
    • +
    • sunWest: E/lx (Sensor Range: E = 1 lx ... 150 klx)
    • +
    • windSpeed: Vs/m (Sensor Range: V = 0 m/s ... 70 m/s)
    • +
    • state:T: t/°C B: E/lx W: Vs/m IR: yes|no
    • +

    + Brightness is the strength of the dawn light. SunEast, + sunSouth and sunWest are the solar radiation from the respective + compass direction. IsRaining is the rain indicator.
    + The attr subType must be weatherStation and attr manufID must be 00D + for Eltako Devices. This is done if the device was created by + autocreate.
    + The Eltako Weather Station FWS61 supports not the day/night indicator + (dayNight).
    + EEP A5-13-03 ... EEP A5-13-06 are not implemented. +
  • +

    + +
  • Digital Input (EEP A5-30-01, A5-30-02)
    + [Thermokon SR65 DI, untested]
    +
      +
    • open|closed
    • +
    • battery: ok|low (only EEP A5-30-01)
    • +
    • contact: open|closed
    • +
    • state: open|closed
    • +

    + The attr subType must be digitalInput.01 or digitalInput.02. This is done if the device was + created by autocreate. +
  • +

    + +
  • Manufacturer Specific Applications (EEP A5-3F-7F)

    + [Thermokon SR65 3AI, untested]
    +
      +
    • I1: U/V I2: U/V I3: U/V
    • +
    • input1: U/V (Sensor Range: U = 0 V ... 10 V)
    • +
    • input2: U/V (Sensor Range: U = 0 V ... 10 V)
    • +
    • input3: U/V (Sensor Range: U = 0 V ... 10 V)
    • +
    • state: I1: U/V I2: U/V I3: U/V
    • +

    + The attr subType must be manufProfile and and attr manufID must be 002 + for Thermokon Devices. This is done if the device was + created by autocreate. +
  • +

    + +
  • Light Sensor (EEP similar 07-06-01)
    + [Eltako FAH60, FAH63, FIH63]
    +
      +
    • E/lx
    • +
    • brightness: E/lx (Sensor Range: E = 0 lx ... 100 lx, 300 lx ... 30 klx)
    • +
    • state: E/lx
    • +

    + Old profile, use subType lightSensor.01 alternative.
    + Set attr subType to FAH or attr model to FAH60|FAH63|FIH63 + manually. +
  • +

    + +
  • Light and Occupancy Sensor (EEP similar A5-08-01)
    + [Eltako FABH63, FBH55, FBH63, FIBH63]
    +
      +
    • yes
    • +
    • no
    • +
    • brightness: E/lx (Sensor Range: E = 0 lx ... 2048 lx)
    • +
    • motion: yes|no
    • +
    • state: yes|no
    • +

    + Old profile, use subType lightTempOccupSensor.01 alternative.
    + Set attr subType to FBH or attr model to FABH63|FBH55|FBH63|FIBH63 + manually. +
  • +

    + +
  • Temperature Sensor (EEP A5-02-05)
    + [Eltako FTF55]
    +
      +
    • t/°C
    • +
    • temperature: t/°C (Sensor Range: t = 0 °C ... 40 °C)
    • +
    • state: t/°C
    • +

    + Old profile, use subType roomSensorControl.05 alternative.
    + Set attr subType to FTF or attr model to FTF55 manually. +
  • +

    + +
  • Room Sensor and Control Unit (EEP A5-02-05, A5-10-03, A5-10-0C, A5-10-05, + A5-10-06, A5-10-04, A5-10-01)
    + [Thermokon SR04 *]
    +
      +
    • T: t/°C SP: 0 ... 255 F: 0|1|2|3|Auto P: yes|no
    • +
    • fan: 0|1|2|3|Auto
    • +
    • learnBtn: on
    • +
    • present: yes
    • +
    • temperature: t/°C
    • +
    • set_point: 0 ... 255
    • +
    • state: T: t/°C SP: 0 ... 255 F: 0|1|2|3|Auto P: yes|no
    • +

    + Old profile, use subType roomSensorControl.05 alternative.
    + Set attr model to SR04|SR04P|SR04T|SR04PT|SR04PMS|SR04PS|SR04PST or + attr subType to SR04. +
  • +

    + +
  • Light and Presence Sensor
    + [Omnio Ratio eagle-PM101]
    +
      +
    • on
    • +
    • off
    • +
    • brightness: E/lx (Sensor Range: E = 0 lx ... 1000 lx)
    • +
    • channel1: on|off
    • (Motion message in depending on the brightness threshold) +
    • channel2: on|off
    • (Motion message) +
    • motion: on|off
    • (Channel 2) +
    • state: on|off
    • (Channel 2) +

    + The sensor also sends switching commands (RORG F6) with + the senderID-1.
    + Set attr model to PM101 manually. Automatic teach-in is not possible, + since no EEP and manufacturer ID are sent. +