notify bei eingehender TCP Botschaft auslösen

Begonnen von klausw, 30 Oktober 2013, 15:43:06

Vorheriges Thema - Nächstes Thema

klausw

ich wiederhole nix, jedenfalls nicht vorsätzlich
im define habe ich iTunes_startUpdater (natürlich umbenannt ;)) aufgerufen, das ist alles
oder wird es da endlos wiederholt? Kann ich mir eigentlich nicht vorstellen
RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280

justme1968

schau hin:) es wird bei einem lese fehler immer wieder eine neue verbindung auf gemacht. dir logik musst du für dich ändern.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klausw

erst vermutete ich ja, das ich zu müde war, aber scheinbar bin ich zu blöd ;)

##############################################################################
#
# 51_NetzerUtils.pm
#
##############################################################################
# Modul for NetzerUtils access
#
#
#
##############################################################################

package main;
use strict;
use warnings;
use POSIX;
use Scalar::Util qw(looks_like_number);
use IO::File;

sub NetzerUtils_Initialize($) {
  my ($hash) = @_;
  $hash->{DefFn}    = "NetzerUtils_Define";
  $hash->{ReadFn}  =  "NetzerUtils_Read";
  $hash->{GetFn}    = "NetzerUtils_Get";
  $hash->{SetFn}    = "NetzerUtils_Set";
  $hash->{AttrFn}   = "NetzerUtils_Attr";
  $hash->{UndefFn}  = "NetzerUtils_Undef";
  $hash->{ExceptFn} = "NetzerUtils_Except";
  $hash->{AttrList} = "poll_interval loglevel:0,1,2,3,4,5" .
                      " direction:input,output pud_resistor:off,up,down" .
                      " interrupt:none,falling,rising,both toggletostate:no,yes";
}

my %setsoutp = (
'on' => 0,
'off' => 0,
'toggle' => 0,
);

my %setsinpt = (
'readValue' => 0,
); 

sub NetzerUtils_Define($$) {
my ($hash, $def) = @_;

my @args = split("[ \t]+", $def);
my $menge = int(@args);
if (int(@args) < 3)
{
  return "Define: to less arguments. Usage:\n" .
         "define <name> NetzerUtils <Host> <port>";
}
#Prüfen, ob GPIO bereits verwendet
#foreach my $dev (devspec2array("TYPE=$hash->{TYPE}")) {
#  if ($args[2] eq InternalVal($dev,"RPI_pin","")) {
#    return "GPIO $args[2] already used by $dev";
#  }
#}

my $name = $args[0];
$hash->{Host} = $args[2];
$hash->{Port} = $args[3];
NetzerUtils_conn($hash);
# create default attributes
#my $msg = CommandAttr(undef, $name . ' direction input');
#return $msg if ($msg);

return undef;
}

sub NetzerUtils_Get($) {
  my ($hash) = @_;
  my $name = $hash->{NAME};
  #my $dir = $attr{$hash->{NAME}}{direction} || "output";
  my $dir = "";
  my $zustand = undef;
  #my $val = fileaccess($hash, "value");
  if ( defined ($val) ) {
    if ( $val == 1) {
      if ($dir eq "output") {$zustand = "on";} else {$zustand = "high";}
    } elsif ( $val == 0 ) {
      if ($dir eq "output") {$zustand = "off";} else {$zustand = "low";}
    }   
  } else {
    Log 1, "$hash->{NAME} GetFn: readout of Pinvalue fail";
  }
  $hash->{READINGS}{Pinlevel}{VAL} = $zustand;
  $hash->{READINGS}{Pinlevel}{TIME} = TimeNow();
  return "Current Value for $name: $zustand";
}

sub NetzerUtils_Set($@) {
  my ($hash, @a) = @_;
  my $name =$a[0];
  my $cmd = $a[1];
  #my $val = $a[2];
 
  if(defined($attr{$name}) && defined($attr{$name}{"direction"})) {
      my $mt = $attr{$name}{"direction"};
      if($mt && $mt eq "output") {
       if(!defined($setsoutp{$cmd})) { #prüfe ob Kommando in Liste
         my $slist = join(' ', keys %setsoutp);
         #return 'Unknown argument ' . $cmd . ', choose one of ' . join(' ', keys %setsoutp)
         return SetExtensions($hash, $slist, @a);
         } else {
             if ($cmd eq 'on') {
                #fileaccess($hash, "value", "1");
                #$hash->{STATE} = 'on';
                my $buf = "m=1\r\n";
                my $cnt= length ($buf);
                syswrite($hash->{CD}, $buf, $cnt);
             }  else {
                my $buf = "m=0\r\n";
                my $cnt= length ($buf);
                syswrite($hash->{CD}, $buf, $cnt);
                #fileaccess($hash, "value", "0");
                #$hash->{STATE} = 'off';
             }           
         }
      } else {
       if(!defined($setsinpt{$cmd})) {
        return 'Unknown argument ' . $cmd . ', choose one of ' . join(' ', keys %setsinpt)
       } else {
       
       }
      }     
  }
 
  if ($cmd eq 'readValue') {
      updatevalue($hash); 
    }
}

sub NetzerUtils_Attr(@) {
my (undef, $name, $attr, $val) = @_;
my $hash = $defs{$name};
my $msg = '';

if ($attr eq 'direction') {
   if (!$val) { #$val nicht definiert: Einstellungen löschen
       $msg = "$hash->{NAME}: no direction value. Use input output";
   } elsif ($val eq "input") {
       fileaccess($hash, "direction", "in");
       #Log 1, "$hash->{NAME}: direction: input";
   } elsif( ( AttrVal($hash->{NAME}, "interrupt", "none") ) ne ( "none" ) ) {
       $msg = "$hash->{NAME}: Delete attribute interrupt or set it to none for output direction";
   } elsif ($val eq "output") {
       fileaccess($hash, "direction", "out");
       #Log 1, "$hash->{NAME}: direction: output";
   } else {
       $msg = "$hash->{NAME}: Wrong direction value. Use input output";
   }
}
return ($msg) ? $msg : undef;
}

sub NetzerUtils_Read($) {
  Log 1, "Read gestartet";
  my ($hash) = @_;
  my $name = $hash->{NAME};
  my $buf;
  my $ret = sysread($hash->{CD}, $buf, 1024*1024);
  if(!defined($ret) || $ret <= 0) {
     NetzerUtils_conn($hash);
     return;
  } else {

     readingsBeginUpdate($hash);
     readingsBulkUpdate($hash, 'zeichenmenge', $ret);
     #for ( $i = 1; $i <= 5; $i++) {
     #}
     readingsBulkUpdate($hash, 'inhalt', $buf);
     readingsEndUpdate($hash, 1);
  }
}

sub NetzerUtils_Undef($$) {
  my ($hash, $arg) = @_;
  if ( defined (AttrVal($hash->{NAME}, "poll_interval", undef)) ) {
    RemoveInternalTimer($hash);
  }
  NetzerUtils_disconn($hash,0);
  return undef;
}

sub NetzerUtils_conn($) {
  my ($hash) = @_;
  my $name   = $hash->{NAME};

  NetzerUtils_disconn($hash,0);

  my $conn = IO::Socket::INET->new(PeerAddr=>"$hash->{Host}:$hash->{Port}");

  if($conn) {
    $hash->{STATE} = "Connected";

    $hash->{FD}    = $conn->fileno();
    $hash->{CD}    = $conn;         # sysread / close won't work on fileno
    $hash->{CONNECTS}++;
    $selectlist{$name} = $hash;
    Log(GetLogLevel($name,3), "$name: updater connected to $hash->{Host}:$hash->{Port}");

    #iTunes_requestUpdate($hash);

  } else {
    NetzerUtils_disconn($hash, 1);
  }
}

sub NetzerUtils_disconn($$) {
  my ($hash, $connect) = @_;
  my $name   = $hash->{NAME};

  return if( !$hash->{CD} );

  close($hash->{CD}) if($hash->{CD});
  delete($hash->{FD});
  delete($hash->{CD});
  delete($selectlist{$name});
  $hash->{STATE} = "Disconnected";
  if($connect) {
    Log3 $name, 4, "$name: updater Connect failed.";
  } else {
    Log3 $name, 4, "$name: updater Disconnected";
  }
}

1;


bei der "if($conn)" Schleife springe ich nach else, da eine Verbindung nicht zustande gekommen ist, richtig?
Dort gehts dann ins sub "NetzerUtils_disconn"
Der wiederum wird verlassen, da "$hash->{CD}" nicht definiert ist.
Aber dann bin ich doch durch. Ich erkenne keine Schleife.

Grüße
Klaus
RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280

justme1968

prüf mal nach dem erzeugen des sockets noch ob es auch verbunden ist. das geht mit $conn->connected.

es kann sein das das socket zwar angelegt wird aber trotzdem die verbindung nicht funktioniert. dadurch landest du dann im read obwohl keine daten da sind. da wird dann die verbindung neu aufgebaut und das ist deine schleife.

ach ja noch was: leg deine readings mit readingsSingleUpdate oder readingsBeginUpdate/readingsBulkUpdate/readingsEndUpdate und nicht direkt selber in den hash.

gruss
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

klausw

ja das mit den readings ist alter kram der noch wegkommt

juhu ich habs:
ein timeout wirkt wunder :)
  my $timeout = $hash->{TIMEOUT} ? $hash->{TIMEOUT} : 3;
  my $conn = IO::Socket::INET->new(PeerAddr=>"$hash->{Host}:$hash->{Port}", Timeout => $timeout);


und schon gehts

$conn->connected ist nicht notwendig da im fehlerfall $conn nicht definiert
RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280

klausw

Zitat von: justme1968 am 16 Dezember 2013, 22:15:02
wenn du so weit bist das du lesen und schreiben kannst schau dir mal readingsProxy an damit kannst du ein device das alle ports kombiniert hat auf mehrere fhem devices aufsplitten die dann getrennt in fhem darstellbar sind. also mit eigenen icon, eigenen webCmd, ....

in dem thread hier: http://forum.fhem.de/index.php/topic,16374.msg109816.html#msg109816 findest du weiter unten ein paar beispiele.

gruss
  andre

Das funktioniert super. Mit nur 2 Zeilen (define und attr valueFn) pro Kanal habe ich ein separates Device erzeugt.
Danke für den Tip :)
RasPi B v2 mit FHEM 18B20 über 1Wire, LED PWM Treiber über I2C, Luchtdruck-, Feuchtesensor und ein paar Schalter/LED\'s zum testen
Module: RPI_GPIO, RPII2C, I2C_EEPROM, I2C_MCP23008, I2C_MCP23017, I2C_MCP342x, I2C_PCA9532, I2C_PCF8574, I2C_SHT21, I2C_BME280