NEWS
[gelöst, mit Umweg] MQTT Adapter - connect, disconnect, connect, dicsconnet
-
Hallo Zusammen,
ich habe einen Fehler bei meinen ESP8266 Controllern, den ich leider nicht gelöst bekomme.
Die Controller programmiert mittels Arduino IDE sollen mittels des MQTT Clients an den IOBroker angebunden werden.
Dies funktioniert soweit auch super. Einziges Problem ist, dass diese folgenden Fehler verursachen, sollte der MQTT Client mal z.B. durch neustart offline gehen:
IOBroker Log:
` > mqtt.0 2017-12-11 15:43:42.907 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^mqtt.0.SideboardLicht../mqtt.0 2017-12-11 15:43:42.906 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^SideboardLicht../
mqtt.0 2017-12-11 15:43:42.871 info Client [TVSchrankLicht] subscribes on "TVSchrankLicht." with regex /^mqtt.0.TVSchrankLicht../
mqtt.0 2017-12-11 15:43:42.869 info Client [TVSchrankLicht] subscribes on "TVSchrankLicht." with regex /^TVSchrankLicht../
mqtt.0 2017-12-11 15:43:42.856 info Client [SideboardLicht] connected
mqtt.0 2017-12-11 15:43:42.848 info Client [SideboardLicht] closed
mqtt.0 2017-12-11 15:43:42.833 info Client [TVSchrankLicht] connected
mqtt.0 2017-12-11 15:43:42.823 info Client [TVSchrankLicht] closed
mqtt.0 2017-12-11 15:43:41.846 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^mqtt.0.SideboardLicht../
mqtt.0 2017-12-11 15:43:41.845 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^SideboardLicht../
mqtt.0 2017-12-11 15:43:41.823 info Client [TVSchrankLicht] subscribes on "TVSchrankLicht." with regex /^mqtt.0.TVSchrankLicht../
mqtt.0 2017-12-11 15:43:41.822 info Client [TVSchrankLicht] subscribes on "TVSchrankLicht." with regex /^TVSchrankLicht../
mqtt.0 2017-12-11 15:43:41.794 info Client [SideboardLicht] connected
mqtt.0 2017-12-11 15:43:41.779 info Client [SideboardLicht] closed
mqtt.0 2017-12-11 15:43:41.754 info Client [TVSchrankLicht] connected
mqtt.0 2017-12-11 15:43:41.745 info Client [TVSchrankLicht] closed `
Ausprobiert hab ich schon mehrmals den Adapter neu zu installieren.
Den Patch für Chunking. (Damit lässt sich der MQTT jedoch nicht starten, Log: )
! host.IOBrokerServer 2017-12-11 15:48:16.293 info Restart adapter system.adapter.mqtt.0 because enabled
! host.IOBrokerServer 2017-12-11 15:48:16.293 error instance system.adapter.mqtt.0 terminated with code 0 (OK)
! host.IOBrokerServer 2017-12-11 15:48:16.293 error Caught by controller[0]: at writeOrBuffer (/opt/iobroker/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:395:5)
! host.IOBrokerServer 2017-12-11 15:48:16.292 error Caught by controller[0]: at doWrite (/opt/iobroker/node_modules/duplexify/node_modules/readable-stream/lib/_stream_writable.js:406:64)
! host.IOBrokerServer 2017-12-11 15:48:16.292 error Caught by controller[0]: at Connection.Duplexify._write (/opt/iobroker/node_modules/duplexify/index.js:201:22)
! host.IOBrokerServer 2017-12-11 15:48:16.292 error Caught by controller[0]: at Writable.write (_stream_writable.js:245:11)
! host.IOBrokerServer 2017-12-11 15:48:16.291 error Caught by controller[0]: at writeOrBuffer (_stream_writable.js:319:5)
! host.IOBrokerServer 2017-12-11 15:48:16.291 error Caught by controller[0]: at doWrite (_stream_writable.js:333:12)
! host.IOBrokerServer 2017-12-11 15:48:16.290 error Caught by controller[0]: at Writable.write [as _write] (/opt/iobroker/node_modules/mqtt-connection/lib/writeToStream.js:10:9)
! host.IOBrokerServer 2017-12-11 15:48:16.290 error Caught by controller[0]: at generate (/opt/iobroker/node_modules/mqtt-packet/writeToStream.js:32:14)
! host.IOBrokerServer 2017-12-11 15:48:16.290 error Caught by controller[0]: at suback (/opt/iobroker/node_modules/mqtt-packet/writeToStream.js:385:23)
! host.IOBrokerServer 2017-12-11 15:48:16.289 error Caught by controller[0]: at Function.Buffer.concat (buffer.js:304:24)
! host.IOBrokerServer 2017-12-11 15:48:16.288 error Caught by controller[0]: TypeError: Cannot read property 'length' of undefined
! mqtt.0 2017-12-11 15:48:15.745 info Client [SideboardLicht] closed
! mqtt.0 2017-12-11 15:48:15.745 info Client [8FachRelayHWR1] closed
! mqtt.0 2017-12-11 15:48:15.745 error TypeError: Cannot read property 'length' of undefined at Function.Buffer.concat (buffer.js:304:24) at suback (/opt/iobroker/node_modules/mqtt-packet/writeToStream.js:385:23) at generate (/
! mqtt.0 2017-12-11 15:48:15.745 error uncaught exception: Cannot read property 'length' of undefined
! mqtt.0 2017-12-11 15:48:15.745 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^mqtt.0.SideboardLicht../
! mqtt.0 2017-12-11 15:48:15.744 info Client [SideboardLicht] subscribes on "SideboardLicht." with regex /^SideboardLicht../
! mqtt.0 2017-12-11 15:48:15.744 info Client [8FachRelayHWR1] connected
! mqtt.0 2017-12-11 15:48:15.743 info Client [SideboardLicht] connected
! mqtt.0 2017-12-11 15:48:15.282 info Starting MQTT authenticated server on port 1883
! mqtt.0 2017-12-11 15:48:14.916 info Patch appliedAuch diverse Foren beiträge hab ich schon durchforstet.
Kann mir da jemand helfen? Hat jemand den gleichen Fehler schon mal beheben können?
Vielen Dank schon mal
Milo
Hier noch die Arduino Codes. Vielleicht ist da auch ein Fehler drinnen:
Meine Library:
PubSubClient MiloEspApi::initMQTT(IPAddress mq_ip, const char* mq_user, const char* mq_pass, String programmname) { PubSubClient client(espClient); _mq_name = programmname; _mq_ip = mq_ip; client.setServer(mq_ip, 1900); client.setClient(espClient); _mq_user = mq_user; _mq_pass = mq_pass; boolean isCon = false; _client = client; while(!isCon) { delay(1000); if (client.connect(_mq_name.c_str(), mq_user,mq_pass)) { log ("MQTT Client verbunden"); client.publish( (_mq_name + "/IP").c_str() , getIP().c_str()); client.subscribe( String(_mq_name + "/*").c_str()); isCon = true; } else log("Fehler beim Verbinden des MQTT Clients"); } return client; } void MiloEspApi::initMQData(String var) { initMQData(var, "INIT"); } void MiloEspApi::reconnectMQ() { //_client.disconnect(); //delay(500); if (_client.connect(_mq_name.c_str(), _mq_user,_mq_pass)) { log ("MQTT Client verbunden"); _client.publish( (_mq_name + "/IP").c_str() , getIP().c_str()); _client.subscribe( String(_mq_name + "/*").c_str()); } else log("Fehler beim Verbinden des MQTT Clients: " + _client.state()); } void MiloEspApi::initMQData(String var, String preset) { _client.publish( (_mq_name + "/" + var).c_str(), preset.c_str()); log ("Init von: " + var + " erfolgt."); delay(500); } void MiloEspApi::sendeMQ(String var, String msg) { _client.publish( (_mq_name + "/" + var).c_str(), msg.c_str()); log("Gesendet: " + var + " --> " + msg); delay(500); }
Arduino IDE:
`// setup Funktion [......] mq_client = api.initMQTT(IPAddress(192,168,22,11), "esp", "4563ML", "TestChip"); mq_client.setCallback(callback); api.log("Initiere MQDaten"); api.initMQData("Relay1",String(mDaten.pD0)); api.initMQData("Relay2",String(mDaten.pD1)); api.log("Initierung MQDaten abgeschlossen"); [........] // Callback void callback(char* topic, byte* payload, unsigned int length) { int i = 0; char message_buff[100]; String head = topic; api.log("Empfangen: " + String(topic)); // api.log("Buchstabe: " + String ( topic[strlen(topic)-1] ) ); for(i=0; i <length; i++)/{/message_buff[i]="payload[i];" }/;/string/msgstring="String(message_buff);" konvertierung/der/nachricht/in/ein/api.log("/-="">" + msgString); int r = atoi ( String(( topic[strlen(topic)-1] )).c_str() ); //api.log ("Relay gefunden: " + String(r)); int state = atoi (msgString.c_str()); switch (r) { case 1: digitalWrite(PortD0, state); api.log("Schalte PortD0 auf: " + String(state)); mDaten.pD0 = state; break; case 2: digitalWrite(PortD1, state); api.log("Schalte PortD1 auf: " + String(state)); mDaten.pD1 = state; break; } api.saveConfig(mDaten); } // Loop void loop() { if (mq_client.loop()) { } else { api.reconnectMQ(); } delay(1000); }</length;>` [/i][/i][/i]
-
Was hast du als mqtt-Broker laufen?
Gruß
Rainer
-
Ahh sorry, den internen von iobroker:
MQTT Adapter in der Version 1.3.2.
Die Einstellungen sind im Anhang.
4334_mqtt2.jpg
4334_mqtt1.jpg -
Ich schlage mich gerade mit sehr ähnlichen Problemen rum.
Schau mal hier: http://forum.iobroker.net/viewtopic.php?f=20&t=9450
Am Ende haben wir 2 Skripts für den iobroker Javascript-Adapter , die evtl. helfen könnten.
Sie starten den Adapter einfach neu.
Ich konnte mit dem Chunking Patch übrigens auch nicht arbeiten, da kamen bei mir auch Fehlermeldungen und MQTT lief gar nicht mehr.
Arbeite ebenfalls mit ESP12 8266 und der pubsub-library.
-
Ich habe mal deinen Arduino Code angeschaut.
Du benutzt da leider eine andere Library.
Wie gesagt nutze ich PubSubClient.h.
Die erscheint mir wesentlich übersichtlicher im Code.
Ob das wirklich besser ist und deinen Fehler behebt, weiß ich allerdings auch nicht.
Es gibt in denen aber auch sowas wie einen automatischen Reconnect bei Verbindungsabbruch.
Würde ich mir also mal anschauen.
Hast du deine MQTT-Library für Arduino selbst geschrieben?
-
@meome:Ich schlage mich gerade mit sehr ähnlichen Problemen rum.
Schau mal hier: http://forum.iobroker.net/viewtopic.php?f=20&t=9450
Am Ende haben wir 2 Skripts für den iobroker Javascript-Adapter , die evtl. helfen könnten.
Sie starten den Adapter einfach neu.
Ich konnte mit dem Chunking Patch übrigens auch nicht arbeiten, da kamen bei mir auch Fehlermeldungen und MQTT lief gar nicht mehr.
Arbeite ebenfalls mit ESP12 8266 und der pubsub-library. `
Das reconnecten löst leider mein Problem nicht, weil ich noch nicht einmal verbinden kann. Bei mir läuft alles, bis man den Raspi neustartet. Dann geht gar nichts mehr..
> Hast du deine MQTT-Library für Arduino selbst geschrieben?
Ich habe mir zwar eine eigene Library geschrieben, damit ich bei den verschiedenste Chips die Verbindungskomponenten nur einmal ändern muss, nutze aber dahinter den PubSubClient. Hab meine Version mal angebunden. Finde da keine Funktion reconnect?
Kannst du mir mal den Code von dir Posten?
4334_pubsubclient.h
4334_pubsubclient.cpp -
Hier ist der reconnect code im void loop():
// ============== RE-CONNECT WIFI IF NOT CONNECTED (alle 10 Sekunden für NOT-Betrieb ohne WLAN) if (WiFi.status() != WL_CONNECTED) { // Ob das funktioniert? Oder in Schleifen resultiert? Oder eingebaut in normales wificonnect? EVERY_N_MILLISECONDS(30000) { Serial.println("NO WIFI. TRY RECONNECT EVERY 30 SECONDS"); setup_wifi(); } } client.loop(); //??? Keine Ahnung // ============== MQTT Reconnect (alle 10 Sekunden versuchen, für reibungslosen Betrieb, nur wenn WLAN CONNECTED.) if ((!client.connected()) && (WiFi.status() == WL_CONNECTED)) { EVERY_N_MILLISECONDS(30000) { Serial.println("NO MQTT. TRY RECONNECT EVERY 30 SECONDS"); reconnect(); } }
void reconnect() { // ============= (RE)CONNECT TO MQTT // Loop until we're reconnected //while (!client.connected() && WiFi.status() == WL_CONNECTED) { // Hier schauen ob WLAN connected UND MQTT weg Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("labspinnen8266")) { //NAME des Boards im MQTT-Frame Serial.println("labspinnen8266 connected with MQTT"); // Once connected, publish an announcement... client.publish("lab/labspinnen8266", "labspinnen8266 connected with MQTT"); // ... and resubscribe client.subscribe("lab/labspinnen8266"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying } //} }
Prüft WLAN und MQTT. Und dann in Endlosschleife reconnect versuchen.
Das klappt bei mir eigentlich sehr gut.
Ach so: Dazu gehört noch #include <fastled.h>// LEDs and also to include command for every_n_milisecs
So habe ich den Befehl EVERY_N_MILLISECOND() integriert.
Warum das nicht zu Endlosschleifen führt, sobald der reconnect stattfindet, ist mir übrigens ein Rätsel, aber EVERY_N_MILLISECONDS scheint zu stoppen, sobald connect stattfindet.
Sorry, ich hacke mich irgendwie so durch.</fastled.h>
-
Mhh, ist leider genau das was ich auch mache
Ich hab jetzt mal den MQTT Mosquitto Broker installiert, damit ich mal ein paar logs habe.
Also der ESP verbindet sich ordnungsgemäß. Verliert dann aber die Verbindung und schmiert ab.
Folgende Fehler Codes:
Initiere MQDaten Init von: Relay1 erfolgt. Init von: Relay2 erfolgt. Init von: Relay3 erfolgt. Init von: Relay4 erfolgt. Init von: Relay5 erfolgt. Init von: Relay6 erfolgt. Init von: Relay7 erfolgt. Init von: Relay8 erfolgt. Initierung MQDaten abgeschlossen Empfangen: TestRelay/Relay1 -> 1 Schalte PortD0 auf: 0 Empfangen: TestRelay/Relay2 -> 0 Schalte PortD1 auf: 1 Empfangen: TestRelay/Relay3 -> 0 Schalte PortD2 auf: 1 Empfangen: TestRelay/Relay4 -> 0 Schalte PortD3 auf: 1 MQTT Fehlercode: -3 WLAN Status: 3 MQTT Client verbunden: RC: 0 MQTT Fehlercode: -4 WLAN Status: 3 MQTT Client verbunden: RC: 0 MQTT Fehlercode: -4 WLAN Status: 3 MQTT Client verbunden: RC: 0 MQTT Fehlercode: -4 WLAN Status: 3 MQTT Client verbunden: RC: 0 MQTT Fehlercode: -4 WLAN Status: 3
Mosquitto Logfile
1513167749: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167750: Socket error on client TestRelay, disconnecting. 1513167804: Saving in-memory database to /var/lib/mosquitto/mosquitto.db. 1513167818: New connection from 192.168.22.170 on port 1900. 1513167818: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167839: Client TestRelay has exceeded timeout, disconnecting. 1513167839: Socket error on client TestRelay, disconnecting. 1513167839: New connection from 192.168.22.170 on port 1900. 1513167839: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting. 1513167848: New connection from 192.168.22.170 on port 1900. 1513167848: New client connected from 192.168.22.170 as TestRelay (c1, k15, u'esp'). 1513167848: Socket error on client TestRelay, disconnecting.
Auffällig ist auch, dass der bis Relay4 funktioniert. Wenn ich das Init beobachte, dann scheint iwas zwischen Relay4 und 5 zu passieren. Weil hier braucht die Ausgabe deutlich länger….
-
Es ist tatsächlich so. Wenn ich bis Relay4 nur gehe, dann kommen keine Verbindungsabbrüche
-
Soooooooo,
> Es ist tatsächlich so. Wenn ich bis Relay4 nur gehe, dann kommen keine Verbindungsabbrüche :cry: :cry:
des Rätsels Lösung heißt:_client.loop();
Hinter den Aktionen (publish & subscribe) muss ein loop ausgeführt werden. Sonst scheint ein Puffer oder dergleichen voll zu laufen.
` > ich habe einen Fehler bei meinen ESP8266 Controllern, den ich leider nicht gelöst bekomme.
Die Controller programmiert mittels Arduino IDE sollen mittels des MQTT Clients an den IOBroker angebunden werden.
Dies funktioniert soweit auch super. Einziges Problem ist, dass diese folgenden Fehler verursachen, sollte der MQTT Client mal z.B. durch neustart offline gehen: `
Das Rätsel mit Chunk Patch konnte ich zwar nicht lösen, aber wenn man den MQTT Adapter von IO Broker als Client laufen lässt und dazu den Mosquitto benutzt, so funktioniert alles. Auch nach einem Systemneustart, meldet sich mein ESP wieder an und es kommt nicht zu Verbindungsabbrüchen. Werde das mal ne Zeitlang testen und jetzt erstmal so in den Hauptbetrieb geben.
Vielen Dank an allen die geholfen haben!
-
Leider sagen mir die Fehlercodes gar nichts.
Ist schon seltsam. Ich denke aber, du solltest dir den Arduino Code nochmal angucken.
MQTT ist es ja egal, wie viel gesendet wird? Oder vlt. wird zu schnell hintereinander gesendet und irgendein Puffer wird zu voll?
Mir ist noch aufgefallen, dass du ganz andere MQTT-Server Einstellungen hast als ich:
Ich habe im MQTT Adaper Einstellungen ALLES deaktiviert, außer: Sende auch Zustände (ack=true).
und ich verwende kein SSL-Passwort.
Vielleicht hat's auch was damit zu tun?
Ansonsten ist mir dein Arduino Code leider schon zu hoch :oops: Sorry. Ich steig da nicht ganz durch.
Ich habe einfach immer das genommen, was in den Beispielen vorgegeben wird, und dann nur ein bisschen abgeändert
-
Ah ja, den client.loop() hatte ich ja auch in meinem Code drin.
Ich wusste/weiß nicht, was der macht.
Meinst du, ich muss ihn ein zweites Mal einbauen? An einer bestimmten Stelle?
Vielleicht würden dann ja auch meine Abbrüche endlich aufhören.
Wo genau hast du ihn hingesetzt?
-
@meome:Ah ja, den client.loop() hatte ich ja auch in meinem Code drin.
Ich wusste/weiß nicht, was der macht.
Meinst du, ich muss ihn ein zweites Mal einbauen? An einer bestimmten Stelle?
Vielleicht würden dann ja auch meine Abbrüche endlich aufhören.
Wo genau hast du ihn hingesetzt? `
Ich habe den jetzt einfach mal großzügig hinter jede Publish und Subscribe Aktion gesetzt. Dadurch wird der ESP auf einmal mega schnell und sendet und empfängt ohne Probleme.
void MiloEspApi::initMQData(String var, String preset) { if (_client.connected() ) { _client.publish( String(_mq_name + "/" + var).c_str(), preset.c_str()); _client.subscribe( String(_mq_name + "/" + var).c_str()); _client.loop(); log ("Init von: " + var + " erfolgt."); } } } void MiloEspApi::sendeMQ(String var, String msg) { if (_client.connected() ) { _client.publish( String(_mq_name + "/" + var).c_str(), msg.c_str()); log("Gesendet: " + var + " --> " + msg); //delay(500); _client.loop(); } }
Zur Erklärung: sendeMQ und initMQDaten sind einfache Funktionen. Du kannst das ganze MiloEspApi:: weglassen, wenn du alles in der Arduino IDE programmierst und dir da eigene Sendefunktionen bauen.
Hier nochmal Auszug aus der Api
` > boolean loop ()
This should be called regularly to allow the client to process incoming messages and maintain its connection to the server.
Returns
false - the client is no longer connected
true - the client is still connected `
-
Danke für's Feedback.
Hab mal in Api reingeschaut. Ich denke, den client.loop ein Mal mitten im loop void zu haben dürfte reichen.
Aber mehr schadet sicher auch nicht
Dann herzlichen Glückwunsch und noch viel Erfolg.
Und wenn dein iobroker-MQTT-Server-Adapter manchmal einfach so abstürzt (rot wird) und nicht zurück kommt - und du dafür den Grund rausfindest, dann melde dich gern nochmal
-
@meome:Danke für's Feedback.
Hab mal in Api reingeschaut. Ich denke, den client.loop ein Mal mitten im loop void zu haben dürfte reichen.
Aber mehr schadet sicher auch nicht
Dann herzlichen Glückwunsch und noch viel Erfolg.
Und wenn dein iobroker-MQTT-Server-Adapter manchmal einfach so abstürzt (rot wird) und nicht zurück kommt - und du dafür den Grund rausfindest, dann melde dich gern nochmal `
So werde ich mich melden