6 Commits

Author SHA1 Message Date
Marc Hoppe
5ce95150df ... 2012-02-10 19:02:31 +01:00
Marc Hoppe
59c63c4f5d ... 2012-02-10 19:02:31 +01:00
Marc Hoppe
f6216d23d4 Enocean: eltakoDimmer: new Commands 'on'/'off' new attr 'dimTime' 2012-02-10 19:02:31 +01:00
Marc Hoppe
6ec7ca22a8 Enocean: eltakoDimmer: new commands 'dimup' and 'dimdown' 2012-02-10 19:01:58 +01:00
Marc Hoppe
b422b35553 EnOcean: if there is an 'attr' 'subId' use it for sending data to an Actuator
There is no subType 'dimmer' and 'dimmctrl' anymore these are replaced by 'eltakoDimmer'.
 The commands supported are 'dimto' and 'teach'
 The readings which will be set are 'state' and 'value'
2012-02-10 19:01:58 +01:00
Marc Hoppe
6b5345e8bb 00_TCM: Read Base-Id of Tcm on start 2012-02-10 19:00:12 +01:00
3 changed files with 179 additions and 41 deletions

View File

@@ -12,7 +12,7 @@ package main;
# EnOcean Serial Protocol 3 (ESP3) (for the TCM310)
# TODO:
# TODO:
# Check BSC Temp
# Check Stick Temp
# Check Stick WriteRadio
@@ -77,10 +77,21 @@ TCM_Define($$)
$attr{$name}{dummy} = 1;
return undef;
}
$hash->{DeviceName} = $dev;
$hash->{MODEL} = $model;
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, "baseid") );
my @fields=split(/[=,]/, $answer);
$hash->{BASEID}=$fields[1];
$cnt++;
} while ($cnt<3 and $hash->{BASEID} eq "");
}
return $ret;
}
@@ -586,7 +597,7 @@ TCM_ReadAnswer($$)
if($^O =~ m/Win/ && $hash->{USBDev}) {
$hash->{USBDev}->read_const_time($to*1000); # set timeout (ms)
# Read anstatt input sonst funzt read_const_time nicht.
$buf = $hash->{USBDev}->read(999);
$buf = $hash->{USBDev}->read(999);
return ("$name Timeout reading answer for $arg", undef)
if(length($buf) == 0);

View File

@@ -10,6 +10,7 @@ sub EnOcean_Initialize($);
sub EnOcean_Parse($$);
sub EnOcean_Set($@);
sub EnOcean_MD15Cmd($$$);
sub EnOcean_GetMyDeviceId($);
my %rorgname = ("F6"=>"switch", # RPS
"D5"=>"contact", # 1BS
@@ -64,10 +65,11 @@ EnOcean_Initialize($)
$hash->{DefFn} = "EnOcean_Define";
$hash->{ParseFn} = "EnOcean_Parse";
$hash->{SetFn} = "EnOcean_Set";
$hash->{AttrFn} = "EnOcean_Attr";
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 " .
"showtime:1,0 loglevel:0,1,2,3,4,5,6 model " .
"subType:switch,contact,sensor,windowHandle,SR04,MD15,PM101,".
"dimmer,dimmCtrl actualTemp";
"subType:switch,contact,sensor,windowHandle,SR04,MD15," .
"eltakoDimmer,eltakoRoll subId actualTemp, dimTime";
for(my $i=0; $i<@ptm200btn;$i++) {
$ptm200btn{$ptm200btn[$i]} = "$i:30";
@@ -76,6 +78,27 @@ EnOcean_Initialize($)
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") {
Log $ll2, "EO_Attr subtype dimmer";
$attr{$name}{eventMap}="B0:on B1:off"
}
}
return undef;
}
#############################
sub
EnOcean_Define($$)
@@ -140,30 +163,80 @@ EnOcean_Set($@)
$hash->{READINGS}{$cmd}{TIME} = $tn;
$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") {
my $data=sprintf("A502000000%s00", $hash->{DEF});
Log $ll2, "dimmCtrl.Teach: " . $data;
my $idSrc=EnOcean_GetMyDeviceId($hash);
my $data=sprintf("A502000000%s00", $idSrc);
Log $ll2, "$st.Teach: " . $data;
IOWrite($hash, "000A0001", $data); # len:000a optlen:00 pakettype:1(radio)
} elsif($cmd eq "dimm") {
return "Usage: dimm percent [time 01-FF FF:slowest] [on/off]" if(@a<2);
my $time=0;
my $onoff=1;
} elsif($cmd eq "dimto") {
return "Usage: $cmd percent" if(@a<2 or $a[1]>100);
# for eltako relative (0-100) (but not compliant to EEP because DB0.2 is 0)
my $dimVal=$a[1];
$dimVal=$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); }
# EEP: A5/38/08 Central Command ->Typ 0x02: Dimming
my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $time, $onoff|0x08, $hash->{DEF});
IOWrite($hash, "000A0001", $data);
Log $ll2, "dimmCtrl.dimm: " . $data;
$sendDimCmd=1;
} elsif($cmd eq "dimup") {
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 {
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;
}
###########################
} else { # Simulate a PTM
@@ -176,14 +249,14 @@ EnOcean_Set($@)
my ($db_3, $status) = split(":", $ptm200btn{$c1}, 2);
$db_3 <<= 5;
$db_3 |= 0x10 if($c1 ne "released"); # set the pressed flag
if($c2) {
my ($d2, undef) = split(":", $ptm200btn{$c2}, 2);
$db_3 |= ($d2<<1) | 0x01;
}
IOWrite($hash, "",
sprintf("6B05%02X000000%s%s", $db_3, $hash->{DEF}, $status));
if($c2) {
my ($d2, undef) = split(":", $ptm200btn{$c2}, 2);
$db_3 |= ($d2<<1) | 0x01;
}
IOWrite($hash, "",
sprintf("6B05%02X000000%s%s", $db_3, $hash->{DEF}, $status));
}
}
select(undef, undef, undef, 0.1) if($i < int(@a)-1);
}
@@ -209,7 +282,7 @@ EnOcean_Parse($$)
return "";
}
my $hash = $modules{EnOcean}{defptr}{$id};
my $hash = $modules{EnOcean}{defptr}{$id};
if(!$hash) {
Log 3, "EnOcean Unknown device with ID $id, please define it";
return "UNDEFINED EnO_${rorgname}_$id EnOcean $id";
@@ -262,15 +335,17 @@ EnOcean_Parse($$)
} else {
if($st eq "keycard") {
$msg = "keycard removed";
} else {
$msg = (($db_3&0x10) ? "pressed" : "released");
}
}
}
# eltakoRoll: BI: unten / B0: oben / released:running/stopped
# released events are disturbing when using a remote, since it overwrites
# the "real" state immediately
@@ -303,7 +378,7 @@ EnOcean_Parse($$)
if("$fn.$tp" eq "20.01" && $iohash->{pair}) { # MD15
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);
EnOcean_MD15Cmd($hash, $name, 128); # 128 == 20 degree C
}
@@ -355,9 +430,7 @@ EnOcean_Parse($$)
push @event, "3:channel1:" . ($db_0 & 0x01 ? "off" : "on");
push @event, "3:channel2:" . ($db_0 & 0x02 ? "off" : "on");
} elsif($st eq "dimmer") {
# todo: create a more general solution for the central-command responses
} elsif($st eq "eltakoDimmer") {
# response command from (Eltako-)Actor ( Central-Command:A5/38/08 )
if($db_3 eq 0x01) { # switch
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
@@ -366,7 +439,7 @@ EnOcean_Parse($$)
} elsif($db_3 eq 0x02) { # dimm
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
@@ -400,10 +473,11 @@ EnOcean_Parse($$)
if($vn eq "state") {
$hash->{STATE} = $vv;
push @changed, $vv;
} elsif($vn eq "value") {
$hash->{VALUE} = $vv if($vv>0);
push @changed, "$vn: $vv";
} else {
push @changed, "$vn: $vv";
}
}
@@ -413,7 +487,7 @@ EnOcean_Parse($$)
}
}
$hash->{CHANGED} = \@changed;
return $name;
}
@@ -430,7 +504,7 @@ EnOcean_MD15Cmd($$$)
$msg = sprintf("%02X000000", $arg1);
} elsif($cmd eq "desired-temp") {
$msg = sprintf("%02X%02X0400", $arg1*255/40,
$msg = sprintf("%02X%02X0400", $arg1*255/40,
AttrVal($name, "actualTemp", ($db_1*40/255)) * 255/40);
} elsif($cmd eq "initialize") {
@@ -440,7 +514,7 @@ EnOcean_MD15Cmd($$$)
if($msg) {
select(undef, undef, undef, 0.2);
EnOcean_A5Cmd($hash, $msg, "00000000");
EnOcean_A5Cmd($hash, $msg, EnOcean_GetMyDeviceId($hash));
if($cmd eq "initialize") {
delete($defs{$name}{READINGS}{CMD});
delete($defs{$name}{READINGS}{$cmd});
@@ -452,10 +526,30 @@ EnOcean_MD15Cmd($$$)
sub
EnOcean_A5Cmd($$$)
{
my ($hash, $msg, $org) = @_;
IOWrite($hash, "000A0701", # varLen=0A optLen=07 msgType=01=radio,
my ($hash, $msg, $org) = @_;
IOWrite($hash, "000A0701", # varLen=0A optLen=07 msgType=01=radio,
sprintf("A5%s%s0001%sFF00",$msg,$org,$hash->{DEF}));
# 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});
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;

View File

@@ -3327,8 +3327,16 @@ A line ending with \ will be concatenated with the next one, so long lines
<a name="EnOcean"></a>
<h3>EnOcean</h3>
<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.
<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>
<a name="EnOceandefine"></a>
<b>Define</b>
@@ -3363,6 +3371,31 @@ A line ending with \ will be concatenated with the next one, so long lines
Do not regulate the MD15.</li>
</ul></li>
<li>Eltako-Dimmer-Switch (FUD12NPN, FUD61NP, FUD61NPN). Set subtype: <code>attr mydimmer subType eltakoDimmer</code>
<br>
Commands:
<ul>
<li>dimto &lt;value&gt;</li>
<li>dimup &lt;value&gt;</li>
<li>dimdown &lt;value&gt;</li>
<li>on</li>
<li>off</li>
<li>teach</li>
</ul>
Attributes:
<ul>
<li>dimTime &lt;value&gt;<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:
<ul>