INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
ESP8266+PubSubClient und MQTT/ioBroker
15.12.2019, 08:44 (Dieser Beitrag wurde zuletzt bearbeitet: 15.12.2019 08:51 von Arduino4Fun.)
Beitrag #1
ESP8266+PubSubClient und MQTT/ioBroker
Hallo,

ich nutze aktuell diverse ESP8266/ESP32 als IoT Geräte. Eines als kleine Wetterstation mit Außensteckdosen. Außenlichtsteuerung usw.

Zur Zusammenführung nutze ich derzeit ein Raspi3 mit ioBroker/MQTT und NodeRed. Auf den ESPs verwende ich unter "Arduino" den PubSubClient von Nick O’Leary.

Nun habe ich ein paar Fragen und hoffe auf ein paar Hinweise von euch

1. Reconnect
Im "mqtt_esp8266" Demo erfolgt das Verbinden/Neuverbinden über void reconnect() und verbleibt einer endlos-Warteschleife, falls nicht connected wird. Alle 5sec wird erneut überprüft. In einem System mit OTA schwierig, da kein Rücksprung in loop() erfolgt. Habe mit aktell überlegt, dass ich mitzähle wie häufig reconnected wird und nach 10x ESP.restart() aktiviert wird. Muss natürlich berücksichtigen, dass wichtige Aktionen abgeschlossen werden. Habt ihr Erfahrung wie häufig/Zeitraum und wie oft/hinterenander ein reconnect in der Praxis vorkommt/vorkommen kann?

(2. Aktuell noch ein Reconnect Problem)
-> hängt mit 2 zusammen, habe den Mechanismus "Sender und Empfänger mit gleichem Topic" noch nicht verstanden

3. publish und subscribe mit gleichem Topic
Bisher nutze ich Sensoren oder Größen die ausschließlich vom ESP zum ioBroker per MQTT gesendet werden und Aktuatoren, welche vom ioBroker aktiviert werden. Ich möchte nun ein z.B. Relais von beiden bedienen, sprich über den ESP per Tastendruck und per ioBroker über MQTT.

Aktuell würde ich das wie folgt umsetztem

void Reconnect
// Once connected, publish an announcement...
client.publish( "twowayTopic/relay","state" );
// ... and resubscribe
client.subscribe( "twowayTopic" );

void callback
Einkommende Nachricht nach topic und payload filtern und Relais aktivieren und Zustand speichern, damit ESP interne Logik Status erhält und KEIN senden der Änderung über client.publish( "twowayTopic/relay","state" );

void RelayButtonPressed
Zustand Relais invertieren, Relais aktivieren UND Änderung per MQTT client.publish( "twowayTopic/relay","state" ); senden

Könnte mir vorstellen, dass eine endlos Zustandsänderug bei fehlerhafter implementierung entsteht. Funktioniert mein Ansatz? Nur senden wenn die Zustandsänderung vom ESP selbst kam?

4. Zyklisches Senden oder senden nur bei Änderung
Ich lese die meisten Sensoren im 500..1000ms Rythmus ein, andere Größen auch schneller. Derzeit prüfe ich immer den neuen gegen einen gespeicherten "alten" Wert und sende nur bei Änderung. Ist dies Vorteilhaft oder nachteilig?

5. KeepAlive Botschaft
Ich habe ein Bedienteil und ein Ausgabeteil per MQTT gekoppelt und eine Bootschaft definiert, welche alle 500ms toggelt, sprich 1Hz. Nur wenn die Botschaft beidseitig kommt wird die Ein-/Ausgabe akzeptiert. Sprich bleibt die Botschaft aus erfolgt Timeout und beide Slaves melden eine Systemdegradierung. Habe nun auch "strukturell" diesen Ansatz in allen Slaves umgesetzt. Geht das eleganter per MQTT?

Wäre klasse wenn ihr mir bei der einen oder anderen Frage Rückmeldung geben würdet

Gruß Arduino4Fun
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 10:29
Beitrag #2
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hallo,

puuuh, ich versuche mal ein paar Gedanken beruhend auf meinen hier laifenden Sachen.
Allgemein: Mosquitto auf einem RaspI als Broker, dazu FHEM auf dem für die komplette Verwaltung und Steuerung.
Sensoren: bunte Mischung Tem./Feuchte Sensoren, teils 433MHz seit 10 Jahren in Betrieb. Aktuelle Sensoren bisher nur ESP8266, einer zum Test mit ESP32 seit 2 Wochen.
Sensoren in 2 Gruppen: sie senden zyklisch (meist alle 5min) ihre Werte per MQTT. Da wird PubSubClient genutzt, Sensoren gehen in DeepSleep, haben eine feste IP und kein OTA drauf.
Sensoren, die extern mit Spannung versorgt werden, mit AsynMQTT usw.
Aktoren meist geschaltete Sachen, ein paar aktuelle WALN-Steckdosen (TECKIN-Abkömmlinge) laufen mit Tasmota weil die sich ohne Eingriff darauf umflashen ließen und es meine Zwecke bisher erfüllt. Aktoren sind auch WS2812-Stripe, Laufschrift (irgenbdein zugeflogenes Pearl-Teil), IR-Sender. Alles mit OTA.
Alle Geräte senden beim Anmelden ihre IP und den RSSI-Wert über MQTT, lastWill wird gesetzt auf "Gerätename offline".
Für den ESP8266 hatte ich mal ein Beispiel im Netz gefunden, daß mit der Tiicker-Lib den WLAN- und MQTT reconnect erledigt, das läuft bei mir so stabil, daß es bleiben durfte.

Wichtige Sachen werden mit QoS 1 geschickt, damit kann sichergestellt weren, daß die Nachricht zum Broker durchkam.
Wahlweise vor Ort bedienbar sind bei mir nur die Funksteckdosen, die schicken bei Änderung immer den aktuellen Staus zurück, schon weil ich in FHEM wissen will, ob da was geschaltet wurde.

Senden nur bei Änderung ist Ansichtssache bei dem geringen Datenaufkommen. Das erfasse ich nur in FHEM beim Schreiben in die Log-Datenbank damit die nicht unnütz gefüllt wird.

Auswertung ist ja in FHEM, das erfasst alle Änderungen, Als allgemeine Nur-Anzeige für ausgewählte Sachen dient ein altes Android-Tablett im Dauerbetrieb, das ist nicht sonderlivh zuverlässig, der Webbrowser beendet sich gern mal einfach so. Sieht man ja und ist ein Touch auf das Browser-Icon. Bedienung von Geräte über den Touch wäre möglich, habe ich aber nicht eingebaut. Sehr wichtiges schickt FHEM über MQTT z.B. an die Laufschrift, Bedienung vom Handy ginge auch, nicht eingebaut. Ein paar direkte Sachen habe ich auf eine Ebene meiner alten Philips-Fernbedienung untergebracht, geht dann über IR-Receiver als MQTT weiter, entweder als direkter MQTT Schaltbefehl an das Gerät oder an FHEM zur weiteren Auswertung.

Ist jetzt erstmal nur ein Abriß, keine Ahnung ob es Dir nutzt...

Gruß aus Berlin
Michael
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 10:59
Beitrag #3
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hi,

danke für die ausführliche Beschreibung. Bisher hat die Nutzung von MQTT publish und subscribe ONLY auch funktioniert. Sprich, abonieren einer Nachrricht und Nutzung im ESP ist problemlos. Das Senden bzw. publishen von Daten zum Broker funktioniert problemlos.

Die Kombination macht es. Nachdem ich es in meiner "größeren" Apllikation nicht hinbekommen habe, bin ich auf eine Minimallösung umgestiegen.

Wemos D1 mini, Button und Relay Shield mit erweitertem "mqtt_esp8266" Demo. Nur Taste einlesen "OneButton" und Relay setzten.

Hier hänge ich nun. Im Broker kann ich das Relais mit dem Zustand des "inTopc", welches subscript wurde, ansteuern, sprich 0 oder 1. Bediene ich die Taste auf dem ESP und sende den Zustand ebenfalls auf dem "inTopic" (ist dies erlaubt?) siehe ich keine Zustandsänderung im Broker.

Also mein Problem ist die beidseitige Änderung des Zustandes durch ESP UND Broker. Habe keine vergleichbare Nutzung bzw. Demo im Web gefunden. Hat jemand ähnliche Struktur?

Gruß Arduino4Fun
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 11:19
Beitrag #4
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hallo,

ich vermeide das zwar eher, aber einen topic abonieren, den man mit publish auch selber schickt, ist kein Problem und ging hier bisher immer. Habe ich manchmal zur Fehlersuche genutzt. Stimmen Deine topic-Namen? Da baue ich mir auch gern Fehler ein... Ansonsten eben MQTTfx o.ä. anwerfen und schauen, was Du da alles schickst.

Gruß aus Berlin
Michael
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 11:39
Beitrag #5
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hallo,

war mein Fehler durch copy == als Zuweisung statt =

Hier mein Demo Code

Code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "OneButton.h"

#define PUBLISH_1 1
#define PUBLISH_2 1

const int     PIN_Button = D3;
const int     PIN_Relay  = D1;

const char*   ssid = "...";
const char*   password = "...";

IPAddress     gateway( 192,168,178,1 );         // IP-Adresse des WLAN-Gateways
IPAddress     subnet( 255,255,255,0 );          // Subnetzmaske
IPAddress     ip( 192,168,178,... );            // feste IP-Adresse für den WeMos
const char*   MQTT_Server = "192.168.178....";   // MQTT-Server ioBroker

WiFiClient    espClient;
PubSubClient  client(espClient);
OneButton     button( PIN_Button, true);

long          lastMsg = 0;
char          msg[50];
int           value  = 0;

void setup_wifi()
{
  delay(10);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.config( ip,gateway,subnet );
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if( strcmp( topic,"HM/Demo/inTopic1")==0 )
  {
    if ((char)payload[0] == '1')
    {
      digitalWrite( BUILTIN_LED, LOW );  
      digitalWrite( PIN_Relay,HIGH );
    }
    else
    {
      digitalWrite( BUILTIN_LED, HIGH );  
      digitalWrite( PIN_Relay,LOW );
    }
  }
}

void reconnect()
{
  while( !client.connected() )
  {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if( client.connect( clientId.c_str() ))
    {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("HM/Demo/OutTopic1", "0");
      client.publish("HM/Demo/OutTopic2", "1");
  #if( PUBLISH_1 == 1)
      client.publish("HM/Demo/inTopic1","0");     // Notwendig "publish und subscribe"???
  #endif
      // ... and resubscribe
      client.subscribe("HM/Demo/inTopic1");
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup()
{
  pinMode( PIN_Relay, OUTPUT);  
  pinMode( BUILTIN_LED, OUTPUT);
  button.attachClick( Button_Pressed );
  
  Serial.begin(115200);
  
  setup_wifi();
  
  client.setServer(MQTT_Server, 1883);
  client.setCallback(callback);
}

bool IsOn = false;
void Button_Pressed()
{
  int relay_value = 0;
  IsOn = !IsOn;

if( IsOn==true ){ relay_value=1; }else{ relay_value=0; }

  digitalWrite( PIN_Relay,IsOn );
  digitalWrite( BUILTIN_LED,!IsOn );  
  #if( PUBLISH_2 == 1)
    snprintf( msg,50,"%d",relay_value );
    client.publish("HM/Demo/inTopic1", msg);
    Serial.println("Send relay data vio MQTT");
  #endif
}

void loop()
{
  button.tick();

if( !client.connected() )
{
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastMsg > 2000)
  {
    lastMsg = now;
    ++value;
    snprintf (msg, 50, "hello world #%ld", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("HM/Demo/OutTopic1", msg);
  }
}

Mit PUBLISH_2 = 0 wird gar nicht gesendet, sprich Broker bekommmt nicht mit. Bei PUBLISH_1 =0 oder =1 sehe ich keine Unterschied. Ist der Ansatz aus der "MQTT-Logik" so o.k.?
Nach dem Betätigen der Taste und senden der Botschaft bekomme ich die gleiche vom Broker zurück, habe sie ja subscribt

Vom Broker bekomme ich folgenden LOG nach Start des Wemos
Code:
mqtt.0    2019-12-15 11:35:50.295    info    Client [ESP8266Client-c4b9] connection closed: Error: read ECONNRESET
mqtt.0    2019-12-15 11:35:50.286    info    Client [ESP8266Client-4e3b] publishOnSubscribe
mqtt.0    2019-12-15 11:35:50.285    info    Client [ESP8266Client-4e3b] subscribes on "mqtt.0.HM.Demo.inTopic1"
mqtt.0    2019-12-15 11:35:50.215    info    Client [ESP8266Client-4e3b] connected with secret ...

Gruß Arduino4Fun
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 12:02 (Dieser Beitrag wurde zuletzt bearbeitet: 15.12.2019 12:04 von amithlon.)
Beitrag #6
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hallo,

ich komme im Moment nicht dazu, genauer reinzuschauen, als Anhang mal ein Sketch von einer Norma-WLAN-Steckdose. Prizipiell sieht das alles im Grundgerüst bei mir ähnlich aus bei den Sachen, die ständig am Strom hängen.
Verbindungsverlust wird über die callBacks erledigt.

Auf den ESPs gewinnt bei mir die Bequenlichkeit, deshalb die Nutzung der String-Klasse statt char-Arrays...

Gruß aus Berlin
Michael


Angehängte Datei(en)
.ino  ESP_sonoff-3_Norma-asyncMQTT.ino (Größe: 6,49 KB / Downloads: 94)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 12:12 (Dieser Beitrag wurde zuletzt bearbeitet: 15.12.2019 12:13 von Arduino4Fun.)
Beitrag #7
RE: ESP8266+PubSubClient und MQTT/ioBroker
(15.12.2019 12:02)amithlon schrieb:  Hallo,

ich komme im Moment nicht dazu, genauer reinzuschauen, als Anhang mal ein Sketch von einer Norma-WLAN-Steckdose. Prizipiell sieht das alles im Grundgerüst bei mir ähnlich aus bei den Sachen, die ständig am Strom hängen.
Verbindungsverlust wird über die callBacks erledigt.

Auf den ESPs gewinnt bei mir die Bequenlichkeit, deshalb die Nutzung der String-Klasse statt char-Arrays...

Gruß aus Berlin
Michael

Hi Michael,

du verwendest anstatt PubSubClient den AsyncMqttClient. Hat dies bei Nutzung mit ESPs Vorteile? Werde mir deinen Code detailliert anschauen.

Danke und Gruß Arduino4Fun
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
15.12.2019, 12:27
Beitrag #8
RE: ESP8266+PubSubClient und MQTT/ioBroker
Hallo,
ich habe bei mir auch einen kleinen MQTT-Zoo laufen.
Beteiligte Komponenten:
ein RasPi 3B mit Mosquitto als MQTT-Broker, angebunden über Ethernet
ein Mega2560 mit PubSubClient, angebunden über Ethernet
ein ESP8266 mit PubSubClient, angebunden über Ethernet und OTA über WiFi
ein ESP8266 mit PubSubClient, angebunden über WiFi und OTA über WiFi

zum Reconnect:
Üblicherweise steht der Aufruf
Code:
client_MQTT.loop();
im loop() des ESP.
Das habe ich bei mir anders gelöst.
In loop() des ESP kann man sich leicht ( mit millis() ) einen Taktgeber bauen der Funktionen z.B. jede Sekunde oder alle fünf Sekunden aufruft.
Damit rufe ich jede Sekunde
Code:
void startPubSubClient() {
  if (!client_MQTT.connected()) {

    if (client_MQTT.state() == -3) {
      client_MQTT.disconnect();
      // Hier restart/reconnect WiFi einfügen
    }
    
  }

  else {
    // Client connected
    client_MQTT.loop();
  }
}
Ist alles in Ordnung wird "client_MQTT.loop();" also nur jede Sekunde einmal ausgeführt. (Das hilft wahrscheinlich auch den ESP per OTA leichter erreichbar zu machen)
Kaum dokumentiert aber vorhanden ist client_MQTT.state().
Ein Blick in die <PubSubClient.h> zeigt:
Code:
...
// Possible values for client.state()
#define MQTT_CONNECTION_TIMEOUT     -4
#define MQTT_CONNECTION_LOST        -3
#define MQTT_CONNECT_FAILED         -2
#define MQTT_DISCONNECTED           -1
#define MQTT_CONNECTED               0
#define MQTT_CONNECT_BAD_PROTOCOL    1
#define MQTT_CONNECT_BAD_CLIENT_ID   2
#define MQTT_CONNECT_UNAVAILABLE     3
#define MQTT_CONNECT_BAD_CREDENTIALS 4
#define MQTT_CONNECT_UNAUTHORIZED    5
...
Damit kann man dann leichter auf Fehlersuche gehen wenn der PubSubClient mal nicht so läuft wie er soll.
Bei -3 also MQTT_CONNECTION_LOST kann man z.B. erst mal versuchen über WiFi.disconnect(); mit anschließendem Reconnect den PubSubClient wieder zu beleben und muss nicht gleich zum Holzhammer ESP.restart(); greifen.

Wegen der "Bedienung" eines Topics von zwei oder mehreren Stellen solltest du auf jeden Fall dem MQTT Broker den letzten Zustand mitteilen. Sonst schauen andere Subscriber für dieses Topic in die Röhre.
Es ist auch normalerweise kein Problem für einen MQTT-Client gleichzeitig Publisher und Subscriber für das gleiche Topic zu sein.
Sollte das nicht funktionieren schau dir die Namensvergabe des Topics noch mal auf gleiche Schreibweise an.

Ansonsten kann ich nur noch MQTT.fx als Hilfsmittel auf dem PC empfehlen um einen Überblick über alle Topics zu behalten und Dubletten mit (fast) gleicher Schreibweise zu finden.

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  ESP8266: ADC und Webserver stw 19 2.019 Gestern 01:03
Letzter Beitrag: Bitklopfer
  ESP8266 - MQTT Probleme mit SSL decrypt tenor 8 184 22.09.2020 19:33
Letzter Beitrag: tenor
Lightbulb SPIFFS DOWNLOAD UPLOAD & DELETE Esp8266 NodeMCU Fips 31 24.293 05.09.2020 19:59
Letzter Beitrag: guenni71
  ESP8266 Datenlogger für Google Sheets xuino 3 336 31.08.2020 14:43
Letzter Beitrag: hotsystems
  Esp8266 GPIO default In- oder Out-put? N1d45 0 283 29.08.2020 06:58
Letzter Beitrag: N1d45
  WeMos D1 mini ESP8266 error: <bits/c++config.h> AnFi 17 4.600 27.08.2020 13:47
Letzter Beitrag: dna
  ESP8266 AP-Modus Android N1d45 2 415 20.08.2020 07:58
Letzter Beitrag: N1d45
  ESP8266 über AT-Befehle Jens Jung 2 441 19.08.2020 15:08
Letzter Beitrag: Jens Jung
  ESP8266 core for Arduino 2.7.0 Fips 15 3.012 09.07.2020 07:01
Letzter Beitrag: Fips
  Erster Versuch mit "ESP8266 NodeMCU V3" Mathias 6 1.084 03.07.2020 18:14
Letzter Beitrag: Mathias

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 2 Gast/Gäste