[anscheinend gelöst] Frage zu Net::Telnet

Begonnen von andies, 16 Oktober 2017, 15:07:54

Vorheriges Thema - Nächstes Thema

andies

Ich bin dabei, ein Modul für vcontrold zu schreiben. Dabei muss ich via Telnet auf ein Gerät zugreifen, das mir dann die entsprechende Information bereitstellt. Da SYSMON auch telnet nutzt, habe ich mir dies angeschaut und versucht große Teile schlichtweg zu kopieren. An einer eigentlich selbstverständlichen Stelle schlägt das aber fehl. Weiß hier jemand weiter?

Die Verbindung sieht normalerweise so aus:
pi@heizung:~ $ telnet localhost 3002
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
vctrld>getTempA
17.700001 Grad
vctrld>quit
good bye!
Connection closed by foreign host.
pi@heizung:~ $


Ich baue die Verbindung in Perl so auf (alles etwas vereinfacht, ich habe die Attribut-Definitionen etc weggelassen):

   my $telnet = new Net::Telnet ( Host => "localhost", Port => "3002", Timeout=>"10", Errmode=>'return', Prompt=>'/vctrld>/', Dump_Log => '/opt/fhem/vcontrold.log');
  my @output = $telnet->print('getTempA');
  @output = $telnet->waitfor('Grad$/');

erhalte aber keine Rückmeldung?! Auch ein ändern der letzten beiden Zeilen in

  my @output = $telnet->cmd('getTempA');

oder in
  my @output = $telnet->print('getTempA');
  @output = $telnet->waitfor('vctrld>$/');

erbringt nichts. In beiden Fällen ist $output leer oder enthält bestenfalls eine 1?!
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

amenomade

In einem Scalar Kontext bedeutet 1 "Success".

In einem List Kontext bekommst Du in @output das Ergebnis vom cmd.
Aber für einen List Kontext kannst Du dann nicht $output nutzen. Eventuell dann $output[0]...aber...
Die Frage ist: wie nutzt Du dann die Ergebnisse?
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

CoolTux

Zitat
In a scalar context, the characters read from the remote side are discarded and 1 is returned on success. On time-out, eof, or other failures, the error mode action is performed. See errmode().

In a list context, just the output generated by the command is returned, one line per element. In other words, all the characters in between the echoed back command string and the prompt are returned. If the command happens to return no output, a list containing one element, the empty string is returned. This is so the list will indicate true in a boolean context. On time-out, eof, or other failures, the error mode action is performed. See errmode().

http://search.cpan.org/~jrogers/Net-Telnet-3.04/lib/Net/Telnet.pm
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

CoolTux

#3
Aber wenn Du eh ein Modul schreibst kannst Du es auch so machen


sub Modulname_Open($) {
   
    my $hash        = shift;
    my $name        = $hash->{NAME};
    my $host        = $hash->{HOST};
    my $port        = 3002;
    my $timeout     = 0.1;

   
    Log3 $name, 4, "Modulname ($name) - Build socket connection";

    my $socket = new Net::Telnet ( Host=>$host,
        Port => $port,
        Timeout=>$timeout,
        Errmode=>'return')
        or return Log3 $name, 3, "Modulname ($name) Couldn't connect to $host:$port";

    $hash->{FD}    = $socket->fileno();
    $hash->{CD}    = $socket;         # sysread / close won't work on fileno
    $selectlist{$name} = $hash;

    readingsSingleUpdate($hash, 'state', 'connected', 1 );
    Log3 $name, 4, "Modulname ($name) - Socket Connected";

Über ein set open einfach die Open Funktion aufrufen und die Verbindung herstellen lassen. Dann das Device in die select Liste der FHEM Hauptschleife werfen


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

   
   
    $string    .= "\r\n";
    Log3 $name, 4, "Modulname ($name) - WriteFn called";
   
    return Log3 $name, 4, "Modulname ($name) - socket not connected"
    unless($hash->{CD});
   
    Log3 $name, 5, "Modulname ($name) - $string";
    syswrite($hash->{CD}, $string);
   
    return undef;
}

Die Funktion aufrufen um Befehle irgendwie an die Telnet Gegenstelle zu senden. Die Antwort wird dann von der FHEM Hauptshcleife abgeholt und an die Read Funktion aufgerufen


sub Modulname_Read($) {
   
    my $hash = shift;
    my $name = $hash->{NAME};
    my $len;
    my $buf;

   
    Log3 $name, 4, "Modulname ($name) - ReadFn gestartet";
    $len = sysread($hash->{CD},$buf,1024);
   
    if( !defined($len) || !$len ) {
   
        Log3 $name, 5, "Modulname ($name) - connection closed by remote Host";
        #Modulname_Close($hash);
        return;
    }
   
    unless( defined $buf) {
   
        Log3 $name, 3, "Modulname ($name) - no data received";
        return;
    }
   
    Log3 $name, 5, "Modulname ($name) - received buffer data, start HEOSMaster_ProcessRead: $buf";
    Modulname_ProcessRead($hash,$buf);
}


Hier kommt dann die Antwort an.

Bei Deiner Funktion wirst Du das Problem haben das sie FHEM blockiert denke ich, auch wenn ich nicht den ganzen Code kenne.



Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

andies

Sorry, das war in der Tat ein Schreibfehler. Ich habe schon alles probiert, also auch
    Log3 $name, 5,  "$name: output ".@output;

und erhalte aber jeweils leere Ausgaben.
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

andies

Zitat von: CoolTux am 16 Oktober 2017, 15:58:04
Aber wenn Du eh ein Modul schreibst kannst Du es auch so machen
Das kannte ich noch gar nicht (wie gesagt: Perlanfänger). Sehe ich das richtig, dass Du ein Terminal simulierst (fileno) und dann einfach in dieses Terminal schreibst (syswrite) und liest (sysread)? Was passiert, wenn die Gegenseite keine 1024 Bits/Bytes zurückgibt? Stockt dann FHEM? Ansonsten sieht das so aus wie das, was ich gern hätte - Danke!
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

CoolTux

Schau Dir mal im Wiki die Developer Guide Seiten an, dann schaust Du Dir die fhem.pl an. Das ist Deine Basis zum verstehen wie man FHEM Module entwickelt.

Hier mal etwas zu select und fileno
https://martin.sluka.de/perlws/2003/keine_Angst_vor_select


Versuch nicht an fhem.pl vorbei zu entwickeln, das gibt irgendwann nur Probleme. Versuch die Dinge zu verwenden welche FHEM den Entwicklern zur Verfügung stellt.   ;D
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

dev0

Man könte auch ganz auf Net::Telnet verzichten und es mit Hilfe der FHEM HttpUtils.pm lösen. Damit ist es mMn noch besser in FHEM integriert. Ich selbst bin aber noch nicht dazu gekommen es umzusetzen, ich verwende noch DevIo.pm für Telnet-Verbindungen zu meinen Geräten.
https://forum.fhem.de/index.php/topic,61970.msg674916.html#msg674916

andies

Ist es das hier: https://github.com/ddtlabs/fhem-getURL/blob/master/98_getURL.pm
Gibt es da eine Art Manual? Ich habe ja ein extrem einfaches Telnet (kein Login, kein passwort) und nur einfachste Kommandos (maximal zwei oder drei Worte) und kriege nur ein Wort zurück. Da reicht mir also sehr wenig (und ich verzweifle, wieso ich das nicht hinkriege).

Das hat übrigens alles noch nichts mit FHEM zu tun...
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

dev0

#9
ZitatGibt es da eine Art Manual?
Ja, den Quelltext.
EDIT: Die enthaltene command.ref beinhaltet bisher nur die http url parameter (wenn ich mich nicht irre, habe jetzt nicht nachgesehen).

ZitatDas hat übrigens alles noch nichts mit FHEM zu tun...
Na dann solltest auch Du auch in einem Perlforum fragen und nicht im FHEM Support Forum.

andies

ich glaube, ich habe mein Perl-Problem zumindest vorläufig gelöst. Es klappt alles mit

$telnet->print($vcontrolentry);  #write command to vcontrold
my $line = $telnet->getline();   #read from vcontrold, typical output vctrld>16.600000 Grad Celsius
my @results = split /[ >]/, $line; # split around > and empty_space

Entscheidend scheint zu sein, dass man die Rückmeldung nicht mit waitfor oder gar cmd, sondern getline abholt. Komisch, aber so klappt es.
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

andies

Ich muss noch einmal hier einhaken, weil ich auch gar nicht weiß, wo ich das sonst schreiben sollte (eigentlich gehört es mA nach in den Strang Anfängerprobleme, denn ich bin Anfänger - aber das wird dort niemand lesen). Also, ich habe das implementiert und festgestellt, dass es Probleme gibt. Das Problem besteht darin, dass FHEM/Telnet zwar das Kommando "Lies die Temperatur aus" sendet, aber die Antwort durch die Heizung (und die ist die Ursache der Probleme!) manchmal wenige Sekunden später eintrifft. Wenn nun noch zwischendurch "Lies Anzahl Brennerstarts" gesendet wurde, habe ich in meinen Readings "Brennerstarts = 17 Grad" oder so stehen. Das geht also nicht.

Zu Hause behelfe ich mir momentan mit folgender Lösung, die sehr wahrscheinlich den Grundsätzen von FHEM widerspricht:
unless ( ($line ne "") or (gettimeofday()>$this_timeout)){
$line = $telnet->getline();
}

Damit wird doch FHEM blockiert, oder?

Ich muss gestehen, dass ich die select-Lösung nicht wirklich durchdringe. Ich habe da so viele Frage, dass  ich mir das nicht zutraue. Aber wäre denn nicht eine etwas "einfachere" Lösung denkbar: Man führt sowohl senden als auch empfangen mit Viessmann/vcontrold nicht direkt aus, sondern sammelt die entsprechenden Kommandos in einer List (hash). Dann setzt man interne Timer, dass diese Liste schrittweise abgearbeitet wird. Alls X Sekunden wird dann beispielsweise gefragt: "Ergebnis da?" Und wenn nein, wird ein neuer Timer gesetzt, wenn ja, kommt das nächste Kommando an die Reihe. Oder ein Timeout greift und man löscht das Kommando aus der Liste. So würde ich das jetzt versuchen. 
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

CoolTux

Sobald eine Funktion wartend läuft, also nicht zeitnah durchlaufen wird (ms Bereich) ist sie blockierend.
Hast Du denn nun schon ein FHEM Modul gemacht?
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

andies

Ja, habe ich, steht hier: https://forum.fhem.de/index.php/topic,78101.0.html
Aber wie ich dort gerade geschrieben habe "die Sache wird schwieriger". Ich hatte mir nach dem Wochenende gedacht "Mensch war das einfach", von wegen...
FHEM 6.1 auf RaspPi3 (Raspbian:  6.1.21-v8+; Perl: v5.32.1)
SIGNALduino (433 MHz) und HM-UART (868 MHz), Sonoff, Blitzwolf, Somfy RTS, CAME-Gartentor, Volkszähler, Keyence-Sensor, Homematic-Sensoren und -thermostat, Ferraris-Zähler für Wasseruhr, Openlink-Nachbau Viessmann

CoolTux

Hast Du auch mal schauen können ob auch Daten kommen ohne das sie angefordert werden. Stichwort Events oder enableChangeEvents?

Wenn ich die Zeit finde schaue ich es mir mal an.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net