2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-15 04:20:56 +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:
rudolfkoenig 2016-02-13 22:12:02 +00:00
parent 3dc1f2c5ae
commit bd8b3f215b
2 changed files with 111 additions and 50 deletions

View File

@ -25,6 +25,7 @@ sub ZWCUL_Write($$$);
sub ZWCUL_ProcessSendStack($);
use vars qw(%zwave_id2class);
my %sentIdx;
my %sets = (
"reopen" => { cmd=>"" },
@ -217,6 +218,7 @@ ZWCUL_cmd($$@)
ZWCUL_tmp9600($hash, $a[0] ? "zm9" : 0); # expect random homeId
return;
}
if($cmdName eq "removeNode") {
delete $hash->{addNode};
delete $hash->{removeNode};
@ -224,6 +226,7 @@ ZWCUL_cmd($$@)
ZWCUL_tmp9600($hash, $a[0] ? "zr9" : 0);
return;
}
if($cmdName eq "nodeInfo") {
my $node = ZWCUL_getNode($hash, sprintf("%02x", $a[0]));
return "Node with decimal id $a[0] not found" if(!$node);
@ -275,24 +278,23 @@ ZWCUL_Write($$$)
Log3 $hash, 5, "ZWCUL_Write $fn $msg";
if($msg =~ m/0013(..)(..)(.*)(....)/) {
my ($t,$l,$p) = ($1,$2,$3);
my $th = $modules{ZWave}{defptr}{"$fn $t"};
if(!$th) {
Log3 $hash, 1, "ZWCUL: no device found for $fn $t";
return;
}
my ($targetId,$l,$p) = ($1,$2,$3);
my ($homeId,$route) = split(",",$fn);
# Do not send wakeupNoMoreInformation in monitor mode
return if($p eq "8408" && $hash->{monitor});
$th->{sentIdx} = 0 if(!$th->{sentIdx} || $th->{sentIdx} == 15);
$th->{sentIdx}++;
$sentIdx{$targetId} = 0 if(!$sentIdx{$targetId} || $sentIdx{$targetId}==15);
$sentIdx{$targetId}++;
my $s100 = ($hash->{baudRate} eq "100k");
$msg = sprintf("%s%s41%02x%02x%s%s",
$fn, $hash->{nodeIdHex}, $th->{sentIdx},
length($p)/2+($s100 ? 11 : 10), $th->{nodeIdHex}, $p);
my $rf = 0x41;
if($route) {
$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));
ZWCUL_SimpleWrite($hash, "zs".$msg);
@ -462,21 +464,13 @@ ZWCUL_Parse($$$$$)
return;
}
if($hash->{addNode} && $T eq "ff" && $S eq "00" &&
$P =~ m/^0101(......)(..)..(.*)/) {
if($hash->{addNode} && $T eq "ff" && $S eq "00" && $P =~ m/^0101/) {
ZWCUL_assignId($hash, "00", $hash->{homeIdSet}, $hash->{addNode});
$hash->{addNodeParam} = $P;
return;
}
$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
if($hash->{removeNode} && $hash->{removeNode} eq $S) { #############
@ -507,8 +501,8 @@ ZWCUL_Parse($$$$$)
}
if($hash->{addNode} && $hash->{addNode} eq $S) { # Another hack
Log3 $hash, 3, "ZWCUL node ".hex($S)." excluded from network";
delete $hash->{removeNode};
Log3 $hash, 3,"ZWCUL node ".hex($S)." (hex $S) included into the network";
delete $hash->{addNode};
ZWCUL_tmp9600($hash, 0);
return;
}
@ -701,13 +695,12 @@ ZWCUL_Ready($)
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
is specified, the ZWCUL networkKey ist set, and the device supports the
SECURITY class, then a secure inclusion is attempted.
</li>
SECURITY class, then a secure inclusion is attempted. </li>
<li>addNodeId &lt;decimalNodeId&gt;<br>
Activate inclusion mode, and assign decimalNodeId to the next node.
To deactivate this mode, use addNode off.
</li>
To deactivate this mode, use addNode off. Note: addNode won't work for a
FHEM2FHEM:RAW attached ZWCUL, use addNodeId instead</li>
<li>removeNode [onNw|on|off]<br>
Activate (or deactivate) exclusion mode. Like with addNode, the CUL will

View File

@ -36,7 +36,8 @@ my %zwave_class = (
"..0105" => '"zwaveGetNodesInRange:noarg"',
"..0106(.*)"=> '"zwaveNodeRangeInfo:$1"',
"..0107(.*)"=> '"zwaveCommandComplete:$1"',
"..010801" => '"zwaveTransferPresentation"'
"..010801" => '"zwaveTransferPresentation"',
"..010c(.*)"=> '"zwaveAssignRoute:$1"'
}},
BASIC => { id => '20',
set => { basicValue => "01%02x",
@ -535,10 +536,25 @@ ZWave_Initialize($)
$hash->{GetFn} = "ZWave_Get";
$hash->{DefFn} = "ZWave_Define";
$hash->{UndefFn} = "ZWave_Undef";
$hash->{AttrFn} = "ZWave_Attr";
$hash->{ParseFn} = "ZWave_Parse";
$hash->{AttrList} = "IODev do_not_notify:1,0 noExplorerFrames:1,0 ".
"ignore:1,0 dummy:1,0 showtime:1,0 classes vclasses ".
"secure_classes WNMI_delay $readingFnAttributes";
no warnings 'qw';
my @attrList = qw(
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;
$hash->{FW_detailFn} = "ZWave_fhemwebFn";
@ -3467,7 +3483,9 @@ ZWave_wakeupTimer($$)
my $nodeId = $hash->{nodeIdHex};
my $cmdEf = (AttrVal($hash->{NAME},"noExplorerFrames",0)==0 ? "25":"05");
# 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};
@ -3515,15 +3533,17 @@ ZWave_processSendStack($$)
$ss->[0] =~ m/^([^:]*?):(.*)$/;
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";
$hash->{lastMsgSent} = gettimeofday();
$zwave_lastHashSent = $hash;
if(!ZWave_isWakeUp($hash)) {
InternalTimer($hash->{lastMsgSent}+3, sub {
Log 2, "ZWave: No ACK from $hash->{NAME} after 3s for $ss->[0]";
InternalTimer($hash->{lastMsgSent}+5, sub { # zme generates NO_ACK after 4s
Log 2, "ZWave: No ACK from $hash->{NAME} after 5s for $ss->[0]";
ZWave_processSendStack($hash, "next");
}, $hash, 0);
}
@ -3550,9 +3570,9 @@ ZWave_addToSendStack($$$)
} else { # clear commands without 0113 and 0013
my $now = gettimeofday();
if(@{$ss} > 1 && $now-$hash->{lastMsgSent} > 3) {
if(@{$ss} > 1 && $now-$hash->{lastMsgSent} > 5) {
Log3 $hash, 2,
"ERROR: $hash->{NAME}: cleaning commands without ack after 3s";
"ERROR: $hash->{NAME}: cleaning commands without ack after 5s";
delete $hash->{SendStack};
return ZWave_addToSendStack($hash, $type, $cmd);
}
@ -3884,6 +3904,46 @@ ZWave_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
sub
@ -4822,28 +4882,36 @@ s2Hex($)
is in seconds, subseconds my be specified. Values outside of 0.2-5.0 are
probably harmful.
</li>
<li><a href="#do_not_notify">do_not_notify</a></li>
<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>
<li><a name="classes">classes</a>
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
class names (capital letters).
</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"
command. It contains a space seperated list of the the command classes
that are supported with SECURITY.
</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
contains the version information for each of the supported classes.
</li>
<li><a href="#noExplorerFrames">noExplorerFrames</a>
turn off the use of Explorer Frames
</li>
<li><a name="zwaveRoute">zwaveRoute</a>
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>
<br>