2011-07-24 11:55:36 +00:00
|
|
|
|
##############################################
|
2011-11-12 07:51:08 +00:00
|
|
|
|
# $Id$
|
2011-07-24 11:55:36 +00:00
|
|
|
|
package main;
|
|
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
sub EnOcean_Define($$);
|
|
|
|
|
sub EnOcean_Initialize($);
|
|
|
|
|
sub EnOcean_Parse($$);
|
|
|
|
|
sub EnOcean_Set($@);
|
2011-12-14 07:57:59 +00:00
|
|
|
|
sub EnOcean_MD15Cmd($$$);
|
2011-08-09 17:44:33 +00:00
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my %EnO_rorgname = ("F6"=>"switch", # RPS
|
2011-08-09 17:44:33 +00:00
|
|
|
|
"D5"=>"contact", # 1BS
|
|
|
|
|
"A5"=>"sensor", # 4BS
|
|
|
|
|
);
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my @EnO_ptm200btn = ("AI", "A0", "BI", "B0", "CI", "C0", "DI", "D0");
|
|
|
|
|
my %EnO_ptm200btn;
|
2011-10-15 11:24:11 +00:00
|
|
|
|
|
|
|
|
|
# Some Manufacturers (e.g. Jaeger Direkt) also sell EnOcean products without an
|
|
|
|
|
# intry in the table below. This table is only needed for A5 category devices
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my %EnO_manuf = (
|
2011-10-09 17:42:18 +00:00
|
|
|
|
"001" => "Peha",
|
|
|
|
|
"002" => "Thermokon",
|
|
|
|
|
"003" => "Servodan",
|
|
|
|
|
"004" => "EchoFlex Solutions",
|
|
|
|
|
"005" => "Omnio AG",
|
|
|
|
|
"006" => "Hardmeier electronics",
|
|
|
|
|
"007" => "Regulvar Inc",
|
|
|
|
|
"008" => "Ad Hoc Electronics",
|
|
|
|
|
"009" => "Distech Controls",
|
|
|
|
|
"00A" => "Kieback + Peter",
|
|
|
|
|
"00B" => "EnOcean GmbH",
|
|
|
|
|
"00C" => "Probare",
|
|
|
|
|
"00D" => "Eltako",
|
|
|
|
|
"00E" => "Leviton",
|
|
|
|
|
"00F" => "Honeywell",
|
|
|
|
|
"010" => "Spartan Peripheral Devices",
|
|
|
|
|
"011" => "Siemens",
|
|
|
|
|
"012" => "T-Mac",
|
|
|
|
|
"013" => "Reliable Controls Corporation",
|
|
|
|
|
"014" => "Elsner Elektronik GmbH",
|
|
|
|
|
"015" => "Diehl Controls",
|
|
|
|
|
"016" => "BSC Computer",
|
|
|
|
|
"017" => "S+S Regeltechnik GmbH",
|
|
|
|
|
"018" => "Masco Corporation",
|
|
|
|
|
"019" => "Intesis Software SL",
|
|
|
|
|
"01A" => "Res.",
|
|
|
|
|
"01B" => "Lutuo Technology",
|
|
|
|
|
"01C" => "CAN2GO",
|
|
|
|
|
);
|
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my %EnO_subType = (
|
2011-10-09 17:42:18 +00:00
|
|
|
|
"A5.20.01" => "MD15",
|
2012-08-12 11:01:31 +00:00
|
|
|
|
1 => "switch",
|
|
|
|
|
2 => "contact",
|
|
|
|
|
3 => "sensor",
|
|
|
|
|
4 => "windowHandle",
|
|
|
|
|
5 => "dimmer",
|
|
|
|
|
6 => "dimmCtrl",
|
|
|
|
|
7 => "FAH",
|
|
|
|
|
8 => "FBH",
|
|
|
|
|
9 => "FTF",
|
2012-09-18 10:07:41 +00:00
|
|
|
|
10 => "SR04",
|
2012-08-12 11:01:31 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
my @EnO_models = qw (
|
|
|
|
|
other
|
|
|
|
|
MD15-FtL-HE
|
|
|
|
|
SR04 SR04P SR04PT SR04PST SR04PMS
|
|
|
|
|
FAH60 FAH63 FIH63
|
|
|
|
|
FABH63 FBH63 FIBH63
|
|
|
|
|
PM101
|
|
|
|
|
FTF55
|
|
|
|
|
FSB61
|
2012-09-19 07:40:43 +00:00
|
|
|
|
FSM61
|
2011-10-09 17:42:18 +00:00
|
|
|
|
);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2011-10-15 11:24:11 +00:00
|
|
|
|
sub
|
|
|
|
|
EnOcean_Initialize($)
|
|
|
|
|
{
|
|
|
|
|
my ($hash) = @_;
|
|
|
|
|
|
|
|
|
|
$hash->{Match} = "^EnOcean:";
|
|
|
|
|
$hash->{DefFn} = "EnOcean_Define";
|
|
|
|
|
$hash->{ParseFn} = "EnOcean_Parse";
|
|
|
|
|
$hash->{SetFn} = "EnOcean_Set";
|
2012-06-07 14:07:39 +00:00
|
|
|
|
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 dummy:0,1 " .
|
2012-08-12 11:01:31 +00:00
|
|
|
|
"showtime:1,0 loglevel:0,1,2,3,4,5,6 ".
|
|
|
|
|
"model:".join(",",@EnO_models)." ".
|
|
|
|
|
"subType:".join(",",values %EnO_subType)." ".
|
|
|
|
|
"actualTemp";
|
2011-10-15 11:24:11 +00:00
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
for(my $i=0; $i<@EnO_ptm200btn;$i++) {
|
|
|
|
|
$EnO_ptm200btn{$EnO_ptm200btn[$i]} = "$i:30";
|
2011-10-15 11:24:11 +00:00
|
|
|
|
}
|
2012-08-12 11:01:31 +00:00
|
|
|
|
$EnO_ptm200btn{released} = "0:20";
|
2011-10-15 11:24:11 +00:00
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-24 11:55:36 +00:00
|
|
|
|
#############################
|
|
|
|
|
sub
|
|
|
|
|
EnOcean_Define($$)
|
|
|
|
|
{
|
|
|
|
|
my ($hash, $def) = @_;
|
|
|
|
|
my @a = split("[ \t][ \t]*", $def);
|
|
|
|
|
my $name = $hash->{NAME};
|
|
|
|
|
return "wrong syntax: define <name> EnOcean 8-digit-hex-code"
|
|
|
|
|
if(int(@a)!=3 || $a[2] !~ m/^[A-F0-9]{8}$/i);
|
|
|
|
|
|
|
|
|
|
$modules{EnOcean}{defptr}{uc($a[2])} = $hash;
|
|
|
|
|
AssignIoPort($hash);
|
2011-08-07 16:46:33 +00:00
|
|
|
|
# Help FHEMWEB split up devices
|
2011-07-24 11:55:36 +00:00
|
|
|
|
$attr{$name}{subType} = $1 if($name =~ m/EnO_(.*)_$a[2]/);
|
2011-12-14 07:57:59 +00:00
|
|
|
|
return undef;
|
2011-07-24 11:55:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#############################
|
|
|
|
|
sub
|
|
|
|
|
EnOcean_Set($@)
|
|
|
|
|
{
|
|
|
|
|
my ($hash, @a) = @_;
|
2011-08-09 17:44:33 +00:00
|
|
|
|
return "no set value specified" if(@a < 2);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
my $name = $hash->{NAME};
|
2011-10-09 17:42:18 +00:00
|
|
|
|
my $st = AttrVal($name, "subType", "");
|
2011-07-24 11:55:36 +00:00
|
|
|
|
my $ll2 = GetLogLevel($name, 2);
|
|
|
|
|
|
2011-10-09 11:34:08 +00:00
|
|
|
|
shift @a;
|
2011-11-05 08:59:29 +00:00
|
|
|
|
my $tn = TimeNow();
|
|
|
|
|
|
2011-10-09 11:34:08 +00:00
|
|
|
|
for(my $i = 0; $i < @a; $i++) {
|
|
|
|
|
my $cmd = $a[$i];
|
|
|
|
|
|
2011-11-05 08:59:29 +00:00
|
|
|
|
#####################
|
|
|
|
|
# See also http://www.oscat.de/community/index.php/topic,985.30.html
|
2011-10-09 17:42:18 +00:00
|
|
|
|
if($st eq "MD15") {
|
2011-11-05 08:59:29 +00:00
|
|
|
|
my %sets = (
|
2011-12-14 07:57:59 +00:00
|
|
|
|
"desired-temp" => "\\d+(\\.\\d)?",
|
2011-11-05 08:59:29 +00:00
|
|
|
|
"actuator" => "\\d+",
|
|
|
|
|
"unattended" => "",
|
2011-12-14 07:57:59 +00:00
|
|
|
|
"initialize" => "",
|
2011-11-05 08:59:29 +00:00
|
|
|
|
);
|
|
|
|
|
my $re = $sets{$a[0]};
|
|
|
|
|
return "Unknown argument $cmd, choose one of ".join(" ", sort keys %sets)
|
|
|
|
|
if(!defined($re));
|
|
|
|
|
return "Need a parameter" if($re && @a < 2);
|
|
|
|
|
return "Argument $a[1] is incorrect (expect $re)"
|
|
|
|
|
if($re && $a[1] !~ m/^$re$/);
|
|
|
|
|
|
|
|
|
|
$hash->{CMD} = $cmd;
|
|
|
|
|
$hash->{READINGS}{CMD}{TIME} = $tn;
|
|
|
|
|
$hash->{READINGS}{CMD}{VAL} = $cmd;
|
|
|
|
|
|
2011-12-14 07:57:59 +00:00
|
|
|
|
my $arg = "true";
|
2011-11-05 08:59:29 +00:00
|
|
|
|
if($re) {
|
|
|
|
|
$arg = $a[1];
|
|
|
|
|
shift(@a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$hash->{READINGS}{$cmd}{TIME} = $tn;
|
|
|
|
|
$hash->{READINGS}{$cmd}{VAL} = $arg;
|
2011-10-09 17:42:18 +00:00
|
|
|
|
|
2012-08-08 06:57:21 +00:00
|
|
|
|
} elsif($st eq "dimmCtrl") { # Tested for Eltako-Dimmer
|
|
|
|
|
if($cmd eq "teach") {
|
|
|
|
|
my $data=sprintf("A502000000%s00", $hash->{DEF});
|
|
|
|
|
Log $ll2, "dimmCtrl.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;
|
|
|
|
|
# for eltako relative (0-100) (but not compliant to EEP because DB0.2 is 0)
|
|
|
|
|
my $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;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
return "Unknown argument $cmd, choose one of: teach, dimm:slider,0,1,100"
|
|
|
|
|
|
|
|
|
|
}
|
2011-12-30 15:15:04 +00:00
|
|
|
|
|
2011-11-05 08:59:29 +00:00
|
|
|
|
###########################
|
2011-10-09 17:42:18 +00:00
|
|
|
|
} else { # Simulate a PTM
|
|
|
|
|
my ($c1,$c2) = split(",", $cmd, 2);
|
|
|
|
|
return "Unknown argument $cmd, choose one of " .
|
2012-08-12 11:01:31 +00:00
|
|
|
|
join(" ", sort keys %EnO_ptm200btn)
|
|
|
|
|
if(!defined($EnO_ptm200btn{$c1}) || ($c2 && !defined($EnO_ptm200btn{$c2})));
|
2011-10-09 17:42:18 +00:00
|
|
|
|
Log $ll2, "EnOcean: set $name $cmd";
|
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my ($db_3, $status) = split(":", $EnO_ptm200btn{$c1}, 2);
|
2011-10-09 17:42:18 +00:00
|
|
|
|
$db_3 <<= 5;
|
|
|
|
|
$db_3 |= 0x10 if($c1 ne "released"); # set the pressed flag
|
|
|
|
|
if($c2) {
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my ($d2, undef) = split(":", $EnO_ptm200btn{$c2}, 2);
|
2011-10-09 17:42:18 +00:00
|
|
|
|
$db_3 |= ($d2<<1) | 0x01;
|
|
|
|
|
}
|
|
|
|
|
IOWrite($hash, "",
|
2011-10-09 11:34:08 +00:00
|
|
|
|
sprintf("6B05%02X000000%s%s", $db_3, $hash->{DEF}, $status));
|
|
|
|
|
|
2011-10-09 17:42:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-07-23 12:28:26 +00:00
|
|
|
|
select(undef, undef, undef, 0.2); # Tested by joerg. He prefers 0.3 :)
|
2011-10-09 11:34:08 +00:00
|
|
|
|
}
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2011-10-09 11:34:08 +00:00
|
|
|
|
my $cmd = join(" ", @a);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
$hash->{CHANGED}[0] = $cmd;
|
|
|
|
|
$hash->{STATE} = $cmd;
|
|
|
|
|
$hash->{READINGS}{state}{TIME} = $tn;
|
|
|
|
|
$hash->{READINGS}{state}{VAL} = $cmd;
|
|
|
|
|
return undef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#############################
|
|
|
|
|
sub
|
|
|
|
|
EnOcean_Parse($$)
|
|
|
|
|
{
|
|
|
|
|
my ($iohash, $msg) = @_;
|
2011-08-09 17:44:33 +00:00
|
|
|
|
my (undef,$rorg,$data,$id,$status,$odata) = split(":", $msg);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my $rorgname = $EnO_rorgname{$rorg};
|
2011-08-09 17:44:33 +00:00
|
|
|
|
if(!$rorgname) {
|
|
|
|
|
Log 2, "Unknown EnOcean RORG ($rorg) received from $id";
|
2011-07-24 11:55:36 +00:00
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $hash = $modules{EnOcean}{defptr}{$id};
|
|
|
|
|
if(!$hash) {
|
|
|
|
|
Log 3, "EnOcean Unknown device with ID $id, please define it";
|
2011-08-09 17:44:33 +00:00
|
|
|
|
return "UNDEFINED EnO_${rorgname}_$id EnOcean $id";
|
2011-07-24 11:55:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my $name = $hash->{NAME};
|
|
|
|
|
my $ll4 = GetLogLevel($name, 4);
|
2011-08-09 17:44:33 +00:00
|
|
|
|
Log $ll4, "$name: ORG:$rorg DATA:$data ID:$id STATUS:$status";
|
|
|
|
|
|
2011-07-24 11:55:36 +00:00
|
|
|
|
my @event;
|
2011-08-09 17:44:33 +00:00
|
|
|
|
#push @event, "1:rp_counter:".(hex($status)&0xf);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2011-08-09 17:44:33 +00:00
|
|
|
|
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", "");
|
2012-08-12 11:01:31 +00:00
|
|
|
|
my $model = AttrVal($name, "model", "");
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
#################################
|
2011-08-09 17:44:33 +00:00
|
|
|
|
# RPS: PTM200 based switch/remote or a windowHandle
|
|
|
|
|
if($rorg eq "F6") {
|
2011-07-24 11:55:36 +00:00
|
|
|
|
my $nu = ((hex($status)&0x10)>>4);
|
|
|
|
|
|
2011-10-15 11:24:11 +00:00
|
|
|
|
# unused flags (AFAIK)
|
2011-08-09 17:44:33 +00:00
|
|
|
|
#push @event, "1:T21:".((hex($status)&0x20)>>5);
|
|
|
|
|
#push @event, "1:NU:$nu";
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
if($nu) {
|
2011-08-09 17:44:33 +00:00
|
|
|
|
|
2011-10-09 11:34:08 +00:00
|
|
|
|
# Theoretically there can be a released event with some of the A0,BI
|
|
|
|
|
# pins set, but with the plastic cover on this wont happen.
|
2012-08-12 11:01:31 +00:00
|
|
|
|
$msg = $EnO_ptm200btn[($db_3&0xe0)>>5];
|
|
|
|
|
$msg .= ",".$EnO_ptm200btn[($db_3&0x0e)>>1] if($db_3 & 1);
|
2011-10-09 11:34:08 +00:00
|
|
|
|
$msg .= " released" if(!($db_3 & 0x10));
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
if($db_3 == 112) { # KeyCard, not tested
|
2011-08-09 17:44:33 +00:00
|
|
|
|
$msg = "keycard inserted";
|
2011-08-07 16:46:33 +00:00
|
|
|
|
|
2011-08-09 17:44:33 +00:00
|
|
|
|
# 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);
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2011-08-09 17:44:33 +00:00
|
|
|
|
} else {
|
|
|
|
|
if($st eq "keycard") {
|
|
|
|
|
$msg = "keycard removed";
|
|
|
|
|
|
|
|
|
|
} else {
|
2011-10-15 11:24:11 +00:00
|
|
|
|
$msg = (($db_3&0x10) ? "pressed" : "released");
|
2011-08-09 17:44:33 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-07 16:46:33 +00:00
|
|
|
|
}
|
2011-10-15 11:24:11 +00:00
|
|
|
|
|
|
|
|
|
# released events are disturbing when using a remote, since it overwrites
|
2012-08-11 06:43:14 +00:00
|
|
|
|
# the "real" state immediately.
|
|
|
|
|
# In the case of an ElTako FSB61 the state should remain released (by Thomas)
|
2011-10-15 11:24:11 +00:00
|
|
|
|
my $event = "state";
|
2012-09-19 07:40:43 +00:00
|
|
|
|
$event = "buttons" if($msg =~ m/released$/ &&
|
|
|
|
|
$model ne "FSB61" &&
|
|
|
|
|
$model ne "FSM61");
|
2011-10-15 11:24:11 +00:00
|
|
|
|
|
|
|
|
|
push @event, "3:$event:$msg";
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
#################################
|
2011-08-09 17:44:33 +00:00
|
|
|
|
# 1BS. Only contact is defined in the EEP2.1 for 1BS
|
2011-10-09 17:42:18 +00:00
|
|
|
|
} elsif($rorg eq "D5") {
|
2011-08-09 17:44:33 +00:00
|
|
|
|
push @event, "3:state:" . ($db_3&1 ? "closed" : "open");
|
|
|
|
|
push @event, "3:learnBtn:on" if(!($db_3&0x8));
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
#################################
|
2011-08-09 17:44:33 +00:00
|
|
|
|
} elsif($rorg eq "A5") {
|
2011-10-09 17:42:18 +00:00
|
|
|
|
if(($db_0 & 0x08) == 0) {
|
|
|
|
|
if($db_0 & 0x80) {
|
|
|
|
|
my $fn = sprintf "%02x", ($db_3>>2);
|
|
|
|
|
my $tp = sprintf "%02X", ((($db_3&3) << 5) | ($db_2 >> 3));
|
|
|
|
|
my $mf = sprintf "%03X", ((($db_2&7) << 8) | $db_1);
|
2012-08-12 11:01:31 +00:00
|
|
|
|
$mf = $EnO_manuf{$mf} if($EnO_manuf{$mf});
|
2011-10-09 17:42:18 +00:00
|
|
|
|
my $m = "teach-in:class A5.$fn.$tp (manufacturer: $mf)";
|
|
|
|
|
Log 1, $m;
|
|
|
|
|
push @event, "3:$m";
|
|
|
|
|
my $st = "A5.$fn.$tp";
|
2012-08-14 06:28:50 +00:00
|
|
|
|
$st = $EnO_subType{$st} if($EnO_subType{$st});
|
2011-10-09 17:42:18 +00:00
|
|
|
|
$attr{$name}{subType} = $st;
|
|
|
|
|
|
2011-12-14 07:57:59 +00:00
|
|
|
|
if("$fn.$tp" eq "20.01" && $iohash->{pair}) { # MD15
|
|
|
|
|
select(undef, undef, undef, 0.1); # max 10 Seconds
|
|
|
|
|
EnOcean_A5Cmd($hash, "800800F0", "00000000");
|
|
|
|
|
select(undef, undef, undef, 0.5);
|
|
|
|
|
EnOcean_MD15Cmd($hash, $name, 128); # 128 == 20 degree C
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-09 17:42:18 +00:00
|
|
|
|
} else {
|
|
|
|
|
push @event, "3:teach-in:no type/manuf. data transmitted";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-18 10:07:41 +00:00
|
|
|
|
} elsif($model =~ m/^SR04/ || $st eq "SR04") {
|
2012-07-10 06:09:54 +00:00
|
|
|
|
my ($fspeed, $temp, $present, $solltemp);
|
2011-08-09 17:44:33 +00:00
|
|
|
|
$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);
|
2012-07-08 06:42:25 +00:00
|
|
|
|
$temp = sprintf("%0.1f", 40-$db_1/6.375); # 40..0
|
2011-08-09 17:44:33 +00:00
|
|
|
|
$present= $db_0&0x1 ? "no" : "yes";
|
2012-07-10 06:09:54 +00:00
|
|
|
|
$solltemp= sprintf("%0.1f", $db_2/6.375);
|
2011-08-09 17:44:33 +00:00
|
|
|
|
|
|
|
|
|
push @event, "3:state:temperature $temp";
|
2012-07-10 06:09:54 +00:00
|
|
|
|
push @event, "3:set_point: $solltemp";
|
2011-08-09 17:44:33 +00:00
|
|
|
|
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";
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
2011-10-09 17:42:18 +00:00
|
|
|
|
} elsif($st eq "MD15") {
|
|
|
|
|
push @event, "3:state:$db_3 %";
|
|
|
|
|
push @event, "3:currentValue:$db_3";
|
|
|
|
|
push @event, "3:serviceOn:" . (($db_2 & 0x80) ? "yes" : "no");
|
|
|
|
|
push @event, "3:energyInput:" . (($db_2 & 0x40) ? "enabled":"disabled");
|
|
|
|
|
push @event, "3:energyStorage:". (($db_2 & 0x20) ? "charged":"empty");
|
|
|
|
|
push @event, "3:battery:" . (($db_2 & 0x10) ? "ok" : "empty");
|
|
|
|
|
push @event, "3:cover:" . (($db_2 & 0x08) ? "open" : "closed");
|
|
|
|
|
push @event, "3:tempSensor:" . (($db_2 & 0x04) ? "failed" : "ok");
|
|
|
|
|
push @event, "3:window:" . (($db_2 & 0x02) ? "open" : "closed");
|
2011-12-14 07:57:59 +00:00
|
|
|
|
push @event, "3:actuatorStatus:".(($db_2 & 0x01) ? "obstructed" : "ok");
|
2012-09-12 13:49:29 +00:00
|
|
|
|
push @event, "3:measured-temp:". sprintf "%0.1f", ($db_1*40/255);
|
2011-12-14 07:57:59 +00:00
|
|
|
|
EnOcean_MD15Cmd($hash, $name, $db_1);
|
2011-10-09 17:42:18 +00:00
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
} elsif($model eq "PM101") {
|
2012-02-09 08:32:12 +00:00
|
|
|
|
####################################
|
|
|
|
|
# Ratio Presence Sensor Eagle PM101, code by aicgazi
|
|
|
|
|
####################################
|
|
|
|
|
my $lux = sprintf "%3d", $db_2;
|
|
|
|
|
# content of $db_2 is the illuminance where max value 0xFF stands for 1000 lx
|
|
|
|
|
$lux = sprintf "%04.2f", ( $lux * 1000 / 255 ) ;
|
|
|
|
|
push @event, "3:brightness:$lux";
|
|
|
|
|
push @event, "3:channel1:" . ($db_0 & 0x01 ? "off" : "on");
|
|
|
|
|
push @event, "3:channel2:" . ($db_0 & 0x02 ? "off" : "on");
|
2011-12-30 15:15:04 +00:00
|
|
|
|
|
2012-08-12 11:01:31 +00:00
|
|
|
|
} elsif($st eq "FAH" || $model =~ /^(FAH60|FAH63|FIH63)$/) {
|
|
|
|
|
####################################
|
|
|
|
|
# Eltako FAH60+FAH63+FIH63
|
|
|
|
|
# (EEP: 07-06-01 plus Data_byte3)
|
|
|
|
|
####################################
|
|
|
|
|
# $db_3 is the illuminance where min 0x00 = 0 lx, max 0xFF = 100 lx;
|
|
|
|
|
# $db_2 must be 0x00
|
|
|
|
|
|
|
|
|
|
if($db_2 eq 0x00) {
|
|
|
|
|
my $luxlow = sprintf "%3d", $db_3;
|
|
|
|
|
$luxlow = sprintf "%d", ( $luxlow * 100 / 255 ) ;
|
|
|
|
|
push @event, "3:brightness:$luxlow";
|
|
|
|
|
push @event, "3:state:$luxlow";
|
|
|
|
|
} else {
|
|
|
|
|
# $db_2 is the illuminance where min 0x00 = 300 lx, max 0xFF = 30000 lx
|
|
|
|
|
my $lux = sprintf "%3d", $db_2;
|
|
|
|
|
$lux = sprintf "%d", (( $lux * 116.48) + 300 ) ;
|
|
|
|
|
push @event, "3:brightness:$lux";
|
|
|
|
|
push @event, "3:state:$lux";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} elsif($st eq "FBH" || $model =~ /^(FABH63|FBH55|FBH63|FIBH63)$/) {
|
|
|
|
|
####################################
|
|
|
|
|
# Eltako FABH63+FBH55+FBH63+FIBH63
|
|
|
|
|
# (EEP: similar 07-08-01)
|
|
|
|
|
####################################
|
|
|
|
|
# $db_0 motion detection where 0x0D = motion and 0x0F = no motion
|
|
|
|
|
# (DB0_Bit1 = 1 or 0)
|
|
|
|
|
|
|
|
|
|
if($db_0 eq 0x0D) {
|
|
|
|
|
push @event, "3:motion:yes";
|
|
|
|
|
push @event, "3:state:yes";
|
|
|
|
|
}
|
|
|
|
|
if($db_0 eq 0x0F) {
|
|
|
|
|
push @event, "3:motion:no";
|
|
|
|
|
push @event, "3:state:no";
|
|
|
|
|
}
|
|
|
|
|
# $db_2 is the illuminance where min 0x00 = 0 lx, max 0xFF = 2048 lx
|
|
|
|
|
my $lux = sprintf "%3d", $db_2;
|
|
|
|
|
$lux = sprintf "%d", ( $lux * 2048 / 255 ) ;
|
|
|
|
|
push @event, "3:brightness:$lux";
|
|
|
|
|
# $db_3 is voltage in EEP 07-08-01 but not used by Eltako !?
|
|
|
|
|
# push @event, "3:voltage:$db_3";
|
|
|
|
|
|
|
|
|
|
} elsif($st eq "FTF" || $model eq "FTF55") {
|
|
|
|
|
####################################
|
|
|
|
|
# Eltako FTF55
|
|
|
|
|
# (EEP: 07-02-05)
|
|
|
|
|
####################################
|
|
|
|
|
# $db_1 is the temperature where 0x00 = 40<34>C and 0xFF 0<>C
|
|
|
|
|
my $temp = sprintf "%3d", $db_1;
|
2012-08-16 12:24:35 +00:00
|
|
|
|
$temp = sprintf "%0.1f", ( 40 - $temp * 40 / 255 ) ;
|
2012-08-12 11:01:31 +00:00
|
|
|
|
push @event, "3:temperature:$temp";
|
|
|
|
|
push @event, "3:state:$temp";
|
|
|
|
|
|
2011-12-30 15:15:04 +00:00
|
|
|
|
} elsif($st eq "dimmer") {
|
|
|
|
|
# todo: create a more general solution for the central-command responses
|
|
|
|
|
|
|
|
|
|
# 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");
|
|
|
|
|
push @event, "3:time:" . ($db_2<<8 + $db_1);
|
|
|
|
|
push @event, "3:timeType:" . (($db_0 & 0x02) ? "delay": "duration");
|
|
|
|
|
|
|
|
|
|
} elsif($db_3 eq 0x02) { # dimm
|
|
|
|
|
push @event, "3:state:" . (($db_0 & 0x01) ? "on": "off");
|
|
|
|
|
push @event, "3:dimmValue:$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
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-09 17:44:33 +00:00
|
|
|
|
} else {
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
}
|
2011-07-24 11:55:36 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-15 11:24:11 +00:00
|
|
|
|
# Flag & 1: reading
|
|
|
|
|
# Flag & 2: changed
|
|
|
|
|
|
2011-07-24 11:55:36 +00:00
|
|
|
|
my $tn = TimeNow();
|
|
|
|
|
my @changed;
|
|
|
|
|
for(my $i = 0; $i < int(@event); $i++) {
|
2011-08-09 17:44:33 +00:00
|
|
|
|
my ($flag, $vn, $vv) = split(":", $event[$i], 3);
|
|
|
|
|
|
|
|
|
|
if($flag & 2) {
|
2011-07-24 11:55:36 +00:00
|
|
|
|
if($vn eq "state") {
|
|
|
|
|
$hash->{STATE} = $vv;
|
|
|
|
|
push @changed, $vv;
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
push @changed, "$vn: $vv";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-09 17:44:33 +00:00
|
|
|
|
if($flag & 1) {
|
|
|
|
|
$hash->{READINGS}{$vn}{TIME} = TimeNow();
|
|
|
|
|
$hash->{READINGS}{$vn}{VAL} = $vv;
|
|
|
|
|
}
|
2011-07-24 11:55:36 +00:00
|
|
|
|
}
|
|
|
|
|
$hash->{CHANGED} = \@changed;
|
|
|
|
|
|
|
|
|
|
return $name;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-14 07:57:59 +00:00
|
|
|
|
sub
|
|
|
|
|
EnOcean_MD15Cmd($$$)
|
|
|
|
|
{
|
|
|
|
|
my ($hash, $name, $db_1) = @_;
|
|
|
|
|
my $cmd = ReadingsVal($name, "CMD", undef);
|
|
|
|
|
if($cmd) {
|
|
|
|
|
my $msg; # Unattended
|
|
|
|
|
my $arg1 = ReadingsVal($name, $cmd, 0); # Command-Argument
|
|
|
|
|
|
|
|
|
|
if($cmd eq "actuator") {
|
|
|
|
|
$msg = sprintf("%02X000000", $arg1);
|
|
|
|
|
|
|
|
|
|
} elsif($cmd eq "desired-temp") {
|
|
|
|
|
$msg = sprintf("%02X%02X0400", $arg1*255/40,
|
|
|
|
|
AttrVal($name, "actualTemp", ($db_1*40/255)) * 255/40);
|
|
|
|
|
|
|
|
|
|
} elsif($cmd eq "initialize") {
|
|
|
|
|
$msg = sprintf("00006400");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($msg) {
|
|
|
|
|
select(undef, undef, undef, 0.2);
|
|
|
|
|
EnOcean_A5Cmd($hash, $msg, "00000000");
|
|
|
|
|
if($cmd eq "initialize") {
|
|
|
|
|
delete($defs{$name}{READINGS}{CMD});
|
|
|
|
|
delete($defs{$name}{READINGS}{$cmd});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub
|
|
|
|
|
EnOcean_A5Cmd($$$)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-24 11:55:36 +00:00
|
|
|
|
1;
|
2012-11-04 13:49:43 +00:00
|
|
|
|
|
|
|
|
|
=pod
|
|
|
|
|
=begin html
|
|
|
|
|
|
|
|
|
|
<a name="EnOcean"></a>
|
|
|
|
|
<h3>EnOcean</h3>
|
|
|
|
|
<ul>
|
|
|
|
|
Devices sold by numerous hardware verndors (e.g. Eltako, Peha, etc), using
|
|
|
|
|
the RF Protocol provided by the EnOcean Alliance.
|
|
|
|
|
<br><br>
|
|
|
|
|
<a name="EnOceandefine"></a>
|
|
|
|
|
<b>Define</b>
|
|
|
|
|
<ul>
|
|
|
|
|
<code>define <name> EnOcean <ID></code>
|
|
|
|
|
<br><br>
|
|
|
|
|
|
|
|
|
|
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>
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
<ul>
|
|
|
|
|
<code>define switch1 EnOcean ffc54500</code><br>
|
|
|
|
|
</ul>
|
|
|
|
|
</ul>
|
|
|
|
|
<br>
|
|
|
|
|
|
|
|
|
|
<a name="EnOceanset"></a>
|
|
|
|
|
<b>Set</b>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>MD15 commands. Note: The command is not sent until the MD15
|
|
|
|
|
wakes up and sends a mesage, usually every 10 minutes.
|
|
|
|
|
<ul>
|
|
|
|
|
<li>actuator <value><br>
|
|
|
|
|
Set the actuator to the specifed percent value (0-100)</li>
|
|
|
|
|
<li>desired-temp <value><br>
|
|
|
|
|
Use the builtin PI regulator, and set the desired temperature to the
|
|
|
|
|
specified degree. The actual value will be taken from the temperature
|
|
|
|
|
reported by the MD15 or from the attribute actualTemp if it is set</li>
|
|
|
|
|
<li>unattended<br>
|
|
|
|
|
Do not regulate the MD15.</li>
|
|
|
|
|
</ul></li>
|
|
|
|
|
|
|
|
|
|
<li>subType dimmCtrl, tested with ElTako Dimmer only
|
|
|
|
|
<ul>
|
|
|
|
|
<li>teach<br>
|
|
|
|
|
initiate teach-in mode
|
|
|
|
|
<li>dimm percent [time 01-FF FF:slowest] [on/off]<br>
|
|
|
|
|
issue dim command.
|
|
|
|
|
</ul>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li>all other:
|
|
|
|
|
<ul>
|
|
|
|
|
<code>set switch1 <value></code>
|
|
|
|
|
<br><br>
|
|
|
|
|
where <code>value</code> is one of A0,AI,B0,BI,C0,CI,D0,DI, combinations of
|
|
|
|
|
these 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 BI<br>
|
|
|
|
|
set switch1 B0,CI<br>
|
|
|
|
|
attr eventMap BI:on B0:off<br>
|
|
|
|
|
set switch1 on<br>
|
|
|
|
|
</code></ul>
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
</ul>
|
|
|
|
|
<br>
|
|
|
|
|
|
|
|
|
|
<a name="EnOceanget"></a>
|
|
|
|
|
<b>Get</b> <ul>N/A</ul><br>
|
|
|
|
|
|
|
|
|
|
<a name="EnOceanattr"></a>
|
|
|
|
|
<b>Attributes</b>
|
|
|
|
|
<ul>
|
|
|
|
|
<li><a href="#eventMap">eventMap</a></li>
|
|
|
|
|
<li><a href="#IODev">IODev</a></li>
|
|
|
|
|
<li><a href="#loglevel">loglevel</a></li>
|
|
|
|
|
<li><a href="#do_not_notify">do_not_notify</a></li>
|
|
|
|
|
<li><a href="#ignore">ignore</a></li>
|
|
|
|
|
<li><a href="#showtime">showtime</a></li>
|
|
|
|
|
<li><a href="#model">model</a></li>
|
|
|
|
|
<li><a href="#subType">subType</a></li>
|
|
|
|
|
<li><a name="actualTemp">actualTemp</a><br>
|
|
|
|
|
The value of the actual temperature, used when controlling MD15 devices.
|
|
|
|
|
Should by filled via a notify from a distinct temperature sensor. If
|
|
|
|
|
absent, the reported temperature from the MD15 is used.
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<br>
|
|
|
|
|
|
|
|
|
|
<a name="EnOceanevents"></a>
|
|
|
|
|
<b>Generated events:</b>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>switch. Switches (remotes) with more than one (pair) of buttons
|
|
|
|
|
are separate devices with separate address.
|
|
|
|
|
<ul>
|
|
|
|
|
<li>A0
|
|
|
|
|
<li>AI
|
|
|
|
|
<li>B0
|
|
|
|
|
<li>BI
|
|
|
|
|
<li>C0
|
|
|
|
|
<li>CI
|
|
|
|
|
<li>D0
|
|
|
|
|
<li>DI
|
|
|
|
|
<li>A0,BI
|
|
|
|
|
<li><BtnX,BtnY> where BtnX and BtnY is one of the above, e.g.
|
|
|
|
|
A0,BI or D0,CI
|
|
|
|
|
<li>buttons:released
|
|
|
|
|
<li>buttons:<BtnX> released<br>
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<li>FSB61/FSM61 (set model to FSB61 or FSM61 manually)<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>released<br>
|
|
|
|
|
The status of the device my become "released", this is not the case
|
|
|
|
|
for a normal switch.
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<li>windowHandle (HOPPE SecuSignal). Set the subType attr to windowHandle.
|
|
|
|
|
<ul>
|
|
|
|
|
<li>closed
|
|
|
|
|
<li>open
|
|
|
|
|
<li>tilted
|
|
|
|
|
<li>open from tilted
|
|
|
|
|
</ul>
|
|
|
|
|
<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>SR04* (Temp sensor + Presence button and desired temp dial).<br>
|
|
|
|
|
Set the
|
|
|
|
|
model attribute to one of SR04 SR04P SR04PT SR04PST SR04PMS or the
|
|
|
|
|
subType attribute to SR04.
|
|
|
|
|
<ul>
|
|
|
|
|
<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>
|
|
|
|
|
<li>MD15-FtL-HE (Heating/Valve-regulator)<br>
|
|
|
|
|
The subType attibute must be MD15. This is done if the device was created by
|
|
|
|
|
autocreate.<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>$actuator %
|
|
|
|
|
<li>currentValue: $actuator
|
|
|
|
|
<li>serviceOn: [yes|no]
|
|
|
|
|
<li>energyInput: [enabled|disabled]
|
|
|
|
|
<li>energyStorage: [charged|empty]
|
|
|
|
|
<li>battery: [ok|empty]
|
|
|
|
|
<li>cover: [open|closed]
|
|
|
|
|
<li>tempSensor: [failed|ok]
|
|
|
|
|
<li>window: [open|closed]
|
|
|
|
|
<li>actuator: [ok|obstructed]
|
|
|
|
|
<li>temperature: $tmp
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<li>Ratio Presence Sensor Eagle PM101.<br>
|
|
|
|
|
Set the model attribute to PM101<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>brightness: $lux
|
|
|
|
|
<li>channel1: [on|off]
|
|
|
|
|
<li>channel2: [on|off]
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<li>FAH60,FAH63,FIH63 brigthness senor.<br>
|
|
|
|
|
Set subType to FAH or model to FAH60/FAH63/FIH63 manually.<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>brightness: $lux
|
|
|
|
|
<li>state: $lux
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
<li>FABH63,FBH55,FBH63,FIBH63 Motion/brightness sensor.<br>
|
|
|
|
|
Set subType to FBH or model to FABH63/FBH55/FBH63/FIBH63 manually.<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>brightness: $lux
|
|
|
|
|
<li>motion:[yes|no]
|
|
|
|
|
<li>state: [motion: yes|no]
|
|
|
|
|
</ul>
|
|
|
|
|
<li>FTF55 Temperature sensor.<br>
|
|
|
|
|
Set subType to FTF or model to FTF55 manually.<br>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>temperature: $temp
|
|
|
|
|
<li>state: $temp
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
=end html
|
|
|
|
|
=cut
|