mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-16 04:36:02 +00:00
10_ZWave.pm/00_ZWDongle.pm: fix ACK-code to work with the unfinished secureInit
git-svn-id: https://svn.fhem.de/fhem/trunk@8744 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
e90c4419c3
commit
a44866ec6f
@ -228,11 +228,9 @@ ZWDongle_Define($$)
|
||||
$hash->{DeviceName} = $dev;
|
||||
$hash->{CallbackNr} = 0;
|
||||
$hash->{nrNAck} = 0;
|
||||
$hash->{WaitForAck}=0;
|
||||
$hash->{SendRetrys}=0;
|
||||
$hash->{MaxSendRetrys}=3;
|
||||
my @empty;
|
||||
$hash->{SendStack} = \@empty;
|
||||
ZWDongle_shiftSendStack($hash, 5, undef);
|
||||
|
||||
my $ret = DevIo_OpenDev($hash, 0, "ZWDongle_DoInit");
|
||||
return $ret;
|
||||
@ -264,6 +262,7 @@ ZWDongle_Set($@)
|
||||
return "Unknown argument $type, choose one of " . join(" ",@r);
|
||||
}
|
||||
|
||||
Log3 $hash, 4, "ZWDongle set $name $type ".join(" ",@a);
|
||||
if($type eq "reopen") {
|
||||
return if(AttrVal($name, "dummy",undef) || AttrVal($name, "disable",undef));
|
||||
DevIo_CloseDev($hash);
|
||||
@ -295,12 +294,11 @@ ZWDongle_Set($@)
|
||||
}
|
||||
|
||||
if($type eq "addNode") {
|
||||
if(@a == 2 && $a[2] =~ m/^sec/i) {
|
||||
if(@a == 2 && $a[1] =~ m/^sec/i) {
|
||||
$hash->{addSecure} = pop(@a);
|
||||
} else {
|
||||
delete($hash->{addSecure});
|
||||
}
|
||||
Log 1, "CMD:".join("/",@a)."/";
|
||||
}
|
||||
|
||||
my @ca = split("%", $cmd, -1);
|
||||
@ -332,6 +330,7 @@ ZWDongle_Get($@)
|
||||
return "$type is unsupported by this controller";
|
||||
}
|
||||
|
||||
Log3 $hash, 4, "ZWDongle get $name $type ".join(" ",@a);
|
||||
my @ga = split("%", $gets{$type}, -1);
|
||||
my $nargs = int(@ga)-1;
|
||||
return "get $name $type needs $nargs arguments" if($nargs != int(@a));
|
||||
@ -474,9 +473,9 @@ ZWDongle_DoInit($)
|
||||
ZWDongle_Get($hash, $name, "homeId");
|
||||
ZWDongle_Get($hash, $name, ("random", 32)); # Sec relevant
|
||||
ZWDongle_Set($hash, $name, ("timeouts", 100, 15)); # Sec relevant
|
||||
ZWDongle_ReadAnswer($hash, "timeouts", "^0106");
|
||||
# NODEINFO_LISTENING, Generic Static controller, Specific Static Controller, 0
|
||||
ZWDongle_Set($hash, $name, ("setNIF", 1, 2, 1, 0)); # Sec relevant (?)
|
||||
ZWDongle_Clear($hash); # Wait, timeouts needs ack
|
||||
$hash->{STATE} = "Initialized";
|
||||
return undef;
|
||||
}
|
||||
@ -498,11 +497,16 @@ ZWDongle_Write($$$)
|
||||
{
|
||||
my ($hash,$fn,$msg) = @_;
|
||||
|
||||
Log3 $hash, 5, "ZWDongle_Write msg $msg";
|
||||
if($fn !~ m/^[0-9A-F]+$/i) { # ACK initiated from ZWDongle
|
||||
ZWDongle_shiftSendStack($hash, 5, $fn);
|
||||
return;
|
||||
}
|
||||
|
||||
Log3 $hash, 5, "ZWDongle_Write $fn $msg";
|
||||
# assemble complete message
|
||||
$msg = "$fn$msg";
|
||||
$msg = sprintf("%02x%s", length($msg)/2+1, $msg);
|
||||
|
||||
$msg = "01$msg" . ZWDongle_CheckSum($msg);
|
||||
|
||||
# push message on stack
|
||||
@ -523,53 +527,59 @@ ZWDongle_Write($$$)
|
||||
unshift($hash->{SendStack}, $w1) if($w1);
|
||||
}
|
||||
|
||||
#send first message if not waiting for ACK
|
||||
ZWave_ProcessSendStack($hash);
|
||||
}
|
||||
|
||||
sub
|
||||
ZWDongle_shiftSendStack($$$)
|
||||
{
|
||||
my ($hash, $level, $txt) = @_;
|
||||
my $ss = $hash->{SendStack};
|
||||
my $cmd = shift @{$ss};
|
||||
Log3 $hash, $level, "$txt, removing $cmd from sendstack" if($txt && $cmd);
|
||||
|
||||
$hash->{WaitForAck}=0;
|
||||
$hash->{SendRetries}=0;
|
||||
$hash->{MaxSendRetries}=3;
|
||||
}
|
||||
|
||||
sub
|
||||
ZWave_ProcessSendStack($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
Log3 $hash, 5, "ZWave_ProcessSendStack: ".@{$hash->{SendStack}}.
|
||||
" items on stack, waitForAck ".$hash->{WaitForAck};
|
||||
#Log3 $hash, 1, "ZWave_ProcessSendStack: ".@{$hash->{SendStack}}.
|
||||
# " items on stack, waitForAck ".$hash->{WaitForAck};
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
my $ts = gettimeofday();
|
||||
|
||||
if($hash->{WaitForAck}){
|
||||
if($ts-$hash->{SendTime} > 1){
|
||||
Log3 $hash, 2,
|
||||
"ZWave_ProcessSendStack: timeout sending message -> trigger resend";
|
||||
$hash->{SendRetrys}++;
|
||||
if($ts-$hash->{SendTime} >= 1){
|
||||
Log3 $hash, 2, "ZWave_ProcessSendStack: no ACK, resending message";
|
||||
$hash->{SendRetries}++;
|
||||
$hash->{WaitForAck} = 0;
|
||||
|
||||
} else {
|
||||
Log3 $hash, 5, "ZWave_ProcessSendStack: waiting for ACK -> check again";
|
||||
InternalTimer($ts+1, "ZWave_ProcessSendStack", $hash, 0);
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($hash->{SendRetrys} > $hash->{MaxSendRetrys}){
|
||||
Log3 $hash, 1,
|
||||
"ZWave_ProcessSendStack: max send retrys reached -> cancel sending";
|
||||
shift @{$hash->{SendStack}};
|
||||
$hash->{WaitForAck} = 0;
|
||||
$hash->{SendRetrys} = 0;
|
||||
$hash->{MaxSendRetrys} = 3;
|
||||
if($hash->{SendRetries} > $hash->{MaxSendRetries}){
|
||||
ZWDongle_shiftSendStack($hash, 1, "ERROR: max send retries reached");
|
||||
}
|
||||
|
||||
return if(!@{$hash->{SendStack}} || $hash->{WaitForAck});
|
||||
|
||||
my $msg = $hash->{SendStack}->[0];
|
||||
Log3 $hash, 5, "ZWave_ProcessSendStack: sending msg ".$msg;
|
||||
|
||||
DevIo_SimpleWrite($hash, $msg, 1);
|
||||
$hash->{WaitForAck} = 1;
|
||||
$hash->{SendTime} = $ts;
|
||||
|
||||
InternalTimer($ts+1, "ZWave_ProcessSendStack", $hash, 0);
|
||||
}
|
||||
|
||||
@ -594,38 +604,39 @@ ZWDongle_Read($@)
|
||||
$hash->{ReadTime} = $ts;
|
||||
|
||||
|
||||
Log3 $name, 5, "ZWDongle RAW buffer: $data";
|
||||
#Log3 $name, 5, "ZWDongle RAW buffer: $data";
|
||||
|
||||
my $msg;
|
||||
while(length($data) > 0) {
|
||||
|
||||
my $fb = substr($data, 0, 2);
|
||||
|
||||
if($fb eq "06") { # ACK
|
||||
Log3 $name, 5, "$name: ACK received";
|
||||
$data = substr($data, 2);
|
||||
# ZWDongle messages are removed if ZW_SEND_DATA:OK is received
|
||||
if(!@{$hash->{SendStack}} || $hash->{SendStack}->[0] !~ m/^01....13/) {
|
||||
shift @{$hash->{SendStack}};
|
||||
$hash->{WaitForAck} = 0;
|
||||
$hash->{SendRetrys} = 0;
|
||||
$hash->{MaxSendRetrys} = 3;
|
||||
# ZWDongle messages are removed upon first ACK.
|
||||
# Other network messages are removed if ZW_SEND_DATA:OK is received
|
||||
my $sst = $hash->{SendStack}->[0];
|
||||
if($sst && $sst !~ m/^01....13/) {
|
||||
ZWDongle_shiftSendStack($hash, 5, "ACK received");
|
||||
}
|
||||
|
||||
|
||||
$data = substr($data, 2);
|
||||
next;
|
||||
}
|
||||
|
||||
if($fb eq "15") { # NACK
|
||||
Log3 $name, 4, "$name: NACK received, resending the message";
|
||||
Log3 $name, 4, "ZWDongle_Read $name: NACK received";
|
||||
$hash->{WaitForAck} = 0;
|
||||
$hash->{SendRetrys}++;
|
||||
$hash->{SendRetries}++;
|
||||
$data = substr($data, 2);
|
||||
next;
|
||||
}
|
||||
|
||||
if($fb eq "18") { # CAN
|
||||
Log3 $name, 4, "$name: CAN received, resending the message";
|
||||
Log3 $name, 4, "ZWDongle_Read $name: CAN received";
|
||||
$hash->{WaitForAck} = 0;
|
||||
$hash->{SendRetrys}++;
|
||||
$hash->{MaxSendRetrys}++ if($hash->{MaxSendRetrys}<7);
|
||||
$hash->{SendRetries}++;
|
||||
$hash->{MaxSendRetries}++ if($hash->{MaxSendRetries}<7);
|
||||
$data = substr($data, 2);
|
||||
next;
|
||||
}
|
||||
@ -661,17 +672,12 @@ ZWDongle_Read($@)
|
||||
next;
|
||||
}
|
||||
$hash->{nrNAck} = 0;
|
||||
Log3 $name, 5, "ZWDongle_Read $name: ACK, processing $msg";
|
||||
Log3 $name, 4, "ZWDongle_Read $name: sending ACK, processing $msg";
|
||||
DevIo_SimpleWrite($hash, "06", 1); # Send ACK
|
||||
|
||||
# SEND_DATA OK: remove message from SendStack. TODO: check the callbackId
|
||||
if($msg =~ m/^0013..00/ ){
|
||||
Log3 $name, 5,
|
||||
"ZWDongle_Read $name: ZW_SEND_DATA:OK received -> removing message";
|
||||
shift @{$hash->{SendStack}};
|
||||
$hash->{WaitForAck} = 0;
|
||||
$hash->{SendRetrys} = 0;
|
||||
$hash->{MaxSendRetrys} = 3;
|
||||
ZWDongle_shiftSendStack($hash, 5, "ZW_SEND_DATA:OK received");
|
||||
}
|
||||
|
||||
last if(defined($local) && (!defined($regexp) || ($msg =~ m/$regexp/)));
|
||||
@ -687,11 +693,7 @@ ZWDongle_Read($@)
|
||||
# trigger sending of next message
|
||||
ZWave_ProcessSendStack($hash) if(length($data) == 0);
|
||||
|
||||
if(defined($local)){
|
||||
Log3 $name, 5, "ZWDongle_Read returning local msg ".
|
||||
($msg ? $msg:"undef")." hash PARTIAL: ".$hash->{PARTIAL};
|
||||
return $msg;
|
||||
}
|
||||
return $msg if(defined($local));
|
||||
return undef;
|
||||
}
|
||||
|
||||
@ -743,12 +745,11 @@ ZWDongle_ReadAnswer($$$)
|
||||
Log3 $hash, 1,"ZWDongle_ReadAnswer: no data read";
|
||||
return ("No data", undef);
|
||||
}
|
||||
Log3 $hash, 5, "ZWDongle_ReadAnswer: read ".length($buf)." bytes";
|
||||
}
|
||||
|
||||
my $ret = ZWDongle_Read($hash, $buf, $regexp);
|
||||
if(defined($ret)){
|
||||
Log3 $hash, 5, "ZWDongle_ReadAnswer: returning $ret";
|
||||
Log3 $hash, 4, "ZWDongle_ReadAnswer for $arg: $ret";
|
||||
return (undef, $ret);
|
||||
}
|
||||
}
|
||||
@ -760,7 +761,7 @@ ZWDongle_Parse($$$)
|
||||
my ($hash, $name, $rmsg) = @_;
|
||||
|
||||
if(!defined($hash->{STATE}) || $hash->{STATE} ne "Initialized"){
|
||||
Log3 $hash, 4,"ZWDongle_Parse dongle not initialized";
|
||||
Log3 $hash, 4,"ZWDongle_Parse $rmsg: dongle not yet initialized";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -350,8 +350,8 @@ my %zwave_class = (
|
||||
"secNonce" => "40" },
|
||||
get => { "secSupported" => "02" },
|
||||
parse => { "..9803(.*)" => '"secSupported:$1"',
|
||||
"..9805(.*)" => 'ZWave_securityInit($hash, $1)',
|
||||
"..9880(.*)" => 'ZWave_securityInit($hash, $1)' } },
|
||||
"..9805(.*)" => 'ZWave_secureInit($hash, $1)', # secScheme
|
||||
"..9880(.*)" => 'ZWave_secureInit($hash, $1)' } },
|
||||
AV_TAGGING_MD => { id => '99' },
|
||||
IP_CONFIGURATION => { id => '9a' },
|
||||
ASSOCIATION_COMMAND_CONFIGURATION
|
||||
@ -380,7 +380,6 @@ my %zwave_cmdArgs = (
|
||||
|
||||
my %zwave_modelConfig;
|
||||
my %zwave_modelIdAlias = ( "010f-0301-1001" => "Fibaro_FGRM222",
|
||||
"013c-0001-0003" => "Philio_PAN04",
|
||||
"0115-0100-0102" => "ZME_KFOB" );
|
||||
|
||||
# Patching certain devices.
|
||||
@ -1454,7 +1453,7 @@ ZWave_sensorbinaryV2Parse($$)
|
||||
}
|
||||
|
||||
sub
|
||||
ZWave_securityInit(@)
|
||||
ZWave_secureInit(@)
|
||||
{
|
||||
my ($hash, $param) = @_;
|
||||
my $iodev = $hash->{IODev};
|
||||
@ -1463,7 +1462,10 @@ ZWave_securityInit(@)
|
||||
$hash->{secStatus} = 0 if(!$hash->{secStatus});
|
||||
my $status = ++$hash->{secStatus};
|
||||
|
||||
Log3 $iodev, 4, "$hash->{NAME}: securityInit status $status";
|
||||
my @stTxt = ( "secScheme", "secKey", "secNonce", "done");
|
||||
my $stTxt = ($status > int(@stTxt) ? "ERR" : $stTxt[$status-1]);
|
||||
Log3 $iodev, 4, "*** $hash->{NAME}: secureInit status $status/$stTxt";
|
||||
|
||||
if($status == 1) {
|
||||
ZWave_Set($hash, $name, "secScheme");
|
||||
return ""; # not evaluated
|
||||
@ -1475,10 +1477,11 @@ ZWave_securityInit(@)
|
||||
return undef; # No Event/Reading
|
||||
|
||||
} elsif($status == 3) {
|
||||
IOWrite($hash, "secKey ACK", "");
|
||||
ZWave_Set($hash, $name, "secNonce");
|
||||
return undef; # No Event/Reading
|
||||
|
||||
} else {
|
||||
} elsif($status == 4) {
|
||||
Log3 $iodev, 4, "secNonce report: $param";
|
||||
delete $iodev->{secInitName};
|
||||
delete $hash->{secStatus};
|
||||
@ -1544,7 +1547,7 @@ ZWave_Parse($$@)
|
||||
if($cmd eq "ZW_SEND_DATA") {
|
||||
Log3 $ioName, 2, "ERROR: cannot SEND_DATA: $arg" if($arg != 1);
|
||||
my $si = $iodev->{secInitName};
|
||||
ZWave_securityInit($defs{$si}) # No extra response for set networkKey
|
||||
ZWave_secureInit($defs{$si}) # No extra response for set networkKey
|
||||
if($si && $defs{$si} && $defs{$si}{secStatus} &&
|
||||
$defs{$si}{secStatus} == 2);
|
||||
return "";
|
||||
@ -1595,7 +1598,7 @@ ZWave_Parse($$@)
|
||||
my $key = AttrVal($ioName, "networkKey", "");
|
||||
if($key) {
|
||||
$iodev->{secInitName} = $dh->{NAME};
|
||||
return ZWave_securityInit($dh);
|
||||
return ZWave_secureInit($dh);
|
||||
} else {
|
||||
Log3 $ioName, 2, "No secure inclusion as $ioName has no networkKey";
|
||||
}
|
||||
@ -1757,8 +1760,8 @@ ZWave_Parse($$@)
|
||||
@{$baseHash->{WakeUp}}=();
|
||||
#send a final wakeupNoMoreInformation
|
||||
my $nodeId = $baseHash->{id};
|
||||
IOWrite($hash, "00", "13${nodeId}02840805");
|
||||
Log3 $hash, 4, "Sending wakeupNoMoreInformation to node: $nodeId";
|
||||
IOWrite($hash, "00", "13${nodeId}02840805");
|
||||
}
|
||||
$baseHash->{lastMsgTimestamp} = time();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user