FHEM Forum

FHEM => Sonstiges => Thema gestartet von: ujaudio am 28 Dezember 2017, 07:39:09

Titel: Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 28 Dezember 2017, 07:39:09
Hallo zusammen,
vielleicht schaffe ich es auf diesem Weg eine Starthilfe zu bekommen. Ich habe ein externes Gerät, welches über Ethernet steuerbar ist. Mit Hilfe von Wireshark und anderer Software gelingt es mir auch, die Kommandos und die entsprechenden Antworten aufzuzeichnen. Aber wie setze ich das dann in FHEM um?
Beispiel:
An eine IP-Adresse und Port muss eine bestimmte ASCII/HEX-Sequenz mit TCP geschickt werden. Zurück kommt dann eine andere ASCII/HEX-Sequenz als Quittung. Wie setze ich das nun mit FHEM (ggf. auch in 99_MyUtils in perl) um?
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: fiedel am 28 Dezember 2017, 10:15:39
Ganz einfach:  ;D
Du liest dich in das Modul ECMD ein, welches genau dafür gemacht ist. Schwierig ist dabei das Erstellen der "classdef", einer Textdatei, die in Form von Regex alle möglichen Befehle und Rückmeldungen deines Gerätes enthalten soll. Es gibt aber viele Beispiele in WIKI und Forum.
Ich drücke mich auch schon eine ganze Weile davor...  ;)

Gruß
Frank
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 28 Dezember 2017, 10:57:56
Zitat von: ujaudio am 28 Dezember 2017, 07:39:09
Hallo zusammen,
vielleicht schaffe ich es auf diesem Weg eine Starthilfe zu bekommen. Ich habe ein externes Gerät, welches über Ethernet steuerbar ist. Mit Hilfe von Wireshark und anderer Software gelingt es mir auch, die Kommandos und die entsprechenden Antworten aufzuzeichnen. Aber wie setze ich das dann in FHEM um?
Beispiel:
An eine IP-Adresse und Port muss eine bestimmte ASCII/HEX-Sequenz mit TCP geschickt werden. Zurück kommt dann eine andere ASCII/HEX-Sequenz als Quittung. Wie setze ich das nun mit FHEM (ggf. auch in 99_MyUtils in perl) um?

Werde mal bitte etwas konkreter was das Device an geht. Worum geht es da genau?
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 28 Dezember 2017, 11:30:59
Zitat von: fiedel am 28 Dezember 2017, 10:15:39
Ganz einfach:  ;D
Du liest dich in das Modul ECMD ein, welches genau dafür gemacht ist. Schwierig ist dabei das Erstellen der "classdef", einer Textdatei, die in Form von Regex alle möglichen Befehle und Rückmeldungen deines Gerätes enthalten soll. Es gibt aber viele Beispiele in WIKI und Forum.
Ich drücke mich auch schon eine ganze Weile davor...  ;)

Gruß
Frank

Hall Frank, danke  für den Hinweis auf ECMD - hatte ich vorher noch nie auf dem Radar. Im Wiki https://wiki.fhem.de/wiki/ECMD (https://wiki.fhem.de/wiki/ECMD) steht dazu zwar erst einmal nichts wirklich Brauchbares (der Zweizeiler hilft mir gar nicht :)), aber die Forumssuche wird mir helfen. In der commandref https://fhem.de/commandref.html#ECMD (https://fhem.de/commandref.html#ECMD) steht aber schon einiges.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 28 Dezember 2017, 11:40:39
Zitat von: CoolTux am 28 Dezember 2017, 10:57:56
Werde mal bitte etwas konkreter was das Device an geht. Worum geht es da genau?

Es geht mir noch immer um das Steuern des Oppo 10x/20x. Es gibt da einige andere, die daran Interesse haben - mich natürlich eingeschlossen.
<unwichtig>
Durch meine private und berufliche Situation komme ich leider nicht sehr intensiv dazu, seit mindestens 2015 beschäftigt mich das Thema. Immerhin kann ich jetzt mal bis 7.1.2018 einigermaßen dran belieben, danach bin ich wieder weit weg vom Haus und einen Geräten. Andererseits freut es mich, dass es noch kein fertiges Modul "71_Oppo" gibt, denn ich habe schon einiges dazu gelernt. Oft sind es nur ein paar Hinweise, damit man z.B. mit den richtigen Suchbegriffen arbeitet.
</unwichtig>
Gestern hatte ich zum ersten Mal das Erfolgserlebnis, dass mein PC mit dem Oppo kommunizierte, nun werde ich mich daran machen, dass auch vom Raspberry mit FHEM mit dem Oppo kommuniziert werden kann. Ob nur mit FHEM-Bordmitteln oder in perl programmiert - da bin ich noch offen, erst muss ich mal die Kommunikation verstehen und zum Laufen bringen.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 28 Dezember 2017, 11:53:51
Du könntest im Zuge eines Modules eine TCP Socketverbindung aufbauen und in die FHEM selectlist geben. Liegen Informationen am Socket an wird automatisch die ReadFn aufgerufen. Wenn du dir das mit Perl und FHEM zu traust kann ich dir hier und da helfen.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 28 Dezember 2017, 13:38:45
Wenn ich ein Modul schreibe, welches über Ethernet kommunizieren soll, dann muss mein Code wohl so anfangen:

package main;

use strict;
use warnings;

use IO::Handle;
use IO::Socket;
use IO::Select;

# usw.


Das define stelle ich mir so vor:

sub
Oppo_Define($$) # das erste $ steht für den immer notwendigen Hash
                # das zweite $ steht für meine Parameter beim Define
                # 1. Parameter: Name des Device, z.B. MeinOppo
                # 2. Parameter: Typ des Oppo, z.B. 105D
                # 3. Parameter: IP-Adresse des Oppo, z.B. 192.158.178.123
                # 4. Parameter: Port des Oppo, z.B. 48360
                # Die Parameter sind später von 0 bis 3 indexiert
{
  my ($hash, $def) = @_;
  my @a = split("[ \t][ \t]*", $def);  # Zerlegen der Parameter in ein Array
  my $name = $a[0];

  return "wrong syntax: define <name> Oppo <type> <ip> <port>" if(@a != 4);
 
  $hash->{NAME} = $a[0];
  $hash->{TYPE} = $a[1];
  $hash->{IP} = $a[2];
  $hash->{PORT} = $a[3];
  $hash->{PROTO} =  'tcp'; # Groß- oder Kleinschreibung? Ich habe beides schon gesehen.
  $hash->{SERVICE} = # ??!? Dazu habe ich noch nichts gefunden.
  $hash->{SLOT} =    # ??!? Dazu habe ich auch noch nichts gefunden.

  my $sock = IO::Socket::INET-> new (
    PeerPort => $hash->{PORT},
    PeerAddr => $hash->{IP},
    Timeout => 1,
    Blocking => 0,
    Proto => $hash->{PROTO}) or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
    # Service, Slot ??!?
  my $select = IO::Select->new($sock); # Das habe ich nur blind kopiert, aber noch nicht verstanden!

# usw.
}


Eigentlich schickt der Oppo ein Broadcast mit IP und Port und erwartet möglicherweise dazu noch eine Antwort per UDP, bevor er wirklich bereit ist zu kommunizieren. Für mich sind da noch jede Menge Hürden.
OPPO schreibt in Doku, dass der OPPO der Server ist und das andere Gerät (also FHEM) der Client. Und weiter heißt es da:
ZitatOnce the Server is running, it will automatically broadcast the message every 10 seconds to notify any interested Client about its availability, as well as the IP address and the port number which are required to establish the TCP connection. The Client needs to receive this broadcasting message, extract the IP address and port number, and establish the connection with the Server. Once the connection is done, the Client should also discard any future broadcasting messages.
Dieses "establish the connection with the Server" macht mir noch Kopfzerbrechen, aber ich werde ich da schon durchbeißen.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 28 Dezember 2017, 14:40:47
Versuche es mal damit. Bitte vorsichtig mit habe es nur kurz zwischen meinen Mittagsschlaf geschrieben. Nach dem define mit
define name Oppo host port
kannst ein set connect machen und er sollte sich mit dem Oppo verbinden.
Danach kannst über set command HEX ihm Daten senden und es sollten daten zurückkommen die du im fhem log sehen solltest

Grüße


package main;

use strict;
use warnings;


use IO::Socket::INET;






my $version = "0.0.1";





# Declare functions
sub Oppo_Initialize($);
sub Oppo_Define($$);
sub Oppo_Undef($$);
sub Oppo_Set($@);
sub Oppo_Open($);
sub Oppo_Close($);
sub Oppo_Read($);
sub Oppo_Write($@);
sub Oppo_Attr(@);




sub Oppo_Initialize($) {

    my ($hash) = @_;
   
    # Provider
    $hash->{ReadFn}     = "Oppo_Read";
    $hash->{WriteFn}    = "Oppo_Write";


    # Consumer
    $hash->{SetFn}      = "Oppo_Set";
    $hash->{DefFn}      = "Oppo_Define";
    $hash->{UndefFn}    = "Oppo_Undef";
    $hash->{AttrFn}     = "Oppo_Attr";
    $hash->{AttrList}   = $readingFnAttributes;


    foreach my $d(sort keys %{$modules{Oppo}{defptr}}) {
        my $hash = $modules{Oppo}{defptr}{$d};
        $hash->{VERSION} = $version;
    }
}

sub Oppo_Define($$) {

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

    return "too few parameters: define <name> Oppo <HOST> <PORT>" if( @a != 4 );
   


    my $name                                        = $a[0];
    my $host                                        = $a[2];
    my $port                                        = $a[3];

    $hash->{HOST}                                   = $host;
    $hash->{PORT}                                   = $port;
    $hash->{VERSION}                                = $version;


    Log3 $name, 3, "Oppo ($name) - defined with host $host";

    $attr{$name}{room} = 'Oppo' if( !defined( $attr{$name}{room} ) );
   
   
    $modules{Oppo}{defptr}{$hash->{HOST}} = $hash;
   
    return undef;
}

sub Oppo_Undef($$) {

    my ( $hash, $arg ) = @_;
   
    my $host = $hash->{HOST};
    my $name = $hash->{NAME};
   
   
    RemoveInternalTimer($hash);
   
    Oppo_Close($hash);
    delete $modules{Oppo}{defptr}{$hash->{HOST}};
   
    Log3 $name, 3, "Oppo ($name) - device $name deleted";
   
    return undef;
}

sub Oppo_Attr(@) {

    my ( $cmd, $name, $attrName, $attrVal ) = @_;
    my $hash = $defs{$name};
   
    my $orig = $attrVal;

   
    if( $attrName eq "disable" ) {
        if( $cmd eq "set" and $attrVal eq "1" ) {
            readingsSingleUpdate ( $hash, "state", "disabled", 1 );
            Log3 $name, 3, "Oppo ($name) - disabled";
        }

        elsif( $cmd eq "del" ) {
            readingsSingleUpdate ( $hash, "state", "active", 1 );
            Log3 $name, 3, "Oppo ($name) - enabled";
        }
    }
   
    if( $attrName eq "disabledForIntervals" ) {
        if( $cmd eq "set" ) {
            Log3 $name, 3, "Oppo ($name) - enable disabledForIntervals";
            readingsSingleUpdate ( $hash, "state", "Unknown", 1 );
        }

        elsif( $cmd eq "del" ) {
            readingsSingleUpdate ( $hash, "state", "active", 1 );
            Log3 $name, 3, "Oppo ($name) - delete disabledForIntervals";
        }
    }

    return undef;
}



sub Oppo_Set($@) {

    my ($hash, $name, $cmd, @args) = @_;
    my ($arg, @params)  = @args;

   
   
   
    if($cmd eq 'connect') {
        return "usage: connect" if( @args != 0 );

        Oppo_Open($hash);

        return undef;
       
    } elsif($cmd eq 'disconnect') {
        return "usage: disconnect" if( @args != 0 );

        Oppo_Close($hash);
       
        return undef;
       
    } elsif($cmd eq 'command') {
        return "usage: command <message>" if( @args < 1 );

        my $cmd = join(" ", @args);

    } else {
        my $list .= "connect:noArg disconnect:noArg command";
        return "Unknown argument $cmd, choose one of $list";
    }
   
    LGTV_WebOS_CreateSendCommand($hash,$cmd);
}

sub Oppo_Open($) {

    my $hash    = shift;
    my $name    = $hash->{NAME};
    my $host    = $hash->{HOST};
    my $port    = $hash->{PORT};
    my $timeout = 0.1;
   
   
    Log3 $name, 4, "Oppo ($name) - Baue Socket Verbindung auf";
   

    my $socket = new IO::Socket::INET   (   PeerHost => $host,
                                            PeerPort => $port,
                                            Proto => 'tcp',
                                            Timeout => $timeout
                                        )
        or return Log3 $name, 4, "Oppo ($name) Couldn't connect to $host:$port";      # open Socket
       
    $hash->{FD}    = $socket->fileno();
    $hash->{CD}    = $socket;         # sysread / close won't work on fileno
    $selectlist{$name} = $hash;
   
    Log3 $name, 4, "Oppo ($name) - Socket Connected";
   
    Oppo_Handshake($hash);
    Log3 $name, 4, "Oppo ($name) - start Handshake";
   
}

sub Oppo_Close($) {

    my $hash    = shift;
    my $name    = $hash->{NAME};
   
    return if( !$hash->{CD} );

    close($hash->{CD}) if($hash->{CD});
    delete($hash->{FD});
    delete($hash->{CD});
    delete($selectlist{$name});
   
    readingsSingleUpdate($hash,'state','off',1);
   
    Log3 $name, 4, "Oppo ($name) - Socket Disconnected";
}

sub Oppo_Write($@) {

    my ($hash,$string)  = @_;
    my $name            = $hash->{NAME};
   
   
    Log3 $name, 4, "Oppo ($name) - WriteFn called";
   
    return Log3 $name, 4, "Oppo ($name) - socket not connected"
    unless($hash->{CD});

    Log3 $name, 4, "Oppo ($name) - $string";
    syswrite($hash->{CD}, $string);
    return undef;
}

sub Oppo_Read($) {

    my $hash = shift;
    my $name = $hash->{NAME};
   
    my $len;
    my $buf;
   
   
    Log3 $name, 4, "Oppo ($name) - ReadFn started";

    $len = sysread($hash->{CD},$buf,512);
   
    if( !defined($len) or !$len ) {

        Oppo_Close($hash);

        return;
    }
   
unless( defined $buf) {
        Log3 $name, 3, "Oppo ($name) - no data received";
        return;
    }
   
   
    Log3 $name, 3, "Oppo ($name) - received Data $buf";
}





1;


=pod
=item device
=item summary     
=item summary_DE   

=begin html

<a name="Oppo"></a>
<h3>Oppo</h3>



=end html

=begin html_DE

<a name="Oppo"></a>
<h3>Oppo</h3>

=end html_DE

=cut
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 28 Dezember 2017, 14:46:39
Hallo,

ich werde mich damit die nächsten Tage beschäftigen und mich auch hier wieder dazu melden. Vorab sage ich aber erst einmal vielen Dank für die Unterstützung. Ich werde Zeile für Zeile durcharbeiten und versuchen alles zu verstehen.

Einen lieben Gruß
Jürgen
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 29 Dezember 2017, 08:28:29
Ich versuche nun wirklich Schritt für Schritt zu verstehen, was ich tue. Nachdem mir CoolTux eine Steilvorlage gegeben hat, muss ich mich da ganz schön anstrengen. Ziel ist ein ordentliches Modul zu bekommen.
Zuerst also mal definieren:
sub Oppo_Define($$) {
# Das erste $ steht für den immer notwendigen Hash.
# Das zweite $ steht für die Parameter beim Define.
# 1. Parameter: Name des Device, z.B. MeinOppo
# 2. Parameter: Typ des Oppo, z.B. 105D
# 3. Parameter: IP-Adresse des Oppo, z.B. 123.456.789.123
# 4. Parameter: Port des Oppo, z.B. 48360

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

  return "wrong syntax: define <name> Oppo <type> <ip-adress> <port>" if (@a != 5);
  return "currently only model 105D supported" if ($a[2] ne "105D");
# Da ich nur mein Model 105D testen kann, wird die erste Version darauf
# beschränkt sein. Bei Zuliefeung entsprechender Informationen, kann ich ggf.
# weitere Modelle implementieren.

  my $name         = $a[0];
# $a[1] ist der Modulname Oppo
  my $type         = $a[2];
  my $host         = $a[3];
  my $port         = $a[4];

  $hash->{NAME}    = $name;
  $hash->{TYPE}    = $type;
  $hash->{HOST}    = $host;
  $hash->{PORT}    = $port;
  $hash->{VERSION} = $version;

  Log3 $name, 3, "Oppo ($name) model $type - defined with ip $host at port $port";

  $attr{$name}{room} = 'Multimedia' if( !defined( $attr{$name}{room} ) );

  [b]$modules{Oppo}{defptr}{$hash->{HOST}} = $hash;[/b]
# Die Definition erfolgt unabhängig davon, ob zu diesem Zeitpunkt die
# Kommunikation mit dem Gerät möglich ist oder nicht.

  return undef;
}

Hier ist mir nicht klar, wozu diese Zeile "$modules{Oppo}{defptr}{$hash->{HOST}} = $hash;" notwendig ist. Aber immerhin: das Device wird angelegt, bei falscher Syntax kommt eine Rückmeldung und es wird nichts angelegt.

Bevor ich mich nun an die Funktionen mache, will ich mal sehen, ob ich das auch wieder löschen kann. Im Wiki https://wiki.fhem.de/wiki/DevelopmentModuleIntro#Einleitung (https://wiki.fhem.de/wiki/DevelopmentModuleIntro#Einleitung) steht, dass  man ein Undef und ein Delete haben muss. Ich habe also beide implementiert:
sub Oppo_Undef($$) {

  my ($hash, $arg) = @_;
  my $host = $hash->{HOST};
  my $name = $hash->{NAME};

  RemoveInternalTimer($hash);

  Oppo_Close($hash);
  delete $modules{Oppo}{defptr}{$hash->{HOST}};

  Log3 $name, 3, "Oppo ($name) - device undefined";

  return undef;
}

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

sub Oppo_Delete($$) {

  my ($hash, $arg) = @_;
  my $host = $hash->{HOST};
  my $name = $hash->{NAME};

# Aktuell nichts zu tun

  Log3 $name, 3, "Oppo ($name) - device deleted";

  return undef;
}

Das Device wird auch entfernt, aber ich bekomme keinen Eintrag im Logfile. Beim Definieren erscheint der zugehörige Eintrag...
2017.12.24 08:08:14 3: Oppo (oppo105) model 105D - defined with ip 192.168.178.39 at port 48360
...aber nicht beim Löschen. Das kann ich mir nicht erklären.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 29 Dezember 2017, 09:30:33
Zitat von: ujaudio am 29 Dezember 2017, 08:28:29
Ich versuche nun wirklich Schritt für Schritt zu verstehen, was ich tue. Nachdem mir CoolTux eine Steilvorlage gegeben hat, muss ich mich da ganz schön anstrengen. Ziel ist ein ordentliches Modul zu bekommen.
Zuerst also mal definieren:
sub Oppo_Define($$) {
# Das erste $ steht für den immer notwendigen Hash.
# Das zweite $ steht für die Parameter beim Define.
# 1. Parameter: Name des Device, z.B. MeinOppo
# 2. Parameter: Typ des Oppo, z.B. 105D
# 3. Parameter: IP-Adresse des Oppo, z.B. 123.456.789.123
# 4. Parameter: Port des Oppo, z.B. 48360

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

  return "wrong syntax: define <name> Oppo <type> <ip-adress> <port>" if (@a != 5);
  return "currently only model 105D supported" if ($a[2] ne "105D");
# Da ich nur mein Model 105D testen kann, wird die erste Version darauf
# beschränkt sein. Bei Zuliefeung entsprechender Informationen, kann ich ggf.
# weitere Modelle implementieren.

  my $name         = $a[0];
# $a[1] ist der Modulname Oppo
  my $type         = $a[2];
  my $host         = $a[3];
  my $port         = $a[4];

  $hash->{NAME}    = $name;
  $hash->{TYPE}    = $type;
  $hash->{HOST}    = $host;
  $hash->{PORT}    = $port;
  $hash->{VERSION} = $version;

  Log3 $name, 3, "Oppo ($name) model $type - defined with ip $host at port $port";

  $attr{$name}{room} = 'Multimedia' if( !defined( $attr{$name}{room} ) );

  [b]$modules{Oppo}{defptr}{$hash->{HOST}} = $hash;[/b]
# Die Definition erfolgt unabhängig davon, ob zu diesem Zeitpunkt die
# Kommunikation mit dem Gerät möglich ist oder nicht.

  return undef;
}

Hier ist mir nicht klar, wozu diese Zeile "$modules{Oppo}{defptr}{$hash->{HOST}} = $hash;" notwendig ist. Aber immerhin: das Device wird angelegt, bei falscher Syntax kommt eine Rückmeldung und es wird nichts angelegt.

Bevor ich mich nun an die Funktionen mache, will ich mal sehen, ob ich das auch wieder löschen kann. Im Wiki https://wiki.fhem.de/wiki/DevelopmentModuleIntro#Einleitung (https://wiki.fhem.de/wiki/DevelopmentModuleIntro#Einleitung) steht, dass  man ein Undef und ein Delete haben muss. Ich habe also beide implementiert:
sub Oppo_Undef($$) {

  my ($hash, $arg) = @_;
  my $host = $hash->{HOST};
  my $name = $hash->{NAME};

  RemoveInternalTimer($hash);

  Oppo_Close($hash);
  delete $modules{Oppo}{defptr}{$hash->{HOST}};

  Log3 $name, 3, "Oppo ($name) - device undefined";

  return undef;
}

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

sub Oppo_Delete($$) {

  my ($hash, $arg) = @_;
  my $host = $hash->{HOST};
  my $name = $hash->{NAME};

# Aktuell nichts zu tun

  Log3 $name, 3, "Oppo ($name) - device deleted";

  return undef;
}

Das Device wird auch entfernt, aber ich bekomme keinen Eintrag im Logfile. Beim Definieren erscheint der zugehörige Eintrag...
2017.12.24 08:08:14 3: Oppo (oppo105) model 105D - defined with ip 192.168.178.39 at port 48360
...aber nicht beim Löschen. Das kann ich mir nicht erklären.
$modules{Oppo}{defptr}{$hash->{HOST}} = $hash;
Diesen Eintrag benötigt man um das Device ein eindeutig zu identifizieren
Aus dem Developer Wiki:
Zitat
Üblicherweise enthält eine Nachricht immer eine Komponente durch welche sich die Nachricht einem Gerät zuordnen lässt (z.B. Adresse, ID-Nummer, ...). Eine solche Identifikation sollte man im Rahmen der Define-Funktion im logischen Modul an geeigneter Stelle speichern, um in der Parse-Funktion eine einfache Zuordnung von Adresse/ID einer Nachricht zur entsprechenden Gerätedefinition zu haben. Dazu wird in der Regel im Modul-Hash im modulspezifischen Berreich eine Liste defptr (Definition Pointer) geführt, welche jede eindeutige Adresse/ID dem entsprechenden Geräte-Hash zuordnet:

Eine Delete Funktion habe ich noch nie benötigt. Es ist ausreichend eine Undef zu haben. Du löschst ja schon darin alle das Device, alle Timer und das entsprechende defptr

Dennoch sollte beim delete des Devices eigentlich die UndefFn aufgerufen werden. Zeig mal bitte Dein ganzes Modul.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 29 Dezember 2017, 13:10:31
Im Anhang das Modul (noch wage ich nicht von mein Modul zusprechen).
verbose ist bei global auf 5 gesetzt, die Meldung, dass ein neues Device definiert wurde, kommt wie programmiert, die analoge Meldung beim Löschen kommt nicht. Mehr als Define und Undef (und Delete) habe ich mir noch gar nicht angeschaut. Als nächstes werde ich Set einbauen müssen, damit ich mal das Kommando
set Mein105D connect
testen kann.

EDIT: erster Test liefert:
No set implemented for Mein105D

EDIT2: habe einen Fehler gefunden, bin am korrigieren - aber meine liebe Ehefrau benötigt mich die nächsten Stunden - bis später
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 29 Dezember 2017, 17:57:29
Aktueller Stand:
Jetzt möchte ich mich mit meinem Gerät verbinden:
set Mein105D connect
Dann bekomme ich sofort im Browser meines PC, dass die Seite nicht erreichbar ist. Via Ethernet sind alle Verbindungen zum Raspberry tot, auch meine ssh-Verbindung bricht zusammen. Also boote ich den Raspberry neu. Nun muss ich mal dem allerletzten Logeintrag nachgehen, der da lautet:
Undefined subroutine &main::Oppo_Handshake called at ./FHEM/71_Oppo.pm line 219.
Soweit hatte ich mich im Code noch gar nicht vorangetastet  :) Jetzt wird's also Zeit...

Falls jemand Interesse hat, nachfolgend noch ein Auszug aus meiner Logdatei.

EDIT:
die Routine Oppo_Handshake gibt es nicht und führt zu dem Absturz.
Das gleiche gilt auch für die Routine LGTV_WebOS_CreateSendCommand - auch hier bekomme ich das gleiche Verhalten  (Absturz).

EDIT2: Ich bin auf der Spur, den Fehler zu beheben  :)
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 30 Dezember 2017, 11:52:35
Mittlerweile habe ich den kompletten Basiscode von CoolTux aus dem Internet gefischt  ;)

Und dann mal "mein" Modul auf das wesentliche abgestrippt, aktuell laufen die Kommandos connect und disconnect in FHEM fehlerfrei durch. Ich habe mal den Oppo eingeschaltet gehabt und ein zweites Mal ausgeschaltet. Dazu im Anhang die beiden Logfiles. Der Inhalt sagt mir recht wenig, vielleicht kann da mal ein Wissender hinschauen, ob es da etwas zu beachten gibt, was ich gar nicht erkenne. Meine Vermutung:

Ob der Oppo dann wirklich Befehle entgegen nimmt - nächster Entwicklungsschritt. Dabei bin ich immer für weitere Tipps dankbar...

EDIT: was mir noch aufgefallen ist:
was passiret eigentlich , wenn man mehrere Mal connected und nicht disconnected?
Bei connect kommt ein internal FD = <numerischer Wert> dazu, bei jedem connect ein anderer. bei disconnect wird der FD wieder entfernt
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 30 Dezember 2017, 12:37:50
So kannst Du ja beim besten willen nichts sehen.
Erstmal reicht es völlig wenn Du bei dem angelegten Device das Attribut verbose 5 machst. Bei Global siehst Du ja nun wirklich nichts.


Wenn Dein Oppo aus ist, kannst Du dann noch ein normalen Ping auf die IP absetzen der beantwortet wird? Wenn die Socketverbindung nicht zu stande kommt, sollte eigentlich eine Fehlermeldung kommen

or return Log3 $name, 4, "Oppo ($name) Couldn't connect to $host:$port"; # open Socket


Hier kannst Du die 4 mal auf 3 setzen. Du kannst generell wo es nötig ist das Loglevel auf 3 setzen wo es noch nicht so ist, dann solltest Du auch mehr sehen wenn Du entweder das globale loglevel generell auf 3 hast oder du einfach das device loglevel auf 3 oder gar höher setzt.

Was passiert eigentlich wenn du nach einem connect einfach mal ein set command ab setzt. Du hast ja gesagt Du weißt wie das Datagramm aussehen muss was Du senden willst. Dann mach einfahc mal set command DATAGRAM
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 30 Dezember 2017, 13:15:24
Oppo eingeschaltet:
pi@raspberrypi:/opt/fhem/FHEM $ ping 192.168.178.39
PING 192.168.178.39 (192.168.178.39) 56(84) bytes of data.
64 bytes from 192.168.178.39: icmp_seq=1 ttl=64 time=0.476 ms
64 bytes from 192.168.178.39: icmp_seq=2 ttl=64 time=0.372 ms
64 bytes from 192.168.178.39: icmp_seq=3 ttl=64 time=0.371 ms
64 bytes from 192.168.178.39: icmp_seq=4 ttl=64 time=0.368 ms
64 bytes from 192.168.178.39: icmp_seq=5 ttl=64 time=0.378 ms
64 bytes from 192.168.178.39: icmp_seq=6 ttl=64 time=0.383 ms
64 bytes from 192.168.178.39: icmp_seq=7 ttl=64 time=0.381 ms
^C
--- 192.168.178.39 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 5994ms
rtt min/avg/max/mdev = 0.368/0.389/0.476/0.043 ms

2017.12.25 13:00:19 4: Oppo (oppo105) - Baue Socket Verbindung auf
2017.12.25 13:00:19 4: Oppo (oppo105) - Socket Connected


Oppo ausgeschaltet:
pi@raspberrypi:/opt/fhem/FHEM $ ping 192.168.178.39
PING 192.168.178.39 (192.168.178.39) 56(84) bytes of data.
From 192.168.178.54 icmp_seq=9 Destination Host Unreachable
From 192.168.178.54 icmp_seq=10 Destination Host Unreachable
From 192.168.178.54 icmp_seq=11 Destination Host Unreachable
^C
--- 192.168.178.39 ping statistics ---
14 packets transmitted, 0 received, +3 errors, 100% packet loss, time 13005ms
pipe 3

2017.12.25 13:02:38 4: Oppo (oppo105) - Baue Socket Verbindung auf
2017.12.25 13:02:38 4: Oppo (oppo105) Couldn't connect to 192.168.178.39:48360


Passt soweit (danke auch für den Hinweis mit dem verbose!).

ZitatWas passiert eigentlich wenn du nach einem connect einfach mal ein set command ab setzt. Du hast ja gesagt Du weißt wie das Datagramm aussehen muss was Du senden willst. Dann mach einfach mal set command DATAGRAM
Sooo einfach ist das nicht, da müssen wohl noch ein paar Unterprogramme dazu, bevor das funktionieren kann  ;)
Außerdem möchte ich den Code nicht einfach kopieren sondern so gut wie möglich verstehen.
Aber das ist jetzt der nächste Schritt:
set command <DATAGRAMM> konkret: set command REMOTE EJT
das ist der einfachste Befehl, wo man sofort am Oppo sieht (und wenn es leise genug ist auch hört), dass die Schublade für die  CD/DVD/BR aufgeht, bzw. zugeht.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 30 Dezember 2017, 14:37:43
Wo ist definiert, dass es nur die 3 set-Möglichkeiten connect, disconnect und command gibt?

Hintergrund: ich wollte es ähnlich machen wie bei dem LGTV...
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 30 Dezember 2017, 15:06:22
In der SetFn Funktion
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 30 Dezember 2017, 15:14:23
Das einzige(!) vorkommen von setFN in der Datei ist
  $hash->{SetFn}      = "Oppo_Set";

??!?

Ich kann nirgendwo die 3 möglichen Kommandos finden, die zu dem Auswahlmenü im Browser führen.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: CoolTux am 30 Dezember 2017, 15:47:09
Es ist wie eine Zuweisung

a = b
$hash->{SetFn}      = "Oppo_Set";

Und? Welche. Wert hat nun $hash->{SetFn}
Diesen Wert suchst du in Deinem Modul. Kleiner Tip. Es muss eine Funktion sein.
Titel: Antw:Kommunikation FHEM - Ethernet - ext.Gerät
Beitrag von: ujaudio am 30 Dezember 2017, 16:19:08
Zitat von: CoolTux am 30 Dezember 2017, 15:47:09
Es ist wie eine Zuweisung

a = b
$hash->{SetFn}      = "Oppo_Set";

Und? Welche. Wert hat nun $hash->{SetFn}
Diesen Wert suchst du in Deinem Modul. Kleiner Tip. Es muss eine Funktion sein.

Natürlich habe ich in der Funktion Oppo_Set gesucht  :) Ich bin nur nicht auf die richtige Idee gekommen. Aufgrund deines Hinweises habe ich mir das nochmals Zeile für Zeile angeschaut, beim 2. Mal bin ich dann endlich auf $list gestoßen. Nun habe ich das zusätzliche gewünschte Kommando  :)

Einen lieben Gruß
Jürgen