Readings nach FHEM schicken

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

Vorheriges Thema - Nächstes Thema

timmib

Guten Tag,

ich würde gerne einen neues FHEM Modul entwickelnm welches die neuesten Werte aus einer externen Datenbank als Reading hat.

Bei der externen Datenbank handelt es sich um InfluxDB. Dazu gehört auch Kapacitor mit dem man z.B. per MQTT und auch HTTPPost verschicken kann.

Im Moment habe ich den Eindruck, dass MQTT die beste Option ist, da FHEM out-of-the-box kein HTTP-Post unterstützt. Aktives Pollen der Datenbank kommt nicht in Frage. FHEM sollte passiv auf Änderungen warten.

Hat jemand einen Vorschlag für mich?

Viele Grüße

Tim

rudolfkoenig

Zitatda FHEM out-of-the-box kein HTTP-Post unterstützt.
Das ist nicht richtig.

M.Schulze

Ich denke schon das es richtig ist.


Welchen Namen hat denn das I.O. Device ?

MfG
Muss ich das Licht aus machen?

rudolfkoenig

ZitatIch denke schon das es richtig ist.
Womoeglich haben wir unterschiedliche Auffassungen von HTTP-Post, oder was "FHEM out-of-the-box" bedeutet.

Otto123

Zitat von: M.Schulze am 25 Januar 2021, 15:28:38
Welchen Namen hat denn das I.O. Device ?
Ich würde meinen der Name spielt hierbei keine Rolle, aber in der Standardinstallation heißt der WEB ;) oder ich habe nicht verstanden was HTTP-Post ist...
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

M.Schulze

Die Tatsache das FHEMWEB HTTP-Posts erfassen kann und Readings draus machen kann ist allenfalls ein "nice to have".

Ich rede von der Anbindung von vielen, verschiedene Geräten über das HTTP Protokoll.

Das sind Geräte die einen Webserver besitzen und auch Requests (HTTP-Posts?) auslösen können.

Als zweistufiges Modell für Module wie im Wiki beschrieben. Wo das erste Modul den Server aufbaut, das Parsen übernimmt, und die 2. Stufe z.B. nur den Query auswertet und den Input für die Response vorbereitet.
Muss ich das Licht aus machen?

herrmannj

Ein Webserver löst sicher keinen request aus, das macht der Client. Bitte nicht mit Worthülsen rumwerfen. Und falls doch fehlt Bitcoin und AI für ein Bingo

betateilchen

Zitat von: herrmannj am 25 Januar 2021, 17:29:13
Und falls doch fehlt Bitcoin und AI für ein Bingo

und Blockchain  8)

Seit wann haben "Commercial User" eigentlich Berechtigungen im Developer Board? Muss ich wohl verpasst haben.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

KölnSolar

Möchte mit Bingo spielen. ;D

Aber zurück zum TE.
Hallo Tim,
das
Zitatda FHEM out-of-the-box kein HTTP-Post unterstützt.
mit dem
ZitatAktives Pollen der Datenbank kommt nicht in Frage. FHEM sollte passiv auf Änderungen warten.
beißt sich. Bei letzterer Anforderung musst Du doch nur per DevIo eine Verbindung zu Deinem Server aufbauen. Der schickt dann die messages an FHEM. Per ReadFn wird Dein FHEM-Modul informiert und kann die message verarbeiten.
Grüße Markus
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

timmib

Hallo zusammen,

also eins nach dem Anderen.


  • Wenn FHEM aus HTTP POST Anfragen Readings machen kann wäre das super. Gibt es hier einen Link zur Dokumentation oder Beispielen? Ich kenne und nutze bisher nur GET auf .../fhem?cmd=...
  • Kapacitor kann auch TCP Servern JSON zuschicken. Dann wäre ein Link auf TcpServerUtils super.

FHEM sollte hier die Rolle des Servers übernehmen. Kapacitor schickt dann aktiv die Werte sobald diese in der InfluxDB eintrudeln.

Viele Grüße

Tim

rudolfkoenig

ZitatWenn FHEM aus HTTP POST Anfragen Readings machen kann wäre das super. Gibt es hier einen Link zur Dokumentation oder Beispielen? Ich kenne und nutze bisher nur GET auf .../fhem?cmd=...
Ob GET oder POST: FHEMWEB nimmt die Parameter vom URL _und_ <body>, und verarbeitet sie gleich.

KölnSolar

ZitatIch kenne und nutze bisher nur GET auf .../fhem?cmd=...
Das ist aber nur FHEMWEB u. nicht FHEM. FHEM besteht aus zig Servern und Clients, ein Servertyp z.B. das von Dir schon genannte MQTT. Das wäre dann der bessere Weg einen Server in FHEM zu realisieren als FHEMWEB(eigentlich nur Frontend von FHEM) vergewaltigen zu wollen.

Und irgendwie schmeißt Du die OSI-Schichten durcheinander
Zitat2.Kapacitor kann auch TCP Servern JSON zuschicken
http u. mqtt u..... setzen auf TCP auf.

Alles meine Meinung als Halbamateur. Die wahren Experten hier sehen das möglicherweise anders.(wie Rudi bereits bestätigt hat  ;))

Grüße Markus
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

timmib

Guten Morgen,

@Rudi
Dann schau ich mir FHEMWEB mal an.

@Marksu
Nene, ich schmeiß da nix durcheinander. Kapacitor kann auch ohne HTTP direkt auf Socket Ebene Daten verschicken.

ZitatDas wäre dann der bessere Weg einen Server in FHEM zu realisieren als FHEMWEB(eigentlich nur Frontend von FHEM) vergewaltigen zu wollen.
Gibt es hierzu Meinungen? Ich persönlich finde immer weniger Code ist besser als mehr Code. D.h. wenn FHEM, oder eines der out-of-the-box Module, das kann ist doch prima.

Viele Grüße

Tim

timmib

#13
Ich habe jetzt mal testweise

curl -X POST -d "setreading kap x 3" http://..../fhem

gemacht. Der Befehl wird aber nicht ausgeführt. Hier der Log.
2021.01.26 08:53:48 4: Connection accepted from WEB_192.168.178.65_49832
2021.01.26 08:53:48 5: POST /fhem HTTP/1.1
Host: 192.168.178.25:8083
User-Agent: curl/7.68.0
Accept: */*
Content-Length: 19
Content-Type: application/x-www-form-urlencoded
2021.01.26 08:53:48 4: WEB_192.168.178.65_49832 POST /fhem&setreading kap x 2;; BUFLEN:0
2021.01.26 08:53:48 4: WEB: /fhem&setreading kap x 2; / RL:3551 / text/html; charset=UTF-8 /  / Cache-Control: no-cache, no-store, must-revalidate


Laut code hatte ich gehofft hier zu landen, was ja am Ende ein AnalyzeCommand bzw. AnalyzeCommandChain auslösen wird.
https://svn.fhem.de/trac/browser/trunk/fhem/FHEM/01_FHEMWEB.pm#L425

Übersehe ich hier etwas?

Viele Grüße

Tim

rudolfkoenig

Etliches:
- Syntax bleibt bei GET und POST gleich, Befehle muessen mit cmd= oder cmd.XXX= spezifiziert werden.
- sinnvollerweise spezifiziert man XHR=1, damit keine Webseite zurueckgeliefert wird
- mit der Voreinstellung braucht man (zusaetzlich zum evtl. konfigurierten Passwort) das richtige(!) fwcsrf Cookie

Folgendes funktioniert bei mir:
curl -X POST -d "cmd=setreading d TEST TEST&XHR=1&fwcsrf=csrf_933865317019376" http://localhost:8083/fhem

Otto123

Ergänzung: Wie man mit dem csrf Token umgehen kann findest Du dir: https://wiki.fhem.de/wiki/CsrfToken-HowTo
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

timmib

Komisch, wenn man es richtig macht geht es sofort.  ;)

Besten Dank.

So stehen die Türen für ein neues tolles Modul offen.

CoolTux

Wenn Du eh ein Modul für FHEM machst wieso dann der Umweg über HTTP, wieso nicht über einen eigenen TCP Socket der vom Modul verwaltet wird?
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

timmib

#18
Genau das war ja meine Frage. Ich fände das mit einem TCPServer eleganter. sonst muss das Modul ordentlicher Weise ja ein eigenes FHEMWEB anlegen.

Gibt es dafür ein überschaubares Beispiel?

betateilchen

ich mache schonmal Popcorn...  8)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

CoolTux

Zitat von: timmib am 26 Januar 2021, 10:56:06
Genau das war ja meine Frage. Ich fände das mit einem TCPServer eleganter. sonst muss das Modul ordentlicher Weise ja ein eigenes FHEMWEB anlegen.

Gibt es dafür ein überschaubares Beispiel?

Überschaubar ist relativ. Von meinen Modulen wüsste ich nur AMAD. Das AMADCommBridge Modul macht genau das was Du suchst.
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

timmib


M.Schulze

Zitat von: timmib am 26 Januar 2021, 10:56:06
Genau das war ja meine Frage. Ich fände das mit einem TCPServer eleganter. sonst muss das Modul ordentlicher Weise ja ein eigenes FHEMWEB anlegen.

Gibt es dafür ein überschaubares Beispiel?

Richtig,

FHEMWEB ist das Beispiel.

Genau so habe ich es auch gemacht:

Im define:
- TcpServer_Open

Im Read:
- TcpServer_Accept, neue Verbindungen akzeptieren
- Daten empfangen, Header trennen, Body (ggf. nach und nach)
- Header-Felder extrahieren
- Request / Response unterscheiden, 1st Line teilen
- URI parsen:


    $URI =~ /^([a-z][a-z0-9+.-]*):(?:\/\/((?:(?=((?:[a-z0-9-._~!${\}&'()*+,;=:]|%[0-9A-F]{2})*))(\3)@)?(?=(\[[0-9A-F:.]{2,}\]|(?:[a-z0-9-._~!${\}&'()*+,;=]|%[0-9A-F]{2})*))\5(?::(?=(\d*))\6)?)(\/(?=((?:[a-z0-9-._~!${\}&'()*+,;=:@\/]|%[0-9A-F]{2})*))\8)?|(\/?(?!\/)(?=((?:[a-z0-9-._~!${\}&'()*+,;=:@\/]|%[0-9A-F]{2})*))\10)?)(?:\?(?=((?:[a-z0-9-._~!${\}&'()*+,;=:@\/?]|%[0-9A-F]{2})*))\11)?(?:#(?=((?:[a-z0-9-._~!${\}&'()*+,;=:@\/?]|%[0-9A-F]{2})*))\12)?$/i;



MfG
Muss ich das Licht aus machen?

CoolTux

Hier mal etwas Code von meinem alten Lehrmeister zum Thema Headerdaten extrahieren.
Danke Andre

##### bleibt zu Anschauungszwecken erhalten
#sub Header2Hash($) {
#
#    my $string  = shift;
#    my %hash    = ();
#
#    foreach my $line (split("\r\n", $string)) {
#        my ($key,$value) = split( ": ", $line );
#        next if( !$value );
#
#        $value =~ s/^ //;
#        $hash{$key} = $value;
#    }
#
#    return \%hash;
#}
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

timmib

Merci, aber Header gibt es hierbei nicht. Der schickt dann einfach JSON.

timmib

So, Prototyp läuft.

Kann sein, das ich mich nochmal melde wegen Close usw.

timmib

Beta ist fertig und kann auf die Menschheit losgelassen werden.

https://forum.fhem.de/index.php?topic=118208.0

timmib

Hi,

hat jemand einen Tipp ob und wie man diese Kollegen hier wegbekommt.

kapacitor_192.168.178.65_60492_MSGCNT
1
kapacitor_192.168.178.65_60492_TIME
2021-01-29 16:34:55
kapacitor_192.168.178.65_60500_MSGCNT
1
kapacitor_192.168.178.65_60500_TIME
2021-01-29 16:35:55
kapacitor_192.168.178.65_60572_MSGCNT
1
kapacitor_192.168.178.65_60572_TIME
2021-01-29 16:36:55
kapacitor_192.168.178.65_60648_MSGCNT
1
kapacitor_192.168.178.65_60648_TIME
2021-01-29 16:37:55
kapacitor_192.168.178.65_60658_MSGCNT
1
kapacitor_192.168.178.65_60658_TIME
2021-01-29 16:38:55
kapacitor_192.168.178.65_60662_MSGCNT
1
kapacitor_192.168.178.65_60662_TIME
2021-01-29 16:39:55
kapacitor_192.168.178.65_60668_MSGCNT
1
kapacitor_192.168.178.65_60668_TIME
2021-01-29 16:40:55
kapacitor_192.168.178.65_60678_MSGCNT
1
kapacitor_192.168.178.65_60678_TIME
2021-01-29 16:41:55


Kann es sein, dass beim Read was fehlt?

sub Kapacitor_Read($) {

    my $hash = shift;
    my $name = $hash->{NAME};

    if ( $hash->{SERVERSOCKET} ) {    # Accept and create a child
        TcpServer_Accept( $hash, 'Kapacitor' );
        return;
    }

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

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

    my $found = Dispatch($hash, $buf);
}


Vielen Dank

Tim

rudolfkoenig

Es gibt auch eine TcpServer_Close Funktion, diese sollte man ab und zu auch aufrufen.

M.Schulze

Zitat von: timmib am 29 Januar 2021, 16:45:20
Hi,

hat jemand einen Tipp ob und wie man diese Kollegen hier wegbekommt.


Fhem.pl verändern.  Ich habe die Stelle auch entfernt. Ist wohl ein Überbleibsel aus alten Zeiten ...
Muss ich das Licht aus machen?

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 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 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 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 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())
}



timmib

Guten Tag,

also ich mach jetzt das Close und das Delete und trotzdem bleiben diese Internals für immer liegen.

kap_192.168.178.65_52476_MSGCNT
1
kap_192.168.178.65_52476_TIME
2021-01-31 07:57:37
kap_192.168.178.65_52488_MSGCNT
1
kap_192.168.178.65_52488_TIME
2021-01-31 07:58:01


Wie kann ich die am besten wegräumen? Es werden mehrfach in der Minute neue Verbindungen aufgebaut. Da ist das recht ungünsitg, oder?

Viele Grüße

Tim


CoolTux

Hatte ich auch bei AMAD. Da hatte ich aber die Möglichkeit dem Client zu sagen das er die Verbindung schließen soll.
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

rudolfkoenig

ZitatWie kann ich die am besten wegräumen?
Siehe meine Antwort #35: https://forum.fhem.de/index.php/topic,118161.msg1127177.html#msg1127177
Kurz: fuer Dispatch die Instanz verwenden, was vom Benutzer definiert wurde.

timmib

#48
Hi Rudolf,

wie komme ich da dran? Muss ich die selber speichern wie beim Child?

Mein Setup ist jetzt wie folgt:
Modul Kapacitor führt den TCPServer und ist Parent.

Er kennt nur eine Art von Child, den KapacitorTask.
Dort werden die Werte für die jeweiligen Task entgegenommen. Entsprechend reagieren diese basierend auf der Task ID, die mitgeschickt wurde.
Im Parse wird dann zum Setzen der empfangen Readings auf den definierten Task gewechselt.
$modules{KapacitorTask}{defptr}{$id}

Hier landen dann auch die MSGCNT, die sich ansammeln.

Schreiben oder Antworten gibt es über den TCP Server nicht. Das Taskmanagement über die Kapacitor API mach ich vom Task aus über HTTP.

Viele Grüße

Tim






rudolfkoenig

Zitatwie komme ich da dran? Muss ich die selber speichern wie beim Child?
TcpServer_Accept speichert den Namen in der Verbindungs-Hash unter SNAME.
D.h. im ReadFn macht man Dispatch($defs{$hash->{SNAME}}, ...);

timmib

#50
Hi,

das hilft leider nicht. Ich habe es ausprobiert.

Wie gesagt, diese Internals werden ja dem Child hinzugefügt. Also dem Gerät, was das Parse implementiert und dessen Readings ich setze.

Noch eine Idee?


rudolfkoenig

Vermutlich ist beim Lesen oder Verstehen meiner Beschreibung was schiefgegangen.

Ich versuchs anders:
- die XX_MSGCNT/XX_TIME Werte werden in Dispatch erhoeht, wobei XX der Name des im Dispatch spezifizierten IODevs ist.
- anhand deiner Listing ist es offensichtlich, dass dein Modul beim Dispatch Aufruf die VerbindungsInstanz spezifiziert (das, womit ReadFn aufgerufen wird), und nicht den vom Benutzer spezifizierte Instanz (aka $hash->{SNAME}).
- damit MSGCNT/TIME was Sinnvolles enthaelt (Anzahl der ueber diesen IODev empfangenen Requests), muss  Dispatch mit $defs{$hash->{SNAME} als IODev Argument aufgerufen werden.

timmib

Das habe ich schon verstanden. Nur landen die MSGCNT/TIME bei mir nicht im Parent(aka. IODev, aka Kapacitor) sondern im Child(aka KapacitorTask).
Und das auch, wenn ich Dispatch so aurufen wie vorgeschlagen. Hier mein Read()


sub Kapacitor_Read($) {

    my $hash = shift;
    my $name = $hash->{NAME};

    if ( $hash->{SERVERSOCKET} ) {    # Accept and create a child
        TcpServer_Accept( $hash, 'Kapacitor' );
        return;
    }

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

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

    my $found = Dispatch($defs{$hash->{SNAME}}, $buf);
}

rudolfkoenig

Dann sind das entweder alte Werte (d.h. die gehoeren geloescht), oder es gibt noch ein weiteres Dispatch Aufruf, ohne $hash->{SNAME}

timmib

Leider, weder noch.

Die Werte sind neu(siehe Anhang) und es gibt auch nur ein einziges Dispatch.


timmib

Hi,

ich habe mir jetzt mal den Code vom Dispatch angeschaut und kapiert was Deine vorgeschlagene Änderung bringt.

Jetzt wird immerhin immer der selbe Werte hochgezählt und nicht mehr immer ein neuer angelegt, weil das Device und damit der Namesgeber vom Internal gleich ist.

Danke.

Viele Grüße

Tim

carlos

Hallo,
Ich habe einen ähnlichen Fall und musste mir mit folgendem Code am Ende der read sub helfen:

    foreach my $d (keys %defs) {
      next if($defs{$d}{TYPE} ne "TraccarDevice");
      my $msgcnt = $defs{$d}{$IOname . "_MSGCNT"};
      my $time = $defs{$d}{$IOname . "_TIME"};
      if (defined($msgcnt)  && defined($time)) {
        Log3 $IOname, 3,"[$sub_name] ($IOname) - Internals: " . $IOname ."_MSGCNT = $msgcnt und " . $IOname . "_TIME = $time found in $d";
        delete($defs{$d}{$IOname . "_MSGCNT"});
        delete($defs{$d}{$IOname . "_TIME"});
        Log3 $IOname, 3,"[$sub_name] ($IOname) - Internals: " . $IOname ."_MSGCNT und " . $IOname . "_TIME deleted in $d";
      }
    }

    CommandDelete(undef, $IOname);


Gruß

Carlos
FHEM svn auf Intel NUC mit proxmox,1 UDOO, 3 Raspberry Pi, signalduino, nanoCUL, div. Homematic Komponenten, toom Baumarkt Funksteckdosen, einige sonoffs, hue, shelly

rudolfkoenig

Ich staune und hoffe, dass der obige Code nicht als Vorlage verwendet wird.

Ich bin bereit Dispatch anzupassen, wenn jemand mir klarmacht, warum der vorgeschlagene Weg (Dispatch mit der von dem Benutzer definierten IODev Instanz aufzurufen), nicht praktikabel ist.


carlos

ok, wenn das so nicht akzeptabel ist dann ändere ich das gerne.
In meinem Fall häufen sie die internals halt bei jeden connect des Clients an den Server im Device.
Keine Ahnung warum und wie das zu unterbinden ist.
Das
CommandDelete(undef, $IOname);
räumt ja auf aber die internal bleiben.Gruß
Carlos
FHEM svn auf Intel NUC mit proxmox,1 UDOO, 3 Raspberry Pi, signalduino, nanoCUL, div. Homematic Komponenten, toom Baumarkt Funksteckdosen, einige sonoffs, hue, shelly

timmib

#59
Ich finde den Counter ein nettes Feature. Man darf hier halt nicht ein temporäres Gerät verwenden sonst wird nicht gezählt sondern hinzugefügt.

Die temporären Geräte muss man halt löschen.

rudolfkoenig

ZitatKeine Ahnung warum und wie das zu unterbinden ist.
Womoeglich helfen dabei meine Hinweise im Antwort #35 und #51.

carlos

Die hatte ich gelesen und auch verstanden.
Hat leider nicht funktioniert.
Jetzt habe ich das noch mal so umgesetzt und FHEM durch gestartet.
Was soll ich sagen, jetzt funktionierts.
Danke, wieder was gelernt.
Gruß

Carlos
FHEM svn auf Intel NUC mit proxmox,1 UDOO, 3 Raspberry Pi, signalduino, nanoCUL, div. Homematic Komponenten, toom Baumarkt Funksteckdosen, einige sonoffs, hue, shelly

M.Schulze

Zitat von: rudolfkoenig am 02 Februar 2021, 10:19:46

Ich bin bereit Dispatch anzupassen, wenn jemand mir klarmacht, warum der vorgeschlagene Weg (Dispatch mit der von dem Benutzer definierten IODev Instanz aufzurufen), nicht praktikabel ist.

1. die 2. Stufe sollte den aktuellen Verbindungs-hash bekommen. (Es ist  bei der Server Programmierung so üblich das die Verbindung durchs Programm getragen wird)
2. die 2. Stufe kann mit der vom Benutzer definierten IODev Instanz gar nichts nützliches anfangen. Sie wäre auch einfach zu bekommen über $defs{$hash->{SNAME}}. Ginge das umgekehrt auch so einfach? Wie? Addvals? Oder gar suchen?

Bei mir ist es so

1. Stufe: Server + Protokoll Parser, speichert Parsing Ergebnis aktuell temporär im jeweiligen Verbindungs-Hash

dann Dispatch
    Dispatch($verbindungs-hash, $verbindungs-hash->{'txscheme'}, \%addvals); # Beispiel txscheme=s0, also ausschließlich s0 und nicht das umfangreiche Parsing Ergebnis des Protokolls das im Verbindungshash verbleibt. Ist halt aktuell so.


2. Stufe:
Zugriff auf Parsing-Ergebnis im Verbindungs-Hash, Schema spezifische Aktivitäten auf Basis der Nutzdaten, Vorbereitung Daten für Response ...


1. Stufe: Senden Response gemäß Protokoll über Verbindungs-Hash

MfG

Muss ich das Licht aus machen?

rudolfkoenig

Zitat2. die 2. Stufe kann mit der vom Benutzer definierten IODev Instanz gar nichts nützliches anfangen. Sie wäre auch einfach zu bekommen über $defs{$hash->{SNAME}}. Ginge das umgekehrt auch so einfach? Wie? Addvals? Oder gar suchen?
Offensichtlich wird der Inhalt meiner Beitraege konsequent ignoriert.

Wenn ein logisches Modul auf die Verbindungsinstanz (oder auf das benutzerdefinierte IODev) zugreift, dann ist es nicht mehr moeglich alternative IODevs  anzubieten. Etliche Hilfsmodule wie FHEM2FHEM oder STACKABLE verlassen sich auch darauf, dass die Kommunikation ausschliesslich ueber Dispatch und IOWrite laeuft.

Um die Antwort konkret zu formulieren: die zweite Stufe greift gar nicht auf das IODev zu.