Forum: Mikrocontroller und Digitale Elektronik MQTT Connect Disconnect


von Marco H. (damarco)


Lesenswert?

Ich habe eine kleine Verständnis Frage, ich dachte...

Connect -> Publish -> close Tcp ... oder innerhalb der alive PingReq 
oder weitere Nachrichten

offenbar ist mir der Broker sauer wenn man die TCP Verbindung einfach 
schließt und schmeißt den client einfach raus.  Baut man die Verbindung 
wieder auf will er unbedingt ein Connect sonst macht er sie wieder zu.

Connect -> publish -> disconnect -> close TCP

ergibt kein Problem das dumme ist nur das der broker nun auch nicht mehr 
feststellt wenn der client fehlt.

Ich dachte immer Mqtt kann mit halb offen Verbindungen umgehen.

Das ganze wäre sau blöd da die TCP Verbindung immer offen sein müsste 
was extrem viel Strom verbraucht. Oder man muss den Client per 
disconnect abmelden. Dann kann aber auch nicht mehr festgestellt werden 
ob der Client noch am leben ist.

Ich habe als Broker HiveMQ.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Marco H. schrieb:
> Baut man die Verbindung
> wieder auf will er unbedingt ein Connect sonst macht er sie wieder zu.

Steht so im Standard:

>> After a Network Connection is established by a Client to a Server, the
>> first Packet sent from the Client to the Server MUST be a CONNECT Packet
>> [MQTT-3.1.0-1].

> Connect -> publish -> disconnect -> close TCP
>
> ergibt kein Problem das dumme ist nur das der broker nun auch nicht mehr
> feststellt wenn der client fehlt.

Dazu gibt es Keep Alive und Will Message (und mit Retain Messages muss 
man eventuell auch noch rummachen).

> Ich dachte immer Mqtt kann mit halb offen Verbindungen umgehen.

Nein, MQTT kennt solche Feinheiten nicht. Eher im Gegenteil, es 
vermeidet sie. Keep Alive gibt es, weil halb-offene Verbindungen in 
vielen Umgebungen nicht zuverlässig erkannt werden können. Damit würde 
ein Broker eventuell nicht merken, dass ein Client schon längs weg ist.

> Das ganze wäre sau blöd da die TCP Verbindung immer offen sein müsste

Offen und am besten noch Keep Alive Pings. Nur ein sprechender Client 
ist ein lebender Client.

> was extrem viel Strom verbraucht

Was willst du hören. Es ist nun mal nicht so einfach wie es aussieht.

von Marco H. (damarco)


Lesenswert?

Das ist ja das Problem, Disconnect meldet den Client auch wirklich ab. 
Ohne die Will etc. zu versenden.  Schließt man die Verbindung ohne 
Disconnect versendet der Broker die Will messages da er den Client 
unschön entfernt.

Ich dachte man kann die Verbindung einfach sauber schließen(TCP 
disconnect) und nach Ablauf der keepalive wird der Client entfernt und 
somit die Will messages gesendet.

Wenn man nicht ein PingReq Paket sendet, das aber nie eintritt wenn 
immer ein Connect packet nötig ist. Da dieses ja den keepalive neu 
startet.

Den Client kann man anhand der ID ja erkennen unabhängig über welche 
Verbindung diese Daten sendet. Das offen halten von TCP overhead ist 
einfach sau blöd meiner Meinung.

Wenn man einen Schalter hat der einen Status liefert bekommt man nie mit 
wenn dieser nicht funktioniert.  So müsste dieser nach Ablauf der 
keepalive sich einmal melden.  Sonst macht der broker mit der Will die 
Lampe im zweifel aus.

Man kann zwar Daten auch mit dem disconnect senden aber dann muss der 
Empfänger selber den Zeitstempel prüfen um zu erkennen das keine Daten 
mehr kamen.

Irrend wie macht es das ganze MQTT zum absurdum ...

von Michael U. (amiga)


Lesenswert?

Hallo,

verstehe ich nicht. Natürlich muß ein Client sich beim Broker melden 
wenn der wissen will, daß dieser noch lebt.

KeepAlive je nach Anwenung z.B. auf 15min setzen, alle 10 Minuten den 
Client wecken und ein Connect schicken und wieder schlafen gehen.
Beim Schalten eben auch wecken, die Message schicken und schlafen gehen.

Wie sonst soll ein Broker z.B. meinen tief schlafenden AVR erkennen?
Gerade KeepAlive, LastWill, Qos-Modi usw. machen doch MQTT so einfach zu 
handhaben.

Gruß aus Berlin
Michael

von Marco H. (damarco)


Lesenswert?

Also der HiveMQ sendet keine Will Messages mehr wenn man den Client MQTT 
disconnected. Macht man die TCP Verbindung zu sendet dieser die Will 
Messages, da ohne MQTT disconnect offenbar der Broker von einen Fehler 
ausgeht.

Genau hier liegt ja mein Problem, ich muss die TCP Verbindung offen 
halten. Müsste mal schauen ewt. kann man das in der config des HiveMQ 
beeinflussen.

: Bearbeitet durch User
von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Marco H. schrieb:
> Also der HiveMQ sendet keine Will Messages mehr wenn man den Client MQTT
> disconnect.

Steht so im Standard. Vielleicht solltest du den lesen.

>> On receipt of DISCONNECT the Server:
>>
>>    * MUST discard any Will Message associated with the current
>>      connection without publishing it, as described in Section
>>      3.1.2.5 [MQTT-3.14.4-3].


> Macht man die TCP Verbindung zu sendet dieser die Will
> Messages, da ohne MQTT disconnect offenbar der Broker von einen Fehler
> ausgeht.

Steht so im Standard. Vielleicht solltest du ...

>> Situations in which the Will Message is published include, but are not
>> limited to:
>>
>>    * An I/O error or network failure detected by the Server.
>>    * The Client fails to communicate within the Keep Alive time.
>>    * The Client closes the Network Connection without first sending a
>>      DISCONNECT Packet.
>>    * The Server closes the Network Connection because of a protocol
>>      error.

> Genau hier liegt ja mein Problem, ich muss die TCP Verbindung offen
> halten.

Ich beende dann hier meine Vorlesestunde aus dem Standard.

von Marco H. (damarco)


Lesenswert?

Aber das ist doch sau blöd ? Gerade für Batterie betriebene Geräte. Die 
müssen die Transportschicht immer offen halten oder sich abmelden. Womit 
sie aber nicht mehr überwacht werden können.

von Michael U. (amiga)


Lesenswert?

Hallo,

Marco H. schrieb:
> Also der HiveMQ sendet keine Will Messages mehr wenn man den
> Client MQTT
> disconnected. Macht man die TCP Verbindung zu sendet dieser die Will
> Messages, da ohne MQTT disconnect offenbar der Broker von einen Fehler
> ausgeht.

Natürlich. LastWill wird ja auch gesnedet, wenn die Verbindung aus 
technischen Gründen verloren geht.
Wenn der Client Disconnect meldet ist es ja seine Absicht, wenn er da 
was publishen will, kann er es ja vor dem Disconnect selber erledigen.
>
> Genau hier liegt ja mein Problem, ich muss die TCP Verbindung offen
> halten. Müsste mal schauen ewt. kann man das in der config des HiveMQ
> beeinflussen.

Verstehe ich immernoch nicht.
z.B. einer meiner Sensoren sendet alle 5 Minuten die Temperatur.
Gäbe es jetzt noch einen Schalter, weckt der bein Öffnen oder Schließen 
den ESP und schickt seine MEssage.
Dann geht der ESP wieder schlafen, damit bricht natürlich die 
TCP-Verbindung ab und die KeepAlive Zeit läuft. Entweder wecke ich jetzt 
den ESP vor Ende des gesetzten KeepAlive und melde mich, dann ist alles 
ok oder jemand klaut den Sensor und nach Ablauf der KeepAlive-Zeit 
schickt der Broker den LastWill raus.

LastWill ist ein Fehlerfall, der eben genau die hinterlegte Meldung an 
die Abbonenten schickt, weil die Verbindung ungeplant abgebrochen ist.
Ist doch Sinn des Ganzen.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Eben nicht sobald die TCP Verbindung ohne disconnect abbricht sendet der 
Broker die Will Messages ;) "steht doch im Protokoll "

Dein Licht würde bei jeden Abbruch wieder ausgehen nur weil der Schalter 
durch eine Störung verschwindet.  Wirklich durchdacht das ganze ...

von Marco H. (damarco)


Lesenswert?

Für deinen Temperatur Sensor würde das bedeuten das es immer 25° sind da 
du durch den disconnect nicht Festellen kannst wenn die letzten Daten 
kamen.

Der Broker könnte per Will messages dem Empfänger einen Fehler senden. 
So muss der Empfänger selber prüfen wenn das letzte Telegramm kam. Von 
der keepalive deines Sensors weiß der aber nichts.

Irrend wie sau blöd, da das MQTT die belange der Transportschicht nicht 
berücksichtigt.

Tja und dein kleiner µP ist mit jeder TCP Verbindung die offen bleibt 
belastet. Auch der PC hat seine Begrenzten Ports > 1024. Wenn alle 5 min 
nur was kommt und hierzu die Verbindung offen zu halten ist wenig 
intelligent.

So richtig blöd wenn man ein Mobilfunk denkt, verbraucht das richtig 
viel Strom. Als sich alle 5 min in Netz zu wählen um ein paar Daten zu 
versenden.

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

Marco H. schrieb:
> Dein Licht würde bei jeden Abbruch wieder ausgehen nur weil der Schalter
> durch eine Störung verschwindet.  Wirklich durchdacht das ganze ...

Warum solle das Licht ausgehen wenn der Schalter verschwindet?
Der Schalter schickt Licht an und das Licht geht an.
Der Schalter schickt Licht aus und das Licht geht aus.
Wenn der Schalter verschwindet bleibt der letzte Status doch erhalten.
LastWill schickt eine Message "Schalter weg". Darauf kann das Licht so 
reagiere, wie ich es geplant habe. Es passiert garnicht oder ich mache 
eine Signalled an der Lampe an, daß der Schalter nicht geht oder ich 
blinke 3x mit dem Licht oder usw.
Die nötige Reaktion bleibt doch jedem Abonnenten überlassen und ich muß 
es festgelegt haben.
Bei der Temperatu z.B. könnte LastWill einen Fehler melden und der 
Anzeigeclient zeit dann Striche an oder garkeine Temperatur oder...

Warum sollte der Abonnent prüfen müssen, wann die letzte gültige Meldung 
kam? Der muß auf die möglichen Messages passend reagieren können.
Wenn alle 5 Minuten eine neue Temperatur kommt reicht der Broker die 
weiter. Kommt bis zum Ableuf von KeepAlive (z.B. 7 Minuten) keine, 
schickt er den Fehler raus. Passend reagieren muß der Empfänger je nach 
dessen Anforderungen.

>So richtig blöd wenn man ein Mobilfunk denkt, verbraucht das richtig
>viel Strom. Als sich alle 5 min in Netz zu wählen um ein paar Daten zu
>versenden.

Der ESP braucht unter 1s zum Booten, WLAN-Connect, Connect zum Broker 
und versenden der Message. Dann geht er einfach wieder schlafen.
Logischweise sind die Verbindungen weg wenn der ESP in den DeepSleep 
geht.

Selbet ein Abonnent könnte nur alle 5 Minuten verbinden und nachschauen, 
per Retain würd er eine inzwischen eingegenage Message vom Brocker 
bekommen, selbst wenn der Publisher schon längst wieder schläft.

Gruß aus Berlin
Michael

von Rolf M. (rmagnus)


Lesenswert?

Marco H. schrieb:
> Connect -> publish -> disconnect -> close TCP
>
> ergibt kein Problem das dumme ist nur das der broker nun auch nicht mehr
> feststellt wenn der client fehlt.

Und wie soll er das feststellen, wenn du die TCP-Verbindung einfach so 
schließt?

> Das ganze wäre sau blöd da die TCP Verbindung immer offen sein müsste
> was extrem viel Strom verbraucht.

Warum?

von Marco H. (damarco)


Lesenswert?

Anhand der keepalive, besser wäre es einen disconnect zu schaffen wo 
sich der Client nur halb abmeldet und die Keepalive weiter läuft.

Bei offener TCP Verbindung werden immer wieder Daten hin und her 
geschoben. Die Hardware müsste in Betrieb bleiben um die Verbindung 
offen zu halten.

von Michael U. (amiga)


Lesenswert?

Hallo,

Marco H. schrieb:
> Anhand der keepalive, besser wäre es einen disconnect zu schaffen wo
> sich der Client nur halb abmeldet und die Keepalive weiter läuft.

KeepAlive läuft auf dem Broker und nur dort. Der Client setzt beim 
Connect nur die gewünschte KeepAlive-Zeit und die LastWill-Message.
Wenn KeepAlive auf dem Broker abläuft weil sich der Client in dieser 
zeit nicht mehr gemeldet hat, sendet der broker den LastWill.

MQTT wurde ja ursprünglich gerade deshalb entwickelt: kleine nötige 
Datenmengen und größtmögliche Sicherheit bei generell instabilen 
Verbindungen. Die Clients müssen nur einmal das gewünschte Verhalten 
beim Broker hinterlegen, dann kümmert dieser sich um diese Sachen.

Gruß aus Berlin
Michael

von Marco H. (damarco)


Lesenswert?

Naja von schlank kann keine Rede sein da dass ganze mit Strings 
funktioniert. Deswegen gibt es ja auch eine Abgespeckte Version MQTT-sn.

Ich glaube du hast nicht verstanden das dass Transportlayer immer 
vorhanden sein muss. Fehler auf dieser Ebene sendet der Broker die Will 
Messages. Das mit der keepalive funktioniert nur wenn der Client mit dem 
Broker verbunden ist und das Transportlayer keinen Fehler aufweist der 
zur Unterbrechung der Verbindung führt -> socket close.

Disconnect heißt auch disconnect es wird keine Will Messages versendet 
da die Verbindung ordentlich beendet wurde.

Das Problem dabei ist das bei TCP/IP immmer wieder pakete ausgetauscht 
werden. Legt man den Client schlafen geht die Verbindung verloren da sie 
in den timeout läuft. Das ganz unabhängig vom MQTT. Das kann auch schon 
bei sehr langsam und unsichern Verbindungen passieren. Bei UDP wäre das 
kein Problem aber MQTT schreibt nun mal TCP/IP vor.

: Bearbeitet durch User
von Johannes S. (Gast)


Lesenswert?

Marco H. schrieb:
> Das Problem dabei ist das bei TCP/IP immmer wieder pakete ausgetauscht
> werden.

Welche denn? Eigentlich nur wenn keepalive aktiviert ist oder in der 
Applikation ein eigener Watchdog zyklisch die Verbindung kontrolliert. 
Ansonsten kannst du den Netzwerkstecker ziehen, nach ein paar Tagen 
wieder einstecken und die Verbindung läuft sofort weiter.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Nö TCP/IP tauscht keine Pakete für einen keep alive aus wenn die 
Verbindung established ist.

Daher versteh ich die Probleme des Threaderstellers nicht.
Er is wohl nur zu doof sich mal die gute MQTT Doku von HiveMQ 
durchzulesen.
http://www.hivemq.com/mqtt-essentials/

Also µC schlafen legen mit ner established TCP Verbindung geht.
Man msus den MQTT timeout nur hoch genug einstellen und das kann der 
Client ja.
Der MQTT Client sollte auch nichts subscribed haben, sollte der Server 
über TCP was senden und bekommt kein ACK zurück so schließt er die TCP 
Verbindung.

von Johannes S. (Gast)


Lesenswert?

Mw E. schrieb:
> Nö TCP/IP tauscht keine Pakete für einen keep alive aus wenn die
> Verbindung established ist.

Und wie wird dann festgestellt das der Gegner lebt? Keepalive sendet 
zwar keine Daten, aber ein einfaches TCP Paket mit gesetztem ACK Flag 
das vom Gegner beantwortet werden muss.
Beim Deep Sleep ist die Frage was der µC am Leben hält und ob beim 
Aufwachen die Verbindungsdaten noch da sind. Wenn ja, halte ich das auch 
für kein Problem den in grösseren Intervallen zu wecken. Und der TCP 
Stack auf einem PC sollte es schon schaffen einige Tausend oder 
Zigtausend Verbindugen offen zu halten, soviele Hardwarenodes muss man 
erstmal haben.

von Michael U. (amiga)


Lesenswert?

Hallo,

Mw E. schrieb:
> Also µC schlafen legen mit ner established TCP Verbindung geht.
> Man msus den MQTT timeout nur hoch genug einstellen und das kann der
> Client ja.
Richtig. Meine ESP werden einfach abgeschaltet, teilweise über 
PowerEnable.
KeepAlive sollte natürlich auf einem für die Anwendung sinnvollen Wert 
stehen, das legt ja der jeweilige Client fest.
Ob der Broker seinerseits da was macht, hat mich nie interessiert. Für 
den ist letztlich nur wichtig, daß sich innerhalb der KeepAlive-Zeit der 
Client mal gemeldet hat, dann setzt er das TimeOut zurück.
Ob das per publish, connect, Brieftaube passiert ist doch von Außen 
ohnehin nicht wichtig.

> Der MQTT Client sollte auch nichts subscribed haben, sollte der Server
> über TCP was senden und bekommt kein ACK zurück so schließt er die TCP
> Verbindung.

Natürlich darf der Client auch Subscriber sein. Je nach gewähltem QoS 
schickt der Broker bei QoS 0 die Message einemal raus und erledigt oder 
versucht es mehrfach, wenn QoS 1 oder 2 ist.

Ein Publisher erhält sowieso nur eine Quittung bei QoS 1 oder 2, die 
aber vom Broker, nicht von den Subscribern.

Retain fängt ja genau den Fall ab. daß der Subscriber gerade nicht 
ereichbar ist. Er bekommt diese Message dann, wenn er mal wieder 
auftaucht.

Wenn eine Anwendung 100 Messages/s erfordert und eine ständige 
Verbindung ist wohl MQTT die falsche Wahl.

Gruß aus Berlin
Michael

von Marco H. (damarco)


Lesenswert?

Nun auf der Broker Seite fürt das zu einen Timeout im Socket. Woraus der 
Broker ein Verbindungsfehler ableitet und die Will Messages sendet.

Man kann eine Tcp auch sauber per Disconnect beenden. Ich vermute das in 
meinen TCP/IP Stack die Verbindung nicht sauber geschlossen wird. Beim 
Mqtt disconnect ist dies den Broker wurst womit es funktioniert.  Ich 
muss das nochmal prüfen.Im Grunde müßte es funktionieren.

Wenn das einfache schlafen legen mit ESP nicht zum senden der Will 
Messages führt muss auch ein TCP disconnect funktionieren.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Johannes S. schrieb:
> Und wie wird dann festgestellt das der Gegner lebt?

Garnicht, das ist ein typisches TCP Problem.
Das ist das "halb offene Verbindung" Problem.
Google mal nach ;)
Daher gibts den keep alive auf MQTT Ebene.
Der MQTT Client sendet 5min (oder andere Einstellung) lang nix?
-> Verbindung oder Client is wohl tot.

Michael U. schrieb:
> Natürlich darf der Client auch Subscriber sein.

Ja türlich, aber bei dem speziellen Fall jetzt eher nicht.
Bei dem Fall, dass die TCP Verbindung nicht geschlossen wird und man den 
Client schlafen legt.
Wenn der Client nun nen topic subscribed hat so bekommt er vom Broker ne 
Nachricht über TCP.
DANN! Fällt dem TCP STack auf, dass sich der Client nicht mehr meldet 
und macht den Socket zu
-> MQTT Broker verschickt lastwill messages.

von Marco H. (damarco)


Lesenswert?

Achso die Verbindungsdaten sind auf jeden Fall verloren.  Wenn die 
Hardware startet ich muss die Verbindungen neu aufbauen.  Wenn ein ESP 
ohne Spannung ist wird dieser auch seinen Speicherinhalt nicht mehr 
haben.

Ein PC kann viele offene Verbindungen verwalten, TCP/IP stacks in 
Controllern bekommen leicht ein Speicher Problem.

von Michael U. (amiga)


Lesenswert?

Hallo,

Marco H. schrieb:
> Nun auf der Broker Seite fürt das zu einen Timeout im Socket. Woraus der
> Broker ein Verbindungsfehler ableitet und die Will Messages sendet.

nein. Der broker sendet den LastWill wenn bis zum Ablauf der KeepAlive 
keine Verbindung zum Client mehr zustand kam. Jede Art von Verbindung 
vom Client seztzt den TimeOut zurück.

Wenn z.B. KeepAlive auf 15 Minuten gesetzt ist geht LastWill 15 Minuten 
nach dem letzten Connect zum Client raus. Wenn der sich innerhalb der 15 
Minuten irgendwie meldet, zählen die 15 Minuten wieder ab da.
Der Client darf sich nur nicht mit disconnect abmelden, das wäre ein 
gewünschtes Ende der Verbindung durch den Client. Dann wird KeepAlive 
ignoriert und es gibt auch kein LastWill.

Gruß aus Berlin
Michael

von Michael U. (amiga)


Lesenswert?

Hallo,

Marco H. schrieb:
> Achso die Verbindungsdaten sind auf jeden Fall verloren.  Wenn die
> Hardware startet ich muss die Verbindungen neu aufbauen.  Wenn ein ESP
> ohne Spannung ist wird dieser auch seinen Speicherinhalt nicht mehr
> haben.

was heißt "Verbindungsdaten" in diesem Fall? Selbstverständlich sind 
WLAN-Daten, Broker-Adresse usw. im Programm des ESP hinterlegt.
Der ESP macht ohnehin beim Neustart einen automatischen 
Verbindungsversuch zum zuletzt genutzten WLAN. Connect zum Broker usw. 
incl. Subscribes, KeepAlive, QoS schicke ich beim Aufwecken ohnehin 
raus. Müßte man nichtmal, der broker merkt sich die letzten 
Einstellunge, die der Client geschickt hat, wenn der unter seinem Namen 
wieder auftaucht. TCP/IP, IP usw. sind dem Broker dabei sowieso egal. 
Für ihn hat der Client nur einen MQTT-Namen.

Welcher Speicherinhalt sollte also erhalten bleiben? Das Programm sollte 
ein µC schon nicht vergessen. ;)

Speziell beim ESP ist sogar recht ungünstig, daß er beom WLAN-Connect 
die Zugangsparameter ins Flash schreibt, egal, ob die verändert sind 
oder nicht. Ist man erst später drüber gestolpert, kann man auch 
verhindern. Allerdings ist von meinen ca. 10 ESp8266 hier um mich rum 
noch keiner daran verstorben.

Was bleibt sind also einige Daten, die der RasPi (da läuft Mosquitto 
drauf) bis zum TCP-Timeout aufhebt, wenn ihm die Verbindung abhanden 
kommt. So lang ist das TCP-Timeout aber auch nicht, daß deshalb sein 
Speicher knapp wird...

Gruß aus Berlin
Michael

von Johannes S. (Gast)


Lesenswert?

Mw E. schrieb:
> Garnicht, das ist ein typisches TCP Problem.

gut, es gibt 2 keep alive: einmal als socket option auf TCP Level, 
einmal als MQTT option. Und da es um die Aussage ging das TCP ständig 
Daten austauscht habe ich das TCP keep alive gemeint. Ohne diese 
SO_KEEPALIVE ist totale Ruhe bei einer TCP Verbindung wenn keiner auf 
Applikationsebene was zu sagen hat.

von Marco H. (damarco)


Lesenswert?

Der Status der TCP/IP Verbindung geht verloren, da der TCP/IP Stack neu 
initialisiert wird.  Wenn dieser sich schlafen legt passiert erst mal 
nichts, wenn er aufwacht muss die Verbindung neu aufgebaut werden. Dabei 
landet er am Broker auf eine andere Socketinstance. Dann merkt er das 
der socket wo der Client ursprünglich verbunden war tot ist. Sendet die 
Will Messages usw.

Wenn man die Verbindung ordentlich schließt sendet der Broker die Will 
Messages. Das steht auch so im Protokoll -> Verbindungsfehler ... Also 
immer wenn der Client was dummes feststellt soll er die Verbindung 
unterbrechen.

Aber wir kommen dem Problem immer näher ;) . Nur zu Info ich benutze 
keinen ESP Client sondern einen µP mit eigenen MQTT Stack.

und ich werde mir was anderes einfallen lassen, da vorgesehen war das 
der Client aufwacht eine Mobilfunkverbindung aufbaut. Sein Mist sendet 
und Empfängt und sich wieder schlafen legt. Zum empfangen muss er sich 
sowie so korrekt Abmelden damit die Messages gespeichert werden.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

So also es scheint so das die Sache mit externen TCP/IP Stack -> w5500 
wirklich als dumm gelaufen bezeichnet werden kann. Beim SAMW25 verhält 
sich die Sache anders. Das Wifi kann man schlafen legen und der AP 
speichert die Pakete zwischen. Er weckt den C1500 auch auf. Ich habe es 
mit dem Code noch nicht probiert, das kommt später.

Jetzt noch eine Praktische Frage.

Mein Subscribe Handler baut die Verbindung nur beim retry wieder auf 
also wenn dieser kein SUBACK erhält versucht er es erneut. Beim 
Disconnect bekommen die Abonnierten Topics den Anfangsstatus -> nicht 
versendet.

Das Problem sie müssten sonst einen anderen Status bekommen da sonst bei 
nicht versendeten Topic nach dem disconnect die Verbindung sofort wieder 
aufgebaut würde.

Es war geplant einen refresh einzubauen. Also der Empfangshändler prüft 
wenn keine Verbindung besteht und wenn Abos vorliegen diese Zeit und 
baut dann die Verbindung auf. Womit die Subscribe Topics erneut 
registriert würden.  Wenn die Nachrichten gespeichert waren bekommt der 
Client diese nachgeliefert. Neue Abos würden erst dann mit registriert. 
Nicht sofort... ich hoffe das ist ok.

Die Verbindung wird sofort aufgebaut bei Ping oder Publish nach dem 
Socket Timeout wird die Verbindung wieder geschlossen.

: Bearbeitet durch User
von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

Es funktioniert doch mit dem w5500 :)

Schlafen legen geht nach wie vor nicht und ich wüsste auch nicht wie das 
mit dem ESP gehen sollte. Der bootet doch nach dem Aufwachen aus den 
deep sleep und der RAM Inhalt bleibt nicht erhalten.

Das Problem lag im Code an den PHY Link check, der schloss den Socket 
immer wenn man den Stecker zog. Was unter normalen Bedingungen durch aus 
akzeptabel ist. Das sorgte eben dafür das die Daten zu der Bestehenden 
Verbindung nicht passten und der Client unschön getrennt wurde.

Bis auf den Empfang von Publish messages funktioniert alles. Danach kann 
man den Code entschlacken ;)

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Meine GÜte ist da wer schwer von Kapie.
Less dir nochmal den MQTT Standard durch und wie TCP funktioniert.
Es ist MQTT EGAL ob der TCP Verbindungszustand verloren geht wenn man 
vorher kein discon schickt.

von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

Nö ist es leider nicht, tritt ein Verbindungsproblem auf wird der Client 
unschön getrennt. Das steht auch so im Standard.

Wie schon richtig erwähnt darf keiner von beiden auf die Idee kommen zu 
senden, sonst stellt einer von beiden fest das die Verbindung nicht 
vorhanden ist.

Die Empfangsfilter funktioniert auch, aus den Abonnierten Topics prüft 
der Filter die Gültigkeit und startet dann die zugehörige callback 
Funktion.

Ich überlege noch dies in einen Callback Handler zu erledigen, 
allerdings müsste ich die Daten retten was wieder Speicher kostet.

Das ursächliche Problem trat nur auf da ich ein close im TCP/Stack 
auslöste anstatt die Verbindung richtig zu beenden.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Das hatt ich doch geschrieben...
Beim schlafen gehen dürfen keine Subscriptions aktiv sein:
Beitrag "Re: MQTT Connect Disconnect"
Wer lesen kann ist klar im Vorteil!

Also vorm schlafen legen desubscriben, wenn man denn unbedingt topics 
subscribed haben muss.

von Marco H. (damarco)


Lesenswert?

oder sauberer Disconnect und die Messages mit Retain senden.

Die Performance des Codes denke ich ist auch ganz ok 100 Messages mit 
Qos 1 inkl. sie wieder auf den gleichen Client zu empfangen mit Qos 1 
laufen in ca 1,5sec durch.

na mal schauen ein paar Bugs muss ich noch beheben ;)

von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

Eine schwierige Geburt der MQTT stack auf einen ESP32 ...


Noch mit ein paar ecken ?

Sagt mal gibt es einen event Handler für den lwip wenn daten angekommen 
sind ?  oder muss ich jedes mal mal per resv(); die Rückgabe prüfen ?

Für etwas was in einer Task läuft relativ blöd .

von Marco H. (damarco)


Lesenswert?

Für alle Negativ bewerter der Code läuft jetzt stabil auf dem ESP32.

Ein schöner Bug im Teil der für eine unique PacketID sorgte griff auch 
in die Liste wenn sie leer war. Deswegen zog der Kernel immer die 
Reißleine beim reconnect, da sie dann meist leer ist ;)

Der Code ist jetzt auch etwas RTOS like..  Ich habe jetzt 6 Clients 
schon tage am laufen...

Was man schon sagen kann das der ESP32 deutlich mehr Strom braucht als 
der Winc1500.

Der Preis lockt schon das Projekt doch auf den ESP laufen zu lassen ;)

von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

Es gibt Neuigkeit :)

- URL,DNS, Websocket Support

Hat etwas gedauert da diese Fähigkeiten diverse Nebenbaustellen 
aufmachten. SHA1,base64,DNS,URI parser, http parser usw.  bis auf dem 
Random Generator alles in Software.

Läuft momentan auf einen Arduino DUE, da sich dieser einfacher debuggen 
lässt als der ESP. Auf diesen kann man dann die Hardware für SHA1 und 
TLS benutzen. TLS geht auf dem sam3x bzw. wiznet nicht.

Die performance liegt beim Websocketconnect und QOS2 bei ca 260 Messages 
in der Sekunde.

Der Websocketsupport wurde integriert da alles weitere den Code so 
aufgeblasen hätten und vieles doppelt verarbeitet würde. Viele Sachen in 
der URI kann man ja für DNS etc gebrauchen. Der HTTP parser wurde auf 
das minimale programmiert und zieht sich das aus der response was 
benötigt wird.

Aus der URL wird auch abgeleitet welchen Connect es bedarf -> 
ws://test.de -> websocket auf standard port oder ws://test.de:8000 , 
path geht auch :)

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Um die Sache etwas aufzuheitern komme ich noch mal auf die 
Ursprungsfrage des Thread zurück.

Das Geheimnis verbirgt sich hinten dem "Clean Session" Flag vom Connect.

Setzt man dieses nicht speichert der Broker alle Messages QOS1,QOS2 
zwischen, optional auch QOS0. Die Anzahl ist abhängig vom inflight Level 
im Broker. Ausschlaggebend ist die Client ID, deswegen sollte man auch 
nicht diese per ramdom erzeugen. Da sonst der Broker den Client nicht 
mehr zuordnen kann und immer wieder neue Session erzeugt.

Alle Abonnierten Themen bleiben im Broker erhalten ohne das "Clean 
Session" Flag. Ist der client nicht bekannt erzeugt der Broker eine neue 
Session. Ob die Session bekannt ist kann man am return Code vom Connect 
ACK ableiten. Dann muss man ggf. die Themen neu abonnieren.

Man kann also das Gerät schlafen legen ohne etwas zu verpassen. Man muss 
nur dafür sorgen das es ab und zu mal wieder aufwacht.

Der Stack läuft jetzt auch allen 3 Plattformen. Sam3x,SAMW25,ESP32.

Auch habe ich das Problem mit der 6 Tage Laufzeit beim ES32 vermutlich 
gefunden. Das Problem tritt auf wenn das Wifi disconnected wird oder 
auch abschmiert. Die Anwendertask prüft dann einen timeout der einen 
connection Thread startet der den Verbindungsaufbau anschiebt.

Der Teil anhält so wenige Anweisungen das dies wie eine for schleife 
ohne Bedingungen wirkt. Der Code in der Schleife ist zu gering und die 
Task kann nicht mehr durch das RTOS unterbrochen werden. Das dumme daran 
ist das ich einen Sekunden Tick durch einen Softwaretimer habe der nun 
auch nicht mehr bedient wird. So kommt das ganze nie mehr aus der 
schleife heraus. (nein es ist keine schleife ;) nach der Prüfung wird 
die Funktion verlassen, wirkt aber so da nur wenige Anweisungen 
ausgeführt werden müssen)

Das Fix jetzt kommts, ist ein vTaskdelay von 100ms also alle 100ms wird 
geschaut ob der Timeout abgelaufen ist. Die Task wird schlafen geschickt 
und der Watchdoog,Softwaretimer wird bedient. Das klingt komisch, ich 
suche auch die stelle an der ich lachen muss. Ich müsste mal nachschauen 
was der Compiler an der entsprechende stelle gebaut hat ;). Das ganze 
ist aber erklärbar. Die Last geht an der Stelle von der Anwendertask auf 
100%, das schlafen legen ist also nicht der falsche weg. Oder warten auf 
ein Event. Das würde aber zu sehr in das Codekonzept eingreifen. Es wäre 
nicht mehr auf nicht RTOS Plattformen portierbar.

: Bearbeitet durch User
von Marco H. (damarco)


Angehängte Dateien:

Lesenswert?

So das Projekt ist eine ganze Ecke weiter :) Jetzt richtig RTOS like mit 
Evenhandler und getrennten Task. Überarbeiten Socket Funktionen usw.

Anbei eine Verbindung zum AWS per TLS und MQTT. Allerdings ist hier der 
MQTT Support etwas eingeschränkt.

- Amazon unterstützt kein QOS2, bei Messages mit QOS 2 wird kein ACK 
gesendet
- beim Abonnieren mit QOS2 wird die Verbindung getrennt
- keine persistenten Verbindungen!, das cleanSession Flag ist unbedingt 
zu setzen und es betrifft auch WILL Messages, WILL QOS die nicht gesetzt 
werden dürfen. Bei nicht unterstützen Flags wird die Verbindung beendet.

Auf der Gegenseite wird ein AWS Account, Zertifikate für TLS und eine 
Policies benötigt. Sonst ist kein Verbindungsaufbau möglich.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.