10 Commits

Author SHA1 Message Date
Marc Hoppe
776a4e28c5 ... 2012-01-29 18:44:41 +01:00
Marc Hoppe
0c772d4224 Merge remote-tracking branch 'vdr/eo_baseid' into enocean
Conflicts:
	FHEM/10_EnOcean.pm
2012-01-29 18:37:28 +01:00
Marc Hoppe
06da7b1621 Merge branch 'master' into enocean 2012-01-29 18:17:20 +01:00
Marc Hoppe
4bdf589e21 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-01-29 18:00:45 +01:00
Marc Hoppe
2e97eb1b45 00_TCM: Read Base-Id of Tcm on start 2012-01-28 22:05:16 +01:00
Marc Hoppe
94de56a72b Merge remote-tracking branch 'origin/master' into enocean 2012-01-07 11:01:35 +01:00
Marc Hoppe
dc8be92ede Merge remote-tracking branch 'origin/master' into enocean
Conflicts:
	FHEM/10_EnOcean.pm
2012-01-01 18:50:57 +01:00
Marc Hoppe
6778594581 Merge remote branch 'origin/master' into enocean 2011-12-27 11:34:13 +01:00
Marc Hoppe
7d9d7ca20e Enocean: new subType dimmCtrl - To send dimm-value directly to (Eltako-)Dimm-actor.
There are 2 new Commands for this subtype:
  - teach
  - dimm dimmVal [time] [on/off]
       dimmVal(%): 0-100
       time: 0-255 dimm-time, where 0:default 1:fastest 255:slowest
       on/off: on:lamp on off:lamp off

Usage:
-define an Enocean device with id from your idbase-range:
   define mydimctrl EnOcean ffabcd81
-set subtype:
   attr mydimctrl subType dimmCtrl
-set the actor to learn mode
-send the teach command:
   set mydimctrl teach
-actor back to normal-mode
-now you can control the dimmer
   set mydimctrl dimm 50 100 on

time is optional (then 0 is used)
on/off is optional (then on is used)

The commands (A5/38/08) are not 100% compliant to the EEP, I think it will only work with eltako-Dimmers
2011-12-26 19:59:00 +01:00
Marc Hoppe
4a1c808cd4 Enocean: added new subType 'dimmer'. The responses of a (Eltako-FUD61NPN)-Dimmer
are evaluated and the data is added to the events state:(on/off) and
 dimmValue:(Percent-Value)

After you defined the device (here:mydimmer) you need to set some attributes:

attr mydimmer subType dimmer
attr mydimmer eventMap B0:on BI:off
2011-12-26 12:42:02 +01:00
2 changed files with 84 additions and 34 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
@@ -76,10 +76,16 @@ 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") {
my $answer=TCM_Get($hash, ($name, "baseid") );
my @fields=split(/[=,]/, $answer);
$hash->{BASEID}=$fields[1];
}
return $ret;
}
@@ -585,7 +591,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

@@ -1,5 +1,5 @@
##############################################
# $Id$
# $Id: 10_EnOcean.pm 1130 2011-12-14 07:57:59Z rudolfkoenig $
package main;
use strict;
@@ -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
@@ -67,7 +68,7 @@ EnOcean_Initialize($)
$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,".
"dimmer,dimmCtrl actualTemp";
"eltakoDimmer subId actualTemp";
for(my $i=0; $i<@ptm200btn;$i++) {
$ptm200btn{$ptm200btn[$i]} = "$i:30";
@@ -140,14 +141,15 @@ EnOcean_Set($@)
$hash->{READINGS}{$cmd}{TIME} = $tn;
$hash->{READINGS}{$cmd}{VAL} = $arg;
} elsif($st eq "dimmCtrl") { # Tested for Eltako-Dimmer
} elsif($st eq "eltakoDimmer") {
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);
} elsif($cmd eq "dimto") {
return "Usage: $cmd percent [time 01-FF FF:slowest] [on/off]" if(@a<2);
my $time=0;
my $onoff=1;
# for eltako relative (0-100) (but not compliant to EEP because DB0.2 is 0)
@@ -156,15 +158,39 @@ EnOcean_Set($@)
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});
my $idSrc=EnOcean_GetMyDeviceId($hash);
#my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $time, $onoff|0x08, $hash->{DEF});
my $data=sprintf("A502%02X%02X%02X%s00", $dimVal, $time, $onoff|0x08, $idSrc);
IOWrite($hash, "000A0001", $data);
Log $ll2, "dimmCtrl.dimm: " . $data;
Log $ll2, "$st.$cnd: " . $data;
} else {
return "Unknown argument $cmd, choose one of: teach, dimm"
return "Unknown argument $cmd, choose one of: teach, dimto"
}
###########################
} elsif($st eq "eltakoRollCtrl") {
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) . ") [time 0-255 sek]";
my $rollcmd= $eltakoRollCtrlCommands{$cmd}
return $usage if( (!defined($rollcmd)) or (@a<1) );
my $time=0;
if(defined($a[1])) { $time=$a[1]; } # time
shift(@a);
# EEP: A5/3F/7F Universal ???
my $data=sprintf("A5%02X%02X%02X%02X%s00", 0, $time, $rollcmd, 0x08, $hash->{DEF});
IOWrite($hash, "000A0001", $data);
Log $ll2, "eltakoRollCtrl.$cmd" . $data;
}
###########################
} else { # Simulate a PTM
my ($c1,$c2) = split(",", $cmd, 2);
@@ -176,14 +202,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 +235,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 +288,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 +331,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
}
@@ -343,11 +371,8 @@ EnOcean_Parse($$)
push @event, "3:actuatorStatus:".(($db_2 & 0x01) ? "obstructed" : "ok");
push @event, "3:measured-temp:". sprintf "%.1f", ($db_1*40/255);
EnOcean_MD15Cmd($hash, $name, $db_1);
} 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");
@@ -356,7 +381,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
@@ -403,7 +428,7 @@ EnOcean_Parse($$)
}
}
$hash->{CHANGED} = \@changed;
return $name;
}
@@ -420,7 +445,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") {
@@ -430,7 +455,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});
@@ -442,10 +467,29 @@ 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 $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;