FHEM Forum

FHEM - Entwicklung => FHEM Development => Thema gestartet von: charlie71 am 05 Januar 2018, 12:15:26

Titel: execute shell command in nonblocking call.
Beitrag von: charlie71 am 05 Januar 2018, 12:15:26
Hallo Leute,
ich habe folgendes Problem, in einem non-blocking call möchte ich ein shell command aufrufen.
Leider funktioniert das nicht, irgend wie scheint das alles im shell execute command hängen zu bleiben. Ich habe alles bis auf den quote execute command auskommentiert, da scheint das Modul zu funktionieren, es wird die finishFn sauber aufgerufen.

Wenn der quote execute command aufgerufen wird, geht leider nichts mehr. Als shell command habe ich whoami gewählt.

Vielen Dank für eure Hilfe
Charlie71

Hier mein Modul code

##############################################
# $Id: myTempNB.pm  2018-01-05  charlie71
#
package main;

use strict;
use warnings;
use Blocking;
use Time::HiRes qw(gettimeofday);

sub myTempNB_Initialize($) {
my ($hash) = @_;
$hash->{DefFn}         = "myTempNB_Define";
$hash->{UndefFn}       = "myTempNB_Undef";

$hash->{AttrList}      = "timeout " . $readingFnAttributes;
}
#####################################
sub myTempNB_Define($$) {
my ( $hash, $def ) = @_;

my @a = split( "[ \t][ \t]*", $def );

return
  "Usage: define <name> myTempNB <address> [<intervall>]"
  if ( @a < 3 || @a > 4 );

my $name  = $a[0];
my $address   = $a[2];
my $inter = 300;

if ( int(@a) == 4 ) {
$inter = $a[3];
if ( $inter < 5 ) {
return
  "interval too small, please use something > 5, default is 300";
}
}

$hash->{name}     = $name;
$hash->{address}  = $address;
$hash->{interval} = $inter;

#Aufraemen
delete( $hash->{helper}{RUNNING_PID} );
RemoveInternalTimer($hash);

# my $res = myTempNB_bcReadData($hash->{NAME} . "|"  . $hash->{address});
# Log3 $hash, 3, "[$name] get Value: $res";

# initial request after 2 secs, there timer is set to interval for further update
InternalTimer( gettimeofday() + 2, "myTempNB_GetUpdate", $hash, 0 );

return undef;
}
#####################################
sub myTempNB_GetUpdate($) {
my ($hash) = @_;
my $name = $hash->{name};
my $timeout = $hash->{interval} - 2;

if ( defined( $main::attr{$name}{timeout} ) ) {
           $timeout = $main::attr{$name}{timeout};
        }


InternalTimer( gettimeofday() + $hash->{interval},
"myTempNB_GetUpdate", $hash, 1 );

Log3( $name, 3, "myTempNB: GetUpdate called ... timeout = $timeout" );


    my $arg        = $hash->{NAME} . "|" . $hash->{address};
    my $blockingFn = "myTempNB_bcReadData";
    my $finishFn   = "myTempNB_bcDone";
    my $abortFn    = "myTempNB_Abort";

   #ja ich weiss die nächsten 2 Zeilen machen wenig sinn, aber ich teste nur
   BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
   delete( $hash->{helper}{RUNNING_PID} );
   
   if (!(exists($hash->{helper}{RUNNING_PID}))) {
      $hash->{helper}{RUNNING_PID} =
         BlockingCall($blockingFn, $arg, $finishFn, $timeout, $abortFn, $hash);
  } else {
    Log3 $hash, 3, "[$name] Blocking Call running no new started";
  }
}

#####################################
sub myTempNB_bcReadData($) {

my ($string) = @_;
my ( $name, $address ) = split( "\\|", $string );
my $val;

my $err_log = "";

my $cmd ="whoami";#nur zum Testen
my $res = 0;

eval {
local $SIG{__DIE__} = sub {
my ($s) = @_;
$err_log = $s;
$res = -1;
};
$val = qx($cmd);
};

my $return;

if ($res == 0) {
$return = "$name|0|$val";
} else {
$return = "$name|1|$err_log";
}
return $return;
}
#####################################

sub myTempNB_bcDone($) {
my ($string) = @_;
return unless ( defined($string) );

my @a    = split("\\|", $string);
my $name = $a[0];
my $hash = $defs{$name};

Log3( $name, 3, "myTempNB: bcDone... $string" );

delete( $hash->{helper}{RUNNING_PID} );


if ( @a < 3 || $a[1] != 1 ) {

#error situation
$hash->{STATE} = "Error";
Log3( $name, 3, $a[2] );
return;
}
my $whoami    = $a[2];
readingsBeginUpdate($hash);
readingsBulkUpdate( $hash, "whoami",         $whoami );
readingsEndUpdate( $hash, 1 );

$hash->{STATE} = "OK";
}

#####################################

sub myTempNB_Abort($) {
my ($hash) = @_;

delete( $hash->{helper}{RUNNING_PID} );

Log3( $hash->{NAME}, 4,
"BlockingCall for " . $hash->{NAME} . " was aborted" );
}

#####################################
sub myTempNB_Undef($) {
my $hash = shift;

RemoveInternalTimer($hash);

BlockingKill( $hash->{helper}{RUNNING_PID} )
  if ( defined( $hash->{helper}{RUNNING_PID} ) );

delete( $modules{myTempNB}{defptr} );

return undef;
}



1;



hier mein Logfile auszug:

2018.01.05 12:11:03.038 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:11:13.042 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:11:23.044 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:11:33.082 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:11:43.084 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:11:53.087 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:03.089 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:13.092 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:23.129 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:33.132 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:43.211 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:12:53.213 3: myTempNB: GetUpdate called ... timeout = 8
2018.01.05 12:13:03.216 3: myTempNB: GetUpdate called ... timeout = 8