mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
ZWave: MULTILEVEL patches
git-svn-id: https://svn.fhem.de/fhem/trunk@4491 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5275e27426
commit
87096f7a68
@ -1,15 +1,6 @@
|
||||
##############################################
|
||||
# $Id$
|
||||
# See ZWDongle.pm for inspiration
|
||||
# TODO
|
||||
# - versioned commands
|
||||
# - use central readings functions
|
||||
# - Generate MISSING ACK
|
||||
# - implement (global?) on-for-timer
|
||||
# - better autocreate integration
|
||||
# - get support in FHEMWEB
|
||||
# - class meter: get
|
||||
# - class SWITCH_ALL
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
@ -72,14 +63,11 @@ my %zwave_class = (
|
||||
get => { sbStatus => "02", },
|
||||
parse => { "03300300" => "state:closed",
|
||||
"033003ff" => "state:open", },},
|
||||
#053105030129
|
||||
|
||||
SENSOR_MULTILEVEL => { id => '31',
|
||||
get => { smStatus => "04" },
|
||||
parse => { "06310501(..)(....)" => 'sprintf("temperature:%0.1f %s",'.
|
||||
'hex($2)/(10**int(hex($1)/32)), hex($1)&8 ? "F":"C")',
|
||||
"06310504(..)(....)" => 'sprintf("power:%0.1f %s",'.
|
||||
'hex($2)/(10**int(hex($1)/32)), hex($1)&8 ? "Btu/h":"W")',
|
||||
"05310505(..)(..)" => 'sprintf("humidity:%0.1f %%", '.
|
||||
'hex($2)/(10**int(hex($1)/32)))', },},
|
||||
parse => { "..3105(..)(..)(.*)" => 'ZWave_ParseMultilevel($1,$2,$3)'},},
|
||||
METER => { id => '32',
|
||||
parse => { "..3202(.*)"=> 'ZWave_ParseMeter($1)' }, },
|
||||
ZIP_ADV_SERVER => { id => '33', },
|
||||
@ -361,24 +349,35 @@ ZWave_Cmd($$@)
|
||||
}
|
||||
$cmdFmt = sprintf($cmdFmt, @a) if($nArg);
|
||||
|
||||
my ($baseClasses, $baseHash) = ($classes, $hash);
|
||||
if($id =~ m/(..)(..)/) { # Multi-Channel, encapsulate
|
||||
my ($lid,$ch) = ($1, $2);
|
||||
$id = $lid;
|
||||
my ($baseId,$ch) = ($1, $2);
|
||||
$id = $baseId;
|
||||
$cmdFmt = "0d01$ch$cmdId$cmdFmt";
|
||||
$cmdId = "60"; # MULTI_CHANNEL
|
||||
$baseHash = $modules{ZWave}{defptr}{"$hash->{homeId} $baseId"};
|
||||
$baseClasses = AttrVal($baseHash->{NAME}, "classes", "");
|
||||
}
|
||||
|
||||
|
||||
my $len = sprintf("%02x", length($cmdFmt)/2+1);
|
||||
|
||||
my $data = "13$id$len$cmdId${cmdFmt}05";
|
||||
if($classes =~ m/WAKE_UP/) {
|
||||
if(!$hash->{WakeUp}) {
|
||||
my $data = "13$id$len$cmdId${cmdFmt}05"; # 13==SEND_DATA
|
||||
if($baseClasses =~ m/WAKE_UP/) {
|
||||
if(!$baseHash->{WakeUp}) {
|
||||
my @arr = ();
|
||||
$hash->{WakeUp} = \@arr;
|
||||
$baseHash->{WakeUp} = \@arr;
|
||||
}
|
||||
my $awake = ($baseHash->{lastMsgTimestamp} &&
|
||||
time() - $baseHash->{lastMsgTimestamp} < 2);
|
||||
|
||||
if($awake && @{$baseHash->{WakeUp}} == 0) {
|
||||
push @{$baseHash->{WakeUp}}, ""; # Block the next
|
||||
|
||||
} else {
|
||||
push @{$baseHash->{WakeUp}}, $data;
|
||||
return ($type eq "get" && AttrVal($name,"verbose",3) > 2 ?
|
||||
"Scheduled for sending after WAKEUP" : undef);
|
||||
}
|
||||
push @{$hash->{WakeUp}}, $data;
|
||||
return ($type eq "get" ? "Scheduled for sending after WAKEUP" : undef);
|
||||
}
|
||||
IOWrite($hash, "00", $data);
|
||||
|
||||
@ -455,6 +454,41 @@ ZWave_ParseMeter($)
|
||||
return "$txt:$v3 $unit";
|
||||
}
|
||||
|
||||
sub
|
||||
ZWave_ParseMultilevel($$$)
|
||||
{
|
||||
my ($type,$fl,$arg) = @_;
|
||||
my %ml_tbl = (
|
||||
'01' => { n => 'temperature', st => ['C', 'F'] },
|
||||
'02' => { n => 'generalPurpose', st => ['%', ''] },
|
||||
'03' => { n => 'luminance', st => ['%', 'Lux'] },
|
||||
'04' => { n => 'power', st => ['W', 'Btu/h'] },
|
||||
'05' => { n => 'humidity', st => ['%'] },
|
||||
'06' => { n => 'velocity', st => ['m/s', 'mph'] },
|
||||
'07' => { n => 'direction', st => [] },
|
||||
'08' => { n => 'atmosphericPressure', st => ['kPa', 'inchHg'] },
|
||||
'09' => { n => 'barometricPressure', st => ['kPa', 'inchHg'] },
|
||||
'0a' => { n => 'solarRadiation', st => ['W/m2'] },
|
||||
'0b' => { n => 'dewpoint', st => ['C', 'F'] },
|
||||
'0c' => { n => 'rain', st => ['mm/h', 'in/h'] },
|
||||
'0d' => { n => 'tideLevel', st => ['m', 'feet'] },
|
||||
'0e' => { n => 'weight', st => ['kg', 'pound'] },
|
||||
'0f' => { n => 'voltage', st => ['V', 'mV'] },
|
||||
'10' => { n => 'current', st => ['A', 'mA'] },
|
||||
'11' => { n => 'CO2-level', st => ['ppm']},
|
||||
'12' => { n => 'airFlow', st => ['m3/h', 'cfm'] },
|
||||
'13' => { n => 'tankCapacity', st => ['l', 'cbm', 'usgal'] },
|
||||
'14' => { n => 'distance', st => ['m', 'cm', 'feet'] },
|
||||
'15' => { n => 'anglePosition', st => ['%', 'relN', 'relS'] },
|
||||
);
|
||||
|
||||
my $pr = (hex($fl)>>5)&0x07; # precision
|
||||
my $sc = (hex($fl)>>3)&0x03; # scale
|
||||
my $ml = $ml_tbl{$type};
|
||||
return "UNKNOWN multilevel type: $type fl: $fl arg: $arg" if(!$ml);
|
||||
return sprintf("%s:%.*f %s", $ml->{n}, $pr, hex($arg)/(10**$pr),
|
||||
int(@{$ml->{st}}) > $sc ? $ml->{st}->[$sc] : "");
|
||||
}
|
||||
|
||||
sub
|
||||
ZWave_SetClasses($$$$)
|
||||
@ -514,6 +548,7 @@ ZWave_mcCapability($$)
|
||||
|
||||
###################################
|
||||
# 0004000a03250300 (sensor binary off for id 11)
|
||||
# { ZWave_Parse($defs{zd}, "0004000c028407", 0) }
|
||||
sub
|
||||
ZWave_Parse($$@)
|
||||
{
|
||||
@ -524,10 +559,24 @@ ZWave_Parse($$@)
|
||||
Log3 $ioName, 1, "ERROR: $ioName homeId is not set!"
|
||||
if(!$iodev->{errReported});
|
||||
$iodev->{errReported} = 1;
|
||||
return;
|
||||
return "";
|
||||
}
|
||||
if($msg =~ m/^01(..)(..*)/) { # 01==ANSWER
|
||||
my ($cmd, $arg) = ($1, $2);
|
||||
$cmd = $zw_func_id{$cmd} if($zw_func_id{$cmd});
|
||||
if($cmd eq "ZW_SEND_DATA") {
|
||||
Log3 $ioName, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1);
|
||||
return "";
|
||||
}
|
||||
Log3 $ioName, 4, "$ioName: unhandled ANSWER: $cmd $arg";
|
||||
return "";
|
||||
}
|
||||
|
||||
if($msg !~ m/^00(..)(..)(..)(.*)/) { # 00=REQUEST
|
||||
Log3 $ioName, 4, "$ioName: UNKNOWN msg $msg";
|
||||
return "";
|
||||
}
|
||||
|
||||
return "" if($msg !~ m/00(..)(..)(..)(..*)/); # Ignore unknown commands
|
||||
my ($cmd, $callbackid, $id, $arg) = ($1, $2, $3, $4);
|
||||
$cmd = $zw_func_id{$cmd} if($zw_func_id{$cmd});
|
||||
|
||||
@ -535,7 +584,7 @@ ZWave_Parse($$@)
|
||||
# Controller commands
|
||||
my $evt;
|
||||
|
||||
Log3 $ioName, 4, "$ioName CMD: $cmd";
|
||||
Log3 $ioName, 4, "$ioName CMD:$cmd ID:$id ARG:$arg";
|
||||
if($cmd eq 'ZW_ADD_NODE_TO_NETWORK' ||
|
||||
$cmd eq 'ZW_REMOVE_NODE_FROM_NETWORK') {
|
||||
my @vals = ("learnReady", "nodeFound", "slave",
|
||||
@ -549,15 +598,18 @@ ZWave_Parse($$@)
|
||||
}
|
||||
|
||||
} elsif($cmd eq "ZW_APPLICATION_UPDATE" && $arg =~ m/....(..)..(.*)$/) {
|
||||
my ($type6,$classes) = ($1, $2, $3);
|
||||
my $ret = ZWave_SetClasses($homeId, $id, $type6, $classes);
|
||||
my ($type6,$classes) = ($1, $2, $3);
|
||||
my $ret = ZWave_SetClasses($homeId, $id, $type6, $classes);
|
||||
|
||||
my $hash = $modules{ZWave}{defptr}{"$homeId $id"};
|
||||
if($hash->{WakeUp} && @{$hash->{WakeUp}}) {
|
||||
IOWrite($hash, "00", shift @{$hash->{WakeUp}});
|
||||
}
|
||||
return $ret;
|
||||
my $hash = $modules{ZWave}{defptr}{"$homeId $id"};
|
||||
if($hash && $hash->{WakeUp} && @{$hash->{WakeUp}}) { # Always the base hash
|
||||
IOWrite($hash, "00", shift @{$hash->{WakeUp}});
|
||||
}
|
||||
return $ret;
|
||||
|
||||
} elsif($cmd eq "ZW_SEND_DATA") {
|
||||
Log3 $ioName, 2, "$ioName ERROR: SEND_DATA returned $id" if($id ne "00");
|
||||
return "";
|
||||
}
|
||||
|
||||
if($evt) {
|
||||
@ -565,10 +617,6 @@ ZWave_Parse($$@)
|
||||
DoTrigger($ioName, "$cmd $evt");
|
||||
Log3 $ioName, 4, "$ioName $cmd $evt";
|
||||
return "";
|
||||
|
||||
} else {
|
||||
Log3 $ioName, 4, "$ioName $cmd $id ($arg)";
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -579,17 +627,24 @@ ZWave_Parse($$@)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
my $baseHash;
|
||||
if($arg =~ /^..600d(..)(..)(.*)/) { # MULTI_CHANNEL CMD_ENCAP
|
||||
$baseHash = $modules{ZWave}{defptr}{"$homeId $id"};
|
||||
$id = "$id$1";
|
||||
$arg = sprintf("%02x$3", length($3)/2);
|
||||
}
|
||||
my $hash = $modules{ZWave}{defptr}{"$homeId $id"};
|
||||
$baseHash = $hash if(!$baseHash);
|
||||
|
||||
|
||||
if(!$hash) {
|
||||
$id = hex($id);
|
||||
Log3 $ioName, 3, "Unknown ZWave device $homeId $id, please define it";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
my @event;
|
||||
my @args = ($arg); # MULTI_CMD handling
|
||||
|
||||
@ -630,10 +685,12 @@ ZWave_Parse($$@)
|
||||
return "" if(!@event);
|
||||
return join(" ", @event) if($local);
|
||||
|
||||
if($hash->{WakeUp} && @{$hash->{WakeUp}}) {
|
||||
IOWrite($hash, "00", shift @{$hash->{WakeUp}});
|
||||
my $wu = $baseHash->{WakeUp};
|
||||
if($wu && @{$wu}) {
|
||||
shift @{$wu} if($wu->[0] eq "");
|
||||
IOWrite($hash, "00", shift @{$wu});
|
||||
}
|
||||
|
||||
$baseHash->{lastMsgTimestamp} = time();
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
for(my $i = 0; $i < int(@event); $i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user