2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-01 07:19:24 +00:00

10_EnOcean: new EEP: multisensor.50 (EEP D2-06-50), profil roomSensorControl.05: signOfLife function added, signal telegram: new MID 0x0B, 0x10, 0x11, MID 0x0D modified, constant light controller: open loop control functions

git-svn-id: https://svn.fhem.de/fhem/trunk@24267 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klaus.schauer 2021-04-17 18:34:00 +00:00
parent 539d2b08be
commit aa72fdc906

View File

@ -63,7 +63,7 @@ my %EnO_rorgname = (
"C5" => "SYSEX", # remote management >> packet type 7 used "C5" => "SYSEX", # remote management >> packet type 7 used
"C6" => "SMLRNREQ", # Smart Ack Learn Request "C6" => "SMLRNREQ", # Smart Ack Learn Request
"C7" => "SMLRNANS", # Smart Ack Learn Answer "C7" => "SMLRNANS", # Smart Ack Learn Answer
"D0" => "SIGNAL", # Smart Ack Mail Box Functions "D0" => "SIGNAL", # signal telegram
"D1" => "MSC", # MSC "D1" => "MSC", # MSC
"D2" => "VLD", # VLD "D2" => "VLD", # VLD
"D4" => "UTE", # UTE "D4" => "UTE", # UTE
@ -394,6 +394,7 @@ my %EnO_eepConfig = (
"D2.05.01" => {attr => {subType => "blindsCtrl.01", webCmd => "opens:stop:closes:position"}}, "D2.05.01" => {attr => {subType => "blindsCtrl.01", webCmd => "opens:stop:closes:position"}},
"D2.05.02" => {attr => {subType => "blindsCtrl.00", defaultChannel => 1, webCmd => "opens:stop:closes:position"}, GPLOT => "EnO_position4angle4:Position/AnglePos,"}, "D2.05.02" => {attr => {subType => "blindsCtrl.00", defaultChannel => 1, webCmd => "opens:stop:closes:position"}, GPLOT => "EnO_position4angle4:Position/AnglePos,"},
"D2.06.01" => {attr => {subType => "multisensor.01"}, GPLOT => "EnO_temp4humi4:Temp/Humi,EnO_brightness4:Brightness,"}, "D2.06.01" => {attr => {subType => "multisensor.01"}, GPLOT => "EnO_temp4humi4:Temp/Humi,EnO_brightness4:Brightness,"},
"D2.06.50" => {attr => {subType => "multisensor.50"}},
"D2.10.00" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.00" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.10.01" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.01" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
"D2.10.02" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"}, "D2.10.02" => {attr => {subType => "roomCtrlPanel.00", webCmd => "setpointTemp"}, GPLOT => "EnO_D2-10-xx:Temp/SPT/Humi,"},
@ -787,7 +788,7 @@ sub EnOcean_Initialize($) {
"blockTemp:no,yes blockDisplay:no,yes blockDateTime:no,yes " . "blockTemp:no,yes blockDisplay:no,yes blockDateTime:no,yes " .
"blockTimeProgram:no,yes blockOccupancy:no,yes blockSetpointTemp:no,yes " . "blockTimeProgram:no,yes blockOccupancy:no,yes blockSetpointTemp:no,yes " .
"blockFanSpeed:no,yes blockKey:no,yes " . "blockFanSpeed:no,yes blockKey:no,yes " .
"brightnessDayNight brightnessDayNightCtrl:custom,sensor brightnessDayNightDelay " . "brightnessDayNight brightnessDayNightCtrl:custom,sensor brightnessDayNightDelay brightnessRefDev " .
"brightnessSunny brightnessSunnySouth brightnessSunnyWest brightnessSunnyEast " . "brightnessSunny brightnessSunnySouth brightnessSunnyWest brightnessSunnyEast " .
"brightnessSunnyDelay brightnessSunnySouthDelay brightnessSunnyWestDelay brightnessSunnyEastDelay " . "brightnessSunnyDelay brightnessSunnySouthDelay brightnessSunnyWestDelay brightnessSunnyEastDelay " .
"calAtEndpoints:no,yes comMode:confirm,biDir,uniDir creator:autocreate,manual " . "calAtEndpoints:no,yes comMode:confirm,biDir,uniDir creator:autocreate,manual " .
@ -812,7 +813,7 @@ sub EnOcean_Initialize($) {
"model:" . join(",", sort keys %EnO_models) . " " . "model:" . join(",", sort keys %EnO_models) . " " .
"observe:on,off observeCmdRepetition:1,2,3,4,5 observeErrorAction:textField-long observeInterval observeLogic:and,or " . "observe:on,off observeCmdRepetition:1,2,3,4,5 observeErrorAction:textField-long observeInterval observeLogic:and,or " .
#observeCmds observeExeptions #observeCmds observeExeptions
"observeRefDev pidActorErrorAction:errorPos,freeze pidActorCallBeforeSetting pidActorErrorPos " . "observeRefDev openLoopCtrlScale pidActorErrorAction:errorPos,freeze pidActorCallBeforeSetting pidActorErrorPos " .
"pidActorLimitLower pidActorLimitUpper pidActorTreshold pidCtrl:on,off pidDeltaTreshold pidFactor_D pidFactor_I " . "pidActorLimitLower pidActorLimitUpper pidActorTreshold pidCtrl:on,off pidDeltaTreshold pidFactor_D pidFactor_I " .
"pidFactor_P pidIPortionCallBeforeSetting pidSensorTimeout " . "pidFactor_P pidIPortionCallBeforeSetting pidSensorTimeout " .
"pollInterval postmasterID productID rampTime rcvRespAction:textField-long ". "pollInterval postmasterID productID rampTime rcvRespAction:textField-long ".
@ -1054,12 +1055,20 @@ sub EnOcean_Define($$) {
$attr{$name}{teachMethod} = 'RPS'; $attr{$name}{teachMethod} = 'RPS';
Log3 $name, 2, "EnOcean $name teach-in EEP F6-10-00 Manufacturer: no ID"; Log3 $name, 2, "EnOcean $name teach-in EEP F6-10-00 Manufacturer: no ID";
} }
# signal telegram learn mode status
$data = EnOcean_signalLearnModeStatus(0, 1, 0, 0, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $data, '0' x 8, '00', 'F' x 8);
} elsif ($attr{$name}{subType} eq "contact" && hex($data) & 8) { } elsif ($attr{$name}{subType} eq "contact" && hex($data) & 8) {
$attr{$name}{eep} = "D5-00-01"; $attr{$name}{eep} = "D5-00-01";
$attr{$name}{manufID} = "7FF"; $attr{$name}{manufID} = "7FF";
readingsSingleUpdate($hash, "teach", "1BS teach-in accepted EEP D5-00-01 Manufacturer: no ID", 1); readingsSingleUpdate($hash, "teach", "1BS teach-in accepted EEP D5-00-01 Manufacturer: no ID", 1);
$attr{$name}{teachMethod} = '1BS'; $attr{$name}{teachMethod} = '1BS';
Log3 $name, 2, "EnOcean $name teach-in EEP D5-00-01 Manufacturer: no ID"; Log3 $name, 2, "EnOcean $name teach-in EEP D5-00-01 Manufacturer: no ID";
# signal telegram learn mode status
$data = EnOcean_signalLearnModeStatus(0, 1, 0, 0, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $data, '0' x 8, '00', 'F' x 8);
} elsif ($attr{$name}{subType} eq "4BS" && hex(substr($data, 6, 2)) & 8) { } elsif ($attr{$name}{subType} eq "4BS" && hex(substr($data, 6, 2)) & 8) {
$hash->{helper}{teachInWait} = "4BS"; $hash->{helper}{teachInWait} = "4BS";
readingsSingleUpdate($hash, "teach", "4BS teach-in is missing", 1); readingsSingleUpdate($hash, "teach", "4BS teach-in is missing", 1);
@ -3474,6 +3483,7 @@ sub EnOcean_Set($@) {
$updateState = 0; $updateState = 0;
($err, $subDef) = EnOcean_AssignSenderID(undef, $hash, "subDef", "confirm"); ($err, $subDef) = EnOcean_AssignSenderID(undef, $hash, "subDef", "confirm");
EnOcean_setTeachConfirmWaitHash(undef, $hash); EnOcean_setTeachConfirmWaitHash(undef, $hash);
} elsif ($cmd eq "dim") { } elsif ($cmd eq "dim") {
return "Usage: $cmd dim/% [rampTime/s lock|unlock]" return "Usage: $cmd dim/% [rampTime/s lock|unlock]"
if(@a < 2 || $a[1] !~ m/^\d+$/ || $a[1] < 0 || $a[1] > 100); if(@a < 2 || $a[1] !~ m/^\d+$/ || $a[1] < 0 || $a[1] > 100);
@ -3552,6 +3562,12 @@ sub EnOcean_Set($@) {
$setCmd = 8; $setCmd = 8;
$sendDimCmd = 1; $sendDimCmd = 1;
} elsif ($cmd eq "openLoopCtrl") {
$hash->{constLightCtrl} = 'openLoopCtrl';
$dimVal = $dimVal // 0;
$setCmd = $dimVal == 0 ? 8 : 9;
$sendDimCmd = 1;
} elsif ($cmd eq "local") { } elsif ($cmd eq "local") {
if ($a[1]) { if ($a[1]) {
return "Usage: $cmd [learn]" if ($a[1] ne "learn"); return "Usage: $cmd [learn]" if ($a[1] ne "learn");
@ -3569,9 +3585,16 @@ sub EnOcean_Set($@) {
$data = sprintf "%02X%02X%02X%02X", $gwCmdID, $dimVal, $rampTime, $setCmd; $data = sprintf "%02X%02X%02X%02X", $gwCmdID, $dimVal, $rampTime, $setCmd;
} else { } else {
my $cmdList = "dim:slider,0,1,100 local:learn on:noArg off:noArg teach:noArg"; my $cmdList = "dim:slider,0,1,100 local:learn off:noArg on:noArg openLoopCtrl:noArg teach:noArg";
return SetExtensions ($hash, $cmdList, $name, @a); return SetExtensions ($hash, $cmdList, $name, @a);
} }
$hash->{helper}{constLightCtrl}[0] = $hash;
$hash->{helper}{constLightCtrl}[1] = 'set';
$hash->{helper}{constLightCtrl}[2] = $cmd;
$hash->{helper}{constLightCtrl}[3] = $dimVal;
$hash->{helper}{constLightCtrl}[4] = 4;
$logLevel = EnOcean_constLightCtrl($hash->{helper}{constLightCtrl});
######*
if ($sendDimCmd) { if ($sendDimCmd) {
readingsSingleUpdate($hash, "block", "unlock", 1); readingsSingleUpdate($hash, "block", "unlock", 1);
if (defined $a[1]) { if (defined $a[1]) {
@ -3965,7 +3988,7 @@ sub EnOcean_Set($@) {
} else { } else {
return "Unknown Gateway command " . $cmd . ", choose one of ". $cmdList . join(" ", sort keys %EnO_gwCmd); return "Unknown Gateway command " . $cmd . ", choose one of ". $cmdList . join(" ", sort keys %EnO_gwCmd);
} }
Log3 $name, 3, "EnOcean set $name $cmd"; Log3 $name, $logLevel // 3, "EnOcean set $name $cmd";
} elsif ($st eq "energyManagement.01") { } elsif ($st eq "energyManagement.01") {
# Energy Management, Demand Response (A5-37-01) # Energy Management, Demand Response (A5-37-01)
@ -7279,7 +7302,6 @@ sub EnOcean_Parse($$) {
# store changes # store changes
EnOcean_CommandSave(undef, undef); EnOcean_CommandSave(undef, undef);
readingsSingleUpdate($hash, 'teach', '4BS teach-in accepted', 1); readingsSingleUpdate($hash, 'teach', '4BS teach-in accepted', 1);
#push @event, "3:teach:4BS teach-in accepted";
Log3 $name, 2, "EnOcean $name remote device with SenderID $senderID assigned"; Log3 $name, 2, "EnOcean $name remote device with SenderID $senderID assigned";
return ''; return '';
@ -7365,9 +7387,9 @@ sub EnOcean_Parse($$) {
"91" => "BASEID_MAX_REACHED", "91" => "BASEID_MAX_REACHED",
); );
my $rcTxt = $codes{$funcNumber} if($codes{$funcNumber}); my $rcTxt = $codes{$funcNumber} if($codes{$funcNumber});
$funcNumber = hex($funcNumber);
if($hash) { if($hash) {
$name = $hash->{NAME}; $name = $hash->{NAME};
$funcNumber = hex($funcNumber);
Log3 $name, $funcNumber == 0 ? 5 : 2, "EnOcean $name RESPONSE: $rcTxt DATA: $data ODATA: $odata"; Log3 $name, $funcNumber == 0 ? 5 : 2, "EnOcean $name RESPONSE: $rcTxt DATA: $data ODATA: $odata";
return $name; return $name;
} else { } else {
@ -7756,6 +7778,7 @@ sub EnOcean_Parse($$) {
} elsif ($st eq "switch.7F" && $manufID eq "00D") { } elsif ($st eq "switch.7F" && $manufID eq "00D") {
$msg = $EnO_ptm200btn[($db[0] & 0xE0) >> 5]; $msg = $EnO_ptm200btn[($db[0] & 0xE0) >> 5];
# 2nd action
$msg .= "," . $EnO_ptm200btn[($db[0] & 0x0E) >> 1] if ($db[0] & 1); $msg .= "," . $EnO_ptm200btn[($db[0] & 0x0E) >> 1] if ($db[0] & 1);
$msg .= " released" if (!($db[0] & 0x10)); $msg .= " released" if (!($db[0] & 0x10));
push @event, "3:buttons:" . ($db[0] & 0x10 ? "pressed" : "released"); push @event, "3:buttons:" . ($db[0] & 0x10 ? "pressed" : "released");
@ -7777,10 +7800,17 @@ sub EnOcean_Parse($$) {
} elsif ($st eq "liquidLeakage") { } elsif ($st eq "liquidLeakage") {
# liquid leakage sensor, not tested # liquid leakage sensor, not tested
$msg = "wet" if ($db[0] == 0x11); $msg = "wet" if ($db[0] == 0x11);
# } elsif (($db[0] & 7) == 6) {
# # bistable switch
# $msg = ($db[0] & 0xE0) >> 5 == 2 ? 'BI' : 'B0';
# push @event, "3:buttons:pressed";
# push @event, "3:channelB:$msg";
# push @event, "3:$event:$msg";
} else { } else {
# Theoretically there can be a released event with some of the A0, BI # Theoretically there can be a released event with some of the A0, BI
# pins set, but with the plastic cover on this wont happen. # pins set, but with the plastic cover on this wont happen.
$msg = $EnO_ptm200btn[($db[0] & 0xE0) >> 5]; $msg = $EnO_ptm200btn[($db[0] & 0xE0) >> 5];
# 2nd action
$msg .= "," . $EnO_ptm200btn[($db[0] & 0x0E) >> 1] if ($db[0] & 1); $msg .= "," . $EnO_ptm200btn[($db[0] & 0x0E) >> 1] if ($db[0] & 1);
$msg .= " released" if (!($db[0] & 0x10)); $msg .= " released" if (!($db[0] & 0x10));
push @event, "3:buttons:" . ($db[0] & 0x10 ? "pressed" : "released"); push @event, "3:buttons:" . ($db[0] & 0x10 ? "pressed" : "released");
@ -8025,6 +8055,10 @@ sub EnOcean_Parse($$) {
$st = "raw"; $st = "raw";
} }
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, $attr{$name}{eep} eq 'raw' ? 1 : 0, 0, $hash->{DEF}, $attr{$name}{eep} eq 'raw' ? 'FF-FF-FF' : $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
} else { } else {
Log3 $name, 4, "EnOcean $name teach-in with subType $st locked, set transceiver in teach mode."; Log3 $name, 4, "EnOcean $name teach-in with subType $st locked, set transceiver in teach mode.";
return ""; return "";
@ -9369,7 +9403,7 @@ sub EnOcean_Parse($$) {
} elsif ($st eq "roomSensorControl.05") { } elsif ($st eq "roomSensorControl.05") {
# Room Sensor and Control Unit (EEP A5-10-01 ... A5-10-0D) # Room Sensor and Control Unit (EEP A5-10-01 ... A5-10-0D)
# [Eltako FTR55D, FTR55H, Thermokon SR04 *, Thanos SR *, untested] # [Eltako FTR55D, FTR55H, Thermokon SR04 *, Thanos SR *]
# $db[3] is the fan speed or night reduction for Eltako # $db[3] is the fan speed or night reduction for Eltako
# $db[2] is the setpoint where 0x00 = min ... 0xFF = max or # $db[2] is the setpoint where 0x00 = min ... 0xFF = max or
# reference temperature for Eltako where 0x00 = 0°C ... 0xFF = 40°C # reference temperature for Eltako where 0x00 = 0°C ... 0xFF = 40°C
@ -9404,6 +9438,12 @@ sub EnOcean_Parse($$) {
} }
} }
push @event, "3:temperature:$temp"; push @event, "3:temperature:$temp";
readingsDelete($hash, "alarm");
if (AttrVal($name, "signOfLife", 'off') 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", 1320), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0);
}
} elsif ($st eq "roomSensorControl.01") { } elsif ($st eq "roomSensorControl.01") {
# Room Sensor and Control Unit (EEP A5-04-01, A5-10-10 ... A5-10-14) # Room Sensor and Control Unit (EEP A5-04-01, A5-10-10 ... A5-10-14)
@ -10766,14 +10806,18 @@ sub EnOcean_Parse($$) {
# $db[0]_bit_2 is store final value, not used, because # $db[0]_bit_2 is store final value, not used, because
# dimming value is always stored # dimming value is always stored
push @event, "3:rampTime:$db[1]"; push @event, "3:rampTime:$db[1]";
push @event, "3:state:" . ($db[0] & 0x01 ? "on" : "off"); push @event, "3:state:" . ($db[0] & 1 ? "on" : "off");
if ($db[0] & 4) { my $dim = $db[0] & 4 ? sprintf("%d", $db[2] * 100 / 255) : $db[2];
# Relative Dimming Range push @event, "3:dim:$dim";
push @event, "3:dim:" . sprintf "%d", $db[2] * 100 / 255; push @event, "3:dimValueLast:$dim" if ($dim > 0);
} else { # constLightCtrl
push @event, "3:dim:$db[2]"; $hash->{helper}{constLightCtrl}[0] = $hash;
} $hash->{helper}{constLightCtrl}[1] = 'parse';
push @event, "3:dimValueLast:$db[2]" if ($db[2] > 0); $hash->{helper}{constLightCtrl}[2] = 'response';
$hash->{helper}{constLightCtrl}[3] = $dim;
$hash->{helper}{constLightCtrl}[4] = 4;
EnOcean_constLightCtrl($hash->{helper}{constLightCtrl});
} elsif ($db[3] == 3) { } elsif ($db[3] == 3) {
# Setpoint shift # Setpoint shift
# $db1 is setpoint shift where 0 = -12.7 K ... 255 = 12.8 K # $db1 is setpoint shift where 0 = -12.7 K ... 255 = 12.8 K
@ -11808,6 +11852,115 @@ sub EnOcean_Parse($$) {
#EnOcean_multisensor_01Snd($ctrl, $hash, $packetType); #EnOcean_multisensor_01Snd($ctrl, $hash, $packetType);
} }
} elsif ($st eq "multisensor.50") {
# Multisensor Windows Handle
# (D2-06-50)
# message type
my $msgType = hex(substr($data, 0, 2));
if ($msgType == 1) {
# windows status
push @event, "1:telegramType:" . ($db[6] & 0x80 ? "heartbeat" : "event");
my %handlePosition = (
0 => ["none", undef],
1 => ["closed", 'F0'],
2 => ["open", 'E0'],
3 => ["tilted", 'D0'],
4 => ["closed", 'F0'],
5 => ["open", 'E0'],
6 => ["tilted", 'D0'],
7 => ["closed", 'F0'],
8 => ["open", 'E0'],
9 => ["tilted", 'D0']
);
my %windowPosition = (
0 => ["none", undef],
1 => ["closed", '09'],
2 => ["closed", '09'],
3 => ["closed", '09'],
4 => ["open", '08'],
5 => ["open", '08'],
6 => ["open", '08'],
7 => ["tilted", '08'],
8 => ["tilted", '08'],
9 => ["tilted", '08']
);
my $position = $db[6] & 0x7F;
my $handle;
if (exists $handlePosition{$position}) {
$handle = $handlePosition{$position}[0];
} else {
$handle = "unknown";
}
push @event, "1:handle:$handle";
# forward handle position (RPS telegam)
if (defined($handlePosition{$position}[1]) && defined(AttrVal($name, "subDefH", undef))) {
EnOcean_SndRadio(undef, $hash, $packetType, "F6", $handlePosition{$position}[1], AttrVal($name, "subDefH", "0" x 8), '20', 'FFFFFFFF');
}
my $window;
if (exists $windowPosition{$position}) {
$window = $windowPosition{$position}[0];
} else {
$window = 'unknown';
}
push @event, "1:window:$window";
# forward window state (1BS telegam)
if (defined($windowPosition{$position}[1]) && defined(AttrVal($name, "subDefW", undef))) {
EnOcean_SndRadio(undef, $hash, $packetType, "D5", $windowPosition{$position}[1], AttrVal($name, "subDefW", "0" x 8), '00', 'FFFFFFFF');
}
push @event, "1:statusCntr:". substr($data, 4, 8);
my $battery = $db[1] & 0x80 ? 'low' : 'ok';
push @event, "1:battery:$battery";
push @event, "1:batteryPercent:". ($db[1] & 0x7F);
my %errorStatus = (
0 => "ok",
1 => "error",
2 => "not_supported",
3 => "reserved"
);
push @event, "1:statusMotion:" . $errorStatus{(($db[0] & 0xC0) >> 6)};
push @event, "1:statusAcceleration:" . $errorStatus{(($db[0] & 0x30) >> 4)};
push @event, "1:statusMagnetic:" . $errorStatus{(($db[0] & 0x0C) >> 2)};
push @event, "1:statusSystem:" . $errorStatus{($db[0] & 3)};
push @event, "1:state:W: $window H: $handle B: $battery";
} elsif ($msgType == 2) {
# alarm status
push @event, "1:burglaryAlarm:" . ($db[0] & 1 ? 'on' : 'off');
} elsif ($msgType == 0x11) {
# calibrate
my %calStatus = (
0 => "ok",
1 => "error",
2 => "invalid"
);
my $calStatus = $db[0] & 0xC0;
if (exists $calStatus{$calStatus}) {
push @event, "3:statusCalibration:$calStatus{$calStatus}";
} else {
push @event, "3:statusCalibration:unknown";
}
my %cal = (
0 => "none",
1 => "close_handle",
2 => "open_handle",
3 => "tilt_handle",
0x0A => "close_window"
);
my $cal = $db[0] & 0x3F;
if (exists $cal{$cal}) {
push @event, "3:calibrationStep:$cal{$cal}";
} else {
push @event, "3:calibrationStep:unknown";
}
} else {
}
readingsDelete($hash, "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", 990), 'EnOcean_readingsSingleUpdate', $hash->{helper}{timer}{alarm}, 0);
}
} elsif ($st eq "roomCtrlPanel.01") { } elsif ($st eq "roomCtrlPanel.01") {
# Room Control Panel # Room Control Panel
# (D2-11-01 - D2-11-08) # (D2-11-01 - D2-11-08)
@ -12553,18 +12706,27 @@ sub EnOcean_Parse($$) {
my $repeatingCounter = $db[0] & 0x0F; my $repeatingCounter = $db[0] & 0x0F;
if ($repeatingCounter < 0x0F) {$hash->{Dev_RepeatingCounter} = $repeatingCounter}; if ($repeatingCounter < 0x0F) {$hash->{Dev_RepeatingCounter} = $repeatingCounter};
} elsif ($signalMID == 11) { } elsif ($signalMID == 11) {
DoTrigger($name, "SIGNAL: DUTYCYCLE_LIMIT: " . ($db[0] >> 4 == 1 ? 'released' : 'reached'), 1); DoTrigger($name, "SIGNAL: DUTYCYCLE_LIMIT: " . (($db[0] & 0x0F) == 1 ? 'released' : 'reached'), 1);
Log3 $name, 2, "EnOcean $name SIGNAL DUTYCYCLE_LIMIT: " . ($db[0] >> 4 == 1 ? 'released' : 'reached'); Log3 $name, 2, "EnOcean $name SIGNAL DUTYCYCLE_LIMIT: " . ($db[0] >> 4 == 1 ? 'released' : 'reached');
} elsif ($signalMID == 12) { } elsif ($signalMID == 12) {
DoTrigger($name, "SIGNAL: Dev_CHANGED", 1); DoTrigger($name, "SIGNAL: Dev_CHANGED", 1);
Log3 $name, 2, "EnOcean $name SIGNAL Dev_CHANGED"; Log3 $name, 2, "EnOcean $name SIGNAL Dev_CHANGED";
} elsif ($signalMID == 13) { } elsif ($signalMID == 13) {
my @harvester = ('very_good', 'good', 'average', 'bad', 'very_bad'); my @harvester = ('very_good', 'good', 'average', 'bad', 'very_bad');
push @event, "3:harvester:" . $harvester[$db[0]]; push @event, "3:harvester:" . $harvester[$db[0] & 0x0F];
} elsif ($signalMID == 14) { } elsif ($signalMID == 14) {
DoTrigger($name, "SIGNAL: TX_MODE_OFF", 1); DoTrigger($name, "SIGNAL: TX_MODE_OFF", 1);
} elsif ($signalMID == 15) { } elsif ($signalMID == 15) {
DoTrigger($name, "SIGNAL: TX_MODE_ON", 1); DoTrigger($name, "SIGNAL: TX_MODE_ON", 1);
} elsif ($signalMID == 16) {
if ($db[0] <= 100) {
push @event, "3:batteryPercentBackup:$db[0]";
} else {
readingsDelete($hash, "batteryPercentBackup");
}
} elsif ($signalMID == 17) {
# learn mode status
#push @event, "3:batteryPercent:$db[0]";
} }
} elsif ($rorg eq "B2") { } elsif ($rorg eq "B2") {
@ -12768,6 +12930,9 @@ sub EnOcean_Parse($$) {
$mid = $EnO_manuf{$mid} if($EnO_manuf{$mid}); $mid = $EnO_manuf{$mid} if($EnO_manuf{$mid});
push @event, "3:teach:GP teach-in accepted Manufacturer: $mid"; push @event, "3:teach:GP teach-in accepted Manufacturer: $mid";
Log3 $name, 2, "EnOcean $name GP teach-in accepted Manufacturer: $mid"; Log3 $name, 2, "EnOcean $name GP teach-in accepted Manufacturer: $mid";
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, 0, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
# store attr subType, manufID, gpDef ... # store attr subType, manufID, gpDef ...
EnOcean_CommandSave(undef, undef); EnOcean_CommandSave(undef, undef);
@ -12781,7 +12946,9 @@ sub EnOcean_Parse($$) {
Log3 $name, 2, "EnOcean $name GP teach-in deletion response send to $senderID"; Log3 $name, 2, "EnOcean $name GP teach-in deletion response send to $senderID";
} }
Log3 $name, 2, "EnOcean $name GP teach-in delete request executed"; Log3 $name, 2, "EnOcean $name GP teach-in delete request executed";
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, 4, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
} }
} elsif ($rorg eq "B1" && $teach) { } elsif ($rorg eq "B1" && $teach) {
@ -12855,7 +13022,6 @@ sub EnOcean_Parse($$) {
} elsif ($rorg eq "D4" && $teach) { } elsif ($rorg eq "D4" && $teach) {
# UTE - Universal Uni- and Bidirectional Teach-In / Teach-Out # UTE - Universal Uni- and Bidirectional Teach-In / Teach-Out
#
Log3 $name, 5, "EnOcean $name UTE teach-in received from $senderID"; Log3 $name, 5, "EnOcean $name UTE teach-in received from $senderID";
my $rorg = sprintf "%02X", $db[0]; my $rorg = sprintf "%02X", $db[0];
my $func = sprintf "%02X", $db[1]; my $func = sprintf "%02X", $db[1];
@ -12904,6 +13070,9 @@ sub EnOcean_Parse($$) {
Log3 $name, 2, "EnOcean $name UTE teach-in response send to $senderID"; Log3 $name, 2, "EnOcean $name UTE teach-in response send to $senderID";
} }
Log3 $name, 2, "EnOcean $name UTE teach-in accepted EEP $rorg-$func-$type Manufacturer: $mid"; Log3 $name, 2, "EnOcean $name UTE teach-in accepted EEP $rorg-$func-$type Manufacturer: $mid";
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, 0, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
} else { } else {
# Teach-In EEP not supported # Teach-In EEP not supported
$attr{$name}{subType} = "raw"; $attr{$name}{subType} = "raw";
@ -12921,6 +13090,9 @@ sub EnOcean_Parse($$) {
Log3 $name, 2, "EnOcean $name UTE teach-in response send to $senderID"; Log3 $name, 2, "EnOcean $name UTE teach-in response send to $senderID";
} }
Log3 $name, 2, "EnOcean $name UTE teach-in accepted EEP $rorg-$func-$type not supported Manufacturer: $mid"; Log3 $name, 2, "EnOcean $name UTE teach-in accepted EEP $rorg-$func-$type not supported Manufacturer: $mid";
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, 1, 0, $hash->{DEF}, "$rorg-$func-$type");
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
} }
# store attr subType, manufID ... # store attr subType, manufID ...
EnOcean_CommandSave(undef, undef); EnOcean_CommandSave(undef, undef);
@ -12936,6 +13108,9 @@ sub EnOcean_Parse($$) {
Log3 $name, 2, "EnOcean $name UTE teach-in deletion response send to $senderID"; Log3 $name, 2, "EnOcean $name UTE teach-in deletion response send to $senderID";
} }
Log3 $name, 2, "EnOcean $name UTE teach-in delete request executed"; Log3 $name, 2, "EnOcean $name UTE teach-in delete request executed";
# signal telegram learn mode status
my $signalData = EnOcean_signalLearnModeStatus(0, 1, 0, 4, 0, $hash->{DEF}, $attr{$name}{eep});
EnOcean_SndRadio(undef, $hash, 1, 'D0', $signalData, defined($attr{$name}{subDef}) ? $attr{$name}{subDef} : '0' x 8, '00', 'F' x 8);
} }
} else { } else {
# Teach-In Respose telegram received # Teach-In Respose telegram received
@ -14924,6 +15099,113 @@ sub EnOcean_Notify(@) {
return undef; return undef;
} }
#####*
sub EnOcean_constLightCtrl($) {
my ($param) = @_;
my ($hash, $mode, $cmd, $dimSet) = @$param;
my $lightCtrl = $hash->{constLightCtrl} // return;
my $name = $hash->{NAME};
#Log3 $hash->{NAME}, 3, "EnOcean $hash->{NAME} constLightCtrl: 1 CMD: $hash->{helper}{constLightCtrl}[2] " . "CTRL: " . ($hash->{helper}{constLightCtrl}[6] // 'undef') . " RESPONSE: " . ($hash->{helper}{constLightCtrl}[7] // 'undef');
RemoveInternalTimer($hash->{helper}{constLightCtrl}) if(exists $hash->{helper}{constLightCtrl});
# stop constLightCtrl
if (!defined($attr{$name}{brightnessRefDev}) || $cmd !~ m/^dim|response|openLoopCtrl|closedLoopCtrl$/) {
delete $hash->{constLightCtrl};
delete $hash->{helper}{constLightCtrl};
return;
}
# constLightCtrl command set dim is executed, lock recursion
return if (!defined($hash->{helper}{constLightCtrl}[6]) && $cmd eq 'dim');
my $brightness = ReadingsVal($attr{$name}{brightnessRefDev}, "brightness", undef);
# stop constLightCtrl
if (!defined($brightness)) {
delete $hash->{constLightCtrl};
delete $hash->{helper}{constLightCtrl};
return;
}
#Log3 $hash->{NAME}, 3, "EnOcean $hash->{NAME} constLightCtrl: 2 CMD: $hash->{helper}{constLightCtrl}[2] " . "CTRL: " . ($hash->{helper}{constLightCtrl}[6] // 'undef');
my $dimCalc = $dimSet;
my $dimTemp;
my $logLevel = 3;
if ($hash->{constLightCtrl} eq 'openLoopCtrl') {
# calc dim
my $openLoopCtrlScale = $attr{$name}{openLoopCtrlScale} // '100:100 0:0';
my ($scaleHigh, $scaleLow) = split("[ \t][ \t]*", $openLoopCtrlScale);
my ($brightnessHigh, $dimHigh) = split(":", $scaleHigh);
my ($brightnessLow, $dimLow) = split(":", $scaleLow);
$brightnessHigh = $brightnessHigh // 100;
$brightnessLow = $brightnessLow // 0;
$dimHigh = $dimHigh // 100;
$dimLow = $dimLow // 0;
$dimCalc = ($dimLow*$brightnessHigh-$brightnessLow*$dimHigh)/($dimLow-$dimHigh)+
($brightnessLow-$brightnessHigh)/($dimLow-$dimHigh)*$brightness;
#Log3 $hash->{NAME}, 3, "EnOcean $hash->{NAME} constLightCtrl: 3 BRIGHTNESS: $brightness DIM: $dimCalc";
$dimCalc = $dimCalc < 0 ? 0 : $dimCalc;
$dimCalc = $dimCalc > 100 ? 100 : $dimCalc;
$dimTemp = $dimCalc;
$dimCalc = int(EnOcean_EMA($hash, 'dim', $dimCalc, 0.25));
}
if ($cmd eq 'dim') {
if (abs($dimCalc - $dimSet) > 5) {
# constLightCtrl execute flag
$hash->{helper}{constLightCtrl}[6] = undef;
# maximum of two responses are expected
$hash->{helper}{constLightCtrl}[7] = 2;
my @setCmd = ($name, 'dim', $dimCalc);
if (defined $hash->{helper}{constLightCtrl}[4]) {
$setCmd[3] = $hash->{helper}{constLightCtrl}[4];
$setCmd[4] = $hash->{helper}{constLightCtrl}[5] if (defined $hash->{helper}{constLightCtrl}[5])
}
EnOcean_Set($hash, @setCmd);
} else {
# clear response flag
$hash->{helper}{constLightCtrl}[7] = undef;
}
$hash->{helper}{constLightCtrl}[6] = 5;
} elsif ($cmd eq 'response') {
if (defined $hash->{helper}{constLightCtrl}[7]) {
# continue constLightCtrl
$hash->{helper}{constLightCtrl}[2] = 'dim';
$hash->{helper}{constLightCtrl}[6] = 5;
# clear response flag
-- $hash->{helper}{constLightCtrl}[7] || ($hash->{helper}{constLightCtrl}[7] = undef);
} else {
# user interaction on the actuator terminates the constLightCtrl
delete $hash->{constLightCtrl};
delete $hash->{helper}{constLightCtrl};
return;
}
} else {
# start constLightCtrl
$hash->{helper}{constLightCtrl}[2] = 'dim';
$hash->{helper}{constLightCtrl}[6] = 2;
# maximum of two responses are expected
$hash->{helper}{constLightCtrl}[7] = 2;
}
InternalTimer(gettimeofday() + $hash->{helper}{constLightCtrl}[6], 'EnOcean_constLightCtrl', $hash->{helper}{constLightCtrl}, 0);
Log3 $hash->{NAME}, 3, "EnOcean $hash->{NAME} constLightCtrl: 4 B: $brightness D: $dimTemp >> $dimCalc CMD: $hash->{helper}{constLightCtrl}[2] " . "CTRL: " . ($hash->{helper}{constLightCtrl}[6] // 'undef') . " RESPONSE: " . ($hash->{helper}{constLightCtrl}[7] // 'undef');
return $logLevel;
}
sub EnOcean_EMA($$$$) {
# exponential moving average (EMA)
# 0 < $wheight < 1
my ($hash, $readingName, $readingVal, $wheight) = @_;
my $average = exists($hash->{helper}{ema}{$readingName}{average}) ? $hash->{helper}{ema}{$readingName}{average} : $readingVal;
$average = $wheight * $readingVal + (1 - $wheight) * $average;
$hash->{helper}{ema}{$readingName}{average} = $average;
return $average;
}
sub EnOcean_signalLearnModeStatus($$$$$$$) {
my ($linkTable, $recTeachRequMsg, $learnModeType, $teachResult, $LearnModeTimeout, $devID, $eep) = @_;
my $data = '11';
$data .= sprintf "%02X%02X", $linkTable << 7 | $recTeachRequMsg << 6 | $learnModeType << 4 | $teachResult, $LearnModeTimeout;
$eep = defined($eep) ? $eep : 'FF-FF-FF';
$eep =~ m/^(..)-(..)-(..)$/;
$data .= $devID . $1 . $2 . $3;
return $data;
}
sub EnOcean_environmentAppCustomCmd($) { sub EnOcean_environmentAppCustomCmd($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -18182,6 +18464,30 @@ sub EnOcean_Delete($$) {
<br><br> <br><br>
</ul> </ul>
<b>Constant Light Controller</b><br>
<ul>
The constant light controller dims lamps depending on the ambient brightness. Two types of constant light
controller are used.<br><br>
For the closed loop control, the ambient brightness in the room itself is measured.
This value is entered as an actual value in the control. The sensor must measure the brightness,
for example, on the table top of the desk. For a stable control, changes in the brightness value
by the outside light and the lamps must be detected immediately and at short intervals.
Currently, the function of the closed loop control is not yet available in the EnOcean module.<br><br>
In the case of open loop control, the lamps are dimmed linearly depending on the outside light.
The brightness sensor must detect the outside brightness and must not be affected by the luminous flux
of the lamps itself. The open loop control is switched on by
<ul><br>
<code>set &lt;device&gt; openLoopCtrl</code><br>
</ul><br><br>
The automatic control can be turned off by any other command. If the dimmaktor reports its stats,
the control is also deactivated any manual input, for example on a wall switch.<br>
The straight-line characteristic is determined via the attribute <a href="#EnOcean_openLoopCtrlScale">openLoopCtrlScale</a>.
Below and above the characteristic thresholds, the dimming values remain constant at the value of dimHigh or dimLow.
The name of the brightness sensor must be specified in the <a href="#EnOcean_brightnessRefDev">brightnessRefDev</a> attribute.<br>
Currently, the constant light control is available for the gateway/dimming profile. More profiles will follow.
<br><br>
</ul>
<b>Remote Management</b><br> <b>Remote Management</b><br>
<ul> <ul>
Remote Management allows EnOcean devices to be configured and maintained over the air. Remote Management allows EnOcean devices to be configured and maintained over the air.
@ -18302,6 +18608,7 @@ sub EnOcean_Delete($$) {
<li>Energy harvesting and reporting</li> <li>Energy harvesting and reporting</li>
<li>Failure & issues reporting</li> <li>Failure & issues reporting</li>
<li>Radio link quality reporting</li> <li>Radio link quality reporting</li>
<li>Learn Mode Status</li>
</ul> </ul>
The Signal Telegram function commands are activated by the attribute <a href="#EnOcean_signal">signal</a>. The Signal Telegram function commands are activated by the attribute <a href="#EnOcean_signal">signal</a>.
All commands are described in the signal telegram chapter of the <a href="#EnOcean_signalGet">get</a>-commands. All commands are described in the signal telegram chapter of the <a href="#EnOcean_signalGet">get</a>-commands.
@ -18336,21 +18643,35 @@ sub EnOcean_Delete($$) {
<b>Security features</b><br> <b>Security features</b><br>
<ul> <ul>
The receiving and sending of encrypted messages is supported. This module currently allows the secure operating mode of The receiving and sending of encrypted messages is supported. This module currently allows the secure operating mode of
a variety of sensors and PTM 215 based switches.<br> a variety of sensors and PTM 210 / PTM 215 based switches.<br>
To receive secured telegrams, you first have to start the teach in mode via<br><br> To receive secured telegrams, you first have to start the teach in mode via<br><br>
<code>set &lt;IODev&gt; teach &lt;t/s&gt;</code><br><br> <code>set &lt;IODev&gt; teach &lt;t/s&gt;</code><br><br>
On the PTM 215 module doing the following:<br> Since the beginning of 2021, the PTM 210 / PTM 215 modules offer a normal mode and two secure modes
<ul>
<li>Implicit RLC (legacy, not recommended)</li>
<li>Explicit RLC (recommended)</li><br>
</ul>
In the case of the Implicit RLC doing the following:<br>
<ul> <ul>
<li>Remove the switch cover of the module</li> <li>Remove the switch cover of the module</li>
<li>Press both buttons of one rocker side (A0 & A1 or B0 & B1)</li> <li>Press both nipples of one rocker side (A0 & AI or B0 & BI)</li>
<li>While keeping the buttons pressed actuate the energy bow twice.</li><br> <li>While keeping the nipples pressed actuate the energy bow twice.</li><br>
</ul> </ul>
This generates two teach-in telegrams which create a Fhem device with the subType "switch.00" and synchronize the Fhem with This generates two teach-in telegrams which create a Fhem device with the subType "switch.00" and synchronize the Fhem with
the PTM 215. Both the Fhem and the PTM 215 now maintain a counter which is used to generate a rolling code encryption scheme. the PTM 210 / PTM 215. Both the Fhem and the PTM210 / PTM 215 now maintain a counter which is used to generate a rolling code encryption scheme.
Also during teach-in, a private key is transmitted to the Fhem. The counter value is allowed to desynchronize for a maximum of Also during teach-in, a private key is transmitted to the Fhem. The counter value is allowed to desynchronize for a maximum of
128 counts, to allow compensating for missed telegrams, if this value is crossed you need to teach-in the PTM 215 again. Also 128 counts, to allow compensating for missed telegrams, if this value is crossed you need to teach-in the PTM 215 again. Also
if your Fhem installation gets erased including the state information, you need to teach in the PTM 215 modules again (which if your Fhem installation gets erased including the state information, you need to teach in the PTM 210 / PTM 215 modules again (which
you would need to do anyway).<br><br> you would need to do anyway).<br><br>
In the case of the Explicit RLC doing the following:<br>
<ul>
<li>Remove the switch cover of the module</li>
<li>Press any 3 nipples</li>
<li>While keeping the nipples pressed actuate the energy bow twice.</li><br>
</ul>
In this mode, the PTM module sends the RLC value as part of every data telegram. With
transmission of the RLC in every data telegram a desynchronization of the RLC counters
between receivers and transmitter like described above cannot happen.<br><br>
To send secured telegrams, you first have send a secure teach-in to the remode device<br><br> To send secured telegrams, you first have send a secure teach-in to the remode device<br><br>
<ul> <ul>
@ -18819,6 +19140,9 @@ sub EnOcean_Delete($$) {
or to a setpoint deviation of +/- 3 K be limited. For this use the optional parameter or to a setpoint deviation of +/- 3 K be limited. For this use the optional parameter
[block] = lock|unlock, unlock is default.<br> [block] = lock|unlock, unlock is default.<br>
The profile behaves like a master or slave, see <a href="#EnOcean_devMode">devMode</a>.<br> The profile behaves like a master or slave, see <a href="#EnOcean_devMode">devMode</a>.<br>
A monitoring period can be set for signOfLife telegrams of the sensor, see
<a href="#EnOcean_signOfLife">signOfLife</a> and <a href="#EnOcean_signOfLifeInterval">signOfLifeInterval</a>.
Default is "off" and an interval of 1320 sec.<br>
The attr subType must be roomSensorControl.05 and attr manufID must be 00D. The attr subType must be roomSensorControl.05 and attr manufID must be 00D.
The attributes must be set manually. The attributes must be set manually.
</li> </li>
@ -19246,7 +19570,9 @@ sub EnOcean_Delete($$) {
for Eltako: t = 1 = fast dimming ... 255 = slow dimming or 0 = dimming speed on the dimmer used<br> for Eltako: t = 1 = fast dimming ... 255 = slow dimming or 0 = dimming speed on the dimmer used<br>
The attr subType must be gateway and gwCmd must be dimming. This is done if the device was The attr subType must be gateway and gwCmd must be dimming. This is done if the device was
created by autocreate.<br> created by autocreate.<br>
For Eltako devices attributes must be set manually. Use the sensor type "PC/FVS" for Eltako devices. For Eltako devices this attributes must be set manually. In addition, the attribute manufID must be set with 00D.
Alternatively, the Eltako device can be fully defined using the inofficial EEPs G5-38-08, H5-38-08 or I5-38-08.
Use the sensor type "PC/FVS" for Eltako devices.
</li> </li>
<br><br> <br><br>
@ -20225,6 +20551,10 @@ sub EnOcean_Delete($$) {
Set switching delay for reading dayNight based on the reading brightness. The reading dayNight is reset or set Set switching delay for reading dayNight based on the reading brightness. The reading dayNight is reset or set
if the thresholds are permanently undershot or exceed during the delay time. if the thresholds are permanently undershot or exceed during the delay time.
</li> </li>
<li><a name="EnOcean_brightnessRefDev">brightnessRefDev</a> &lt;name&gt;<br>
Name of the device whose reference value is read. The reference values is
the reading brightness.
</li>
<li><a name="EnOcean_brightnessSunny">brightnessSunny</a> E_min/lx:E_max/lx, <li><a name="EnOcean_brightnessSunny">brightnessSunny</a> E_min/lx:E_max/lx,
[brightnessSunny] = 0...99000:0...99000, 20000:40000 is default.<br> [brightnessSunny] = 0...99000:0...99000, 20000:40000 is default.<br>
Set switching thresholds for reading isSunny based on the reading brightness. Set switching thresholds for reading isSunny based on the reading brightness.
@ -20501,6 +20831,10 @@ sub EnOcean_Delete($$) {
[observeRefDev] = &lt;name of the own device&gt; is default<br> [observeRefDev] = &lt;name of the own device&gt; is default<br>
Names of the devices to be observed. The list must be separated by spaces. Names of the devices to be observed. The list must be separated by spaces.
</li> </li>
<li><a name="EnOcean_openLoopCtrlScale">openLoopCtrlScale</a> &lt;dimHigh&gt;:&lt;brightness1&gt; &lt;dimLow&gt;:&lt;brightness2&gt;,
[openLoopCtrlScale] = 100:100 0:0 is default.<br>
Bases of the straight-line characteristic of the open loop control dimming function.
</li>
<li><a name="EnOcean_pidActorCallBeforeSetting">pidActorCallBeforeSetting</a>, <li><a name="EnOcean_pidActorCallBeforeSetting">pidActorCallBeforeSetting</a>,
[pidActorCallBeforeSetting] = not defined is default<br> [pidActorCallBeforeSetting] = not defined is default<br>
Callback-function, which can manipulate the actorValue. Further information see modul PID20. Callback-function, which can manipulate the actorValue. Further information see modul PID20.
@ -20935,7 +21269,8 @@ sub EnOcean_Delete($$) {
</li> </li>
<br><br> <br><br>
<li>Switch (EEP F6-02-01 ... F6-03-02)<br> <li>Pushbutton Switch (EEP F6-02-01 ... F6-03-02)<br>
[EnOcean PTM 210, PTM 215 Module]<br>
<ul> <ul>
<li>A0</li> <li>A0</li>
<li>AI</li> <li>AI</li>
@ -21002,7 +21337,7 @@ sub EnOcean_Delete($$) {
<br><br> <br><br>
<li>Pushbutton Switch (EEP D2-03-00)<br> <li>Pushbutton Switch (EEP D2-03-00)<br>
[EnOcean PTM 215 Modul]<br> [EnOcean PTM 210 / PTM 215 Module]<br>
<ul> <ul>
<li>A0</li> <li>A0</li>
<li>AI</li> <li>AI</li>
@ -21484,6 +21819,9 @@ sub EnOcean_Delete($$) {
<a href="#scaleDecimals">scaleDecimals</a> for the additional scaled reading <a href="#scaleDecimals">scaleDecimals</a> for the additional scaled reading
setpointScaled. Use attribut <a href="#userReadings">userReadings</a> to setpointScaled. Use attribut <a href="#userReadings">userReadings</a> to
adjust the scaling alternatively.<br> adjust the scaling alternatively.<br>
A monitoring period can be set for signOfLife telegrams of the sensor, see
<a href="#EnOcean_signOfLife">signOfLife</a> and <a href="#EnOcean_signOfLifeInterval">signOfLifeInterval</a>.
Default is "off" and an interval of 1320 sec.<br>
The attr subType must be roomSensorControl.05 and attr The attr subType must be roomSensorControl.05 and attr
manufID must be 00D for Eltako Devices. This is done if the device was manufID must be 00D for Eltako Devices. This is done if the device was
created by autocreate. created by autocreate.
@ -22581,6 +22919,7 @@ sub EnOcean_Delete($$) {
see <a href="#EnOcean_teach-in">Bidirectional Teach-In / Teach-Out</a>. see <a href="#EnOcean_teach-in">Bidirectional Teach-In / Teach-Out</a>.
</li> </li>
<br><br> <br><br>
<li>Multisensor Window Handle (D2-06-01)<br> <li>Multisensor Window Handle (D2-06-01)<br>
[Soda GmbH]<br> [Soda GmbH]<br>
<ul> <ul>
@ -22588,16 +22927,16 @@ sub EnOcean_Delete($$) {
<li>alarms: &lt;alarms&gt; (Range: alarms = 00000000 ... FFFFFFFF)</li> <li>alarms: &lt;alarms&gt; (Range: alarms = 00000000 ... FFFFFFFF)</li>
<li>battery: ok|low</li> <li>battery: ok|low</li>
<li>batteryLowClick: enabled|disabled</li> <li>batteryLowClick: enabled|disabled</li>
<li>burglaryAlarm: off|on|invalid|not_supported|unknown</li>
<li>handle: up|down|left|right|invalid|not_supported|unknown</li>
<li>blinkInterval: t/s|unknown (Range: t = 3 s ... 255 s)</li> <li>blinkInterval: t/s|unknown (Range: t = 3 s ... 255 s)</li>
<li>blinkIntervalSet: t/s|unknown (Range: t = 3 s ... 255 s)</li> <li>blinkIntervalSet: t/s|unknown (Range: t = 3 s ... 255 s)</li>
<li>brightness: E/lx|over_range|invalid|not_supported|unknown (Sensor Range: E = 0 lx ... 60000 lx)</li> <li>brightness: E/lx|over_range|invalid|not_supported|unknown (Sensor Range: E = 0 lx ... 60000 lx)</li>
<li>burglaryAlarm: off|on|invalid|not_supported|unknown</li>
<li>buttonLeft: pressed|released|invalid|not_supported|unknown</li> <li>buttonLeft: pressed|released|invalid|not_supported|unknown</li>
<li>buttonLeftPresses: &lt;buttonLeftPresses&gt; (Range: buttonLeftPresses = 00000000 ... FFFFFFFF)</li> <li>buttonLeftPresses: &lt;buttonLeftPresses&gt; (Range: buttonLeftPresses = 00000000 ... FFFFFFFF)</li>
<li>buttonRight: pressed|released|invalid|not_supported|unknown</li> <li>buttonRight: pressed|released|invalid|not_supported|unknown</li>
<li>buttonRightPresses: &lt;buttonRightPresses&gt; (Range: buttonRightPresses = 00000000 ... FFFFFFFF)</li> <li>buttonRightPresses: &lt;buttonRightPresses&gt; (Range: buttonRightPresses = 00000000 ... FFFFFFFF)</li>
<li>energyStorage: 1/%|unknown</li> <li>energyStorage: 1/%|unknown</li>
<li>handle: up|down|left|right|invalid|not_supported|unknown</li>
<li>handleClosedClick: enabled|disabled</li> <li>handleClosedClick: enabled|disabled</li>
<li>handleMoveClosed: &lt;handleMoveClosed&gt; (Range: handleMoveClosed = 00000000 ... FFFFFFFF)</li> <li>handleMoveClosed: &lt;handleMoveClosed&gt; (Range: handleMoveClosed = 00000000 ... FFFFFFFF)</li>
<li>handleMoveOpend: &lt;handleMoveOpend&gt; (Range: handleMoveOpend = 00000000 ... FFFFFFFF)</li> <li>handleMoveOpend: &lt;handleMoveOpend&gt; (Range: handleMoveOpend = 00000000 ... FFFFFFFF)</li>
@ -22621,6 +22960,41 @@ sub EnOcean_Delete($$) {
</li> </li>
<br><br> <br><br>
<li>Window and Handle Position Multisensor (D2-06-50)<br>
[senso secure SIEGENIA-AUBI KG]<br>
<ul>
<li>closed|open|tilted</li>
<li>alarm: dead_sensor</li>
<li>battery: ok|low</li>
<li>batteryPercent: 0 ... 100/%</li>
<li>burglaryAlarm: off|on</li>
<li>calibrationStep: none|close_handle|open_handle|tilt_handle|close_window</li>
<li>handle: closed|open|tilted</li>
<li>statusAcceleration: ok|error|not_supported</li>
<li>statusCalibration: ok|error|invalid</li>
<li>statusCntr: &lt;statusCntr&gt; (Range: statusCntr = 00000000 ... FFFFFFFF)</li>
<li>statusMagnetic: ok|error|not_supported</li>
<li>statusMotion: ok|error|not_supported</li>
<li>statusSystem: ok|error|not_supported</li>
<li>telegramType: event|heartbeat</li>
<li>window: closed|open|tilted</li>
<li>state: W: closed|open|tilted H: closed|open|tilted B: ok|low</li>
</ul><br>
The multisensor is configured using the following attributes:<br>
<ul>
<li><a href="#EnOcean_subDefH">subDefH</a></li>
<li><a href="#EnOcean_subDefW">subDefW</a></li>
</ul>
A monitoring period can be set for signOfLife telegrams of the sensor, see
<a href="#EnOcean_signOfLife">signOfLife</a> and <a href="#EnOcean_signOfLifeInterval">signOfLifeInterval</a>.
Default is "on" and an interval of 990 sec.<br>
After the teach-in, the sensor must be calibrated immediately. The procedure is described in the user manual.
If calibration was successful, the reading calibrationStep displays none and statusCalibration ok.<br>
The attr subType must be multisensor.50. This is done if the device was
created by autocreate.
</li>
<br><br>
<li>Room Control Panels (D2-10-00 - D2-10-02)<br> <li>Room Control Panels (D2-10-00 - D2-10-02)<br>
[Kieback & Peter RBW322-FTL]<br> [Kieback & Peter RBW322-FTL]<br>
<ul> <ul>