Readings nach FHEM schicken

Begonnen von timmib, 25 Januar 2021, 12:33:18

Vorheriges Thema - Nächstes Thema

CoolTux

Zitat von: M.Schulze am 29 Januar 2021, 17:49:35
Fhem.pl verändern.  Ich habe die Stelle auch entfernt. Ist wohl ein Überbleibsel aus alten Zeiten ...

Das ist für ein Community Modul eine sehr sehr schlechte Lösung. Es sei denn Du lieferst einen Patch mit entsprechender Erklärung.
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

M.Schulze

#31
Zitat von: CoolTux am 29 Januar 2021, 18:14:35
Das ist für ein Community Modul eine sehr sehr schlechte Lösung. Es sei denn Du lieferst einen Patch mit entsprechender Erklärung.

Ich denke es geht um diese beiden Zeilen in Fhem.pl.

$defs{$found}{"${name}_MSGCNT"}++;
$defs{$found}{"${name}_TIME"} = TimeNow();


${name}_  ist variabel da die port nummer mit drin ist. Die ändert sich aber kontinuierlich, nach jedem accept mit jeder neuen Verbindung wird dispatch aufgerufen.

Folge: Die definition wird zugemüllt. Funktioniert aber.

Wer braucht diese Zeilen?

Siehe Anhang


Muss ich hier das Licht aus machen?

timmib

Ich dachte man macht ein Close nur wenn man keine Verbindungen mehr zulassen will. also das Socket komplett schliesst. In meinem Fall kommen ja immer wieder neue Clients.

rudolfkoenig

ZitatWer braucht diese Zeilen?
Alle, die nachvollziehen wollen, welche IODevs welchen Beitrag beim Empfang leisten. Beispiel: 3 CULs verteilt auf unterschiedliche Stockwerke. Als IODev sollte man beim Dispatch nicht die aktuelle Verbindungsinstanz angeben, sondern die "definierte", wo auch die Attribute gesetzt werden.

ZitatIch dachte man macht ein Close nur wenn man keine Verbindungen mehr zulassen will.
TcpServer_Close muss man fuer jede einzelne Verbindung, die man mit Accept bekommt, aufrufen, wenn sysread undef liefert.
Sonst bleiben die Verbindungsinstanzen uebrig, und erzeugen eine Endlosschleife, da select immer wieder deren Ende meldet.

M.Schulze

Zitat von: rudolfkoenig am 29 Januar 2021, 18:54:31
Als IODev sollte man beim Dispatch nicht die aktuelle Verbindungsinstanz angeben, sondern die "definierte", wo auch die Attribute gesetzt werden.

Die untergeordnete logische Definition braucht zwingend  die aktuelle/passende Verbindungsinstanz zum Gerät. Aus mehreren Gründen.
Wird das erreicht wenn Dispatch statt mit der aktuelle Verbindungsinstanz mit der "ursprünglich definierten = Instanz die den Server aufbaut hat" aufgerufen wird?


Muss ich hier das Licht aus machen?

rudolfkoenig

ZitatWird das erreicht wenn Dispatch statt mit der aktuelle Verbindungsinstanz mit der "ursprünglich definierten = Instanz die den Server aufbaut hat" aufgerufen wird?
Weiss nicht, was mit "Wird das erreicht" gemeint ist, vmtl. nicht.

Wenn die logische Definition zwingend die aktuelle Verbindung braucht, dann wuerde ich zunaechst lange darueber nachdenken, ob die Trennung der Schichten an richtiger Stelle erfolgt ist.

Wenn das nicht anders zu loesen ist, dann wuerde ich den Namen des Verbindungskanals zu den Nutzdaten bei Dispatch dazupacken, und fuer die andere Richtung bei IOWrite ebenfalls, dann kann die andere Seite das richtig zuordnen.

Ausser Dispatch/ParseFn bzw. IOWrite/WriteFn sollte zwischen den beiden Schichten keine Verbindung geben (insb. keine direkten Funktionsaufrufe), um mehrere IO-Module fuer ein logisches Modul zu erlauben. Wenn man das ignoriert, dann muessen nachfolgende IO-Module das Rad neu erfinden, und neue Benutzer weiter verwirren, siehe MQTT2_DEVICE vs. MQTT_DEVICE.

timmib

Hi,

ich habe das jetzt brav eingebaut und sehe auch die Log einträge. Aber der zeigt die Verbindungen immernoch als offen an.

    my $ret = sysread( $hash->{CD}, $buf, 2048 );

    # When there is an error in connection return
    if ( !defined($ret) or $ret <= 0 ) {
        TcpServer_Close($hash);
        Log3 $name, 0, "Kapacitor: [$name] Connection closed";
        # Log3( $name, 3, "Kapacitor ($name) - Connection closed for $name" );
        return;
    }


kap_192.168.178.65_54936
Connected
kap_192.168.178.65_54938
Connected
kap_192.168.178.65_54940
Connected
kap_192.168.178.65_54948
Connected
kap_192.168.178.65_54952
Connected
kap_192.168.178.65_54954
Connected
kap_192.168.178.65_54956
Connected
kap_192.168.178.65_54960
Connected
kap_192.168.178.65_54966
Connected


Kapacitor: [kap_192.168.178.65_54960] Connection closed

rudolfkoenig

Connection Management muss das Modul schon selbst machen, das Framework kann nicht beurteilen, wann irgendwelche Verbindungen "sinnlos" geworden sind.
FHEMWEB schliesst nach eine Minute Inaktivitaet alle Verbindiungen, die nicht fuer Statusupdates verwendet werden. Ueblicherweise oeffnet ein Browser 6 Kanaele, und davon ist nur einer fuer Statusupdates.

timmib

Kapier ich nicht. Was soll ich denn noch mehr machen als Close?

rudolfkoenig

Wennn "idle" Verbindungen notwendig sind, dann nichts.
Sonst nach eine Minute (oder 10, etc) Inaktivitaet sie schliessen.
Eine Verbindung "frisst" Ressourcen (FD, CPU, etc), ob das stoert oder nicht, muss der Modulschreiber beurteilen.

M.Schulze

Zitat von: timmib am 29 Januar 2021, 21:12:38
Kapier ich nicht. Was soll ich denn noch mehr machen als Close?

Also das TcpServer_Close($hash); gehört da denke ich nicht rein. Das gehört ins undefine.


Ich habe da noch ein CommandDelete drin. Vielleicht spielt das ja eine Rolle beim Schließen der Verbindung.



} elsif (!$ret) { # 0==EOF, undef=error

      CommandDelete(undef, $cname);

      Log3 $sname, 3, "Connection closed for $cname: ".
        (defined($ret) ? 'EOF' : $!);

      return;
    }



Muss ich hier das Licht aus machen?

timmib


M.Schulze

Zitat von: timmib am 29 Januar 2021, 23:53:51
Was macht denn CommandDelete?

Löscht die angegebene Verbindungsinstanz. Schließt aber keine zu diesem Zeitpunkt noch offene Verbindung.

Wer schließt die Verbindungen? Client oder Server?

TcpServer_Close ist vielleicht doch nicht falsch. Jedenfalls dann nicht wenn der Server die Verbindung trennen soll. Wenn es wie bei mir ausschließlich der Client macht braucht man es nicht.
Muss ich hier das Licht aus machen?

timmib

Mein Ziel ist es, das der Server die Verbindung schließt. Evtl guck ich mir Mal den Go Code von Kapacitor an. Wäre Mal ganz spannend wie das Verbindungsmanagement machen.

timmib

Also der schließt "direkt" nach dem Senden. Ist quasi im finally, in Go nutzt man wohl "defer" dafür.

func (h *tcpHandler) Handle(event alert.Event) {
buf := h.bp.Get()
defer h.bp.Put(buf)
ad := event.AlertData()

err := json.NewEncoder(buf).Encode(ad)
if err != nil {
h.diag.Error("failed to marshal alert data json", err)
return
}

conn, err := net.Dial("tcp", h.addr)
if err != nil {
h.diag.Error("tcp handler failed to connect", err, keyvalue.KV("address", h.addr))
return
}
defer conn.Close()

buf.WriteByte('\n')
conn.Write(buf.Bytes())
}