2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-04 11:26:55 +00:00

10_ZWave.pm: flexible initialization after inclusion (Forum #37121)

git-svn-id: https://svn.fhem.de/fhem/trunk@8580 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2015-05-14 19:09:57 +00:00
parent 8897bfe7fd
commit c3bf9f2da2
2 changed files with 92 additions and 45 deletions

View File

@ -85,8 +85,10 @@ use vars qw(%zw_type6);
'34' => 'RTC_TIMER_READ', '34' => 'RTC_TIMER_READ',
'35' => 'RTC_TIMER_DELETE', '35' => 'RTC_TIMER_DELETE',
'36' => 'RTC_TIMER_CALL', '36' => 'RTC_TIMER_CALL',
'40' => 'ZW_SET_LEARN_NODE_STATE',
'41' => 'ZW_GET_NODE_PROTOCOL_INFO', '41' => 'ZW_GET_NODE_PROTOCOL_INFO',
'42' => 'ZW_SET_DEFAULT', '42' => 'ZW_SET_DEFAULT',
'43' => 'ZW_NEW_CONTROLLER',
'44' => 'ZW_REPLICATION_COMMAND_COMPLETE', '44' => 'ZW_REPLICATION_COMMAND_COMPLETE',
'45' => 'ZW_REPLICATION_SEND_DATA', '45' => 'ZW_REPLICATION_SEND_DATA',
'46' => 'ZW_ASSIGN_RETURN_ROUTE', '46' => 'ZW_ASSIGN_RETURN_ROUTE',
@ -772,7 +774,8 @@ ZWDongle_Ready($)
<ul> <ul>
<li>ZW_ADD_NODE_TO_NETWORK [learnReady|nodeFound|controller|done|failed] <li>ZW_ADD_NODE_TO_NETWORK [learnReady|nodeFound|controller|done|failed]
</li> </li>
<li>ZW_REMOVE_NODE_TO_NETWORK [learnReady|nodeFound|slave|controller|done|failed] <li>ZW_REMOVE_NODE_FROM_NETWORK
[learnReady|nodeFound|slave|controller|done|failed]
</li> </li>
<li>UNDEFINED ZWave_${type6}_$id ZWave $homeId $id $classes" <li>UNDEFINED ZWave_${type6}_$id ZWave $homeId $id $classes"
</li> </li>

View File

@ -220,15 +220,15 @@ my %zwave_class = (
configLong => "04%02x04%08x" }, configLong => "04%02x04%08x" },
get => { config => "05%02x" }, get => { config => "05%02x" },
parse => { "^..70..(..)(..)(.*)" => 'ZWave_configParse($hash,$1,$2,$3)'} }, parse => { "^..70..(..)(..)(.*)" => 'ZWave_configParse($hash,$1,$2,$3)'} },
ALARM => { id => '71', ALARM => { id => '71',
get => { alarm => "04%02x" }, get => { alarm => "04%02x" },
parse => { "..7105(..)(..)(.*)" => 'ZWave_alarmParse($1,$2,$3)'} }, parse => { "..7105(..)(..)(.*)" => 'ZWave_alarmParse($1,$2,$3)'} },
MANUFACTURER_SPECIFIC => { id => '72', MANUFACTURER_SPECIFIC => { id => '72',
get => { model => "04" }, get => { model => "04" },
parse => { "087205(....)(....)(....)" => 'ZWave_mfsParse($1,$2,$3,0)', parse => { "087205(....)(....)(....)" =>'ZWave_mfsParse($hash,$1,$2,$3,0)',
"087205(....)(....)(.{4})" => 'ZWave_mfsParse($1,$2,$3,1)', "087205(....)(....)(.{4})" =>'ZWave_mfsParse($hash,$1,$2,$3,1)',
"087205(....)(.{4})(.{4})" => '"modelId:$1-$2-$3"'} }, "087205(....)(.{4})(.{4})" =>'ZWave_mfsParse($hash,$1,$2,$3,2)'},
init => { ORDER=>49, CMD => '"get $NAME model"' } },
POWERLEVEL => { id => '73' }, POWERLEVEL => { id => '73' },
PROTECTION => { id => '75', PROTECTION => { id => '75',
set => { protectionOff => "0100", set => { protectionOff => "0100",
@ -272,7 +272,8 @@ my %zwave_class = (
set => { associationAdd => "01%02x%02x*", set => { associationAdd => "01%02x%02x*",
associationDel => "04%02x%02x*" }, associationDel => "04%02x%02x*" },
get => { association => "02%02x", }, get => { association => "02%02x", },
parse => { "..8503(..)(..)..(.*)" => '"assocGroup_$1:Max $2 Nodes $3"'} }, parse => { "..8503(..)(..)..(.*)" => '"assocGroup_$1:Max $2 Nodes $3"'},
init => { ORDER=> 1, CMD=> '"set $NAME associationAdd 1 $CTRLID"' } },
VERSION => { id => '86', VERSION => { id => '86',
get => { version => "11", get => { version => "11",
versionClass => "13%02x" }, versionClass => "13%02x" },
@ -341,10 +342,12 @@ my %zwave_cmdArgs = (
my %zwave_modelConfig; my %zwave_modelConfig;
my %zwave_modelIdAlias = ( "010f-0301-1001" => "Fibaro_FGRM222", my %zwave_modelIdAlias = ( "010f-0301-1001" => "Fibaro_FGRM222",
"013c-0001-0003" => "Philio_PAN04" ); "013c-0001-0003" => "Philio_PAN04",
"0115-0100-0102" => "ZME_KFOB" );
# Patching certain devices. # Patching certain devices.
my %zwave_deviceSpecial = ( use vars qw(%zwave_deviceSpecial);
%zwave_deviceSpecial = (
Fibaro_FGRM222 => { Fibaro_FGRM222 => {
MANUFACTURER_PROPRIETARY => { MANUFACTURER_PROPRIETARY => {
set => { positionSlat=>"010f26010100%02x", set => { positionSlat=>"010f26010100%02x",
@ -354,10 +357,13 @@ my %zwave_deviceSpecial = (
'sprintf("position:Blinds %d Slat %d",hex($1),hex($2))' } } }, 'sprintf("position:Blinds %d Slat %d",hex($1),hex($2))' } } },
Philio_PAN04 => { Philio_PAN04 => {
METER => { METER => {
get => { meter => "01", get_ADD => { meterWatt => "0110", #Watt
meterWatt => "0110", #Watt meterVoltage=> "0120", #Voltage
meterVoltage=> "0120", #Voltage meterAmpere => "0128" } } },#Ampere
meterAmpere => "0128" } } } #Ampere ZME_KFOB => {
ZWAVEPLUS_INFO => {
# Example only. ORDER must be >= 50
init => { ORDER=>50, CMD => '"get $NAME zwavePlusInfo"' } } }
); );
sub sub
@ -405,26 +411,53 @@ ZWave_Define($$)
$modules{ZWave}{defptr}{"$homeId $id"} = $hash; $modules{ZWave}{defptr}{"$homeId $id"} = $hash;
AssignIoPort($hash); # FIXME: should take homeId into account AssignIoPort($hash); # FIXME: should take homeId into account
if(@a) { if(@a) { # Autocreate: set the classes, execute the init calls
$hash->{lastMsgTimestamp} = time(); # device is awake.
ZWave_SetClasses($homeId, $id, undef, $a[0]); ZWave_SetClasses($homeId, $id, undef, $a[0]);
ZWave_execInits($hash, 0);
if($attr{$name}{classes} =~ m/ASSOCIATION/) {
my $iodev = $hash->{IODev};
my $homeReading = ReadingsVal($iodev->{NAME}, "homeId", "") if($iodev);
my $ctrlId = $1 if($homeReading && $homeReading =~ m/CtrlNodeId:(..)/);
if($ctrlId) {
Log3 $name, 1, "Adding the controller $ctrlId to association group 1";
IOWrite($hash, "00", "130a04850101${ctrlId}05");
} else {
Log3 $name, 1, "Cannot associate $name, missing controller id";
}
}
} }
return undef; return undef;
} }
sub
ZWave_doExecInits($)
{
my ($cmdArr) = @_;
my $cmd = shift @{$cmdArr};
my $ret = AnalyzeCommand(undef, $cmd);
Log 1, "ZWAVE INIT: $cmd: $ret" if ($ret);
InternalTimer(gettimeofday()+0.5, "ZWave_doExecInits", $cmdArr, 0)
if(@{$cmdArr});
}
sub
ZWave_execInits($$)
{
my ($hash, $min) = @_; # min = 50 for model-specific stuff
my @clList = split(" ", $attr{$hash->{NAME}}{classes});
my (@initList, %seen);
foreach my $cl (@clList) {
next if($seen{$cl});
$seen{$cl} = 1;
my $ptr = ZWave_getHash($hash, $cl, "init");
push @initList, $ptr if($ptr && $ptr->{ORDER} >= $min);
}
my $NAME = $hash->{NAME};
my $iodev = $hash->{IODev};
my $homeReading = ReadingsVal($iodev->{NAME}, "homeId", "") if($iodev);
my $CTRLID = $1 if($homeReading && $homeReading =~ m/CtrlNodeId:(..)/);
my @cmd;
foreach my $i (sort { $a->{ORDER}<=>$b->{ORDER} } @initList) {
push @cmd, eval $i->{CMD};
}
InternalTimer(gettimeofday()+0.5, "ZWave_doExecInits", \@cmd, 0)
if(@cmd);
}
################################### ###################################
sub sub
ZWave_Cmd($$@) ZWave_Cmd($$@)
@ -434,7 +467,6 @@ ZWave_Cmd($$@)
my $name = shift(@a); my $name = shift(@a);
my $cmd = shift(@a); my $cmd = shift(@a);
# Collect the commands from the distinct classes # Collect the commands from the distinct classes
my %cmdList; my %cmdList;
my $classes = AttrVal($name, "classes", ""); my $classes = AttrVal($name, "classes", "");
@ -549,12 +581,9 @@ ZWave_Cmd($$@)
my $awake = ($baseHash->{lastMsgTimestamp} && my $awake = ($baseHash->{lastMsgTimestamp} &&
time() - $baseHash->{lastMsgTimestamp} < 2); time() - $baseHash->{lastMsgTimestamp} < 2);
if($awake && @{$baseHash->{WakeUp}} == 0) { if(!$awake) {
push @{$baseHash->{WakeUp}}, ""; # Block the next
} else {
push @{$baseHash->{WakeUp}}, $data.$id; push @{$baseHash->{WakeUp}}, $data.$id;
return (AttrVal($name,"verbose",3) > 2 ? return (AttrVal($name,"verbose",3) > 2 ?
"Scheduled for sending after WAKEUP" : undef); "Scheduled for sending after WAKEUP" : undef);
} }
@ -741,9 +770,16 @@ ZWave_mcCapability($$)
} }
sub sub
ZWave_mfsParse($$$$) ZWave_mfsParse($$$$$)
{ {
my ($mf, $prod, $id, $config) = @_; my ($hash, $mf, $prod, $id, $config) = @_;
if($config == 2) {
setReadingsVal($hash, "modelId", "$mf-$prod-$id", TimeNow());
ZWave_execInits($hash, 50);
return "modelId:$mf-$prod-$id";
}
my $xml = $attr{global}{modpath}. my $xml = $attr{global}{modpath}.
"/FHEM/lib/openzwave_manufacturer_specific.xml"; "/FHEM/lib/openzwave_manufacturer_specific.xml";
($mf, $prod, $id) = (lc($mf), lc($prod), lc($id)); # Just to make it sure ($mf, $prod, $id) = (lc($mf), lc($prod), lc($id)); # Just to make it sure
@ -759,7 +795,7 @@ ZWave_mfsParse($$$$)
if($l =~ m/<Product type="([^"]*)".*id="([^"]*)".*name="([^"]*)"/) { if($l =~ m/<Product type="([^"]*)".*id="([^"]*)".*name="([^"]*)"/) {
if($mf eq $lastMf && $prod eq lc($1) && $id eq lc($2)) { if($mf eq $lastMf && $prod eq lc($1) && $id eq lc($2)) {
if($config) { if($config) {
$ret = "modelConfig:$1" if($l =~ m/config="([^"]*)"/); $ret = "modelConfig:".(($l =~ m/config="([^"]*)"/) ? $1:"unknown");
return $ret; return $ret;
} else { } else {
$ret = "model:$mName $3"; $ret = "model:$mName $3";
@ -1275,25 +1311,33 @@ sub
ZWave_getHash($$$) ZWave_getHash($$$)
{ {
my ($hash, $cl, $type) = @_; my ($hash, $cl, $type) = @_;
my $ptr; # must be standalone, as there is a $ptr in the calling fn.
my $ptr = $zwave_class{$cl}{$type} $ptr = $zwave_class{$cl}{$type}
if($zwave_class{$cl} && $zwave_class{$cl}{$type}); if($zwave_class{$cl} && $zwave_class{$cl}{$type});
if($cl eq "CONFIGURATION" && $type ne "parse") { if($cl eq "CONFIGURATION" && $type ne "parse") {
my $mc = ZWave_configGetHash($hash); my $mc = ZWave_configGetHash($hash);
if($mc) { if($mc) {
my $mcp = $mc->{$type}; my $mcp = $mc->{$type};
my %nptr = (); if($mcp) {
map({$nptr{$_} = $ptr->{$_}} keys %{$ptr}); my %nptr = ();
map({$nptr{$_} = $mcp->{$_}} keys %{$mcp}); map({$nptr{$_} = $ptr->{$_}} keys %{$ptr});
$ptr = \%nptr; map({$nptr{$_} = $mcp->{$_}} keys %{$mcp});
$ptr = \%nptr;
}
} }
} }
my $modelId = ReadingsVal($hash->{NAME}, "modelId", ""); my $modelId = ReadingsVal($hash->{NAME}, "modelId", "");
$modelId = $zwave_modelIdAlias{$modelId} if($zwave_modelIdAlias{$modelId}); $modelId = $zwave_modelIdAlias{$modelId} if($zwave_modelIdAlias{$modelId});
my $p = $zwave_deviceSpecial{$modelId}; my $p = $zwave_deviceSpecial{$modelId};
$ptr = $p->{$cl}{$type} if($p && $p->{$cl} && $p->{$cl}{$type}); if($p && $p->{$cl}) {
$ptr = $p->{$cl}{$type} if($p->{$cl}{$type});
my $add = $p->{$cl}{$type."_ADD"};
$ptr = {} if($add && !$ptr);
map { $ptr->{$_} = $add->{$_} } keys %{$add} if($add);
}
return $ptr; return $ptr;
} }
@ -1320,7 +1364,7 @@ ZWave_Parse($$@)
Log3 $ioName, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1); Log3 $ioName, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1);
return ""; return "";
} }
Log3 $ioName, 4, "$ioName: unhandled ANSWER: $cmd $arg"; Log3 $ioName, 4, "$ioName unhandled ANSWER: $cmd $arg";
return ""; return "";
} }
@ -1483,7 +1527,7 @@ ZWave_Parse($$@)
if($arg =~ m/^$k/) { if($arg =~ m/^$k/) {
my $val = $ptr->{$k}; my $val = $ptr->{$k};
$val = eval $val if(index($val, '$') >= 0); $val = eval $val if(index($val, '$') >= 0);
push @event, $val; push @event, $val if(defined($val));
} }
} }
push @event, "UNPARSED:$className $arg" if(!@event); push @event, "UNPARSED:$className $arg" if(!@event);