Kommunikation FHEM - Ethernet - ext.Gerät

Begonnen von ujaudio, 28 Dezember 2017, 07:39:09

Vorheriges Thema - Nächstes Thema

ujaudio

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?
Einen lieben Gruß
Jürgen

fiedel

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
FeatureLevel: 6.1 auf Wyse N03D ; Deb. 11 ; Perl: v5.14.2 ; IO: HM-MOD-RPI-PCB + VCCU|CUL 868 V 1.66|LinkUSBi |TEK603
HM: SEC-SCO|SCI-3-FM|LC-SW4-PCB|ES-PMSW1-PL|RC-4-2|SEN-MDIR-O|SEC-WDS-2
CUL: HMS100TF|FS20 S4A-2 ; OWDevice: DS18S20|DS2401|DS2406|DS2423

CoolTux

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?
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

ujaudio

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 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 steht aber schon einiges.
Einen lieben Gruß
Jürgen

ujaudio

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.
Einen lieben Gruß
Jürgen

CoolTux

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.
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

ujaudio

#6
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.
Einen lieben Gruß
Jürgen

CoolTux

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
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

ujaudio

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
Einen lieben Gruß
Jürgen

ujaudio

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 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.
Einen lieben Gruß
Jürgen

CoolTux

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 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.
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

ujaudio

#11
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
Einen lieben Gruß
Jürgen

ujaudio

#12
Aktueller Stand:

  • define funktioniert einwandfrei, bei verbose=5 auch mit Eintrag im Logbuch
  • das device wird ordnungsgemäß angezeigt , sieht alles richtig gut aus
  • delete (eigentlich undef) funktioniert einwandfrei, bei verbose=5 auch mit Eintrag im Logbuch
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  :)
Einen lieben Gruß
Jürgen

ujaudio

#13
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:

  • connect läuft fehlerfrei durch, wenn der Oppo eingeschaltet ist
  • disconnect läuft fehlerfrei durch, wenn der Oppo eingeschaltet ist und zuvor connected war
  • connect macht keine Probleme, wenn der Oppo komplett ausgeschaltet ist
  • disconnect macht keine Probleme, wenn es gar kein erfolgreiches connect davor gab

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
Einen lieben Gruß
Jürgen

CoolTux

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
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