FHEM Forum

FHEM - Hardware => FRITZ!Box => Thema gestartet von: gibacht am 15 Dezember 2013, 14:45:34

Titel: Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 15 Dezember 2013, 14:45:34
Hallo,

Ich möchte den Status meiner Squeezeboxen abfragen. Gibt es irgendeine Möglichkeit die Antwort auf den gesendeten Telnet-Befehl (z.B. "mixer muting ?") in einer Variablen zu speichern?

sub SB_switch (@) {
   my ($typ,$eno,$ename) = @_;
        my ($id1) = "00:04:20:2c:59:f5";
        my ($ip) = "192.168.178.2";
        my ($port) = "9090";
        use Net::Telnet;
   my $telnet = new Net::Telnet ( Timeout=>15, Errmode=>'die', Port=>$port);
        $telnet->open($ip);
        if ($typ =~ m"mute"i) { # off or OFF
      my @lines = $telnet->cmd("mixer muting ?");  # Das hier bringt leider einen timeout
                Log 3, @lines;
                }
   $telnet->print('exit');

Leider habe ich nirgends ein Information / Antwort finden können und wäre für einen Tipp sehr dankbar!

Viele Grüße Dirk






Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 17:34:36
Zitat von: gibacht am 15 Dezember 2013, 14:45:34
Hallo,

Ich möchte den Status meiner Squeezeboxen abfragen. Gibt es irgendeine Möglichkeit die Antwort auf den gesendeten Telnet-Befehl (z.B. "mixer muting ?") in einer Variablen zu speichern?

sub SB_switch (@) {
   my ($typ,$eno,$ename) = @_;
        my ($id1) = "00:04:20:2c:59:f5";
        my ($ip) = "192.168.178.2";
        my ($port) = "9090";
        use Net::Telnet;
   my $telnet = new Net::Telnet ( Timeout=>15, Errmode=>'die', Port=>$port);
        $telnet->open($ip);
        if ($typ =~ m"mute"i) { # off or OFF
      my @lines = $telnet->cmd("mixer muting ?");  # Das hier bringt leider einen timeout
                Log 3, @lines;
                }
   $telnet->print('exit');

Leider habe ich nirgends ein Information / Antwort finden können und wäre für einen Tipp sehr dankbar!

Viele Grüße Dirk

Schade, dass ich noch keine Antwort erhalten habe. Woran liegt es?
Fehlen evtl. noch Details, oder geht das einfach nicht?
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: justme1968 am 16 Dezember 2013, 17:48:26
musst du dich auf der squeezebox wirklich nicht einloggen? oder könnte es sein das dein telnet darauf wartet weil der prompt nicht richtig gesetzt ist?

siehe Net::Telnet doku:
ZitatThe methods login() and cmd() use the prompt setting in the object to determine when a login or remote command is complete. Those methods will fail with a time-out if you don't set the prompt correctly.

gruss
  andre
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 18:42:41
Hallo Andre,
danke für Deine Rückmeldung.

Das käm eigentlich nur in Frage, wenn SSH aktiviert wäre. Das ist aber nicht der Fall.
Die Befehle werden von der Squeezebox angenommen und umgesetzt. (Z.B. "mixer muting 0"). Mein einziges Problem ist, dass ich die Antwort auf die Statusabfrage (z.B. "mixer muting ?") nicht in nicht in Fhem reinbekomme. Diese würde ich dann gerne u.a. zur Aktualisierung der Symbole im Webfrontend nutzen.

Wenn ich per Telnet auf der Squeezebox eingeloggt bin und "mixer muting ?" eingebe, antwortet diese z.B. so:
"00:04:20:2c:59:f6 mixer muting 1". Diesen String möchte ich in eine Variable speichern, um diese dann weiter bearbeiten / nutzen zu können.

Viele Grüße Dirk
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: justme1968 am 16 Dezember 2013, 18:56:32
wie schaut denn eine terminal session aus wenn du es von hand per telnet machst. gibt es wirklich keinen prompt am zeilenanfang?

ich glaube den braucht das Net::Telnet modul um zu erkennen wann die ausgabe des kommandos fertig ist.

wie gesagt: schau mal in die doku von Net::Telnet.

gruss
  andre
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 19:02:07
nein ein Prompt ("#") kommt nicht. Und die Dokus habe ich schon alle durch.
Eigentlich müsste die S-Box beim Einloggen per Telent doch dann auch den Login abfragen.
Das tut sie aber nicht.
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 19:05:32
Zitat von: gibacht am 16 Dezember 2013, 19:02:07
nein ein Prompt ("#") kommt nicht. Und die Dokus habe ich schon alle durch.
Eigentlich müsste die S-Box beim Einloggen per Telent doch dann auch den Login abfragen.
Das tut sie aber nicht.

Habe gerade noch einmal getestet und den Logeintrag kopiert:
SB_mute_Notify return value: command timed-out at ./FHEM/99_myUtils.pm
Hier steht auch kein Hinweis auf einen fehlenden Login, so wie ja in der Doku beschrieben ist.
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: justme1968 am 16 Dezember 2013, 19:08:56
wenn es keinen prompt gibt ist das vermutlich genau das problem. Net::Telnet braucht einen prompt um zu erkennen wann die ausgabe beendet ist. versuch mal den prompt auf \n also newline zu setzen.

ansonsten ist Net::Telnet vielleicht der falsche weg und IO::Socket::INET besser geeignet.

gruss
  andre
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 19:15:55
hmm, mit newline klapps auch nicht.
Du meinst ich sollte dann auf die xml/txt-Methode über http setzen.
Oje, und das für einen blutigen Anfänger..., über diesen Lösungsansatz bin ich auch schon gestolpert, habe ihn
aber dann wegen zu wenig Hintergrundwissen verworfen.



Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: justme1968 am 16 Dezember 2013, 19:22:45
nein. das hatte ich nicht gemeint. sondern direkt ein socket auf den telnet port aufmachen. dein kommando mit syswrite und die antwort direkt mit sysread lesen. oder mit send und recv.

wenn du im fehlerfall nicht blockieren willst ist es sinnvoll vor dem read mit select zu warten bis daten da sind und erst dann zu lesen. wenn die daten nach x sekunden nicht da sind kannst du dann abbrechen.

gruss
  andre
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 16 Dezember 2013, 19:27:21
ok, ich lese mal weiter. Vielen Dank erst einmal. Vielleicht hat ja jemand mitgelesen und hat eine Lösung, so dass ich das Rad nicht neu erfinden muß.

Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 22 Dezember 2013, 18:12:57
So, nachdem mir Andre eine andere Vorgensweise vorgschlagen hat, habe ich stundenlang gesucht und folgendes getestet.
Leider funktioniert der Verbindungsaufbau mit dem Squeezeserver nicht. Meldung: "illegal seek". Ich würde mich freuen wenn jemand einen Tipp hätte.

use CGI qw(:standard);
use IO::Socket;
use IO::Socket::INET;
use MIME::Base64;
use Time::HiRes qw(usleep nanosleep);

sub radio($)
{
  my ($socket,$client_socket);
  my $response ="";

  $socket = new IO::Socket::INET (
      PeerHost => '192.168.178.2',
      PeerPort => '9090',
                Proto => 'tcp',
  ) or die "ERROR in Socket Creation : $!\n";

  $socket->send('mixer muting ?');
  usleep(30000);
  $socket->recv($response, 2);
  if($response !~  m/OK/)
    {
    Log 1, "Error from radio ! Response from Radio : $response" ;
    }

  $socket->close();
  return;
}
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: justme1968 am 22 Dezember 2013, 18:25:03
schau dir mal das beispiel hier an: http://forum.fhem.de/index.php/topic,15928.msg116012.html#msg116012 (http://forum.fhem.de/index.php/topic,15928.msg116012.html#msg116012). vielleicht hilft dir das weiter. vor allem etwas weiter unten die version mit timout. du brauchst natürlich nicht eine readFn sondern kannst nach dem auf machen mit select auf die antwort warten und dann gleich zu machen.

gruss
  andre
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 22 Dezember 2013, 19:04:27
Danke für die Info, aber das Problem mit dem fehlerhaften connect löst der Thread auch nicht,
da der Verbindungsaufbau (per io::socket::inet) ist der gleiche ist.
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: erwin am 27 Dezember 2013, 22:20:08
Hi Gibacht,

bei mir schaut ein vergleichbares stück code so aus:

  ....
  # create a connecting socket
  my $socket = new IO::Socket::INET (
    PeerHost => $serverhost,
    PeerPort => $serverport,
    Proto => 'tcp',
  );
  unless ($socket) {
    return "cannot connect to the server $!\n"; #  unless $socket;
  }
  my $size = $socket->send($devname);
  # notify server that request has been sent
  shutdown($socket, 1);

  # receive a response of up to 1024 characters from server
  my $response = "";
  $socket->recv($response, 1024);

  $socket->close();
  return "$response";
  ....


PS: es könnt aber auch sein, dass dein Gerät ein \n oder \r am Schluß braucht....
l.g. erwin
Titel: Antw:Telnet - Prompt eines Geräts als String abfragen
Beitrag von: gibacht am 12 Januar 2014, 16:05:34
Vielen Dank. Es funktioniert....