mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
00_ZWCUL: add zwaveRouting (experimental)
git-svn-id: https://svn.fhem.de/fhem/trunk@10824 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
3dc1f2c5ae
commit
bd8b3f215b
@ -25,6 +25,7 @@ sub ZWCUL_Write($$$);
|
|||||||
sub ZWCUL_ProcessSendStack($);
|
sub ZWCUL_ProcessSendStack($);
|
||||||
|
|
||||||
use vars qw(%zwave_id2class);
|
use vars qw(%zwave_id2class);
|
||||||
|
my %sentIdx;
|
||||||
|
|
||||||
my %sets = (
|
my %sets = (
|
||||||
"reopen" => { cmd=>"" },
|
"reopen" => { cmd=>"" },
|
||||||
@ -217,6 +218,7 @@ ZWCUL_cmd($$@)
|
|||||||
ZWCUL_tmp9600($hash, $a[0] ? "zm9" : 0); # expect random homeId
|
ZWCUL_tmp9600($hash, $a[0] ? "zm9" : 0); # expect random homeId
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($cmdName eq "removeNode") {
|
if($cmdName eq "removeNode") {
|
||||||
delete $hash->{addNode};
|
delete $hash->{addNode};
|
||||||
delete $hash->{removeNode};
|
delete $hash->{removeNode};
|
||||||
@ -224,6 +226,7 @@ ZWCUL_cmd($$@)
|
|||||||
ZWCUL_tmp9600($hash, $a[0] ? "zr9" : 0);
|
ZWCUL_tmp9600($hash, $a[0] ? "zr9" : 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($cmdName eq "nodeInfo") {
|
if($cmdName eq "nodeInfo") {
|
||||||
my $node = ZWCUL_getNode($hash, sprintf("%02x", $a[0]));
|
my $node = ZWCUL_getNode($hash, sprintf("%02x", $a[0]));
|
||||||
return "Node with decimal id $a[0] not found" if(!$node);
|
return "Node with decimal id $a[0] not found" if(!$node);
|
||||||
@ -275,24 +278,23 @@ ZWCUL_Write($$$)
|
|||||||
|
|
||||||
Log3 $hash, 5, "ZWCUL_Write $fn $msg";
|
Log3 $hash, 5, "ZWCUL_Write $fn $msg";
|
||||||
if($msg =~ m/0013(..)(..)(.*)(....)/) {
|
if($msg =~ m/0013(..)(..)(.*)(....)/) {
|
||||||
my ($t,$l,$p) = ($1,$2,$3);
|
my ($targetId,$l,$p) = ($1,$2,$3);
|
||||||
my $th = $modules{ZWave}{defptr}{"$fn $t"};
|
my ($homeId,$route) = split(",",$fn);
|
||||||
if(!$th) {
|
|
||||||
Log3 $hash, 1, "ZWCUL: no device found for $fn $t";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Do not send wakeupNoMoreInformation in monitor mode
|
$sentIdx{$targetId} = 0 if(!$sentIdx{$targetId} || $sentIdx{$targetId}==15);
|
||||||
return if($p eq "8408" && $hash->{monitor});
|
$sentIdx{$targetId}++;
|
||||||
|
|
||||||
$th->{sentIdx} = 0 if(!$th->{sentIdx} || $th->{sentIdx} == 15);
|
|
||||||
$th->{sentIdx}++;
|
|
||||||
|
|
||||||
my $s100 = ($hash->{baudRate} eq "100k");
|
my $s100 = ($hash->{baudRate} eq "100k");
|
||||||
|
|
||||||
$msg = sprintf("%s%s41%02x%02x%s%s",
|
my $rf = 0x41;
|
||||||
$fn, $hash->{nodeIdHex}, $th->{sentIdx},
|
if($route) {
|
||||||
length($p)/2+($s100 ? 11 : 10), $th->{nodeIdHex}, $p);
|
$rf = 0x81;
|
||||||
|
$p = sprintf("00%d0%s%s",length($route)/2, $route, $p);
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = sprintf("%s%s%02x%02x%02x%s%s",
|
||||||
|
$homeId, $hash->{nodeIdHex}, $rf, $sentIdx{$targetId},
|
||||||
|
length($p)/2+($s100 ? 11 : 10), $targetId, $p);
|
||||||
$msg .= ($s100 ? zwlib_checkSum_16($msg) : zwlib_checkSum_8($msg));
|
$msg .= ($s100 ? zwlib_checkSum_16($msg) : zwlib_checkSum_8($msg));
|
||||||
|
|
||||||
ZWCUL_SimpleWrite($hash, "zs".$msg);
|
ZWCUL_SimpleWrite($hash, "zs".$msg);
|
||||||
@ -462,21 +464,13 @@ ZWCUL_Parse($$$$$)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($hash->{addNode} && $T eq "ff" && $S eq "00" &&
|
if($hash->{addNode} && $T eq "ff" && $S eq "00" && $P =~ m/^0101/) {
|
||||||
$P =~ m/^0101(......)(..)..(.*)/) {
|
|
||||||
ZWCUL_assignId($hash, "00", $hash->{homeIdSet}, $hash->{addNode});
|
ZWCUL_assignId($hash, "00", $hash->{homeIdSet}, $hash->{addNode});
|
||||||
$hash->{addNodeParam} = $P;
|
$hash->{addNodeParam} = $P;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$rmsg = sprintf("0004%s%s%02x%s", $S, $S, length($P)/2, $P);
|
$rmsg = sprintf("0004%s%s%02x%s", $S, $S, length($P)/2, $P);
|
||||||
my $th = $modules{ZWave}{defptr}{"$H $S"};
|
|
||||||
|
|
||||||
if(!($S eq $hash->{nodeIdHex} && $H eq $hash->{homeIdSet}) && !$th) {
|
|
||||||
DoTrigger("global", "UNDEFINED ZWNode_${H}_$S ZWave $H ".hex($S));
|
|
||||||
$th = $modules{ZWave}{defptr}{"$H $S"};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else { # ACK
|
} else { # ACK
|
||||||
if($hash->{removeNode} && $hash->{removeNode} eq $S) { #############
|
if($hash->{removeNode} && $hash->{removeNode} eq $S) { #############
|
||||||
@ -507,8 +501,8 @@ ZWCUL_Parse($$$$$)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($hash->{addNode} && $hash->{addNode} eq $S) { # Another hack
|
if($hash->{addNode} && $hash->{addNode} eq $S) { # Another hack
|
||||||
Log3 $hash, 3, "ZWCUL node ".hex($S)." excluded from network";
|
Log3 $hash, 3,"ZWCUL node ".hex($S)." (hex $S) included into the network";
|
||||||
delete $hash->{removeNode};
|
delete $hash->{addNode};
|
||||||
ZWCUL_tmp9600($hash, 0);
|
ZWCUL_tmp9600($hash, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -701,13 +695,12 @@ ZWCUL_Ready($)
|
|||||||
Activate (or deactivate) inclusion mode. The CUL will switch to dataRate
|
Activate (or deactivate) inclusion mode. The CUL will switch to dataRate
|
||||||
9600 until terminating this mode with off, or a node is included. If onSec
|
9600 until terminating this mode with off, or a node is included. If onSec
|
||||||
is specified, the ZWCUL networkKey ist set, and the device supports the
|
is specified, the ZWCUL networkKey ist set, and the device supports the
|
||||||
SECURITY class, then a secure inclusion is attempted.
|
SECURITY class, then a secure inclusion is attempted. </li>
|
||||||
</li>
|
|
||||||
|
|
||||||
<li>addNodeId <decimalNodeId><br>
|
<li>addNodeId <decimalNodeId><br>
|
||||||
Activate inclusion mode, and assign decimalNodeId to the next node.
|
Activate inclusion mode, and assign decimalNodeId to the next node.
|
||||||
To deactivate this mode, use addNode off.
|
To deactivate this mode, use addNode off. Note: addNode won't work for a
|
||||||
</li>
|
FHEM2FHEM:RAW attached ZWCUL, use addNodeId instead</li>
|
||||||
|
|
||||||
<li>removeNode [onNw|on|off]<br>
|
<li>removeNode [onNw|on|off]<br>
|
||||||
Activate (or deactivate) exclusion mode. Like with addNode, the CUL will
|
Activate (or deactivate) exclusion mode. Like with addNode, the CUL will
|
||||||
|
@ -36,7 +36,8 @@ my %zwave_class = (
|
|||||||
"..0105" => '"zwaveGetNodesInRange:noarg"',
|
"..0105" => '"zwaveGetNodesInRange:noarg"',
|
||||||
"..0106(.*)"=> '"zwaveNodeRangeInfo:$1"',
|
"..0106(.*)"=> '"zwaveNodeRangeInfo:$1"',
|
||||||
"..0107(.*)"=> '"zwaveCommandComplete:$1"',
|
"..0107(.*)"=> '"zwaveCommandComplete:$1"',
|
||||||
"..010801" => '"zwaveTransferPresentation"'
|
"..010801" => '"zwaveTransferPresentation"',
|
||||||
|
"..010c(.*)"=> '"zwaveAssignRoute:$1"'
|
||||||
}},
|
}},
|
||||||
BASIC => { id => '20',
|
BASIC => { id => '20',
|
||||||
set => { basicValue => "01%02x",
|
set => { basicValue => "01%02x",
|
||||||
@ -535,10 +536,25 @@ ZWave_Initialize($)
|
|||||||
$hash->{GetFn} = "ZWave_Get";
|
$hash->{GetFn} = "ZWave_Get";
|
||||||
$hash->{DefFn} = "ZWave_Define";
|
$hash->{DefFn} = "ZWave_Define";
|
||||||
$hash->{UndefFn} = "ZWave_Undef";
|
$hash->{UndefFn} = "ZWave_Undef";
|
||||||
|
$hash->{AttrFn} = "ZWave_Attr";
|
||||||
$hash->{ParseFn} = "ZWave_Parse";
|
$hash->{ParseFn} = "ZWave_Parse";
|
||||||
$hash->{AttrList} = "IODev do_not_notify:1,0 noExplorerFrames:1,0 ".
|
no warnings 'qw';
|
||||||
"ignore:1,0 dummy:1,0 showtime:1,0 classes vclasses ".
|
my @attrList = qw(
|
||||||
"secure_classes WNMI_delay $readingFnAttributes";
|
IODev
|
||||||
|
WNMI_delay
|
||||||
|
classes
|
||||||
|
do_not_notify:1,0
|
||||||
|
dummy:1,0
|
||||||
|
ignore:1,0
|
||||||
|
noExplorerFrames:1,0
|
||||||
|
secure_classes
|
||||||
|
showtime:1,0
|
||||||
|
vclasses
|
||||||
|
zwaveRoute
|
||||||
|
);
|
||||||
|
use warnings 'qw';
|
||||||
|
$hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
|
||||||
|
|
||||||
map { $zwave_id2class{lc($zwave_class{$_}{id})} = $_ } keys %zwave_class;
|
map { $zwave_id2class{lc($zwave_class{$_}{id})} = $_ } keys %zwave_class;
|
||||||
|
|
||||||
$hash->{FW_detailFn} = "ZWave_fhemwebFn";
|
$hash->{FW_detailFn} = "ZWave_fhemwebFn";
|
||||||
@ -3467,7 +3483,9 @@ ZWave_wakeupTimer($$)
|
|||||||
my $nodeId = $hash->{nodeIdHex};
|
my $nodeId = $hash->{nodeIdHex};
|
||||||
my $cmdEf = (AttrVal($hash->{NAME},"noExplorerFrames",0)==0 ? "25":"05");
|
my $cmdEf = (AttrVal($hash->{NAME},"noExplorerFrames",0)==0 ? "25":"05");
|
||||||
# wakeupNoMoreInformation
|
# wakeupNoMoreInformation
|
||||||
IOWrite($hash, $hash->{homeId}, "0013${nodeId}028408${cmdEf}$nodeId");
|
IOWrite($hash,
|
||||||
|
$hash->{homeId}.($hash->{route} ? ",".$hash->{route} : ""),
|
||||||
|
"0013${nodeId}028408${cmdEf}$nodeId");
|
||||||
}
|
}
|
||||||
delete $hash->{wakeupAlive};
|
delete $hash->{wakeupAlive};
|
||||||
|
|
||||||
@ -3515,15 +3533,17 @@ ZWave_processSendStack($$)
|
|||||||
|
|
||||||
$ss->[0] =~ m/^([^:]*?):(.*)$/;
|
$ss->[0] =~ m/^([^:]*?):(.*)$/;
|
||||||
my ($type, $msg) = ($1, $2);
|
my ($type, $msg) = ($1, $2);
|
||||||
IOWrite($hash, $hash->{homeId}, "00$msg");
|
IOWrite($hash,
|
||||||
|
$hash->{homeId}.($hash->{route}?",".$hash->{route}:""),
|
||||||
|
"00$msg");
|
||||||
$ss->[0] = "sent$type:$msg";
|
$ss->[0] = "sent$type:$msg";
|
||||||
|
|
||||||
$hash->{lastMsgSent} = gettimeofday();
|
$hash->{lastMsgSent} = gettimeofday();
|
||||||
$zwave_lastHashSent = $hash;
|
$zwave_lastHashSent = $hash;
|
||||||
|
|
||||||
if(!ZWave_isWakeUp($hash)) {
|
if(!ZWave_isWakeUp($hash)) {
|
||||||
InternalTimer($hash->{lastMsgSent}+3, sub {
|
InternalTimer($hash->{lastMsgSent}+5, sub { # zme generates NO_ACK after 4s
|
||||||
Log 2, "ZWave: No ACK from $hash->{NAME} after 3s for $ss->[0]";
|
Log 2, "ZWave: No ACK from $hash->{NAME} after 5s for $ss->[0]";
|
||||||
ZWave_processSendStack($hash, "next");
|
ZWave_processSendStack($hash, "next");
|
||||||
}, $hash, 0);
|
}, $hash, 0);
|
||||||
}
|
}
|
||||||
@ -3550,9 +3570,9 @@ ZWave_addToSendStack($$$)
|
|||||||
|
|
||||||
} else { # clear commands without 0113 and 0013
|
} else { # clear commands without 0113 and 0013
|
||||||
my $now = gettimeofday();
|
my $now = gettimeofday();
|
||||||
if(@{$ss} > 1 && $now-$hash->{lastMsgSent} > 3) {
|
if(@{$ss} > 1 && $now-$hash->{lastMsgSent} > 5) {
|
||||||
Log3 $hash, 2,
|
Log3 $hash, 2,
|
||||||
"ERROR: $hash->{NAME}: cleaning commands without ack after 3s";
|
"ERROR: $hash->{NAME}: cleaning commands without ack after 5s";
|
||||||
delete $hash->{SendStack};
|
delete $hash->{SendStack};
|
||||||
return ZWave_addToSendStack($hash, $type, $cmd);
|
return ZWave_addToSendStack($hash, $type, $cmd);
|
||||||
}
|
}
|
||||||
@ -3884,6 +3904,46 @@ ZWave_Undef($$)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
ZWave_computeRoute($;$)
|
||||||
|
{
|
||||||
|
my ($spec,$attrVal) = @_;
|
||||||
|
for my $dev (devspec2array($spec)) {
|
||||||
|
my $av = AttrVal($dev, "zwaveRoute", $attrVal);
|
||||||
|
next if(!$av);
|
||||||
|
|
||||||
|
my @h;
|
||||||
|
for my $r (split(" ", $av)) {
|
||||||
|
if(!$defs{$r} || $defs{$r}{TYPE} ne "ZWave") {
|
||||||
|
my $msg = "zwaveRoute: $r is not a ZWave device";
|
||||||
|
Log 1, $msg;
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
push(@h, $defs{$r}{nodeIdHex});
|
||||||
|
}
|
||||||
|
$defs{$dev}{route} = join("",@h);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
ZWave_Attr(@)
|
||||||
|
{
|
||||||
|
my ($type, $devName, $attrName, @param) = @_;
|
||||||
|
|
||||||
|
if($attrName eq "zwaveRoute") {
|
||||||
|
if($type eq "del") {
|
||||||
|
delete $defs{$devName}{route};
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
return ZWave_computeRoute($devName,join(" ",@param)) if($init_done);
|
||||||
|
InternalTimer(1, "ZWave_computeRoute", "TYPE=ZWave", 0);
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
# Show the help from the device.xml, if the correct entry is selected
|
# Show the help from the device.xml, if the correct entry is selected
|
||||||
sub
|
sub
|
||||||
@ -4822,28 +4882,36 @@ s2Hex($)
|
|||||||
is in seconds, subseconds my be specified. Values outside of 0.2-5.0 are
|
is in seconds, subseconds my be specified. Values outside of 0.2-5.0 are
|
||||||
probably harmful.
|
probably harmful.
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
<li><a name="classes">classes</a>
|
||||||
<li><a href="#ignore">ignore</a></li>
|
|
||||||
<li><a href="#dummy">dummy</a></li>
|
|
||||||
<li><a href="#showtime">showtime</a></li>
|
|
||||||
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
|
||||||
<li><a href="#classes">classes</a>
|
|
||||||
This attribute is needed by the ZWave module, as the list of the possible
|
This attribute is needed by the ZWave module, as the list of the possible
|
||||||
set/get commands depends on it. It contains a space separated list of
|
set/get commands depends on it. It contains a space separated list of
|
||||||
class names (capital letters).
|
class names (capital letters).
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#secure_classes">secure_classes</a>
|
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||||||
|
<li><a href="#dummy">dummy</a></li>
|
||||||
|
<li><a href="#ignore">ignore</a></li>
|
||||||
|
<li><a href="#noExplorerFrames">noExplorerFrames</a>
|
||||||
|
turn off the use of Explorer Frames
|
||||||
|
</li>
|
||||||
|
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
|
||||||
|
<li><a name="secure_classes">secure_classes</a>
|
||||||
This attribute is the result of the "set DEVICE secSupportedReport"
|
This attribute is the result of the "set DEVICE secSupportedReport"
|
||||||
command. It contains a space seperated list of the the command classes
|
command. It contains a space seperated list of the the command classes
|
||||||
that are supported with SECURITY.
|
that are supported with SECURITY.
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#vclasses">vclasses</a>
|
<li><a href="#showtime">showtime</a></li>
|
||||||
|
<li><a name="vclasses">vclasses</a>
|
||||||
This is the result of the "get DEVICE versionClassAll" command, and
|
This is the result of the "get DEVICE versionClassAll" command, and
|
||||||
contains the version information for each of the supported classes.
|
contains the version information for each of the supported classes.
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#noExplorerFrames">noExplorerFrames</a>
|
|
||||||
turn off the use of Explorer Frames
|
<li><a name="zwaveRoute">zwaveRoute</a>
|
||||||
</li>
|
space separated list of (ZWave) device names. They will be used in the
|
||||||
|
given order to route messages from the controller to this device. Specify
|
||||||
|
them in the order from the controller to the device. Do not specify the
|
||||||
|
controller and the device itself, only the routers inbetween. Used only
|
||||||
|
if the IODev is a ZWCUL device. </li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user