mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 09:16:53 +00:00
EnOcean updates
git-svn-id: https://svn.fhem.de/fhem/trunk@975 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
16208776e1
commit
bc9f649bdd
@ -46,7 +46,7 @@ TCM_Initialize($)
|
||||
$hash->{ReadyFn} = "TCM_Ready";
|
||||
$hash->{Clients} = ":EnOcean:";
|
||||
my %matchList= (
|
||||
"1:EnOcean" => "^EnOcean:0B",
|
||||
"1:EnOcean" => "^EnOcean:",
|
||||
);
|
||||
$hash->{MatchList} = \%matchList;
|
||||
|
||||
@ -210,10 +210,23 @@ TCM_Read($)
|
||||
Log $ll2, "$name: wrong checksum: got $crc, computed $mycrc" ;
|
||||
return;
|
||||
}
|
||||
if($net =~ m/^0B/) { # Receive Radio Telegram (RRT)
|
||||
Dispatch($hash, "EnOcean:$net", undef);
|
||||
|
||||
# Receive Radio Telegram (RRT)
|
||||
if($net =~ m/^0B(..)(........)(........)(..)/) {
|
||||
my ($org, $d1,$id,$status) = ($1, $2);
|
||||
|
||||
# Re-translate the ORG to RadioORG / TCM310 equivalent
|
||||
my %orgmap = ("05"=>"F6", "06"=>"D5", "07"=>"A5", );
|
||||
if($orgmap{$org}) {
|
||||
$org = $orgmap{$org};
|
||||
} else {
|
||||
Log 1, "TCM120: unknown ORG mapping for $org";
|
||||
}
|
||||
Dispatch($hash, "EnOcean:$org:$d1:$id:$status", undef);
|
||||
|
||||
} else { # Receive Message Telegram (RMT)
|
||||
TCM_Parse120($hash, $net, 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -254,18 +267,14 @@ TCM_Read($)
|
||||
}
|
||||
|
||||
if($t eq "01") { # Radio
|
||||
my %orgmap = ("F6"=>"05", "D5"=>"06", "A5"=>"07", );
|
||||
$mdata =~ m/^(..)(.*)(........)(..)$/;
|
||||
my $org = $orgmap{$1};
|
||||
Log 1, "TCM310: unknown ORG mapping for $1" if(!$org);
|
||||
my $net = sprintf("0B%s%s%s%s%s",
|
||||
$org ? $org:"00", $2, "0"x(8-length($2)), $3, $4);
|
||||
$odata =~ m/^(..)(........)(..)(..)$/;
|
||||
my %addvals = (SubTelNum => $1, DestinationID => $2,
|
||||
RSSI => $3, SecurityLevel => $4,);
|
||||
my ($org, $d1, $id, $status) = ($1,$2,$3,$4);
|
||||
|
||||
my %addvals = (SubTelNum => hex($1), DestinationID => $2,
|
||||
RSSI => hex($3), SecurityLevel => hex($4),);
|
||||
$hash->{RSSI} = $3;
|
||||
|
||||
Dispatch($hash, "EnOcean:$net", \%addvals);
|
||||
Dispatch($hash, "EnOcean:$org:$d1:$id:$status:$odata", \%addvals);
|
||||
|
||||
} else {
|
||||
Log $ll2, "$name: unknown packet type $t: $data" ;
|
||||
|
@ -7,27 +7,34 @@ use warnings;
|
||||
|
||||
sub EnOcean_Define($$);
|
||||
sub EnOcean_Initialize($);
|
||||
sub EnOcean_Pair(@);
|
||||
sub EnOcean_Parse($$);
|
||||
sub EnOcean_PushCmdStack($$);
|
||||
sub EnOcean_SendCmd($$$$);
|
||||
sub EnOcean_Set($@);
|
||||
sub EnOcean_convTemp($);
|
||||
|
||||
# TODO
|
||||
# Send120
|
||||
# Send310
|
||||
# Test windowHandle
|
||||
|
||||
sub
|
||||
EnOcean_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{Match} = "^EnOcean:0B";
|
||||
$hash->{Match} = "^EnOcean:";
|
||||
$hash->{DefFn} = "EnOcean_Define";
|
||||
$hash->{ParseFn} = "EnOcean_Parse";
|
||||
$hash->{SetFn} = "EnOcean_Set";
|
||||
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 " .
|
||||
"showtime:1,0 loglevel:0,1,2,3,4,5,6 model " .
|
||||
"subType:remote,sensor,modem,windowHandle,contact,SR04PT ";
|
||||
"subType:switch,contact,sensor,windowHandle,SR04";
|
||||
}
|
||||
|
||||
my %rorgname = ("F6"=>"switch", # RPS
|
||||
"D5"=>"contact", # 1BS
|
||||
"A5"=>"sensor", # 4BS
|
||||
);
|
||||
my @ptm200btn = ("AI", "A0", "BI", "B0", "CI", "C0", "DI", "D0");
|
||||
my %ptm200btn;
|
||||
|
||||
#############################
|
||||
sub
|
||||
@ -44,35 +51,37 @@ EnOcean_Define($$)
|
||||
AssignIoPort($hash);
|
||||
# Help FHEMWEB split up devices
|
||||
$attr{$name}{subType} = $1 if($name =~ m/EnO_(.*)_$a[2]/);
|
||||
|
||||
for(my $i=0; $i<@ptm200btn;$i++) {
|
||||
$ptm200btn{$ptm200btn[$i]} = "$i:30";
|
||||
}
|
||||
$ptm200btn{released} = "0:20";
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
my %sets = ( Btn0=>"10:30", Btn1=>"30:30", Btn2=>"20:30", Btn2=>"70:30",
|
||||
"Btn0,Btn2"=>"15:30", "Btn1,Btn2"=>"35:30",
|
||||
"Btn0,Btn3"=>"17:30", "Btn1,Btn3"=>"37:30",
|
||||
"released"=>"00:20" );
|
||||
|
||||
#############################
|
||||
# Simulate a PTM
|
||||
sub
|
||||
EnOcean_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
return "no set value specified" if(@a != 2);
|
||||
return "no set value specified" if(@a < 2);
|
||||
return "there a no set commands with argument" if(@a > 2);
|
||||
|
||||
my $cmd = $a[1];
|
||||
my $arg = $a[2];
|
||||
my $cmdhash = $sets{$cmd};
|
||||
return "Unknown argument $cmd, choose one of " . join(" ", sort keys %sets)
|
||||
if(!defined($cmdhash));
|
||||
my $cmdhash = $ptm200btn{$cmd};
|
||||
return "Unknown argument $cmd, choose one of " .
|
||||
join(" ", sort keys %ptm200btn) if(!defined($cmdhash));
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $ll2 = GetLogLevel($name, 2);
|
||||
Log $ll2, "EnOcean: set $name $cmd";
|
||||
|
||||
my ($d1, $status) = split(":", $cmdhash, 2);
|
||||
IOWrite($hash, "", sprintf("6B05%s000000%s%s", $d1, $hash->{DEF}, $status));
|
||||
my ($db_3, $status) = split(":", $cmdhash, 2);
|
||||
IOWrite($hash, "",
|
||||
sprintf("6B05%s000000%s%s", ($db_3<<5), $hash->{DEF}, $status));
|
||||
|
||||
my $tn = TimeNow();
|
||||
$hash->{CHANGED}[0] = $cmd;
|
||||
@ -87,117 +96,119 @@ sub
|
||||
EnOcean_Parse($$)
|
||||
{
|
||||
my ($iohash, $msg) = @_;
|
||||
my %ot = ("05"=>"remote", "06"=>"sensor", "07"=>"sensor",
|
||||
"08"=>"remote", "0A"=>"modem", "0B"=>"modem", );
|
||||
my (undef,$rorg,$data,$id,$status,$odata) = split(":", $msg);
|
||||
|
||||
$msg =~ m/^EnOcean:0B(..)(........)(........)(..)/;
|
||||
my ($org,$data,$id,$status) = ($1,$2,$3,$4,$5);
|
||||
|
||||
my $ot = $ot{$org};
|
||||
if(!$ot) {
|
||||
Log 2, "Unknown EnOcean ORG: $org received from $id";
|
||||
my $rorgname = $rorgname{$rorg};
|
||||
if(!$rorgname) {
|
||||
Log 2, "Unknown EnOcean RORG ($rorg) received from $id";
|
||||
return "";
|
||||
}
|
||||
|
||||
$id = ($id & 0xffff) if($org eq "0A");
|
||||
$id = (($id & 0xffff0000)>>16) if($org eq "0B");
|
||||
|
||||
my $hash = $modules{EnOcean}{defptr}{$id};
|
||||
if(!$hash) {
|
||||
Log 3, "EnOcean Unknown device with ID $id, please define it";
|
||||
return "UNDEFINED EnO_${ot}_$id EnOcean $id";
|
||||
return "UNDEFINED EnO_${rorgname}_$id EnOcean $id";
|
||||
}
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $st = AttrVal($name, "subType", "");
|
||||
my $ll4 = GetLogLevel($name, 4);
|
||||
Log $ll4, "EnOcean: ORG:$org, DATA:$data, ID:$id, STATUS:$status";
|
||||
Log $ll4, "$name: ORG:$rorg DATA:$data ID:$id STATUS:$status";
|
||||
|
||||
my @event;
|
||||
#push @event, "1:rp_counter:".(hex($status)&0xf);
|
||||
|
||||
push @event, "0:rp_counter:".(hex($status)&0xf);
|
||||
my $dl = length($data);
|
||||
my $db_3 = hex substr($data,0,2);
|
||||
my $db_2 = hex substr($data,2,2) if($dl > 2);
|
||||
my $db_1 = hex substr($data,4,2) if($dl > 4);
|
||||
my $db_0 = hex substr($data,6,2) if($dl > 6);
|
||||
my $st = AttrVal($name, "subType", "");
|
||||
|
||||
my $d1 = hex substr($data,0,2);
|
||||
#################################
|
||||
if($org eq "05") { # PTM remote. Queer reporting methods.
|
||||
# RPS: PTM200 based switch/remote or a windowHandle
|
||||
if($rorg eq "F6") {
|
||||
my $nu = ((hex($status)&0x10)>>4);
|
||||
|
||||
push @event, "0:T21:".((hex($status)&0x20)>>5);
|
||||
push @event, "0:NU:$nu";
|
||||
#push @event, "1:T21:".((hex($status)&0x20)>>5);
|
||||
#push @event, "1:NU:$nu";
|
||||
|
||||
if($nu) {
|
||||
$msg = sprintf "Btn%d", ($d1&0xe0)>>5;
|
||||
$msg .= sprintf ",Btn%d", ($d1&0x0e)>>1 if($d1 & 1);
|
||||
$msg .= ($d1&0x10) ? " pressed" : " released";
|
||||
|
||||
$msg = $ptm200btn[($db_3&0xe0)>>5];
|
||||
$msg .= ",".$ptm200btn[($db_3&0x0e)>>1] if($db_3 & 1);
|
||||
|
||||
} else {
|
||||
#confusing for normal use
|
||||
#my $nbu = (($d1&0xe0)>>5);
|
||||
#$msg = sprintf "Buttons %d", $nbu ? ($nbu+1) : 0;
|
||||
$msg = "buttons " . ($d1&0x10 ? "pressed" : "released");
|
||||
|
||||
if($st eq "windowHandle") {
|
||||
$msg = "closed" if($d1 == 0xF0);
|
||||
$msg = "open" if($d1 == 0xE0);
|
||||
$msg = "tilted" if($d1 == 0xD0);
|
||||
$msg = "open from tilted" if($d1 == 0xC0);
|
||||
# Couldnt test
|
||||
if($db_3 == 112) { # KeyCard
|
||||
$msg = "keycard inserted";
|
||||
|
||||
# Only the windowHandle is setting these bits when nu=0
|
||||
} elsif($db_3 & 0xC0) {
|
||||
$msg = "closed" if($db_3 == 0xF0);
|
||||
$msg = "open" if($db_3 == 0xE0);
|
||||
$msg = "tilted" if($db_3 == 0xD0);
|
||||
$msg = "open from tilted" if($db_3 == 0xC0);
|
||||
|
||||
} else {
|
||||
if($st eq "keycard") {
|
||||
$msg = "keycard removed";
|
||||
|
||||
} else {
|
||||
$msg = "buttons ". (($db_3&0x10) ? "pressed" : "released");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
push @event, "1:state:$msg";
|
||||
push @event, "3:state:$msg";
|
||||
|
||||
#################################
|
||||
} elsif($org eq "06") {
|
||||
if($st eq "contact") {
|
||||
push @event, "1:state:" . ($d1 == 9 ? "closed" : "open");
|
||||
# 1BS. Only contact is defined in the EEP2.1 for 1BS
|
||||
} elsif($rorg eq "D5") {
|
||||
push @event, "3:state:" . ($db_3&1 ? "closed" : "open");
|
||||
push @event, "3:learnBtn:on" if(!($db_3&0x8));
|
||||
|
||||
#################################
|
||||
} elsif($rorg eq "A5") {
|
||||
if($st eq "SR04") {
|
||||
my ($fspeed, $temp, $present);
|
||||
$fspeed = 3;
|
||||
$fspeed = 2 if($db_3 >= 145);
|
||||
$fspeed = 1 if($db_3 >= 165);
|
||||
$fspeed = 0 if($db_3 >= 190);
|
||||
$fspeed = "Auto" if($db_3 >= 210);
|
||||
$temp = sprintf("%0.1f", $db_1/6.375); # 40..0
|
||||
$present= $db_0&0x1 ? "no" : "yes";
|
||||
|
||||
push @event, "3:state:temperature $temp";
|
||||
push @event, "3:set_point:$db_3";
|
||||
push @event, "3:fan:$fspeed";
|
||||
push @event, "3:present:$present" if($present eq "yes");
|
||||
push @event, "3:learnBtn:on" if(!($db_0&0x8));
|
||||
push @event, "3:T:$temp SP: $db_3 F: $fspeed P: $present";
|
||||
|
||||
} else {
|
||||
push @event, "1:state:sensor:$d1";
|
||||
push @event, "1:sensor:$d1";
|
||||
push @event, "3:state:$db_3";
|
||||
push @event, "3:sensor1:$db_3";
|
||||
push @event, "3:sensor2:$db_2";
|
||||
push @event, "3:sensor3:$db_1";
|
||||
push @event, "3:D3:".(($db_0&0x8)?1:0);
|
||||
push @event, "3:D2:".(($db_0&0x4)?1:0);
|
||||
push @event, "3:D1:".(($db_0&0x2)?1:0);
|
||||
push @event, "3:D0:".(($db_0&0x1)?1:0);
|
||||
|
||||
}
|
||||
|
||||
#################################
|
||||
} elsif($org eq "07") {
|
||||
my $d2 = hex substr($data,2,2);
|
||||
my $d3 = hex substr($data,4,2);
|
||||
my $d4 = hex substr($data,6,2);
|
||||
if($st eq "SR04PT") {
|
||||
push @event, "1:state:alive";
|
||||
push @event, "1:present:".(($d4&0x1)?"No":"Yes");
|
||||
push @event, "1:desired:$d1";
|
||||
} else {
|
||||
push @event, "1:state:$d1";
|
||||
push @event, "1:sensor1:$d1";
|
||||
push @event, "1:sensor2:$d2";
|
||||
push @event, "1:sensor3:$d3";
|
||||
push @event, "1:D3:".(($d4&0x8)?1:0);
|
||||
push @event, "1:D2:".(($d4&0x4)?1:0);
|
||||
push @event, "1:D1:".(($d4&0x2)?1:0);
|
||||
push @event, "1:D0:".(($d4&0x1)?1:0);
|
||||
}
|
||||
|
||||
#################################
|
||||
} elsif($org eq "08") { # CTM remote.
|
||||
# Dont understand the SR bit
|
||||
$msg = sprintf "Btn%d", ($d1&0xe0)>>5;
|
||||
$msg .= ($d1&0x10) ? " pressed" : " released";
|
||||
push @event, "1:state:$msg";
|
||||
|
||||
#################################
|
||||
} elsif($org eq "0A") {
|
||||
push @event, "1:state:Modem:".substr($msg, 12, 6);
|
||||
|
||||
#################################
|
||||
} elsif($org eq "0B") {
|
||||
push @event, "1:state:Modem:ACK";
|
||||
|
||||
} elsif($org eq "00") {
|
||||
}
|
||||
|
||||
my $tn = TimeNow();
|
||||
my @changed;
|
||||
for(my $i = 0; $i < int(@event); $i++) {
|
||||
my ($dochanged, $vn, $vv) = split(":", $event[$i], 3);
|
||||
if($dochanged) {
|
||||
my ($flag, $vn, $vv) = split(":", $event[$i], 3);
|
||||
|
||||
if($flag & 2) {
|
||||
if($vn eq "state") {
|
||||
$hash->{STATE} = $vv;
|
||||
push @changed, $vv;
|
||||
@ -208,8 +219,10 @@ EnOcean_Parse($$)
|
||||
}
|
||||
}
|
||||
|
||||
$hash->{READINGS}{$vn}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{$vn}{VAL} = $vv;
|
||||
if($flag & 1) {
|
||||
$hash->{READINGS}{$vn}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{$vn}{VAL} = $vv;
|
||||
}
|
||||
}
|
||||
$hash->{CHANGED} = \@changed;
|
||||
|
||||
|
@ -2742,17 +2742,6 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
Define an EnOcean device, connected via a <a href="#TCM">TCM</a>. The
|
||||
<ID> parameter is an 8 digit hex number. For remotes and sensors the
|
||||
<a href="#autocreate">autocreate</a> module may help you.<br>
|
||||
In order to control devices, you cannot reuse the ID's of other devices
|
||||
(like remotes), instead you have to create your own, which must be in the
|
||||
allowed ID-Range of the underlying IO device. For this first query the
|
||||
TCM with the "<code>get <tcm> idbase</code>" command. You can use
|
||||
up to 128 ID's starting with the base shown there. If you are using an
|
||||
ID outside of the allowed range, you'll see an ERR_ID_RANGE message in the
|
||||
fhem log.<br>
|
||||
|
||||
For each ID there is the possibility to use 8 different commands, so
|
||||
in fact you can control 8*128/2=512 switches.<br><br>
|
||||
|
||||
|
||||
Example:
|
||||
<ul>
|
||||
@ -2766,20 +2755,26 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<ul>
|
||||
<code>set switch1 <value></code>
|
||||
<br><br>
|
||||
where <code>value</code> is one of the values for the Remote-Events, see below.
|
||||
combinations of these buttons: Btn0,Btn2 Btn0,Btn3 Btn1,Btn2 Btn1,Btn3 and
|
||||
released.<br>
|
||||
In fact we are trying to emulate a PTM100 type remote, which is capable to
|
||||
report either single buttons, some combinations of 2 buttons and the
|
||||
released state.<br>
|
||||
where <code>value</code> is one of A0,AI,B0,BI,C0,CI,D0,DI and
|
||||
released, in fact we are trying to emulate a PTM100 type remote.
|
||||
<br>
|
||||
|
||||
If you define an <a href="#eventMap">eventMap</a> attribute with on/off,
|
||||
then you'll be able to easily set the device from the <a
|
||||
href="#FHEMWEB">WEB</a> frontend.<br><br>
|
||||
In order to control devices, you cannot reuse the ID's of other devices
|
||||
(like remotes), instead you have to create your own, which must be in the
|
||||
allowed ID-Range of the underlying IO device. For this first query the
|
||||
TCM with the "<code>get <tcm> idbase</code>" command. You can use
|
||||
up to 128 ID's starting with the base shown there. If you are using an
|
||||
ID outside of the allowed range, you'll see an ERR_ID_RANGE message in the
|
||||
fhem log.<br>
|
||||
|
||||
Example:
|
||||
<ul><code>
|
||||
set switch1 Btn1<br>
|
||||
set switch1 Btn0,Btn2<br>
|
||||
attr eventMap Btn1:on Btn0,Btn2:off<br>
|
||||
set switch1 BI<br>
|
||||
set switch1 B0<br>
|
||||
attr eventMap BI:on B0:off<br>
|
||||
set switch1 on<br>
|
||||
</code></ul>
|
||||
</ul>
|
||||
@ -2805,16 +2800,20 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<a name="EnOceanevents"></a>
|
||||
<b>Generated events:</b>
|
||||
<ul>
|
||||
<li>Remote / Wall Switch. Switches with more than one (pair) of buttons
|
||||
<li>switch. Switches (remotes) with more than one (pair) of buttons
|
||||
are separate devices with separate address.
|
||||
<ul>
|
||||
<li>Btn0 pressed
|
||||
<li>Btn1 pressed
|
||||
<li>Btn2 pressed
|
||||
<li>Btn3 pressed
|
||||
<li>Btn0,Btn1 pressed
|
||||
<li><all other combinations of BtnX/BtnY> pressed
|
||||
<li>released
|
||||
<li>A0
|
||||
<li>AI
|
||||
<li>B0
|
||||
<li>BI
|
||||
<li>C0
|
||||
<li>CI
|
||||
<li>D0
|
||||
<li>DI
|
||||
<li>A0,BI
|
||||
<li><all other combinations of BtnX/BtnY>
|
||||
<li>buttons released
|
||||
</ul>
|
||||
<li>windowHandle (HOPPE SecuSignal). Set the subType attr to windowHandle.
|
||||
<ul>
|
||||
@ -2823,17 +2822,26 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<li>tilted
|
||||
<li>open from tilted
|
||||
</ul>
|
||||
<li>STM-250 Door and window contact. Set the subType attr to contact.
|
||||
<li>keycard. Set the subType attr to keycard. (untested)
|
||||
<ul>
|
||||
<li>keycard inserted
|
||||
<li>keycard removed
|
||||
</ul>
|
||||
<li>STM-250 Door and window contact.
|
||||
<ul>
|
||||
<li>closed
|
||||
<li>open
|
||||
<li>learnBtn: on
|
||||
</ul>
|
||||
<li>SR04PT (Temp sensor + Presence button and desired temp dial). Set the
|
||||
subType attr to SR04PT:
|
||||
<li>SR04* (Temp sensor + Presence button and desired temp dial). Set the
|
||||
subType attr to SR04:
|
||||
<ul>
|
||||
<li>alive
|
||||
<li>present: [Yes|No]
|
||||
<li>desired: [0-255]
|
||||
<li>temperature: XY.Z
|
||||
<li>set_point: [0..255]
|
||||
<li>fan: [0,1,2,3,Auto]
|
||||
<li>present: yes
|
||||
<li>learnBtn: on
|
||||
<li>T: XY.Z SP: [0..255] F: [0,1,2,3,Auto] P: [yes|no]
|
||||
</ul>
|
||||
</ul>
|
||||
</ul>
|
||||
|
Loading…
x
Reference in New Issue
Block a user