From 19567d607035376c3b55e192033051138c4988ae Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Mon, 7 Sep 2015 18:56:00 +0000 Subject: [PATCH] 00_FBAHA: Compare the id with the stored FBNAME (Forum #40396) git-svn-id: https://svn.fhem.de/fhem/trunk@9212 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/00_FBAHA.pm | 81 ++++++++++++++++++++++++++++++++++++++---- fhem/FHEM/10_FBDECT.pm | 18 +++++++--- fhem/FHEM/HttpUtils.pm | 4 ++- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/fhem/FHEM/00_FBAHA.pm b/fhem/FHEM/00_FBAHA.pm index 3b8c23738..db762abaa 100644 --- a/fhem/FHEM/00_FBAHA.pm +++ b/fhem/FHEM/00_FBAHA.pm @@ -28,6 +28,7 @@ FBAHA_Initialize($) $hash->{UndefFn} = "FBAHA_Undef"; $hash->{ShutdownFn} = "FBAHA_Undef"; $hash->{ReadAnswerFn} = "FBAHA_ReadAnswer"; + $hash->{NotifyFn} = "FBAHA_Notify"; # Normal devices $hash->{DefFn} = "FBAHA_Define"; @@ -62,6 +63,17 @@ FBAHA_Define($$) return $ret; } +##################################### +sub +FBAHA_Notify($$) +{ + my ($ntfy, $dev) = @_; + return if($dev->{NAME} ne "global" || + !grep(m/^INITIALIZED$/, @{$dev->{CHANGED}})); + delete $modules{telnet}{NotifyFn}; + FBAHA_reassign($ntfy); + return; +} ##################################### sub @@ -162,6 +174,7 @@ FBAHA_getDevList($$) my $data = ""; for(;;) { my ($err, $buf) = FBAHA_ReadAnswer($hash, "CONFIG_RSP", "^06"); + last if($err && $err =~ m/Timeout/); return ($err) if($err); $data .= substr($buf, 32); last if($buf =~ m/^060[23]/); @@ -213,6 +226,45 @@ FBAHA_configInd($$) return @answer; } +##################################### +# Check all FBDECTs, reorg them if the id has changed and FBNAME is set. +sub +FBAHA_reassign($) +{ + my ($me) = @_; + my $myname = $me->{NAME}; + + my $devList = FBAHA_Get($me, ($myname, "devList")); + my %fbdata; + foreach my $l (split("\n", $devList)) { + next if($l !~ m/NAME:(.*), ID:(.*), (.*), TYPE:(.*) PROP:(.*)/); + if($fbdata{$1}) { + Log 1, "FBAHA: multiple devices are using the same name, wont reorder"; + return; + } + $fbdata{$1} = $2; + } + + foreach my $sdev (devspec2array("TYPE=FBDECT")) { + my $hash = $defs{$sdev}; + my $name = $hash->{NAME}; + my $fbname = ReadingsVal($name, "FBNAME", ""); + my $fbid = $fbdata{$fbname}; + my $oldid = $hash->{id}; + + next if(!$fbid || $oldid eq $fbid || $hash->{IODev}{NAME} ne $myname); + Log 2, "FBAHA: changing the id of $name/$fbname from $oldid to $fbid"; + + delete $modules{FBDECT}{defptr}{"$myname:$oldid"}; + $modules{FBDECT}{defptr}{"$myname:$fbid"} = $hash; + $hash->{DEF} =~ s/^$myname:$oldid /$myname:$fbid /; # New syntax + $hash->{DEF} =~ s/^$oldid /$myname:$fbid /; # Old Syntax + $hash->{id} = $fbid; + } + + return; +} + ##################################### sub FBAHA_DoInit($) @@ -221,6 +273,7 @@ FBAHA_DoInit($) my $name = $hash->{NAME}; delete $hash->{HANDLE}; # else reregister fails / RELEASE is deadly my $ret = FBAHA_Set($hash, ($name, "reregister")); + FBAHA_reassign($hash) if(!$ret && $init_done); return $ret; } @@ -314,8 +367,8 @@ FBAHA_ReadAnswer($$$) if($nfound <= 0) { next if ($! == EAGAIN() || $! == EINTR()); my $err = ($! ? $! : "Timeout"); - $hash->{TIMEOUT} = 1; - DevIo_Disconnected($hash); + #$hash->{TIMEOUT} = 1; + #DevIo_Disconnected($hash); return("FBAHA_ReadAnswer $arg: $err", undef); } my $buf = DevIo_SimpleRead($hash); @@ -361,8 +414,8 @@ FBAHA_Ready($) (fritz.box or localhost), and <port> 2002, or UNIX:SEQPACKET:/var/tmp/me_avm_home_external.ctl, the latter only works on the fritz.box. With FRITZ!OS 5.50 the network port is available, on some - Labor variants only the UNIX socket is available. -
+ Labor variants only the UNIX socket is available.
+ Example: +
+ As sometimes the FRITZ!Box reassigns the internal id's of the FBDECT devices, + the FBAHA module compares upon connect/reconnect the stored names (FBNAME) + with the current value. This feature will only work, if you assign each + FBDECT device a unique Name in the FRITZ!Box, and excecute the FHEM "get + FBDECTDEVICE devInfo" command, which saves the FBNAME reading.
+ @@ -439,8 +499,9 @@ FBAHA_Ready($) FRITZ.BOX) und <port> 2002 ist, oder UNIX:SEQPACKET:/var/tmp/me_avm_home_external.ctl, wobei das nur fuer FHEM@FRITZ!BOX zur Verfügung steht. Mit FRITZ!OS 5.50 steht auch der - Netzwerkport zur Verfügung, auf manchen Laborvarianten nur das UNIX socket. -
+ Netzwerkport zur Verfügung, auf manchen Laborvarianten nur das UNIX + socket.
+ Beispiel: +
+ Da manchmal die FRITZ!Box die interne Nummer der FBDECT Geräte + neu vergibt, werden beim Verbindungsaufbau zum AHA Server die gespeicherten + Namen (FBNAME) mit dem aktuellen Wert verglichen. Damit das funktioniert, + müssen alle FBDECT Geräte auf dem FRITZ!Box einen eindeutigen Namen + bekommen, und in FHEM muss für alle Geräte "get FBDECTDEVICE + devInfo" ausgeführt werden, um FBNAME als Reading zu speichern.
+ =end html_DE diff --git a/fhem/FHEM/10_FBDECT.pm b/fhem/FHEM/10_FBDECT.pm index 33512b7d9..dcd7cf933 100644 --- a/fhem/FHEM/10_FBDECT.pm +++ b/fhem/FHEM/10_FBDECT.pm @@ -133,21 +133,29 @@ FBDECT_Get($@) if($cmd eq "devInfo") { my @answ = FBAHA_getDevList($hash->{IODev}, $hash->{id}); return $answ[0] if(@answ == 1); + + readingsBeginUpdate($hash); + + if($answ[0] && + $answ[0] =~ m/NAME:(.*), ID:(.*), (.*), TYPE:(.*) PROP:(.*)/) { + readingsBulkUpdate($hash, "FBNAME", $1, 1); + readingsBulkUpdate($hash, "FBTYPE", $4, 1); + readingsBulkUpdate($hash, "FBPROP", $5, 1); + } + my $d = pop @answ; - my $state = "inactive" if($answ[0] =~ m/ inactive,/); while($d) { my ($ptyp, $plen, $pyld) = FBDECT_decodePayload($d, $hash, 0); Log3 $hash, 4, "Payload: $d -> $ptyp: $pyld"; last if($ptyp eq ""); - if($ptyp eq "state" && - ReadingsVal($hash->{NAME}, $ptyp, "") ne $pyld) { - readingsSingleUpdate($hash, $ptyp, ($state ? $state : $pyld), 1); - } + readingsBulkUpdate($hash, $ptyp, $pyld, 1); push @answ, " $ptyp: $pyld"; $d = substr($d, 16+$plen*2); } + readingsEndUpdate($hash, 1); return join("\n", @answ); } + return undef; } diff --git a/fhem/FHEM/HttpUtils.pm b/fhem/FHEM/HttpUtils.pm index 967fb51da..e387ee37c 100644 --- a/fhem/FHEM/HttpUtils.pm +++ b/fhem/FHEM/HttpUtils.pm @@ -353,7 +353,9 @@ HttpUtils_ParseAnswer($$) my $code= $header0[1]; # Close if server doesn't support keepalive - HttpUtils_Close($hash) if($hash->{keepalive} and $hash->{httpheader} =~ m/^Connection:\s*close\s*$/mi); + HttpUtils_Close($hash) + if($hash->{keepalive} && + $hash->{httpheader} =~ m/^Connection:\s*close\s*$/mi); if(!defined($code) || $code eq "") { return ("$hash->{displayurl}: empty answer received", "");