From 2ecd611a08f05a11a45cedc5d3a99bb3a5edfb83 Mon Sep 17 00:00:00 2001 From: jamesgo <> Date: Tue, 13 Oct 2015 05:16:04 +0000 Subject: [PATCH] 98_GAEBUS.pm: handling of timeouts in BlockingCall improved git-svn-id: https://svn.fhem.de/fhem/trunk@9447 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/98_GAEBUS.pm | 129 ++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 33 deletions(-) diff --git a/fhem/contrib/98_GAEBUS.pm b/fhem/contrib/98_GAEBUS.pm index 037354053..e0bddb7f3 100644 --- a/fhem/contrib/98_GAEBUS.pm +++ b/fhem/contrib/98_GAEBUS.pm @@ -16,6 +16,9 @@ # 15.09.2015 : A.Goebel : get rid of perl warnings when attribute value is empty # 16.09.2015 : A.Goebel : allow write to parameters protected by #install # 21.09.2015 : A.Goebel : implement BlockingCall Interface +# 07.10.2015 : A.Goebel : beautify and complete commandref +# 12.10.2015 : A.Goebel : fix handling of timeouts in BlockingCall Interface (additional parameter in doEbusCmd forces restart (no shutdown restart)) +# timeout for reads increased package main; @@ -36,7 +39,7 @@ sub GAEBUS_SimpleWrite(@); sub GAEBUS_Disconnected($); sub GAEBUS_Shutdown($); -sub GAEBUS_doEbusCmd($$$$$$); +sub GAEBUS_doEbusCmd($$$$$$$); sub GAEBUS_GetUpdates($); sub GAEBUS_GetUpdatesDoit($); @@ -289,7 +292,7 @@ GAEBUS_Set($@) my $readingname = $attr{$name}{$oneattr}; next if ($readingname ne $type); - my $answer = GAEBUS_doEbusCmd ($hash, "w", $readingname, $oneattr, $arg, ""); + my $answer = GAEBUS_doEbusCmd ($hash, "w", $readingname, $oneattr, $arg, "", 0); return "$answer"; } } @@ -374,7 +377,7 @@ GAEBUS_Get($@) Log3 ($name, 4, "$name Get name $readingname"); Log3 ($name, 4, "$name Get cmd r $readingcmdname"); - my $answer = GAEBUS_doEbusCmd ($hash, "r", $readingname, $readingcmdname, "", $cmdaddon); + my $answer = GAEBUS_doEbusCmd ($hash, "r", $readingname, $readingcmdname, "", $cmdaddon, 0); #return "$answer"; return undef; @@ -390,7 +393,7 @@ GAEBUS_Get($@) Log3 ($name, 3, "$name get cmd v $readingcmdname"); - my $answer = GAEBUS_doEbusCmd ($hash, "v", $readingname, $readingcmdname, "", ""); + my $answer = GAEBUS_doEbusCmd ($hash, "v", $readingname, $readingcmdname, "", "", 0); #return (defined($answer ? $answer : "")); return "$answer"; @@ -769,7 +772,44 @@ GAEBUS_ReadCSV($) } sub -GAEBUS_doEbusCmd($$$$$$) +GAEBUS_state($) +{ + my $hash = shift; + my $name = $hash->{NAME}; + my $answer = ""; + my $actMessage = ""; + + if (($hash->{STATE} ne "Connected") or (!$hash->{TCPDev}->connected()) ) + { + return ""; + } + + my $timeout = 10; + + syswrite ($hash->{TCPDev}, "state\n"); + if ($hash->{SELECTOR}->can_read($timeout)) + { + sysread ($hash->{TCPDev}, $actMessage, 4096); + if ($actMessage =~ /^signal acquired/) { + $answer = "ok"; + return "$answer"; + } else { + chomp ($actMessage); + $answer = $actMessage; + } + + } + else + { + $answer = "no answer"; + } + + Log3 ($name, 2, "$name state $answer"); + return "$answer"; +} + +sub +GAEBUS_doEbusCmd($$$$$$$) { my $hash = shift; my $action = shift; # "r" = set reading, "v" = verbose mode, "w" = write to ebus @@ -777,6 +817,7 @@ GAEBUS_doEbusCmd($$$$$$) my $readingcmdname = shift; my $writeValues = shift; my $cmdaddon = shift; + my $inBlockingCall = shift; my $actMessage; my $name = $hash->{NAME}; @@ -786,11 +827,18 @@ GAEBUS_doEbusCmd($$$$$$) GAEBUS_CloseDev($hash); GAEBUS_OpenDev($hash,1); - return undef unless ($hash->{STATE} eq "Connected"); + if ($hash->{STATE} ne "Connected") { + if ($inBlockingCall) { + return ""; + } + else { + return undef; + } + } } #my $timeout = 1.8; - my $timeout = 5.0; + my $timeout = 15.0; $timeout = 10.0 if ($action eq "v"); $timeout = 10.0 if ($action eq "w"); @@ -817,7 +865,7 @@ GAEBUS_doEbusCmd($$$$$$) Log3 ($name, 3, "$name execute $cmd"); - if ($hash->{SELECTOR}->can_read(0)) + if ($hash->{SELECTOR}->can_read(0.1)) { sysread ($hash->{TCPDev}, $actMessage, 4096); $actMessage =~ s/\n//g; @@ -834,33 +882,39 @@ GAEBUS_doEbusCmd($$$$$$) Log3 ($name, 3, "$name answer $action $readingname $actMessage"); - unless ($actMessage =~ "Usage:") # pass Usage: directly - { - # no Usage: message - unless ($actMessage =~ /^ERR:/) # pass ERR: message directly - { - # no ERR: message - # = normal answer + #unless ($actMessage =~ "Usage:") # pass Usage: directly + #{ + # # no Usage: message + # unless ($actMessage =~ /^ERR:/) # pass ERR: message directly + # { + # # no ERR: message + # # = normal answer + # } + #} - if ($action eq "r") { - if (defined ($readingname)) { - # BlockingCall changes - readingsSingleUpdate ($hash, $readingname, "$actMessage", 1); - return $readingname."|".$actMessage; - } - } - - } - } - - #return undef if ($action eq "r"); - return $actMessage; } else { - return "timeout reading answer for ($readingname) $cmd"; + #return "timeout reading answer for ($readingname) $cmd"; + + $actMessage = "timeout reading answer for $cmd"; + Log3 ($name, 2, "$name $actMessage"); } + if ($action eq "r") { + if (defined ($readingname)) { + # BlockingCall changes + readingsSingleUpdate ($hash, $readingname, "$actMessage", 1); + } + + } + + if ($inBlockingCall) { + $actMessage = $readingname."|".$actMessage; + } + + return $actMessage; + } sub @@ -901,6 +955,14 @@ GAEBUS_GetUpdatesDoit($) return "$name"; } + # syncronize with ebusd + + my $state = GAEBUS_state($hash); + unless ($state eq "ok") { + Log3 ($name, 2, "$name: ebusd no signal ($state)"); + return "$name"; + } + foreach my $oneattr (keys %{$attr{$name}}) { # only for "r" commands @@ -922,7 +984,7 @@ GAEBUS_GetUpdatesDoit($) #Log3 ($name, 2, "$name check modulo ".$hash->{UpdateCnt}." mod $doCntNo -> ".($hash->{UpdateCnt} % $doCntNo)); if (($hash->{UpdateCnt} % $doCntNo) == 0) { - $readingsToUpdate .= "|".GAEBUS_doEbusCmd ($hash, "r", $readingname, $oneattr, "", $cmdaddon); + $readingsToUpdate .= "|".GAEBUS_doEbusCmd ($hash, "r", $readingname, $oneattr, "", $cmdaddon, 1); } # limit number of reopens if ebusd cannot be reached @@ -999,8 +1061,6 @@ GAEBUS_GetUpdatesAborted($) The GAEBUS module is the representation of a Ebus connector in FHEM. The GAEBUS module is designed to connect to ebusd (ebus daemon) via a socket connection (default is port 8888)
- - @@ -1013,7 +1073,7 @@ GAEBUS_GetUpdatesAborted($) 192.168.0.244:8888 or servername:8888. When using the standard port, the port can be omitted.

- Example:
+ Example:

define ebus1 GAEBUS localhost 300

When initializing the object the configuration of the ebusd (.csv files from /etc/ebusd) are read.
@@ -1070,6 +1130,7 @@ GAEBUS_GetUpdatesAborted($)
  • ebusWritesEnabled 0,1
    disable (0) or enable (1) that commands can be send to ebus devices
    See also description for Set and Get
    + If Attribute is missing, default value is 0 (disable writes)

  • Attributes of the format
    [r]~<class>~<variable-name>~<comment from csv>
    @@ -1078,6 +1139,8 @@ GAEBUS_GetUpdatesAborted($) The value assigned to an attribute specifies the name of the reading for this variable.
    The name of the reading can be suffixed by "<number>" which is a multiplicator for the evaluation within the specified interval. (eg. OutsideTemp:3 will evaluate this reading every 3-th cycle)
    + All text followed the reading seperated by a blank is given as an additional parameter to ebusd. + This can be used to request a single value if more than one is retrieved from ebus.

  • Attributes of the format
    [w]~<class>~<variable-name>~<comment from csv>