2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-21 07:56:03 +00:00

10_EnOcean: attribute devChannel adjusted

git-svn-id: https://svn.fhem.de/fhem/trunk@6749 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klaus-schauer 2014-10-12 08:43:21 +00:00
parent cb16c782b3
commit 2e3f1b3166

View File

@ -233,6 +233,8 @@ my %EnO_subType = (
#"A5.20.12" => "hvac.12", #"A5.20.12" => "hvac.12",
"A5.30.01" => "digitalInput.01", "A5.30.01" => "digitalInput.01",
"A5.30.02" => "digitalInput.02", "A5.30.02" => "digitalInput.02",
"A5.30.03" => "digitalInput.03",
"A5.30.04" => "digitalInput.04",
"A5.38.08" => "gateway", "A5.38.08" => "gateway",
"A5.3F.7F" => "manufProfile", "A5.3F.7F" => "manufProfile",
"D2.01.00" => "actuator.01", "D2.01.00" => "actuator.01",
@ -336,7 +338,7 @@ EnOcean_Initialize($)
"pollInterval rampTime repeatingAllowed:yes,no " . "pollInterval rampTime repeatingAllowed:yes,no " .
"remoteManagement:off,on rlc rlcAlgo rlcTX " . "remoteManagement:off,on rlc rlcAlgo rlcTX " .
"scaleDecimals:0,1,2,3,4,5,6,7,8,9 scaleMax scaleMin " . "scaleDecimals:0,1,2,3,4,5,6,7,8,9 scaleMax scaleMin " .
"securityLevel:unencrypted sensorMode:switch,pushbutton " . "securityCode securityLevel:unencrypted sensorMode:switch,pushbutton " .
"shutTime shutTimeCloses subDef " . "shutTime shutTimeCloses subDef " .
"subDef0 subDefI " . "subDef0 subDefI " .
"subType:$subTypeList subTypeSet:$subTypeList subTypeReading:$subTypeList " . "subType:$subTypeList subTypeSet:$subTypeList subTypeReading:$subTypeList " .
@ -381,8 +383,7 @@ EnOcean_Define($$)
} }
# Get # Get
sub sub EnOcean_Get ($@)
EnOcean_Get ($@)
{ {
my ($hash, @a) = @_; my ($hash, @a) = @_;
return "no get value specified" if (@a < 2); return "no get value specified" if (@a < 2);
@ -426,6 +427,7 @@ EnOcean_Get ($@)
# 1: execute set commands and and update reading state # 1: execute set commands and and update reading state
# 2: execute set commands delayed # 2: execute set commands delayed
my $updateState = 1; my $updateState = 1;
Log3 $name, 5, "EnOcean $name EnOcean_Get command: " . join(" ", @a);
shift @a; shift @a;
for (my $i = 0; $i < @a; $i++) { for (my $i = 0; $i < @a; $i++) {
@ -438,49 +440,53 @@ EnOcean_Get ($@)
$rorg = "C5"; $rorg = "C5";
my $seq = int(rand(2) + 1) << 6; my $seq = int(rand(2) + 1) << 6;
shift(@a); shift(@a);
Log3 $name, 3, "EnOcean get $name $cmd";
my $cntr = (((3 << 11) | $manufID) << 12) | $cmdID; my $cntr = (((3 << 11) | $manufID) << 12) | $cmdID;
$data = sprintf "%02X%08X%06X00", $seq, $cntr, ($eep << 3) | 1; $data = sprintf "%02X%08X%06X00", $seq, $cntr, ($eep << 3) | 1;
#$data = sprintf "0004%04X", $manufID; #$data = sprintf "0004%04X%06X", $manufID, ($eep << 3) | 1;
$destinationID = "FFFFFFFF"; $destinationID = "FFFFFFFF";
Log3 $name, 3, "EnOcean get $name $cmd $data";
} elsif ($cmd eq "remotePing") { } elsif ($cmd eq "remotePing") {
$cmdID = 6; $cmdID = 6;
$manufID = 0x7FF; $manufID = 0x7FF;
$packetType = 7; $packetType = 7;
$rorg = "C5"; $rorg = "C5";
my $seq = int(rand(2) + 1) << 6; #my $seq = int(rand(2) + 1) << 6;
shift(@a); shift(@a);
Log3 $name, 3, "EnOcean get $name $cmd"; #my $cntr = ($manufID << 12) | $cmdID;
my $cntr = ($manufID << 12) | $cmdID;
#$data = sprintf "%02X%08X00000000", $seq, $cntr; #$data = sprintf "%02X%08X00000000", $seq, $cntr;
$data = sprintf "0006%04X", $manufID; $data = sprintf "0006%04X", $manufID;
$destinationID = $hash->{DEF}; $destinationID = $hash->{DEF};
#($rorg, $data) = EnOcean_encapsulation($packetType, $rorg, $data, $destinationID); Log3 $name, 3, "EnOcean get $name $cmd $data";
#($rorg, $data) = EnOcean_Encapsulation($packetType, $rorg, $data, $destinationID);
} elsif ($cmd eq "remoteCommands") { } elsif ($cmd eq "remoteCommands") {
$cmdID = 7; $cmdID = 7;
$manufID = 0x7FF; $manufID = 0x7FF;
$packetType = 7;
$rorg = "C5"; $rorg = "C5";
my $seq = int(rand(2) + 1) << 6; #my $seq = int(rand(2) + 1) << 6;
shift(@a); shift(@a);
Log3 $name, 3, "EnOcean get $name $cmd"; #my $cntr = ($manufID << 12) | $cmdID;
my $cntr = ($manufID << 12) | $cmdID; #$data = sprintf "%02X%08X00000000", $seq, $cntr;
$data = sprintf "%02X%08X00000000", $seq, $cntr; $data = sprintf "0007%04X", $manufID;
$destinationID = $hash->{DEF}; $destinationID = $hash->{DEF};
($rorg, $data) = EnOcean_encapsulation($packetType, $rorg, $data, $destinationID); Log3 $name, 3, "EnOcean get $name $cmd $data";
#($rorg, $data) = EnOcean_Encapsulation($packetType, $rorg, $data, $destinationID);
} elsif ($cmd eq "remoteStatus") { } elsif ($cmd eq "remoteStatus") {
$cmdID = 8; $cmdID = 8;
$manufID = 0x7FF; $manufID = 0x7FF;
$packetType = 7;
$rorg = "C5"; $rorg = "C5";
my $seq = int(rand(2) + 1) << 6; #my $seq = int(rand(2) + 1) << 6;
shift(@a); shift(@a);
Log3 $name, 3, "EnOcean get $name $cmd"; #my $cntr = ($manufID << 12) | $cmdID;
my $cntr = ($manufID << 12) | $cmdID; #$data = sprintf "%02X%08X00000000", $seq, $cntr;
$data = sprintf "%02X%08X00000000", $seq, $cntr; $data = "000807FF";
$destinationID = $hash->{DEF}; $destinationID = $hash->{DEF};
($rorg, $data) = EnOcean_encapsulation($packetType, $rorg, $data, $destinationID); Log3 $name, 3, "EnOcean get $name $cmd $data";
#($rorg, $data) = EnOcean_Encapsulation($packetType, $rorg, $data, $destinationID);
} elsif ($st eq "actuator.01") { } elsif ($st eq "actuator.01") {
# Electronic switches and dimmers with Energy Measurement and Local Control # Electronic switches and dimmers with Energy Measurement and Local Control
@ -489,7 +495,7 @@ EnOcean_Get ($@)
shift(@a); shift(@a);
my $channel = shift(@a); my $channel = shift(@a);
$channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel); $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel);
if (!defined $channel || $channel eq "all") { if (!defined $channel || $channel eq "all" || $channel eq "FF") {
$channel = 30; $channel = 30;
} elsif ($channel eq "input") { } elsif ($channel eq "input") {
$channel = 31; $channel = 31;
@ -547,6 +553,7 @@ EnOcean_Get ($@)
# Room Control Panel # Room Control Panel
# (D2-10-00 - D2-10-02) # (D2-10-00 - D2-10-02)
$rorg = "D2"; $rorg = "D2";
shift(@a);
$updateState = 2; $updateState = 2;
if ($cmd eq "data") { if ($cmd eq "data") {
# data request # data request
@ -599,6 +606,8 @@ EnOcean_Set($@)
Log3 $name, 4, "EnOcean $name set commands disabled."; Log3 $name, 4, "EnOcean $name set commands disabled.";
return; return;
} }
my $cmdID;
my $cmdList = "";
my $data; my $data;
my $destinationID = AttrVal($name, "destinationID", undef); my $destinationID = AttrVal($name, "destinationID", undef);
if (AttrVal($name, "comMode", "uniDir") eq "biDir") { if (AttrVal($name, "comMode", "uniDir") eq "biDir") {
@ -625,19 +634,117 @@ EnOcean_Set($@)
if ($subDef !~ m/^[\dA-F]{8}$/) {return "SenderID $subDef wrong, choose <8-digit-hex-code>.";} if ($subDef !~ m/^[\dA-F]{8}$/) {return "SenderID $subDef wrong, choose <8-digit-hex-code>.";}
my $switchMode = AttrVal($name, "switchMode", "switch"); my $switchMode = AttrVal($name, "switchMode", "switch");
my $tn = TimeNow(); my $tn = TimeNow();
if (AttrVal($name, "remoteManagement", "off") eq "on") {
# Remote Management
$cmdList = "action:noArg lock:noArg remote_teach-in:noArg remote_teach-out:noArg setCode:noArg unlock:noArg ";
}
# control set actions # control set actions
# $updateState = -1: no set commands available e. g. sensors # $updateState = -1: no set commands available e. g. sensors
# 0: execute set commands # 0: execute set commands
# 1: execute set commands and and update reading state # 1: execute set commands and and update reading state
# 2: execute set commands delayed # 2: execute set commands delayed
my $updateState = 1; my $updateState = 1;
Log3 $name, 5, "EnOcean $name EnOcean_Set command: " . join(" ", @a);
shift @a; shift @a;
for (my $i = 0; $i < @a; $i++) { for (my $i = 0; $i < @a; $i++) {
my $cmd = $a[$i]; my $cmd = $a[$i];
my ($cmd1, $cmd2); my ($cmd1, $cmd2);
if ($st eq "roomSensorControl.05") { if ($cmd eq "unlock") {
$cmdID = 1;
my $secCode = AttrVal($name, "securityCode", undef);
return "Security Code not defined, set attr $name securityCode <00000001 ... FFFFFFFE>!" if (!defined($secCode));
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = (((4 << 11) | $manufID) << 12) | $cmdID;
$data = sprintf "%02X%08X%s", $seq, $cntr, uc($secCode);
####
$destinationID = $hash->{DEF};
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} elsif ($cmd eq "lock") {
$cmdID = 2;
my $secCode = AttrVal($name, "securityCode", undef);
return "Security Code not defined, set attr $name securityCode <00000001 ... FFFFFFFE>!" if (!defined($secCode));
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = (((4 << 11) | $manufID) << 12) | $cmdID;
$data = sprintf "%02X%08X%s", $seq, $cntr, uc($secCode);
####
$destinationID = $hash->{DEF};
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} elsif ($cmd eq "setCode") {
$cmdID = 3;
my $secCode = AttrVal($name, "securityCode", undef);
return "Security Code not defined, set attr $name securityCode <00000001 ... FFFFFFFE>!" if (!defined($secCode));
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = (((4 << 11) | $manufID) << 12) | $cmdID;
$data = sprintf "%02X%08X%s", $seq, $cntr, uc($secCode);
####
$destinationID = $hash->{DEF};
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} elsif ($cmd eq "action") {
$cmdID = 5;
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = ($manufID << 12) | $cmdID;
####
$data = sprintf "%02X%08X00000000", $seq, $cntr;
$destinationID = $hash->{DEF};
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} elsif ($cmd eq "remote_teach-in") {
$cmdID = 0x201;
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = (((4 << 11) | $manufID) << 12) | $cmdID;
####
my $eep = AttrVal($name, "eep", undef);
return "EEP not defined, set attr $name eep <rorg>-<function>-<type>" if (!defined($eep));
$eep =~ m/^(..)(.)(..)(.)(..)$/;
$data = sprintf "%02X%08X%s%s%s01", $seq, $cntr, $1, $3, $5;
$destinationID = "FFFFFFFF";
$destinationID = $hash->{DEF};
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} elsif ($cmd eq "remote_teach-out") {
$cmdID = 0x201;
$manufID = 0x7FF;
$rorg = "C5";
my $seq = int(rand(2) + 1) << 6;
shift(@a);
my $cntr = (((4 << 11) | $manufID) << 12) | $cmdID;
####
my $eep = AttrVal($name, "eep", undef);
return "EEP not defined, set attr $name eep <rorg>-<function>-<type>" if (!defined($eep));
$eep =~ m/^(..)(.)(..)(.)(..)$/;
$data = sprintf "%02X%08X%s%s%s03", $seq, $cntr, $1, $3, $5;
#$destinationID = "FFFFFFFF";
$destinationID = $hash->{DEF};
($rorg, $data) = EnOcean_Encapsulation($packetType, $rorg, $data, $destinationID);
Log3 $name, 3, "EnOcean get $name $cmd $data";
$updateState = 0;
} 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 *, untested]
# $db[3] is the fan speed or night reduction for Eltako # $db[3] is the fan speed or night reduction for Eltako
@ -654,6 +761,7 @@ EnOcean_Set($@)
$actualTemp = 20 if ($actualTemp !~ m/^[+-]?\d+(\.\d+)?$/); $actualTemp = 20 if ($actualTemp !~ m/^[+-]?\d+(\.\d+)?$/);
$actualTemp = 0 if ($actualTemp < 0); $actualTemp = 0 if ($actualTemp < 0);
$actualTemp = 40 if ($actualTemp > 40); $actualTemp = 40 if ($actualTemp > 40);
$actualTemp = sprintf "%0.1f", $actualTemp;
my $setCmd = 8; my $setCmd = 8;
if ($manufID eq "00D") { if ($manufID eq "00D") {
# EEP A5-10-06 plus DB3 [Eltako FVS] # EEP A5-10-06 plus DB3 [Eltako FVS]
@ -668,7 +776,7 @@ EnOcean_Set($@)
# #
if (defined $a[1]) { if (defined $a[1]) {
if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) { if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) {
$setpointTemp = $a[1]; $setpointTemp = sprintf "%0.1f", $a[1];
shift(@a); shift(@a);
} else { } else {
return "Usage: $a[1] is not numeric or out of range"; return "Usage: $a[1] is not numeric or out of range";
@ -922,7 +1030,7 @@ EnOcean_Set($@)
$data = sprintf "%02X%02X%02X%02X", $fanStage, $setpoint, $actualTemp, $setCmd; $data = sprintf "%02X%02X%02X%02X", $fanStage, $setpoint, $actualTemp, $setCmd;
} else { } else {
return "Unknown argument " . $cmd . ", choose one of fanStage:auto,0,1,2,3 setpoint setpointScaled switch:on,off teach" return "Unknown argument " . $cmd . ", choose one of " . $cmdList . "fanStage:auto,0,1,2,3 setpoint setpointScaled switch:on,off teach"
} }
} }
@ -945,7 +1053,7 @@ EnOcean_Set($@)
"valveClosed" => "", "valveClosed" => "",
); );
my $re = $sets{$a[0]}; my $re = $sets{$a[0]};
return "Unknown argument $cmd, choose one of ".join(" ", sort keys %sets) return "Unknown argument $cmd, choose one of " . $cmdList . join(" ", sort keys %sets)
if (!defined($re)); 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$/); return "Argument $a[1] is incorrect (expect $re)" if ($re && $a[1] !~ m/^$re$/);
@ -978,7 +1086,7 @@ EnOcean_Set($@)
$cmd = $a[1]; $cmd = $a[1];
shift(@a); shift(@a);
} else { } else {
return "Unknown Gateway command " . $cmd . ", choose one of " . join(" ", sort keys %EnO_gwCmd); return "Unknown Gateway command " . $cmd . ", choose one of " . $cmdList . join(" ", sort keys %EnO_gwCmd);
} }
my $gwCmdID; my $gwCmdID;
$rorg = "A5"; $rorg = "A5";
@ -1418,7 +1526,7 @@ EnOcean_Set($@)
$data = sprintf "%02X%02X%02X%02X", $gwCmdID, $blindParam1, $blindParam2, $setCmd; $data = sprintf "%02X%02X%02X%02X", $gwCmdID, $blindParam1, $blindParam2, $setCmd;
} else { } else {
return "Unknown Gateway command " . $cmd . ", choose one of ". join(" ", sort keys %EnO_gwCmd); return "Unknown Gateway command " . $cmd . ", choose one of ". $cmdList . join(" ", sort keys %EnO_gwCmd);
} }
Log3 $name, 2, "EnOcean set $name $cmd"; Log3 $name, 2, "EnOcean set $name $cmd";
@ -1668,7 +1776,7 @@ EnOcean_Set($@)
} }
} }
} else { } else {
return "Unknown argument " . $cmd . ", choose one of closes:noArg down opens:noArg position:slider,0,5,100 stop:noArg teach:noArg up" return "Unknown argument " . $cmd . ", choose one of " . $cmdList . "closes:noArg down opens:noArg position:slider,0,5,100 stop:noArg teach:noArg up"
} }
if ($shutCmd || $cmd eq "stop") { if ($shutCmd || $cmd eq "stop") {
$updateState = 0; $updateState = 0;
@ -1713,7 +1821,7 @@ EnOcean_Set($@)
} }
$channel = shift(@a); $channel = shift(@a);
$channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel); $channel = AttrVal($name, "defaultChannel", AttrVal($name, "devChannel", undef)) if (!defined $channel);
if (!defined $channel || $channel eq "all") { if (!defined $channel || $channel eq "all" || $channel eq "FF") {
CommandDeleteReading(undef, "$name channel.*"); CommandDeleteReading(undef, "$name channel.*");
CommandDeleteReading(undef, "$name dim.*"); CommandDeleteReading(undef, "$name dim.*");
readingsSingleUpdate($hash, "channelAll", "on", 1); readingsSingleUpdate($hash, "channelAll", "on", 1);
@ -2115,7 +2223,7 @@ EnOcean_Set($@)
($measurementDelta | 0x0F) << 4 | $unitCmd, ($measurementDelta | 0xFF00) >> 8, ($measurementDelta | 0x0F) << 4 | $unitCmd, ($measurementDelta | 0xFF00) >> 8,
$responseTimeMax, $responseTimeMin; $responseTimeMax, $responseTimeMin;
} else { } else {
my $cmdList = "dim:slider,0,1,100 on off local measurement"; $cmdList .= "dim:slider,0,1,100 on off local measurement";
return SetExtensions ($hash, $cmdList, $name, @a); return SetExtensions ($hash, $cmdList, $name, @a);
} }
Log3 $name, 3, "EnOcean set $name $cmd $data"; Log3 $name, 3, "EnOcean set $name $cmd $data";
@ -2128,6 +2236,7 @@ EnOcean_Set($@)
if ($cmd eq "desired-temp"|| $cmd eq "setpointTemp") { if ($cmd eq "desired-temp"|| $cmd eq "setpointTemp") {
if (defined $a[1]) { if (defined $a[1]) {
if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) { if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) {
$a[1] = sprintf "%0.1f", $a[1];
readingsSingleUpdate($hash, "setpointTemp", $a[1], 1); readingsSingleUpdate($hash, "setpointTemp", $a[1], 1);
readingsSingleUpdate($hash, "setpointTempSet", $a[1], 0); readingsSingleUpdate($hash, "setpointTempSet", $a[1], 0);
Log3 $name, 3, "EnOcean set $name setpointTemp $a[1]"; Log3 $name, 3, "EnOcean set $name setpointTemp $a[1]";
@ -2143,6 +2252,7 @@ EnOcean_Set($@)
if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) { if (($a[1] =~ m/^[+-]?\d+(\.\d+)?$/) && ($a[1] >= 0) && ($a[1] <= 40)) {
Log3 $name, 3, "EnOcean set $name $cmd $a[1]"; Log3 $name, 3, "EnOcean set $name $cmd $a[1]";
$cmd =~ s/(\b)([a-z])/$1\u$2/g; $cmd =~ s/(\b)([a-z])/$1\u$2/g;
$a[1] = sprintf "%0.1f", $a[1];
readingsSingleUpdate($hash, "setpoint" . $cmd, $a[1], 1); readingsSingleUpdate($hash, "setpoint" . $cmd, $a[1], 1);
readingsSingleUpdate($hash, "setpoint" . $cmd . "Set", $a[1], 0); readingsSingleUpdate($hash, "setpoint" . $cmd . "Set", $a[1], 0);
shift(@a); shift(@a);
@ -2259,7 +2369,7 @@ EnOcean_Set($@)
Log3 $name, 3, "EnOcean set $name $cmd"; Log3 $name, 3, "EnOcean set $name $cmd";
} else { } else {
my $cmdList = "cooling:auto,off,on,no_change desired-temp setpointTemp:slider,0,1,40 " . $cmdList .= "cooling:auto,off,on,no_change desired-temp setpointTemp:slider,0,1,40 " .
"comfortTemp deleteTimeProgram:noArg " . "comfortTemp deleteTimeProgram:noArg " .
"economyTemp preComfortTemp buildingProtectionTemp config:noArg " . "economyTemp preComfortTemp buildingProtectionTemp config:noArg " .
"clearCmds:noArg fanSpeed:slider,0,1,100 heating:auto,off,on,no_change " . "clearCmds:noArg fanSpeed:slider,0,1,100 heating:auto,off,on,no_change " .
@ -2280,7 +2390,7 @@ EnOcean_Set($@)
} elsif ($cmd eq "open") { } elsif ($cmd eq "open") {
$setCmd = 8; $setCmd = 8;
} else { } else {
return "Unknown argument $cmd, choose one of open:noArg closed:noArg teach:noArg"; return "Unknown argument $cmd, choose one of " . $cmdList . "open:noArg closed:noArg teach:noArg";
} }
$data = sprintf "%02X", $setCmd; $data = sprintf "%02X", $setCmd;
Log3 $name, 2, "EnOcean set $name $cmd"; Log3 $name, 2, "EnOcean set $name $cmd";
@ -2360,8 +2470,8 @@ EnOcean_Set($@)
($cmd1, $cmd2) = split(",", $cmd, 2); ($cmd1, $cmd2) = split(",", $cmd, 2);
# check values # check values
if (!defined($EnO_ptm200btn{$cmd1}) || ($cmd2 && !defined($EnO_ptm200btn{$cmd2}))) { if (!defined($EnO_ptm200btn{$cmd1}) || ($cmd2 && !defined($EnO_ptm200btn{$cmd2}))) {
my $list = join(" ", sort keys %EnO_ptm200btn); $cmdList .= join(" ", sort keys %EnO_ptm200btn);
return SetExtensions($hash, $list, $name, @a); return SetExtensions($hash, $cmdList, $name, @a);
} }
my $channelA = ReadingsVal($name, "channelA", undef); my $channelA = ReadingsVal($name, "channelA", undef);
my $channelB = ReadingsVal($name, "channelB", undef); my $channelB = ReadingsVal($name, "channelB", undef);
@ -2428,12 +2538,14 @@ EnOcean_Set($@)
Log3 $name, 2, "EnOcean set $name $cmd"; Log3 $name, 2, "EnOcean set $name $cmd";
} }
} elsif (AttrVal($name, "remoteManagement", "off") eq "on") {
} else { } else {
# subtype does not support set commands # subtype does not support set commands
$updateState = -1; $updateState = -1;
return; if (AttrVal($name, "remoteManagement", "off") eq "on") {
return "Unknown argument $cmd, choose one of $cmdList";
} else {
return;
}
} }
# send commands # send commands
@ -2471,8 +2583,8 @@ EnOcean_Parse($$)
my ($err, $response); my ($err, $response);
Log3 undef, 5, "EnOcean received $msg"; Log3 undef, 5, "EnOcean received $msg";
my @msg = split(":", $msg); my @msg = split(":", $msg);
my ($packetType, $rorg, $data, $id, $status, $odata, $destinationID, $fnNumber, $manufID, $RSSI, $delay, $subTelNum); my ($rorg, $data, $id, $status, $odata, $destinationID, $fnNumber, $manufID, $RSSI, $delay, $subTelNum);
$packetType = hex($msg[1]); my $packetType = hex($msg[1]);
if ($packetType == 1) { if ($packetType == 1) {
# packet type RADIO # packet type RADIO
@ -2488,6 +2600,7 @@ EnOcean_Parse($$)
if($hash) { if($hash) {
$name = $hash->{NAME}; $name = $hash->{NAME};
Log3 $name, 5, "EnOcean $name received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id STATUS: $status"; Log3 $name, 5, "EnOcean $name received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id STATUS: $status";
$manufID = uc(AttrVal($name, "manufID", ""));
} else { } else {
Log3 undef, 5, "EnOcean received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id STATUS: $status"; Log3 undef, 5, "EnOcean received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id STATUS: $status";
# SenderID unknown, created new device # SenderID unknown, created new device
@ -2527,10 +2640,10 @@ EnOcean_Parse($$)
if($hash) { if($hash) {
$name = $hash->{NAME}; $name = $hash->{NAME};
Log3 $name, 2, "EnOcean $name received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id Log3 $name, 2, "EnOcean $name received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id
DestinationID $destinationID FunctionNumber: $fnNumber ManufacturerID: $manufID"; DestinationID $destinationID Function Number: $fnNumber ManufacturerID: $manufID";
} else { } else {
Log3 undef, 2, "EnOcean received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id Log3 undef, 2, "EnOcean received PacketType: $packetType RORG: $rorg DATA: $data SenderID: $id
DestinationID $destinationID FunctionNumber: $fnNumber ManufacturerID: $manufID"; DestinationID $destinationID Function Number: $fnNumber ManufacturerID: $manufID";
return ""; return "";
} }
$fnNumber = hex($fnNumber); $fnNumber = hex($fnNumber);
@ -2582,7 +2695,6 @@ EnOcean_Parse($$)
my @event; my @event;
my $model = AttrVal($name, "model", ""); my $model = AttrVal($name, "model", "");
$manufID = uc(AttrVal($name, "manufID", ""));
my $st = AttrVal($name, "subType", ""); my $st = AttrVal($name, "subType", "");
my $subtypeReading = AttrVal($name, "subTypeReading", undef); my $subtypeReading = AttrVal($name, "subTypeReading", undef);
$st = $subtypeReading if (defined $subtypeReading); $st = $subtypeReading if (defined $subtypeReading);
@ -3978,7 +4090,7 @@ EnOcean_Parse($$)
push @event, "3:voltage:$voltage"; push @event, "3:voltage:$voltage";
push @event, "3:state:C: $contact V: $vibration E: $lux U: $voltage"; push @event, "3:state:C: $contact V: $vibration E: $lux U: $voltage";
} elsif ($st =~ m/^digitalInput/) { } elsif ($st =~ m/^digitalInput\.0[12]$/) {
# Digital Input (EEP A5-30-01, A5-30-02) # Digital Input (EEP A5-30-01, A5-30-02)
my $contact; my $contact;
if ($st eq "digtalInput.01") { if ($st eq "digtalInput.01") {
@ -3990,13 +4102,41 @@ EnOcean_Parse($$)
$contact = $db[1] <= 195 ? "closed" : "open"; $contact = $db[1] <= 195 ? "closed" : "open";
push @event, "3:battery:$battery"; push @event, "3:battery:$battery";
} else { } else {
# Single Input Contact (EEP A5-30-01) # Single Input Contact (EEP A5-30-02)
# $db[0]_bit_0 is the input state where 0 = closed, 1 = open # $db[0]_bit_0 is the input state where 0 = closed, 1 = open
$contact = $db[0] & 1 ? "open" : "closed"; $contact = $db[0] & 1 ? "open" : "closed";
} }
push @event, "3:contact:$contact"; push @event, "3:contact:$contact";
push @event, "3:state:$contact"; push @event, "3:state:$contact";
} elsif ($st eq "digitalInput.03") {
# 4 digital inputs, wake, temperature (EEP A5-30-03)
my $in0 = $db[1] & 1;
my $in1 = ($db[1] & 2) > 1;
my $in2 = ($db[1] & 4) > 2;
my $in3 = ($db[1] & 8) > 3;
my $wake = ($db[1] & 16) > 4;
my $temperature = 40 - $db[2] * 40 / 255;
push @event, "3:in0:$in0";
push @event, "3:in1:$in1";
push @event, "3:in2:$in2";
push @event, "3:in3:$in3";
push @event, "3:wake:$wake";
push @event, "3:temperature:$temperature";
push @event, "3:state:T: $temperature I: " . $in0 . $in1 . $in2 . $in3 . " W: " . $wake;
} elsif ($st eq "digitalInput.04") {
# 3 digital inputs, 1 digital input 8 bit (EEP A5-30-04)
my $in0 = $db[0] & 1;
my $in1 = ($db[0] & 2) > 1;
my $in2 = ($db[0] & 4) > 2;
my $in3 = $db[1];
push @event, "3:in0:$in0";
push @event, "3:in1:$in1";
push @event, "3:in2:$in2";
push @event, "3:in3:$in3";
push @event, "3:state:" . $in0 . $in1 . $in2 . " " . $in3;
} elsif ($st eq "gateway") { } elsif ($st eq "gateway") {
# Gateway (EEP A5-38-08) # Gateway (EEP A5-38-08)
# $db[3] is the command ID ($gwCmdID) # $db[3] is the command ID ($gwCmdID)
@ -4846,10 +4986,10 @@ EnOcean_Parse($$)
if ($hash->{helper}{sysEx}{$seq}{fnNumber} == 0x604 || $hash->{helper}{sysEx}{$seq}{fnNumber} == 0x606) { if ($hash->{helper}{sysEx}{$seq}{fnNumber} == 0x604 || $hash->{helper}{sysEx}{$seq}{fnNumber} == 0x606) {
# query ID answer, Ping answer # query ID answer, Ping answer
my $eep = substr($data, 0, 6) >> 3; my $eep = hex(substr($data, 0, 6)) >> 3;
my $rorg = sprintf "%02X", $eep >> 13; my $rorg = sprintf "%02X", ($eep >> 13);
my $func = sprintf "%02X", ($eep & 0x1F80) >> 7; my $func = sprintf "%02X", (($eep & 0x1F80) >> 7);
my $type = sprintf "%02X", $eep & 127; my $type = sprintf "%02X", ($eep & 127);
my $mid = $hash->{helper}{sysEx}{$seq}{manufID}; my $mid = $hash->{helper}{sysEx}{$seq}{manufID};
$attr{$name}{manufID} = $mid; $attr{$name}{manufID} = $mid;
$mid = $EnO_manuf{$mid} if($EnO_manuf{$mid}); $mid = $EnO_manuf{$mid} if($EnO_manuf{$mid});
@ -4877,22 +5017,20 @@ EnOcean_Parse($$)
} elsif ($hash->{helper}{sysEx}{$seq}{fnNumber} == 0x608) { } elsif ($hash->{helper}{sysEx}{$seq}{fnNumber} == 0x608) {
# last function # last function
$data =~ m/^(.)(.)(....)(..)$/; $data =~ m/^(.)(.)(.)(...)(..)$/;
my $codeSetFlag = $1 >> 3; my $codeSetFlag = $1 >> 3;
my $seqLast = $2; my $seqLast = $2;
my $fnNumberLast = $3; my $fnNumberLast = $4;
my $fnRetCode = $4; my $fnRetCode = $5;
Log3 $name, 2, "EnOcean $name RMCC Answer Status: Code Set Flag: $codeSetFlag Log3 $name, 2, "EnOcean $name RMCC Answer Status: Code Set Flag: $codeSetFlag
SEQ: $seqLast Function Number: $fnNumberLast Return Code $fnRetCode"; SEQ: $seqLast Function Number: $fnNumberLast Return Code $fnRetCode";
} else { } else {
Log3 $name, 2, "EnOcean $name RMCC/RPC Function Number: " . Log3 $name, 2, "EnOcean $name RMCC/RPC Function Number " .
sprintf "%03X", $hash->{helper}{sysEx}{$seq}{fnNumber} . " not supported."; sprintf ("%04X", $hash->{helper}{sysEx}{$seq}{fnNumber}) . " not supported.";
} }
delete $hash->{helper}{sysEx}{$seq}; delete $hash->{helper}{sysEx}{$seq};
} }
} elsif ($packetType == 7) { } elsif ($packetType == 7) {
$data =~ m/^(..)(..)(.*)$/;
($fnNumber, $manufID, $data) = (hex($1), $2, $3);
if ($fnNumber == 1) { if ($fnNumber == 1) {
Log3 $name, 2, "EnOcean $name RMCC Unlock Request with ManufacturerID: $manufID"; Log3 $name, 2, "EnOcean $name RMCC Unlock Request with ManufacturerID: $manufID";
@ -4903,7 +5041,11 @@ EnOcean_Parse($$)
Log3 $name, 2, "EnOcean $name RMCC Set code Request with ManufacturerID: $manufID"; Log3 $name, 2, "EnOcean $name RMCC Set code Request with ManufacturerID: $manufID";
} elsif ($fnNumber == 4) { } elsif ($fnNumber == 4) {
Log3 $name, 2, "EnOcean $name RMCC Query ID with ManufacturerID: $manufID"; my $eep = hex(substr($data, 0, 6)) >> 3;
my $rorg = sprintf "%02X", ($eep >> 13);
my $func = sprintf "%02X", (($eep & 0x1F80) >> 7);
my $type = sprintf "%02X", ($eep & 127);
Log3 $name, 2, "EnOcean $name RMCC Query ID with EEP $rorg-$func-$type ManufacturerID: $manufID";
} elsif ($fnNumber == 5) { } elsif ($fnNumber == 5) {
Log3 $name, 2, "EnOcean $name RMCC Action Request with ManufacturerID: $manufID"; Log3 $name, 2, "EnOcean $name RMCC Action Request with ManufacturerID: $manufID";
@ -4923,10 +5065,10 @@ EnOcean_Parse($$)
Log3 $name, 2, "EnOcean $name RPC Remote Learn with EEP $rorg-$func-$type ManufacturerID: $manufID Flag: $flag"; Log3 $name, 2, "EnOcean $name RPC Remote Learn with EEP $rorg-$func-$type ManufacturerID: $manufID Flag: $flag";
} elsif ($fnNumber == 0x604 || $fnNumber == 0x606) { } elsif ($fnNumber == 0x604 || $fnNumber == 0x606) {
my $eep = substr($data, 0, 6) >> 3; my $eep = hex(substr($data, 0, 6)) >> 3;
my $rorg = sprintf "%02X", $eep >> 13; my $rorg = sprintf "%02X", ($eep >> 13);
my $func = sprintf "%02X", ($eep & 0x1F80) >> 7; my $func = sprintf "%02X", (($eep & 0x1F80) >> 7);
my $type = sprintf "%02X", $eep & 127; my $type = sprintf "%02X", ($eep & 127);
$attr{$name}{manufID} = $manufID; $attr{$name}{manufID} = $manufID;
$manufID = $EnO_manuf{$manufID} if($EnO_manuf{$manufID}); $manufID = $EnO_manuf{$manufID} if($EnO_manuf{$manufID});
$attr{$name}{eep} = "$rorg-$func-$type"; $attr{$name}{eep} = "$rorg-$func-$type";
@ -4940,7 +5082,7 @@ EnOcean_Parse($$)
CommandSave(undef, undef); CommandSave(undef, undef);
} else { } else {
Log3 $name, 2, "EnOcean $name RMCC/RPC Function Number: " . sprintf "%03X", $fnNumber . " not supported."; Log3 $name, 2, "EnOcean $name RMCC/RPC Function Number " . sprintf("%04X", $fnNumber) . " not supported.";
} }
} }
@ -5046,6 +5188,14 @@ sub EnOcean_Attr(@) {
CommandDeleteAttr(undef, "$name devUpdate"); CommandDeleteAttr(undef, "$name devUpdate");
} }
} elsif ($attrName eq "securityCode") {
if (!defined $attrVal){
} elsif ($attrVal !~ m/^[\dA-Fa-f]{8}$/ || $attrVal eq "00000000" || uc($attrVal) eq "FFFFFFFF") {
Log3 $name, 2, "EnOcean $name attribute-value [$attrName] = $attrVal wrong";
CommandDeleteAttr(undef, "$name devUpdate");
}
} elsif ($attrName eq "summerMode") { } elsif ($attrName eq "summerMode") {
if (!defined $attrVal){ if (!defined $attrVal){
@ -5116,13 +5266,13 @@ sub EnOcean_Notify(@) {
# ADT encapsulation # ADT encapsulation
sub sub
EnOcean_encapsulation($$$$) EnOcean_Encapsulation($$$$)
{ {
my ($packetType, $rorg, $data, $destinationID) = @_; my ($packetType, $rorg, $data, $destinationID) = @_;
if ($destinationID eq "FFFFFFFF") { if ($destinationID eq "FFFFFFFF") {
return ($rorg, $data); return ($rorg, $data);
} else { } else {
$data = $rorg . $data . $destinationID; $data = $rorg . $data;
return ("A6", $data); return ("A6", $data);
} }
} }
@ -5767,25 +5917,29 @@ EnOcean_SndRadio($$$$$$$$)
$status = substr($status, 0, 1) . "F"; $status = substr($status, 0, 1) . "F";
} }
my $securityLevel = AttrVal($hash->{NAME}, "securityLevel", 0); my $securityLevel = AttrVal($hash->{NAME}, "securityLevel", 0);
if ($securityLevel eq "unencrypted") {$securityLevel = 0;} $securityLevel = 0 if ($securityLevel eq "unencrypted");
if ($destinationID ne "FFFFFFFF" || $securityLevel) { if ($rorg eq "A6") {
# ADT telegram
$data .= $destinationID;
} elsif ($destinationID ne "FFFFFFFF" || $securityLevel) {
# SubTelNum = 03, DestinationID:8, RSSI = FF, SecurityLevel:2 # SubTelNum = 03, DestinationID:8, RSSI = FF, SecurityLevel:2
$odata = sprintf "03%sFF%02X", $destinationID, $securityLevel; $odata = sprintf "03%sFF%02X", $destinationID, $securityLevel;
$odataLength = 7; $odataLength = 7;
} }
# Data Length:4 Optional Length:2 Packet Type:2 # Data Length:4 Optional Length:2 Packet Type:2
$header = sprintf "%04X%02X%02X", (length($data)/2 + 6), $odataLength, $packetType; $header = sprintf "%04X%02X%02X", (length($data) / 2 + 6), $odataLength, $packetType;
Log3 $hash->{NAME}, 5, "EnOcean $hash->{NAME} sent PacketType: $packetType RORG: $rorg DATA: $data SenderID: $senderID STATUS: $status ODATA: $odata"; Log3 $hash->{NAME}, 5, "EnOcean $hash->{NAME} sent PacketType: $packetType RORG: $rorg DATA: $data SenderID: $senderID STATUS: $status ODATA: $odata";
$data = $rorg . $data . $senderID . $status . $odata; $data = $rorg . $data . $senderID . $status . $odata;
} elsif ($packetType == 7) { } elsif ($packetType == 7) {
my $delay = 0; my $delay = 0;
$delay = 1 if ($destinationID eq "FFFFFFFF"); $delay = 1 if ($destinationID eq "FFFFFFFF");
$senderID = "00000000"; $senderID = "00000000";
#$senderID = "00000000" if ($destinationID eq "FFFFFFFF");
$odata = sprintf "%s%sFF%02X", $destinationID, $senderID, $delay; $odata = sprintf "%s%sFF%02X", $destinationID, $senderID, $delay;
$odataLength = 10; $odataLength = 10;
# Data Length:4 Optional Length:2 Packet Type:2 # Data Length:4 Optional Length:2 Packet Type:2
$header = sprintf "%04X%02X%02X", (length($data)/2 + 6), $odataLength, $packetType; $header = sprintf "%04X%02X%02X", (length($data) / 2), $odataLength, $packetType;
Log3 $hash->{NAME}, 3, "EnOcean $hash->{NAME} sent PacketType: $packetType DATA: $data ODATA: $odata"; Log3 $hash->{NAME}, 5, "EnOcean $hash->{NAME} sent PacketType: $packetType DATA: $data ODATA: $odata";
$data .= $odata; $data .= $odata;
} }
IOWrite($hash, $header, $data); IOWrite($hash, $header, $data);
@ -8310,13 +8464,45 @@ EnOcean_Undef($$)
<li>open|closed</li> <li>open|closed</li>
<li>battery: ok|low (only EEP A5-30-01)</li> <li>battery: ok|low (only EEP A5-30-01)</li>
<li>contact: open|closed</li> <li>contact: open|closed</li>
<li>state: open|closed</li> <li>state: open|closed</li>
</ul><br> </ul><br>
The attr subType must be digitalInput.01 or digitalInput.02. This is done if the device was The attr subType must be digitalInput.01 or digitalInput.02. This is done if the device was
created by autocreate. created by autocreate.
</li> </li>
<br><br> <br><br>
<li>Digital Input (EEP A5-30-03)<br>
4 digital Inputs, Wake, Temperature [untested]<br>
<ul>
<li>T: t/&#176C I: 0|1 0|1 0|1 0|1 W: 0|1</li>
<li>in0: 0|1</li>
<li>in1: 0|1</li>
<li>in2: 0|1</li>
<li>in3: 0|1</li>
<li>wake: 0|1</li>
<li>temperature: t/&#176C (Sensor Range: t = 0 &#176C ... 40 &#176C)</li>
<li>state: T: t/&#176C I: 0|1 0|1 0|1 0|1 W: 0|1</li>
</ul><br>
The attr subType must be digitalInput.03. This is done if the device was
created by autocreate.
</li>
<br><br>
<li>Digital Input (EEP A5-30-04)<br>
3 digital Inputs, 1 digital Input 8 bits [untested]<br>
<ul>
<li>0|1 0|1 0|1 0...255</li>
<li>in0: 0|1</li>
<li>in1: 0|1</li>
<li>in2: 0|1</li>
<li>in3: 0...255</li>
<li>state: 0|1 0|1 0|1 0...255</li>
</ul><br>
The attr subType must be digitalInput.04. This is done if the device was
created by autocreate.
</li>
<br><br>
<li>Gateway (EEP A5-38-08)<br> <li>Gateway (EEP A5-38-08)<br>
Switching<br> Switching<br>
[Eltako FLC61, FSA12, FSR14]<br> [Eltako FLC61, FSA12, FSR14]<br>