Compare commits
6 Commits
6cee10a397
...
2cfb5f7cee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cfb5f7cee | ||
|
|
0ad35c9742 | ||
|
|
77106140e7 | ||
|
|
4536c9f754 | ||
|
|
d0ccfba735 | ||
|
|
dfb1994ad6 |
@@ -81,6 +81,17 @@ TCM_Define($$)
|
|||||||
$hash->{DeviceName} = $dev;
|
$hash->{DeviceName} = $dev;
|
||||||
$hash->{MODEL} = $model;
|
$hash->{MODEL} = $model;
|
||||||
my $ret = DevIo_OpenDev($hash, 0, undef);
|
my $ret = DevIo_OpenDev($hash, 0, undef);
|
||||||
|
|
||||||
|
if($hash->{STATE} eq "opened") {
|
||||||
|
# Read Base-Id of Enocean-Module
|
||||||
|
my $cnt=0;
|
||||||
|
do { # this does not always work, so we try several times
|
||||||
|
my $answer=TCM_Get($hash, ($name, "idbase") );
|
||||||
|
my @fields=split(/[=,]/, $answer);
|
||||||
|
$hash->{BASEID}=$fields[1];
|
||||||
|
$cnt++;
|
||||||
|
} while ($cnt<3 and $hash->{BASEID} eq "");
|
||||||
|
}
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
##############################################
|
##############################################
|
||||||
# $Id$
|
# $Id: 10_EnOcean.pm 1130 2011-12-14 07:57:59Z rudolfkoenig $
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
@@ -10,6 +10,7 @@ sub EnOcean_Initialize($);
|
|||||||
sub EnOcean_Parse($$);
|
sub EnOcean_Parse($$);
|
||||||
sub EnOcean_Set($@);
|
sub EnOcean_Set($@);
|
||||||
sub EnOcean_MD15Cmd($$$);
|
sub EnOcean_MD15Cmd($$$);
|
||||||
|
sub EnOcean_GetMyDeviceId($);
|
||||||
|
|
||||||
my %rorgname = ("F6"=>"switch", # RPS
|
my %rorgname = ("F6"=>"switch", # RPS
|
||||||
"D5"=>"contact", # 1BS
|
"D5"=>"contact", # 1BS
|
||||||
@@ -64,10 +65,11 @@ EnOcean_Initialize($)
|
|||||||
$hash->{DefFn} = "EnOcean_Define";
|
$hash->{DefFn} = "EnOcean_Define";
|
||||||
$hash->{ParseFn} = "EnOcean_Parse";
|
$hash->{ParseFn} = "EnOcean_Parse";
|
||||||
$hash->{SetFn} = "EnOcean_Set";
|
$hash->{SetFn} = "EnOcean_Set";
|
||||||
|
$hash->{AttrFn} = "EnOcean_Attr";
|
||||||
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 " .
|
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 " .
|
||||||
"showtime:1,0 loglevel:0,1,2,3,4,5,6 model " .
|
"showtime:1,0 loglevel:0,1,2,3,4,5,6 model " .
|
||||||
"subType:switch,contact,sensor,windowHandle,SR04,MD15,PM101,".
|
"subType:switch,contact,sensor,windowHandle,SR04,MD15," .
|
||||||
"dimmer,dimmCtrl actualTemp";
|
"eltakoDimmer,eltakoRoll subId actualTemp, dimTime";
|
||||||
|
|
||||||
for(my $i=0; $i<@ptm200btn;$i++) {
|
for(my $i=0; $i<@ptm200btn;$i++) {
|
||||||
$ptm200btn{$ptm200btn[$i]} = "$i:30";
|
$ptm200btn{$ptm200btn[$i]} = "$i:30";
|
||||||
@@ -76,6 +78,28 @@ EnOcean_Initialize($)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------
|
||||||
|
|
||||||
|
sub EnOcean_Attr($)
|
||||||
|
{
|
||||||
|
my @a = @_;
|
||||||
|
|
||||||
|
my $name= $a[1];
|
||||||
|
my $ll2 = GetLogLevel($name, 2);
|
||||||
|
|
||||||
|
if($a[2] eq "subType") {
|
||||||
|
Log $ll2, "EO_Attr subtype";
|
||||||
|
|
||||||
|
if( $a[3] eq "eltakoDimmer"
|
||||||
|
or $a[3] eq "eltakoSwitch") {
|
||||||
|
Log $ll2, "EO_Attr subtype dimmer/switch";
|
||||||
|
$attr{$name}{eventMap}="B0:on B1:off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
sub
|
sub
|
||||||
EnOcean_Define($$)
|
EnOcean_Define($$)
|
||||||
@@ -140,29 +164,110 @@ EnOcean_Set($@)
|
|||||||
$hash->{READINGS}{$cmd}{TIME} = $tn;
|
$hash->{READINGS}{$cmd}{TIME} = $tn;
|
||||||
$hash->{READINGS}{$cmd}{VAL} = $arg;
|
$hash->{READINGS}{$cmd}{VAL} = $arg;
|
||||||
|
|
||||||
} elsif($st eq "dimmCtrl") { # Tested for Eltako-Dimmer
|
###########################
|
||||||
|
} elsif($st eq "eltakoDimmer") {
|
||||||
|
my $sendDimCmd=0;
|
||||||
|
my $time=AttrVal($name, "time", 0);
|
||||||
|
my $onoff=1;
|
||||||
|
my $dimVal=100;
|
||||||
|
$dimVal=$hash->{VALUE} if(defined $hash->{VALUE});
|
||||||
|
|
||||||
if($cmd eq "teach") {
|
if($cmd eq "teach") {
|
||||||
my $data=sprintf("A502000000%s00", $hash->{DEF});
|
my $idSrc=EnOcean_GetMyDeviceId($hash);
|
||||||
Log $ll2, "dimmCtrl.Teach: " . $data;
|
my $data=sprintf("A502000000%s00", $idSrc);
|
||||||
|
Log $ll2, "$st.Teach: " . $data;
|
||||||
IOWrite($hash, "000A0001", $data); # len:000a optlen:00 pakettype:1(radio)
|
IOWrite($hash, "000A0001", $data); # len:000a optlen:00 pakettype:1(radio)
|
||||||
|
|
||||||
} elsif($cmd eq "dimm") {
|
} elsif($cmd eq "dimto") {
|
||||||
return "Usage: dimm percent [time 01-FF FF:slowest] [on/off]" if(@a<2);
|
return "Usage: $cmd percent" if(@a<2 or $a[1]>100);
|
||||||
my $time=0;
|
|
||||||
my $onoff=1;
|
|
||||||
# for eltako relative (0-100) (but not compliant to EEP because DB0.2 is 0)
|
# for eltako relative (0-100) (but not compliant to EEP because DB0.2 is 0)
|
||||||
my $dimVal=$a[1];
|
$dimVal=$a[1];
|
||||||
shift(@a);
|
shift(@a);
|
||||||
if(defined($a[1])) { $time=$a[1]; shift(@a); }
|
if(defined($a[1])) { $time=$a[1]; shift(@a); }
|
||||||
if(defined($a[1])) { $onoff=($a[1] eq "off") ? 0 : 1; shift(@a); }
|
if(defined($a[1])) { $onoff=($a[1] eq "off") ? 0 : 1; shift(@a); }
|
||||||
# EEP: A5/38/08 Central Command ->Typ 0x02: Dimming
|
$sendDimCmd=1;
|
||||||
my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $time, $onoff|0x08, $hash->{DEF});
|
|
||||||
IOWrite($hash, "000A0001", $data);
|
} elsif($cmd eq "dimup") {
|
||||||
Log $ll2, "dimmCtrl.dimm: " . $data;
|
return "Usage: $cmd percent" if(@a<2 or $a[1]>100);
|
||||||
|
$dimVal+=$a[1];
|
||||||
|
Log $ll2, "$st.$cmd val:" . $hash->{VALUE} . " par:" . $a[1] . " val:" . $dimVal;
|
||||||
|
shift(@a);
|
||||||
|
$sendDimCmd=1;
|
||||||
|
|
||||||
|
} elsif($cmd eq "dimdown") {
|
||||||
|
return "Usage: $cmd percent" if(@a<2 or $a[1]>100);
|
||||||
|
$dimVal-=$a[1];
|
||||||
|
shift(@a);
|
||||||
|
$sendDimCmd=1;
|
||||||
|
|
||||||
|
} elsif($cmd eq "on" or $cmd eq "B0") {
|
||||||
|
$sendDimCmd=1;
|
||||||
|
|
||||||
|
} elsif($cmd eq "off" or $cmd eq "B1") {
|
||||||
|
$onoff=0;
|
||||||
|
$sendDimCmd=1;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return "Unknown argument $cmd, choose one of: teach, dimm"
|
return "Unknown argument $cmd, choose one of: teach, dimto, dimup, dimdown, on ,off";
|
||||||
|
|
||||||
|
}
|
||||||
|
if($sendDimCmd) {
|
||||||
|
if($dimVal > 100) { $dimVal=100; }
|
||||||
|
if($dimVal <= 0) { $dimVal=0; $onoff=0; }
|
||||||
|
# EEP: A5/38/08 Central Command ->Typ 0x02: Dimming
|
||||||
|
my $idSrc=EnOcean_GetMyDeviceId($hash);
|
||||||
|
my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $time, $onoff|0x08, $idSrc);
|
||||||
|
IOWrite($hash, "000A0001", $data);
|
||||||
|
Log $ll2, "$st.$cmd: " . $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
###########################
|
||||||
|
} elsif($st eq "eltakoRoll") {
|
||||||
|
if($cmd eq "teach") {
|
||||||
|
my $data=sprintf("A5FFF80D80%s00", $hash->{DEF});
|
||||||
|
Log $ll2, "eltakoRollCtrl.Teach: " . $data;
|
||||||
|
IOWrite($hash, "000A0001", $data); # len:000a optlen:00 pakettype:1(radio)
|
||||||
|
} else {
|
||||||
|
my %eltakoRollCtrlCommands = ( down=>0x02, up=>0x01, stop=>0x00 );
|
||||||
|
my $usage = "Usage: (" . join("|", sort keys %eltakoRollCtrlCommands) . ")";
|
||||||
|
my $rollcmd= $eltakoRollCtrlCommands{$cmd};
|
||||||
|
return $usage if(!defined($rollcmd));
|
||||||
|
my $time=AttrVal($name, "time", 0);
|
||||||
|
# EEP: A5/3F/7F Universal ???
|
||||||
|
my $idSrc=EnOcean_GetMyDeviceId($hash);
|
||||||
|
my $data=sprintf("A5%02X%02X%02X%02X%s00", 0, $time, $rollcmd, 0x08, $idSrc);
|
||||||
|
IOWrite($hash, "000A0001", $data);
|
||||||
|
Log $ll2, "eltakoRoll.$cmd" . $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
###########################
|
||||||
|
} elsif($st eq "eltakoSwitch") {
|
||||||
|
my $sendCmd=0;
|
||||||
|
my $onoff=1;
|
||||||
|
|
||||||
|
if($cmd eq "teach") {
|
||||||
|
my $idSrc=EnOcean_GetMyDeviceId($hash);
|
||||||
|
my $data=sprintf("A501000000%s00", $idSrc);
|
||||||
|
Log $ll2, "$st.Teach: " . $data;
|
||||||
|
IOWrite($hash, "000A0001", $data); # len:000a optlen:00 pakettype:1(radio)
|
||||||
|
|
||||||
|
} elsif($cmd eq "on" or $cmd eq "B0") {
|
||||||
|
$sendCmd=1;
|
||||||
|
|
||||||
|
} elsif($cmd eq "off" or $cmd eq "B1") {
|
||||||
|
$onoff=0;
|
||||||
|
$sendCmd=1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return "Unknown argument $cmd, choose one of: teach, on ,off";
|
||||||
|
|
||||||
|
}
|
||||||
|
if($sendDimCmd) {
|
||||||
|
# EEP: A5/38/08 Central Command ->Typ 0x01: Switch
|
||||||
|
my $idSrc=EnOcean_GetMyDeviceId($hash);
|
||||||
|
my $data=sprintf("A5010000%02X%s00", $onoff|0x08, $idSrc);
|
||||||
|
IOWrite($hash, "000A0001", $data);
|
||||||
|
Log $ll2, "$st.$cmd: " . $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
@@ -196,6 +301,7 @@ EnOcean_Set($@)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
sub
|
sub
|
||||||
EnOcean_Parse($$)
|
EnOcean_Parse($$)
|
||||||
@@ -271,6 +377,8 @@ EnOcean_Parse($$)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
# eltakoRoll: BI: unten / B0: oben / released:running/stopped
|
||||||
|
|
||||||
|
|
||||||
# released events are disturbing when using a remote, since it overwrites
|
# released events are disturbing when using a remote, since it overwrites
|
||||||
# the "real" state immediately
|
# the "real" state immediately
|
||||||
@@ -303,7 +411,7 @@ EnOcean_Parse($$)
|
|||||||
|
|
||||||
if("$fn.$tp" eq "20.01" && $iohash->{pair}) { # MD15
|
if("$fn.$tp" eq "20.01" && $iohash->{pair}) { # MD15
|
||||||
select(undef, undef, undef, 0.1); # max 10 Seconds
|
select(undef, undef, undef, 0.1); # max 10 Seconds
|
||||||
EnOcean_A5Cmd($hash, "800800F0", "00000000");
|
EnOcean_A5Cmd($hash, "800800F0", EnOcean_GetMyDeviceId($hash));
|
||||||
select(undef, undef, undef, 0.5);
|
select(undef, undef, undef, 0.5);
|
||||||
EnOcean_MD15Cmd($hash, $name, 128); # 128 == 20 degree C
|
EnOcean_MD15Cmd($hash, $name, 128); # 128 == 20 degree C
|
||||||
}
|
}
|
||||||
@@ -355,9 +463,7 @@ EnOcean_Parse($$)
|
|||||||
push @event, "3:channel1:" . ($db_0 & 0x01 ? "off" : "on");
|
push @event, "3:channel1:" . ($db_0 & 0x01 ? "off" : "on");
|
||||||
push @event, "3:channel2:" . ($db_0 & 0x02 ? "off" : "on");
|
push @event, "3:channel2:" . ($db_0 & 0x02 ? "off" : "on");
|
||||||
|
|
||||||
} elsif($st eq "dimmer") {
|
} elsif($st eq "eltakoDimmer") {
|
||||||
# todo: create a more general solution for the central-command responses
|
|
||||||
|
|
||||||
# response command from (Eltako-)Actor ( Central-Command:A5/38/08 )
|
# response command from (Eltako-)Actor ( Central-Command:A5/38/08 )
|
||||||
if($db_3 eq 0x01) { # switch
|
if($db_3 eq 0x01) { # switch
|
||||||
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
|
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
|
||||||
@@ -366,12 +472,7 @@ EnOcean_Parse($$)
|
|||||||
|
|
||||||
} elsif($db_3 eq 0x02) { # dimm
|
} elsif($db_3 eq 0x02) { # dimm
|
||||||
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
|
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
|
||||||
push @event, "3:dimmValue:$db_2";
|
push @event, "3:value:$db_2";
|
||||||
|
|
||||||
} elsif($db_3 eq 0x03) { # setpoint-switch, todo
|
|
||||||
} elsif($db_3 eq 0x04) { # basic setpoint, todo
|
|
||||||
} elsif($db_3 eq 0x05) { # control-variable, todo
|
|
||||||
} elsif($db_3 eq 0x06) { # fan-stage, todo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -400,10 +501,11 @@ EnOcean_Parse($$)
|
|||||||
if($vn eq "state") {
|
if($vn eq "state") {
|
||||||
$hash->{STATE} = $vv;
|
$hash->{STATE} = $vv;
|
||||||
push @changed, $vv;
|
push @changed, $vv;
|
||||||
|
} elsif($vn eq "value") {
|
||||||
|
$hash->{VALUE} = $vv if($vv>0);
|
||||||
|
push @changed, "$vn: $vv";
|
||||||
} else {
|
} else {
|
||||||
push @changed, "$vn: $vv";
|
push @changed, "$vn: $vv";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +542,7 @@ EnOcean_MD15Cmd($$$)
|
|||||||
|
|
||||||
if($msg) {
|
if($msg) {
|
||||||
select(undef, undef, undef, 0.2);
|
select(undef, undef, undef, 0.2);
|
||||||
EnOcean_A5Cmd($hash, $msg, "00000000");
|
EnOcean_A5Cmd($hash, $msg, EnOcean_GetMyDeviceId($hash));
|
||||||
if($cmd eq "initialize") {
|
if($cmd eq "initialize") {
|
||||||
delete($defs{$name}{READINGS}{CMD});
|
delete($defs{$name}{READINGS}{CMD});
|
||||||
delete($defs{$name}{READINGS}{$cmd});
|
delete($defs{$name}{READINGS}{$cmd});
|
||||||
@@ -458,4 +560,24 @@ EnOcean_A5Cmd($$$)
|
|||||||
# type=A5 msg:4 senderId:4 status=00 subTelNum=01 destId:4 dBm=FF Security=00
|
# type=A5 msg:4 senderId:4 status=00 subTelNum=01 destId:4 dBm=FF Security=00
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------
|
||||||
|
|
||||||
|
#
|
||||||
|
# compose the Src-Id for a command to send
|
||||||
|
#
|
||||||
|
sub EnOcean_GetMyDeviceId($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $myId=0; # default: use Device-ID of EUL
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $baseId=hex($hash->{IODev}{BASEID}) if(defined $hash->{IODev}{BASEID});
|
||||||
|
my $subId = AttrVal($name, "subId", "");
|
||||||
|
if(defined $baseId and defined $subId) {
|
||||||
|
# if there is a base-id an a subid -> use this combination
|
||||||
|
$myId=sprintf("%08X", $baseId | $subId);
|
||||||
|
}
|
||||||
|
return $myId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -3348,8 +3348,16 @@ A line ending with \ will be concatenated with the next one, so long lines
|
|||||||
<a name="EnOcean"></a>
|
<a name="EnOcean"></a>
|
||||||
<h3>EnOcean</h3>
|
<h3>EnOcean</h3>
|
||||||
<ul>
|
<ul>
|
||||||
Devices sold by numerous hardware verndors (e.g. Eltako, Peha, etc), using
|
Devices sold by numerous hardware vendors (e.g. Eltako, Peha, etc), using
|
||||||
the RF Protocol provided by the EnOcean Alliance.
|
the RF Protocol provided by the EnOcean Alliance.
|
||||||
|
<br>
|
||||||
|
To send commands to an Enocean-actuator the <a href="#TCM">TCM</a> can either use the
|
||||||
|
unique Chip-ID (then you can control only one actuator, but nobody else
|
||||||
|
can send commands to your device from a normal enocean-module). Or you can set/use the
|
||||||
|
Base-ID and define a Sub-ID for every device to control (then up to 128 devices
|
||||||
|
can be controlled, but anyone take over your devices simply by sniffing and copying the base-id).
|
||||||
|
<br>
|
||||||
|
To use Sub-IDs set the attribute <code>subId</code> to different values (0-127) for all your devices.
|
||||||
<br><br>
|
<br><br>
|
||||||
<a name="EnOceandefine"></a>
|
<a name="EnOceandefine"></a>
|
||||||
<b>Define</b>
|
<b>Define</b>
|
||||||
@@ -3384,6 +3392,31 @@ A line ending with \ will be concatenated with the next one, so long lines
|
|||||||
Do not regulate the MD15.</li>
|
Do not regulate the MD15.</li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
|
|
||||||
|
<li>Eltako-Dimmer-Switch (FUD12NPN, FUD61NP, FUD61NPN). Set subtype: <code>attr mydimmer subType eltakoDimmer</code>
|
||||||
|
<br>
|
||||||
|
Commands:
|
||||||
|
<ul>
|
||||||
|
<li>dimto <value></li>
|
||||||
|
<li>dimup <value></li>
|
||||||
|
<li>dimdown <value></li>
|
||||||
|
<li>on</li>
|
||||||
|
<li>off</li>
|
||||||
|
<li>teach</li>
|
||||||
|
</ul>
|
||||||
|
Attributes:
|
||||||
|
<ul>
|
||||||
|
<li>dimTime <value><br>. Set Dimm-velocity (0-255) 0: fast</li>
|
||||||
|
</ul></li>
|
||||||
|
|
||||||
|
<li>Eltako-Roller-Shutter (FSB12, FSB61). Set subtype: <code>attr myroll subType eltakoRoll</code>
|
||||||
|
<br>
|
||||||
|
Commands:
|
||||||
|
<ul>
|
||||||
|
<li>up</li>
|
||||||
|
<li>down</li>
|
||||||
|
<li>stop</li>
|
||||||
|
<li>teach</li>
|
||||||
|
</ul></li>
|
||||||
|
|
||||||
<li>all other:
|
<li>all other:
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user