From 6274ad461e4c98ee291e575f9980450d26d69e71 Mon Sep 17 00:00:00 2001 From: "klaus.schauer" <> Date: Thu, 7 Feb 2019 05:41:36 +0000 Subject: [PATCH] 10_EnOcean: # profile multiFuncSensor (EEP A5-14-01 ... A5-14-06), doorContact (EEP A5-14-07, A5-14-08), windowContact (EEP A5-14-09, A5-14-0A): modified and functionary logic unified # secure functions: rlc functions modified # profile hvac.04: sensor logic modified git-svn-id: https://svn.fhem.de/fhem/trunk@18514 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/10_EnOcean.pm | 98 +++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/fhem/FHEM/10_EnOcean.pm b/fhem/FHEM/10_EnOcean.pm index df84a6379..76aab2bb4 100755 --- a/fhem/FHEM/10_EnOcean.pm +++ b/fhem/FHEM/10_EnOcean.pm @@ -6682,9 +6682,9 @@ sub EnOcean_Parse($$) $rorgname = $EnO_rorgname{$rorg}; if (!$rorgname) { if($hash) { - Log3 $hash->{NAME}, 2, "EnOcean $hash->{NAME} RORG $rorg unknown."; + Log3 $hash->{NAME}, 4, "EnOcean $hash->{NAME} RORG $rorg unknown."; } else { - Log3 undef, 2, "EnOcean RORG $rorg received from $senderID unknown."; + Log3 undef, 4, "EnOcean $senderID RORG $rorg unknown."; } return ""; } @@ -6725,7 +6725,7 @@ sub EnOcean_Parse($$) $msg = join(':', @msg); $rorgname = $EnO_rorgname{$rorg}; if (!$rorgname) { - Log3 undef, 2, "EnOcean RORG $rorg received from $senderID unknown."; + Log3 undef, 4, "EnOcean $senderID RORG $rorg unknown."; return ""; } delete $iohash->{helper}{cdm}; @@ -6789,12 +6789,17 @@ sub EnOcean_Parse($$) # SenderID unknown, created new device Log3 undef, 5, "EnOcean received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $senderID STATUS: $status"; my $learningMode = AttrVal($IODev, "learningMode", "demand"); + my $learningDev = AttrVal($IODev, "learningDev", "teachMsg"); my $ret = "UNDEFINED EnO_$senderID EnOcean $senderID $msg"; if ($rorgname =~ m/^GPCD|GPSD|SMLRNANS|SMREC|SIGNAL$/) { Log3 undef, 4, "EnOcean Received $rorgname telegram to the unknown device with SenderID $senderID."; return ''; + } elsif ($learningDev eq 'teachMsg' && ($rorgname =~ m/^VLD|MSC|SEC|ENC$/ || $rorgname eq '4BS' && (hex(substr($data, 6, 2))) & 8)) { + Log3 undef, 4, "EnOcean Received $rorgname telegram to the unknown device with SenderID $senderID."; + return ''; + } elsif ($rorg eq 'A5' && hex(substr($data, 0, 2)) >> 2 == 0x3F && (hex(substr($data, 0, 4)) >> 3 & 0x7F) == 0 && @@ -7132,7 +7137,7 @@ sub EnOcean_Parse($$) ($rorg, $data) = ($1, $2); $rorgname = $EnO_rorgname{$rorg}; if (!$rorgname) { - Log3 undef, 1, "EnOcean RORG $rorg received from $senderID unknown."; + Log3 undef, 4, "EnOcean $senderID RORG $rorg unknown."; return ""; } if ($destinationID ne $3) { @@ -7488,7 +7493,7 @@ sub EnOcean_Parse($$) EnOcean_SndRadio(undef, $hash, $packetType, $rorg, $data, "00000000", "00", $hash->{DEF}); Log3 $name, 2, "EnOcean $name 4BS teach-in response sent to " . $hash->{DEF}; - } elsif ($st eq "hvac.04" || "hvac.06") { + } elsif ($st eq "hvac.04" || $st eq "hvac.06") { # heating radiator valve actuating drive (EEP A5-20-04) # Battery Powered Actuator (EEP A5-20-06) $attr{$name}{comMode} = "biDir"; @@ -10020,22 +10025,30 @@ sub EnOcean_Parse($$) # $db[2] is the illuminance where min 0x00 = 0 lx, max 0xFA = 1000 lx # $db[0]_bit_1 is Vibration where 0 = off, 1 = on # $db[0]_bit_0 is Contact where 0 = closed, 1 = open - my $lux = $db[2] << 2; - if ($db[2] == 251) {$lux = "over range";} - my $voltage = sprintf "%0.1f", $db[3] * 0.02; - if ($db[3] > 250) {push @event, "3:errorCode:$db[3]";} - my $vibration = $db[0] & 2 ? "on" : "off"; - my $contact = $db[0] & 1 ? "open" : "closed"; - push @event, "3:brightness:$lux"; - push @event, "3:contact:$contact"; - push @event, "3:vibration:$vibration"; - push @event, "3:voltage:$voltage"; - push @event, "3:state:C: $contact V: $vibration E: $lux U: $voltage"; - + if (!exists($hash->{helper}{lastEvent}) || $hash->{helper}{lastEvent} ne $data) { + my $lux = $db[2] << 2; + if ($db[2] == 251) {$lux = "over range";} + my $voltage = sprintf "%0.2f", $db[3] * 0.02; + if ($db[3] > 250) {push @event, "3:errorCode:$db[3]";} + my $vibration = $db[0] & 2 ? "on" : "off"; + my $contact = $db[0] & 1 ? "open" : "closed"; + push @event, "3:brightness:$lux"; + push @event, "3:contact:$contact"; + push @event, "3:vibration:$vibration"; + push @event, "3:voltage:$voltage"; + push @event, "3:state:C: $contact V: $vibration E: $lux U: $voltage"; + $hash->{helper}{lastEvent} = $data; + } + CommandDeleteReading(undef, "$name alarm"); + if (AttrVal($name, "signOfLife", 'on') eq 'on') { + RemoveInternalTimer($hash->{helper}{timer}{alarm}) if(exists $hash->{helper}{timer}{alarm}); + @{$hash->{helper}{timer}{alarm}} = ($hash, 'alarm', 'dead_sensor', 1, 5); + InternalTimer(gettimeofday() + AttrVal($name, "signOfLifeInterval", 132), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0); + } } elsif ($st eq "doorContact") { # dual door contact (EEP A5-14-07, A5-14-08) if (!exists($hash->{helper}{lastEvent}) || $hash->{helper}{lastEvent} ne $data) { - my $voltage = sprintf "%0.1f", $db[3] * 0.02; + my $voltage = sprintf "%0.2f", $db[3] * 0.02; my $doorContact = $db[0] & 4 ? 'open' : 'closed'; my $lockContact = $db[0] & 2 ? 'unlocked' : 'locked'; my $vibration = $db[0] & 1 ? 'on' : 'off'; @@ -10050,13 +10063,13 @@ sub EnOcean_Parse($$) if (AttrVal($name, "signOfLife", 'on') eq 'on') { RemoveInternalTimer($hash->{helper}{timer}{alarm}) if(exists $hash->{helper}{timer}{alarm}); @{$hash->{helper}{timer}{alarm}} = ($hash, 'alarm', 'dead_sensor', 1, 5); - InternalTimer(gettimeofday() + AttrVal($name, "signOfLifeInterval", 66), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0); + InternalTimer(gettimeofday() + AttrVal($name, "signOfLifeInterval", 132), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0); } } elsif ($st eq "windowContact") { # window contact (EEP A5-14-09, A5-14-0A) if (!exists($hash->{helper}{lastEvent}) || $hash->{helper}{lastEvent} ne $data) { - my $voltage = sprintf "%0.1f", $db[3] * 0.02; + my $voltage = sprintf "%0.2f", $db[3] * 0.02; my %window = (0 => 'closed', 1 => 'tilt', 2 => 'reserved', 3 => 'open'); my $window = $window{(($db[0] & 6) >> 1)}; my $vibration = $db[0] & 1 ? 'on' : 'off'; @@ -10070,7 +10083,7 @@ sub EnOcean_Parse($$) if (AttrVal($name, "signOfLife", 'on') eq 'on') { RemoveInternalTimer($hash->{helper}{timer}{alarm}) if(exists $hash->{helper}{timer}{alarm}); @{$hash->{helper}{timer}{alarm}} = ($hash, 'alarm', 'dead_sensor', 1, 5); - InternalTimer(gettimeofday() + AttrVal($name, "signOfLifeInterval", 990), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0); + InternalTimer(gettimeofday() + AttrVal($name, "signOfLifeInterval", 132), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0); } } elsif ($st =~ m/^digitalInput\.0[12]$/) { @@ -13925,11 +13938,7 @@ sub EnOcean_Notify(@) if (defined(AttrVal($name, "temperatureRefDev", undef)) && $devName eq AttrVal($name, "temperatureRefDev", "") && $parts[0] eq "temperature") { - if (AttrVal($name, "subType", "") =~ m/^hvac\.0(1|6)$/) { - readingsSingleUpdate($hash, "temperature", $parts[1], 1); - #Log3 $name, 2, "EnOcean $name $devName $s"; - } - if (AttrVal($name, "subType", "") eq "hvac.04" && AttrVal($name, "measurementCtrl", "enable") eq 'disable') { + if (AttrVal($name, "subType", "") =~ m/^hvac\.0(1|4|6)$/) { readingsSingleUpdate($hash, "temperature", $parts[1], 1); #Log3 $name, 2, "EnOcean $name $devName $s"; } @@ -16383,15 +16392,19 @@ sub EnOcean_sec_decodeVAES($$$) { # # Returns: RLC in hexadecimal format # -sub EnOcean_sec_getRLC($$) { +sub EnOcean_sec_getRLC($$$$) { my $hash = $_[0]; my $rlcVar = $_[1]; + my $expectRlc = $_[2]; + my $rlc = $_[3]; my $name = $hash->{NAME}; - + my $old_rlc = $rlc; # Fetch newest RLC from receiver hash - my $old_rlc = ReadingsVal($name, "." . $rlcVar, $attr{$name}{$rlcVar}); - if (hex($old_rlc) < hex($attr{$name}{$rlcVar})) { - $old_rlc = $attr{$name}{$rlcVar}; + if ($expectRlc == 0) { + $old_rlc = ReadingsVal($name, "." . $rlcVar, $attr{$name}{$rlcVar}); + if (hex($old_rlc) < hex($attr{$name}{$rlcVar})) { + $old_rlc = $attr{$name}{$rlcVar}; + } } Log3 $name, 5, "EnOcean $name EnOcean_sec_getRLC RLC old: $old_rlc " . hex($old_rlc); @@ -16593,17 +16606,11 @@ sub EnOcean_sec_convertToNonsecure($$$) { }; Log3 $name, 5, "EnOcean $name EnOcean_sec_convertToNonsecure MAC: $mac"; - # TODO RLC could be transmitted with data, could not test this - #if(!defined($rlc)) { - # print "No RLC in message, using stored value\n"; - # $rlc = getRLC($senderID); - #} - # Maximum RLC search window is 128 foreach my $rlc_window (0..128) { #print "Trying RLC offset $rlc_window\n"; # Fetch stored RLC - $rlc = EnOcean_sec_getRLC($hash, "rlcRcv"); + $rlc = EnOcean_sec_getRLC($hash, "rlcRcv", $expect_rlc, $rlc); # Fetch private Key for VAES if ($attr{$name}{keyRcv} =~ /[\dA-F]{32}/) { $private_key = pack('H32',$attr{$name}{keyRcv}); @@ -16640,6 +16647,8 @@ sub EnOcean_sec_convertToNonsecure($$$) { Log3 $name, 5, "EnOcean $name EnOcean_sec_convertToNonsecure RORG: " . uc($1) . " DATA: " . uc($2); return (undef, uc($1), uc($2)); } + # Couldn't verify or decrypt message, only one calculation if rlcTX = true + return ("Can't verify or decrypt telegram", undef, undef) if ($expect_rlc == 1); } } # Couldn't verify or decrypt message in RLC window @@ -16738,7 +16747,7 @@ sub EnOcean_sec_convertToSecure($$$$) } #Get and update RLC - my $rlc = EnOcean_sec_getRLC($hash, "rlcSnd"); + my $rlc = EnOcean_sec_getRLC($hash, "rlcSnd", 0, undef); #Log3 $hash->{NAME}, 5, "EnOcean_sec_convertToSecure: Got actual RLC: $rlc"; #Get key of device @@ -20588,11 +20597,14 @@ EnOcean_Delete($$)
The attr subType must be multiFuncSensor. This is done if the device was created by autocreate. + A monitoring period can be set for signOfLife telegrams of the sensor, see + signOfLife and signOfLifeInterval. + Default is "on" and an interval of 132 sec.

  • Dual Door Contact (EEP A5-14-07, A5-14-08)
    - [untested]
    + [Eimsig EM-FSGE-00 sensor]
    • C: open|closed B: unlocked|locked V: on|off U: U/V
    • alarm: dead_sensor
    • @@ -20606,12 +20618,12 @@ EnOcean_Delete($$) created by autocreate.
      A monitoring period can be set for signOfLife telegrams of the sensor, see signOfLife and signOfLifeInterval. - Default is "on" and an interval of 66 sec. + Default is "on" and an interval of 132 sec.

    • Window/Door Contact (EEP A5-14-09, A5-14-0A)
      - [untested]
      + [Eimsig EM-FSGE-00 sensor]
      • W: open|tilt|closed B: unlocked|locked V: on|off U: U/V
      • alarm: dead_sensor
      • @@ -20624,7 +20636,7 @@ EnOcean_Delete($$) created by autocreate.
        A monitoring period can be set for signOfLife telegrams of the sensor, see signOfLife and signOfLifeInterval. - Default is "on" and an interval of 990 sec. + Default is "on" and an interval of 132 sec.