MQTT / NodeMCU in beide Richtungen kommunizieren

Hallo Commutity,

ich habe vom Symcon Event 2021 aus der Hardware Session noch den NodeMCU herum liegen und möchte mir nun einen Controller für eine LED Beleuchtung bauen. Dabei möchte ich im IPSymcon den Helligkeitswert per MQTT an den NodeMCU übertragen und dieser schaltet dann über den digitalen Ausgang die Helligkeit.

Die Kommunikation vom NodeMCU zu Symcon funktioniert soweit, beim Initialisieren kommen die RGBW Werte an ! Allerdings komme ich nicht weiter in die andere Richtung, wenn ich die Variablen im Webfront verändere passiert auf dem NodeMCU nichts.

Ich habe hierzu im Forum folgendes Thema gefunden

MQTT mit PubSubClient auf NodeMCU

und einige Komponenten aus dem Codebeispiel von @Silberstreifen übernommen, leider komme ich dabei nicht weiter ! Muss auf Serverseite dazu noch was konfiguriert werden ?

Hier mal mein Code, kann mir jemand einen Tipp geben ?

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <MQTT.h>

WiFiClient WiFi_Client;
MQTTClient MQTT_Client(512);

// ****************************************
// WLAN und MQTT Konfirugation
// ****************************************
const char* wifi_ssid   = "Gast-WiFi";
const char* wifi_key    = "Gast-Zugang!";
const char* mqtt_host   = "192.168.1.35";         // Symbox

const char* host        = "LED01";
String mqtt_topic       = "LED_CONTROL/"+String(host)+"/";

// ****************************************
// Variablen
// ****************************************
bool LED_Init = true;
int LED_R = 11;
int LED_G = 22;
int LED_B = 33;
int LED_W = 44;


// ****************************************
// MessageReceived
// ****************************************
void MessageReceived(String &topic, String &payload) {
  MQTT_Client.publish(mqtt_topic+"DEBUG", topic + " = " + payload);
}

// ****************************************
// Connect to WIFI + MQTT
// ****************************************
void connect() {
  // WiFi
  if(WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN,HIGH);
    delay(500);
    Serial.print("Connecting to WiFi ("+String(wifi_ssid)+")..");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(200);
    }
    Serial.println(" OK!");
    digitalWrite(LED_BUILTIN,LOW);
  }
  // MQTT
  if(WiFi.status() == WL_CONNECTED) {
    if(!MQTT_Client.connected()) {
      digitalWrite(LED_BUILTIN,HIGH);
      delay(500);
      Serial.print("Connecting to MQTT Host ("+String(mqtt_host)+")..");
      while(!MQTT_Client.connect("","","")){
        Serial.print(".");
        delay(200);
      }
      Serial.println(" OK!");
      digitalWrite(LED_BUILTIN,LOW);
    }
  }
}

// ****************************************
// WIFI und MQTT starten  
// ****************************************
void setup() {
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(D1,OUTPUT);
  Serial.begin(6900);
  WiFi.mode(WIFI_STA);
  WiFi.hostname(host);
  WiFi.begin(wifi_ssid, wifi_key);
  MQTT_Client.begin(mqtt_host, WiFi_Client);
  MQTT_Client.onMessage(MessageReceived);
}





// ****************************************
// ****************************************
// Loop()
// ****************************************
// ****************************************
void loop() {

  connect();
  digitalWrite(LED_BUILTIN,LOW);

  if (LED_Init==true){
    // Variablen Initialisieren
    MQTT_Client.publish(mqtt_topic+"DEBUG","INIT");
    MQTT_Client.publish(mqtt_topic+"STATUS_R",String(LED_R));
    MQTT_Client.publish(mqtt_topic+"STATUS_G",String(LED_G));
    MQTT_Client.publish(mqtt_topic+"STATUS_B",String(LED_B));
    MQTT_Client.publish(mqtt_topic+"STATUS_W",String(LED_W));
    LED_Init = false;
  }

  MQTT_Client.loop();

}

Schöne Grüße
Andreas

gucke Dir mein Beispiel nochmal in Ruhe an. Du musst das Subscribe einbauen, dann wird es gehen. Dann kannst Du auch Nachrichten an den ESP schicken.

Hi Silberstreifen,

danke für die Rückmeldung, wenn man schon abschreibt, sollte man richtig abschreiben :slight_smile:
ich habe noch einiges umgebaut, leider funktioniert es noch nicht ! Ich hätte jetzt erwartet, dass im MessageReceived() die empfangene Meldung auf meine DEBUG Variable geschrieben und an Symcon zurück gesendet wird, was aber nicht passiert.

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>
#include <MQTT.h>

WiFiClient WiFi_Client;
MQTTClient MQTT_Client(512);

// ****************************************
// WLAN und MQTT Konfirugation
// ****************************************
const char* host        = "LED01";

const char* wifi_ssid   = "WiFi";
const char* wifi_key    = "PassWord!";

const char* mqtt_host   = "192.168.1.35";         // Symbox

String mqtt_topic       = "LED_CONTROL/"+String(host)+"/";

// ****************************************
// Variablen
// ****************************************
String DEBUG = "INIT";
int LED_R = 11;
int LED_G = 22;
int LED_B = 33;
int LED_W = 44;


// ****************************************
// Variablen initialisieren
// ****************************************
void initialisieren() {
  MQTT_Client.publish(mqtt_topic+"DEBUG", DEBUG);
  MQTT_Client.publish(mqtt_topic+"STATUS_R",String(LED_R));
  MQTT_Client.publish(mqtt_topic+"STATUS_G",String(LED_G));
  MQTT_Client.publish(mqtt_topic+"STATUS_B",String(LED_B));
  MQTT_Client.publish(mqtt_topic+"STATUS_W",String(LED_W));
}

// ****************************************
// MessageReceived
// ****************************************
void MessageReceived( String &topic, String &payload) {
  DEBUG = topic + " = " + payload;
  Serial.println("Received : "+DEBUG);
  MQTT_Client.publish(mqtt_topic+"DEBUG", DEBUG);
  if(topic == mqtt_topic+"reset") ESP.restart();
}

// ****************************************
// Connect to WIFI + MQTT
// ****************************************
void connect() {
  // WiFi
  if(WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN,HIGH);
    delay(500);
    Serial.print("Connecting to WiFi ("+String(wifi_ssid)+")..");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(200);
    }
    Serial.println(" OK!");
    digitalWrite(LED_BUILTIN,LOW);
  }
  // MQTT
  if(WiFi.status() == WL_CONNECTED) {
    if(!MQTT_Client.connected()) {
      digitalWrite(LED_BUILTIN,HIGH);
      delay(500);
      Serial.print("Connecting to MQTT Host ("+String(mqtt_host)+")..");
      while(!MQTT_Client.connect("","","")){
        Serial.print(".");
        delay(200);
      }
      Serial.println(" OK!");
      MQTT_Client.subscribe(mqtt_topic+"reset");
      digitalWrite(LED_BUILTIN,LOW);
    }
  }
}

// ****************************************
// WIFI und MQTT starten  
// ****************************************
void setup() {
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(D1,OUTPUT);
  Serial.begin(9600);
  Serial.println("\n\n-------\n START\n-------\n");
  WiFi.mode(WIFI_STA);
  WiFi.hostname(host);
  WiFi.begin(wifi_ssid, wifi_key);
  MQTT_Client.begin(mqtt_host, WiFi_Client);
  MQTT_Client.onMessage(MessageReceived);
  connect();
  initialisieren();

  ArduinoOTA.setHostname(host);
  ArduinoOTA.setPassword("");
  ArduinoOTA.begin();
}


// ****************************************
// ****************************************
// Loop()
// ****************************************
// ****************************************
void loop() {

  ArduinoOTA.handle();
  if(!MQTT_Client.connected())connect();
  MQTT_Client.loop();


}

Nach dem Event hatte ich mich auch kurz mit dem Skript versucht und gequält. Dann habe ich die guten Ratschläge befolgt und den NodeMCU mit Tasmota geflashed. Dazu das Modul Tasmota2MQTT von @KaiS.
Dann gibt es kein Halten mehr und du kannst dich mehr mit den tausenden Möglichkeiten befassen als mit dem Skript zu quälen.

@Dolzman Soviel ich davon verstehen, wenn Du im Gast WiFi bist kannst Du nicht in ein anderes Netzwerk kommen. Ev liegt es einfach nur daran ;-(

@Helmut Ich hatte die WLAN Daten nur für den Beitrag verändert, real bin ich natürlich im Haupt WLAN und die Daten kommen ja auch korrekt im IPS an, nur mit der Gegenrichtung habe ich Probleme

@Ubari Das Modul werde ich mir mal anschauen

Wenn die Kommunikation in beide Richtungen funktioniert, werde ich mir einen Satz NodeMCU´s bestellen und habe schon ganz viele Ideen was man damit machen kann.

So, ich habe jetzt den Code mal 1:1 übernommen irgendwas funktioniert noch nicht !

Frage: Wenn man im connect() den mqtt_client.subscribe(Topic+"/reset"); absetzt dann müsste dieser doch direkt im MessageReceived() ankommen und per print im Terminal rausgeschrieben werden oder ? Selbst hier bekomme ich keine Message.

im IPS mache ich folgendes:
die TOPICS kommen im MQTT Server Konfigurator an, ich erstelle die Variablen und verändere diese dann im Webfront. Benötige ich jetzt nochmal ein Action Script oder wird so die Variablenänderung auch an den Client gesendet ?

Hast du auch eine Instanz in IPS mit dem reset topic erstellt?
IPS sendet nur die Werte von topics an die Geräte welche dieses topic abboniert haben.
Michael

wenn Du z.B. „Status_R“ an den ESP senden willst, dann musst Du auf dem ESP eine subscribe-Nachricht generieren, damit dieser sich bei IPS als empfangsbereit anmeldet.

MQTT_Client.subscribe(mqtt_topic+"Status_R");

Einfach diese Zeile unter der anderen subscribe-Zeile ergänzen.
In Symcon musst Du dann den Wert mit RequestAction oder im Webfront ändern. Sonst wird nichts gesendet.

So, jetzt funktionierts !
Ich dachte, wenn die Topics veröffentlicht wurden, dann empfängt er diese auch, es hat hier tatsächlich das Abonnieren der Topics gefehlt ! War also ein Anfängerfehler von einem MQTT Neuling :slight_smile:

ich habe jetzt im void initialisieren() die Topics veröffentlich und abboniert, dann funktioniert es auch !

Zur Vollständigkeit hier der nun laufende Code,
Vielen Dank für eure Hilfestellung !

Gruß
Andreas

#include <ESP8266WiFi.h>
#include <MQTT.h>

WiFiClient WiFi_Client;
MQTTClient MQTT_Client(512);

// ****************************************
// WLAN und MQTT Konfirugation
// ****************************************
const char* host        = "LED01";

const char* wifi_ssid   = "deineWiFiSSID";
const char* wifi_key    = "deinWiFiPW";

const char* mqtt_host   = "192.168.1.35";         // Symbox

String mqtt_topic       = "LED_CONTROL/"+String(host)+"/";

// ****************************************
// Variablen
// ****************************************
String DEBUG = "INIT";
int LED_R = 0;  // 0 - 255
int LED_G = 0;  // 0 - 255
int LED_B = 0;  // 0 - 255
int LED_W = 0;  // 0 - 255

// ****************************************
// Variablen initialisieren
// ****************************************
void initialisieren() {
  Serial.println("Initialisierung");
  // Topics initialisieren
  MQTT_Client.publish(mqtt_topic+"DEBUG", DEBUG);
  MQTT_Client.publish(mqtt_topic+"STATUS_R",String(LED_R));
  MQTT_Client.publish(mqtt_topic+"STATUS_G",String(LED_G));
  MQTT_Client.publish(mqtt_topic+"STATUS_B",String(LED_B));
  MQTT_Client.publish(mqtt_topic+"STATUS_W",String(LED_W));
  delay(200);
  // Topics abbonieren
  MQTT_Client.subscribe(mqtt_topic+"DEBUG");
  MQTT_Client.subscribe(mqtt_topic+"STATUS_R");
  MQTT_Client.subscribe(mqtt_topic+"STATUS_G");
  MQTT_Client.subscribe(mqtt_topic+"STATUS_B");
  MQTT_Client.subscribe(mqtt_topic+"STATUS_W");
  delay(200);
}

// ****************************************
// MessageReceived
// ****************************************
void MessageReceived( String &topic, String &payload) {
  if (DEBUG!="INIT") {
    DEBUG = topic + " = " + payload;
    Serial.println("Received Message : "+DEBUG);
    MQTT_Client.publish(mqtt_topic+"DEBUG", DEBUG);

    if(topic == mqtt_topic+"STATUS_R") LED_R=atoi(payload.c_str());
    if(topic == mqtt_topic+"STATUS_G") LED_G=atoi(payload.c_str());
    if(topic == mqtt_topic+"STATUS_B") LED_B=atoi(payload.c_str());
    if(topic == mqtt_topic+"STATUS_W") LED_W=atoi(payload.c_str());
  }
}

// ****************************************
// Connect to WIFI + MQTT
// ****************************************
void connect() {
  // WiFi
  if(WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_BUILTIN,HIGH);
    delay(500);
    Serial.print("Connecting to WiFi ("+String(wifi_ssid)+")..");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(200);
    }
    Serial.print("OK  (Eigene IP: ");
    Serial.print(WiFi.localIP());
    Serial.println(")");
    digitalWrite(LED_BUILTIN,LOW);
  }
  // MQTT
  if(WiFi.status() == WL_CONNECTED) {
    if(!MQTT_Client.connected()) {
      digitalWrite(LED_BUILTIN,HIGH);
      delay(500);
      Serial.print("Connecting to MQTT Server ("+String(mqtt_host)+")....");
      while(!MQTT_Client.connect("","","")){
        Serial.print(".");
        delay(200);
      }
      Serial.println("OK");
      digitalWrite(LED_BUILTIN,LOW);
    }
  }
}

// ****************************************
// WIFI und MQTT starten  
// ****************************************
void setup() {
  pinMode(LED_BUILTIN,OUTPUT);
  pinMode(D1,OUTPUT);
  Serial.begin(9600);
  Serial.println("\n\n=========\n= START =\n=========\n");
  WiFi.mode(WIFI_STA);
  WiFi.hostname(host);
  WiFi.begin(wifi_ssid, wifi_key);
  MQTT_Client.begin(mqtt_host, WiFi_Client);
  MQTT_Client.onMessage(MessageReceived);
  connect();
  initialisieren();
  DEBUG="";
}

// ****************************************
// ****************************************
// Loop()
// ****************************************
// ****************************************
void loop() {

  if(!MQTT_Client.connected())connect();
  MQTT_Client.loop();

}