• Ich möchte auf dem esp Befehle über mqtt empfangen. Bisher nutze ich folgenden Weg: Mit “Nachricht = (char)payload[0];” in der callback-Funktion weise ich der Variablen Nachricht das erste Zeichen von payload zu.
    Damit steure ich dann über if-Abfragen. if(Nachricht == ‘a’) {mache dies und das}. Damit kann man natürlich keine sprechenden Befehle gestalten. Ich würde gern Zeichenketten für die Befehle nutzen.
    Ich dachte ich bekomme das über char* Nachricht hin - in einer for-Schleife mit Nachricht[i] = payload[i], klappt aber nicht 😞
    Hat jemand eine Idee, wie ich mein Ziel erreichen kann. Gern auch auf einem ganz anderen Weg 😉


  • void callback(char* topic, byte* payload, unsigned int length) {
      char *cstring = (char *) payload;
      cstring[length] = '\0';
      Serial.println(cstring);   
    }
    

    payload ist doch ein Zeiger. Kannst man den nicht mit z.B. strcmp auch gegen eine Zeichenkette vergleichen?


  • So geht es auch

    void callback(char* topic, byte* payload, unsigned int length) {
        // Die Variable leeren
        msg = "";
        for (byte i = 0; i < length; i++) {
            char tmp = char(payload[i]);
            // Wird in die Globale-Variable `msg` geschrieben.
            msg += tmp;
        }
     
        Serial.println(msg);
        updateDisplay();
    }
    

    Hier noch zwei Links die dir evtl. weiterhelfen könnten:

    Hier wird besprochen wie man auf mehrere Topics “reacten” kann, mit ein paar Einblicken in den Code:
    https://my.makesmart.net/topic/144/esp8266-und-mqtt-subscribe-auf-ein-oled-anzeigen/

    Und hier kommt der Code her den ich dir gerade gepostet hab, der durch eine Schleife die komplette Message speichert:
    https://makesmart.net/esp8266-d1-mini-mqtt/


  • Oder falls du lieber beim payload mit Strings arbeiten möchtest:

    payload[length] = '\0';
    String s = String((char*)payload);
    

    Das kannst du dann ja auch in float, int oä wandeln
    float f = s.toFloat(); oder int i= s.toInt();


  • msg in in meiner geposteten Lösung btw. auch ein String also könntest du auch die beiden Vorschläge kombinieren und schauen wie du am besten zurechtkommst @ooheinzz 👍


  • Super vielen Dank. Bin gerade beim Arbeiten und komme deswegen erst heute Abende dazu, dass auszuprobieren.


  • payload[length] = '\0';
    String s = String((char*)payload);
    Serial.print("s: ");
    Serial.println(s);
    

    klappt soweit. Der payload landet in s und wird auf dem seriellen Monitor ausgegeben.
    Ganz oben im Code - vor void setup() - habe s deklariert (String s;) In der Hoffnung überall auf s zugreifen zu können. Außerhalb von callback hat

    Serial.println(s);

    aber keine Wirkung. Es wird aber auch kein Fehler angezeigt - s wird als Variable offenbar erkannt.
    Ich möchte die Variable in if-Abfragen in anderen Funktionen verwenden.
    (Wie ich Strings miteinander vergleiche, muss ich noch rausbekommen 😉


  • Teil doch mal deinen kompletten Code, dann fällt es einfacher zu helfen.

    Strings lassen sich mit == vergleichen.

    String a = "hallo";
    String b = "hallo";
    
    if(a == "hallo"){
       // gleich
    }
    
    if(a == b){
       // gleich
    }
    

    Den Gültigkeitsbereich von Variablen nennt man Scope. Wenn du überall auf s zugreifen willst, musst du es außerhalb von Blöcken initialisieren.

    String s;
    
    void setup(){
    
    }
    
    void loop(){
    
    }
    

    Das macht s zu einer globalen Variable und du kannst von überall darauf zugreifen. Zufälligerweise habe ich dazu schon ein Video produziert, was ich demnächst veröffentlichen möchte. 👍


  • @ooheinzz schrieb:

    payload[length] = ‘\0’;
    String s = String((char*)payload);
    Serial.print("s: ");
    Serial.println(s);

    klappt soweit. Der payload landet in s und wird auf dem seriellen Monitor ausgegeben.
    Ganz oben im Code - vor void setup() - habe s deklariert (String s;) In der Hoffnung überall auf s zugreifen zu können. Außerhalb von callback hat

    Serial.println(s);

    aber keine Wirkung. Es wird aber auch kein Fehler angezeigt - s wird als Variable offenbar erkannt.
    Ich möchte die Variable in if-Abfragen in anderen Funktionen verwenden.
    (Wie ich Strings miteinander vergleiche, muss ich noch rausbekommen 😉

    Hast du vllt jn der callback s noch mal deklariert anstatt einfach nur s =… Zu nutzen?


  • @Daniel-Scheidler Das war das Problem. Ich habe s in der callback nochmal deklariert.

    Der ganze Code sieht jetzt so aus und macht was er soll.

    nclude <Arduino.h>
    #include <ESP8266WiFi.h>
    #include <PubSubClient.h> //für MQTT
    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME280.h>
    #include <ArduinoOTA.h>
    #include <Adafruit_NeoPixel.h>

    // ++++++++++++++++++++++++++++++++++++++++++ Raum auswählen ++++++++++++++++++++++++
    //#define RAUM “Schlafzimmer”
    //#define HOSTNAME “SensorSchlafzimmer”
    // --------------------------------------------
    #define RAUM “Arbeitszimmer”
    #define HOSTNAME “SensorArbeitszimmer”
    // --------------------------------------------
    //#define RAUM “Wohnzimmer”
    //#define HOSTNAME “SensorWohnzimmer”
    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    #define UPDATE_TIME 10 // UpdateRythmus für pushen der Sensor-Werte in Sekunden
    #define LED_red D4
    #define LED_blue D0 // D0 kann kein PWM
    #define LED_green D3
    #define PUSH_TEMP “temp/”
    #define PUSH_PRESURE “presure/”
    #define PUSH_HUMIDITY “humidity/”
    #define PUSH_HELLIGKEIT “helligkeit/”
    #define MQTT_SERVER “192.168.178.29”
    #define ssid “"
    #define password "

    #define MQTT_USER “mqtt”
    #define MQTT_PW “Picasso”
    #define OTA_PASSWord “Picasso”

    #define DELAYVAL 500 // NeoPixel
    #define PIN D6 // NeoPixel
    #define NUMPIXELS 32 // NeoPixel
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

    unsigned long timer1 = 0; // für Updaterythmus in der Loop
    unsigned long timer2 = 0;
    char Nachricht; //ein Zeichen
    String s;

    // Funktionen deklarieren
    void setup_wifi();
    void callback(char* topic, byte* payload, unsigned int length);
    void reconnect();
    void intPublish(int x, int var); // wandelt int in char und schickt per mqtt
    void floatPublish(int x, float var); // wandelt flaot in char und schickt per mqtt
    void subscribe(int delayOn, int delayOff);
    void printValues(); //BME 280
    void licht(int r, int g, int b, int time);
    void LichtAus(int zeitBisAus);

    WiFiClient wifiClient;
    PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
    unsigned long lastMsg = 0;
    #define MSG_BUFFER_SIZE (50)
    char msg[MSG_BUFFER_SIZE];
    int value = 0;

    Adafruit_BME280 bme; // I2C

    void setup() {
    Serial.begin(9600);
    Serial.println(F(“BME280 test”));
    setup_wifi();
    client.setServer(MQTT_SERVER, 1883);
    client.setCallback(callback);

    pinMode(LED_red, OUTPUT);
    pinMode(LED_green, OUTPUT);
    pinMode(LED_blue, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);

    if (! bme.begin(0x76, &Wire)) {
    Serial.println(“Could not find a valid BME280 sensor, check wiring!”);
    while (1);
    }

    Serial.println("-- Default Test --");
    Serial.println(“normal mode, 16x oversampling for all, filter off,”);
    Serial.println(“0.5ms standby period”);
    Serial.println();

    ArduinoOTA.setHostname(HOSTNAME);
    //ArduinoOTA.setPassword(OTA_PASSWord);
    ArduinoOTA.begin();

    // +++++++++++++++++++++++++++++++++++++++ Neo Pixel
    #if defined(AVR_ATtiny85) && (F_CPU == 16000000)
    clock_prescale_set(clock_div_1);
    #endif
    pixels.begin();

    } //void setup ended

    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ L O O P ++++++++++++++++++++++

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

    if(millis()-timer1 > UPDATE_TIME*1000){
    floatPublish(1, (bme.readTemperature()));
    floatPublish(2, (bme.readHumidity()));
    intPublish(3, (bme.readPressure() / 100.0F));
    intPublish(4, analogRead(A0));
    timer1 = millis();
    printValues();

    }
    LichtAus(10000);
    ArduinoOTA.handle();
    subscribe(50,1000);
    } // function loop ended

    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    void setup_wifi() {
    delay(10);
    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    WiFi.hostname(HOSTNAME RAUM);

    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());
    } //function setup_wifi ended

    void callback(char* topic, byte* payload, unsigned int length) {
    Serial.print(“Nachricht eingegangen [”);
    Serial.print(topic);
    Serial.print("] ");
    for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    }
    Serial.println();
    String topicStr = topic;

    Nachricht = (char)payload[0];

    payload[length] = ‘\0’;
    s = String((char*)payload);
    Serial.print("s: ");
    Serial.println(s);

    } // function callback ended

    void reconnect() {
    while (!client.connected()) {
    Serial.print(“Attempting MQTT connection…”);
    String clientId = “ESP8266Client-”;
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str(), MQTT_USER, MQTT_PW))
    {
    Serial.println(“connected”);
    client.publish(“outTopic”, “SenBox1 läuft!”);
    client.subscribe(“call/Arbeitszimmer”);
    } else {
    Serial.print(“failed, rc=”);
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");

      delay(5000);
    }
    

    }
    } // function reconnect ended

    void printValues() {
    Serial.print(“Temperature = “);
    Serial.print(bme.readTemperature());
    Serial.println(” *C”);

    Serial.print("Pressure = ");
    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");
    
    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");
    int helligkeit = analogRead(A0);
    Serial.print("Helligkeit: ");
    Serial.println(helligkeit);
    
    Serial.println();
    Serial.println(s); 
    

    } // function printValues ended

    void intPublish(int x, int var){
    char buffer[10];
    sprintf(buffer, “%d”, var);

    if(x==1){
    client.publish(PUSH_TEMP RAUM, buffer);
    } else if(x==2){
    client.publish(PUSH_HUMIDITY RAUM, buffer);
    } else if(x==3){
    client.publish(PUSH_PRESURE RAUM, buffer);
    } else if(x==4) {
    client.publish(PUSH_HELLIGKEIT RAUM, buffer);
    }
    } // function in Publish ended

    void floatPublish(int x, float var){
    //runden auf zwei Nachkommastellen
    int y = var * 100;
    float z = y/100.00;
    char buffer[6];
    sprintf(buffer, “%f”, z);

    if(x==1){
      client.publish(PUSH_TEMP RAUM, buffer);
    } else if(x==2) {
      client.publish(PUSH_HUMIDITY RAUM, buffer);
    } else if(x==3) {
      client.publish(PUSH_PRESURE RAUM, buffer);
    } 
    

    } // function floatPublish ended

    void subscribe(int delayOn, int delayOff) {
    if(Nachricht == ‘r’){
    digitalWrite(LED_red,HIGH);
    } else if(Nachricht == ‘b’){
    digitalWrite(LED_blue,HIGH);
    } else if(Nachricht == ‘g’){
    digitalWrite(LED_green,HIGH);
    }
    }

    void LichtAus(int zeitBisAus){
    /* Befehl kommt über mqtt.
    Nach festgelegtem intervall wird das Licht über mqtt ausgeschaltet.
    Dauer bis zum Abschalten wird über NeoPixel signalisiert */
    int intervall = zeitBisAus/NUMPIXELS/3;
    if(s == “Wort”){
    Serial.print(“Nachricht: “);
    Serial.print(Nachricht);
    Serial.println(” eingegangen!!”);
    for(int i =0; i<NUMPIXELS; i++){
    pixels.setPixelColor(i, pixels.Color(0, 50, 0));
    pixels.show();
    delay(intervall);
    }
    for(int i =0; i<NUMPIXELS; i++){
    pixels.setPixelColor(i, pixels.Color(50, 40, 0));
    pixels.show();
    delay(intervall);
    }
    for(int i =0; i<NUMPIXELS; i++){
    pixels.setPixelColor(i, pixels.Color(50, 0, 0));
    pixels.show();
    delay(intervall);
    }

    pixels.clear();
    pixels.show();
    client.publish("FlurLicht/cmnd/POWER","OFF");
    s = "";
    

    }

    }


  • Ansich ist es (fast) egal wo du es schreibst. Nur dass Discord halt nur Nachrichten bis 2000 Zeichen akzeptiert 😉 Heißt, alle längeren Nachrichten werden nicht synchronisiert.
    Aber Hauptsache das Problem ist gelöst 🙂
    Formatierten Code kannst du hier ansonsten in Markdowns verpacken
    ```c++
    … hier dein Code …

Ähnliche Themen

  • 8
  • 1
  • 13
  • 10
  • 1