Compare char* with String - MQTT Comunication

Hi,
This is Sonoff basic with ESP8285. The mqtt comunication with the server works good i send and recieve topics from the ESP and the server.

This is the callback function where the topic is defined as char*

void callback(char* topic, byte* payload, unsigned int length) {
  mqttmessage = "";
  for (int i = 0; i < length; i++) {
    mqttmessage += (char)payload[i];
  }

I need to findout from which topic is the comming payload. In this case the name of the topic is "ventilator/on" and i recieve this topic on to ESP whit the correct name but the comparition doesent work. This is the code:

// Here the comparition is everytime false
  if (String(topic)=="ventilator/on"){
   client.publish("ventilator/print", "** ON TOPIC"); 
  }

I try and in this way:

 // Other variant which doesent work
  if (String(topic).equals("ventilator/off")) {
    ventilatoroff = mqttmessage.toInt();
    client.publish("ventilator/print", "** OFF TOPIC");
  }

I was using this way to convert char* to String and then to compare the two strings. Now it doesent work.

Please can you help me
10x

Welcome

Why not simply use strcmp ?

Hi, 10xs for the fast answere. I tryed this but it gave this error:
cannot convert 'String' to 'const char'*

this is the code:

if (strcmp(String(topic), "ventilator/off") == 0) {
      ventilatoroff = mqttmessage.toInt();
      client.publish("ventilator/print", "** 1OFF TOPIC");
    
  }

try

if (strcmp(topic, "ventilator/off") == 0) {
  ...
}

topic is already a cString pointer so no need to convert that to a String

Hi i tryed this but it doesent work. Strange i have project that work with this code:

if (String(topic)=="ventilator/on"){
   client.publish("ventilator/print", "** ON TOPIC"); 
  }

Now i did as You said but same result:

if (strcmp(topic, "ventilator/off") == 0) {
      ventilatoroff = mqttmessage.toInt();
      client.publish("ventilator/print", "** 1OFF TOPIC");
    
  }

Let's see the deceleration of mqttmessage.

where in this code is the topic exteracted,

void callback(char* topic, byte* payload, unsigned int length) {
  mqttmessage = "";
  for (int i = 0; i < length; i++) {
    mqttmessage += (char)payload[i];
  }

I do the thing like this.

void IRAM_ATTR mqttCallback(char* topic, byte * payload, unsigned int length)
{
  // clear locations
  memset( x_message.payload, '\0', payloadSize );
  x_message.topic = ""; //clear string buffer
  x_message.topic = topic;
  int i = 0;
  for ( i; i < length; i++)
  {
    x_message.payload[i] = ((char)payload[i]);
  }
  x_message.payload[i] = '\0';
  xQueueOverwrite( xQ_Message, (void *) &x_message );// send data to queue
} // void mqttCallback(char* topic, byte* payload, unsigned int length)

or like this


void IRAM_ATTR mqttCallback(char* topic, byte * payload, unsigned int length)
{
  memset( x_message.payload, '\0', payloadSize ); // clear payload char buffer
  x_message.topic = ""; //clear topic string buffer
  x_message.topic = topic; //store new topic
  memcpy( x_message.payload, payload, length );
  xQueueOverwrite( xQ_Message, (void *) &x_message );// send data to queue
} // void mqttCallback(char* topic, byte* payload, unsigned int length)

Hi, your code look verry good! I use the code from the example i dont have this level of programing skils. Can you show me how would resolve the comparition problem that i have please.

print the topic

The sensore is connected to the RX of the esp and i cannot use serial comunication to print it. I print the topic back to the server trough MQTT using this code:

 //Here i send the topic name to the server
  temp_str = String(topic);
  temp_str.toCharArray(temp, temp_str.length() + 1);
  client.publish("ventilator/print", temp);

how its look the name of the topic is as expected.

I have used comparition in this way in ESP8266 and its work fine:

if (String(topic) == "solenoid/setings1") {

But the Sonoff version that i use now is using ESP8285 and maybe this modul is limited by memory ... and any of the code that i try doesnt work

Im reading about

The Evils of Arduino Strings
here: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

So the question is how to compare the name of recieved topic (char*) and "ventilator/on" without using String?

post the full code. if topic is a cString you don't need all this messing around with String

Post all your code. The code you posted does not extract the topic.

c-string

always loved camelCase

probably C string in plain English?

I dunno anymore

Lol

Hi, this is all the code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

//***********OTA**************
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <credentials.h>
//***********OTA**************

//***********DHT22**************
#include "DHT.h"
#define DHTPIN 3
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
//***********DHT22**************

unsigned long delayTime;

// Pin config
int LED_SONOFF = 13;

//Network Credentials
const char* ssid = mySSID;
const char* password = myPASSWORD;
const char* mqtt_server = myMQTT;

WiFiClient espClient;
PubSubClient client(espClient);
String temp_str; //see last code block below use these to convert the float that you get back from DHT to a string =str
//String hum_str;
char temp[32];

// VENTILATOR VARIALES
int ventilatoron = 70;
int ventilatoroff = 65;
int h = 0;
int t = 0;
boolean ventilatorwork = false;
String mqttmessage;
String teststring = "ventilator/on";
//Millis var
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long period = 2000;  //DHT READING PERIOD

//Pin
//int sensorPin = A0;    // select the input pin for the potentiometer
//int ledPin = 2;      // select the pin for the LED
//int battery = 0;  // variable to store the value coming from the analogread

//int ota = 0;


void setup_wifi() {

  //Satic ip configuration
  IPAddress staticIP(192, 168, 1, 56);
  IPAddress gateway(192, 168, 1, 1);
  IPAddress subnet(255, 255, 255, 0);
  IPAddress dns(192, 168, 1, 1);
  //delay(10);

  // Satic connection
  if (WiFi.config(staticIP, gateway, subnet, dns, dns) == false) {
    //Serial.println("Configuration failed.");
  }
  //WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED_SONOFF, LOW); // LOW will turn on the LED
    delay(100);
    digitalWrite(LED_SONOFF, HIGH); // HIGH will turn off the LED
    delay(100);
    // Serial.print(".");
    currentMillis = millis();
    if (currentMillis >= period)  //test whether the period has elapsed
    {
      // Serial.println(" ");
      // Serial.println("The rooter doesen't respond!");
      //Serial.print("Go to sleep for 5 min.");
      //ESP.deepSleep(300e6);
      //delay(500);
    }
  }

  randomSeed(micros());

  // Serial.println("");
  // Serial.println("WiFi connected");
  // Serial.println("IP address: ");
  // Serial.println(WiFi.localIP());
  startMillis = millis();  //initial start time
}

void callback(char* topic, byte* payload, unsigned int length) {
  mqttmessage = "";
  for (int i = 0; i < length; i++) {
    mqttmessage += (char)payload[i];
  }

  /*//Here i send the topic name to the server
  temp_str = String(topic);
  temp_str.toCharArray(temp, temp_str.length() + 1);
  client.publish("ventilator/print", temp);
  //delay(100);
*/
  // Here the comparition is everytime false
  teststring = "ventilator/on";
  if (String(topic) == teststring) {
    ventilatoron = mqttmessage.toInt();
    client.publish("ventilator/print", "** ON TOPIC");
  }

  // Other variant which doesent work
  teststring = "ventilator/off";
  if (String(topic).equals(teststring)) {
    ventilatoroff = mqttmessage.toInt();
    client.publish("ventilator/print", "** OFF TOPIC");
    //delay(100);
  }

  /*if (strcmp(topic, teststring) == 0) {
    ventilatoroff = mqttmessage.toInt();
    client.publish("ventilator/print", "** 1OFF TOPIC");

  }*/
  /* String topic_str = String(topic);
    if (strcmp(topic_str, "ventilator/off") == 0) {
      ventilatoroff = mqttmessage.toInt();
      client.publish("ventilator/print", "** 2OFF TOPIC");

    }*/

  // Serial.print("Message arrived [");
  // Serial.print(topic);
  // Serial.println("] ");
  // Serial.println(sleeptime);
  // Switch on the OTA FLAG or Go to Sleep
  //if (mqttmessage == "OTA") {
    // Serial.print(sleeptime);
    // Serial.println();
  //  ota = 1;
  //} else {
    // Serial.print(sleeptime);
    // Serial.println();
    //ESP.deepSleep(sleeptime.toInt());
   // delay(1);
  //}

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    // Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "VENTILATOR_SONOFF";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      // Serial.println("connected");
      client.subscribe("ventilator/start");
      client.subscribe("ventilator/on");
      client.subscribe("ventilator/off");
      startMillis = millis();  //initial start time
    }
    else {
      currentMillis = millis();
      if (currentMillis - startMillis >= period)  //test whether the period has elapsed
      {
        // Serial.println("The server doesen't respond!");
        // Serial.print("Go to sleep for 5 min.");
        //ESP.deepSleep(300e6);
        delay(500);
      }
      // Serial.print("failed, rc=");
      // Serial.print(client.state());
      // Serial.println(" try again in 2 seconds");
      // Wait 2 seconds before retrying
      delay(2000);
    }
  }
}

void setup() {
  pinMode(LED_SONOFF, OUTPUT);
  //Serial.begin(115200);
  //while (!Serial);   // time to get serial running



  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  if (!client.connected()) {
    reconnect();
  }
  digitalWrite(LED_SONOFF, HIGH); // HIGH will turn off the LED

  // ******DHT***********
  dht.begin();
  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("VENTILATOR_SONOFF");
  ArduinoOTA.begin();
  startMillis = millis();
}

void ventilator_on() {
  ventilatorwork = true;
  client.publish("ventilator/print", "VENTILATOR IS ON");
  delay(100);
}

void ventilator_off() {
  ventilatorwork = false;
  client.publish("ventilator/print", "VENTILATOR IS OFF");
  delay(100);
}

void anRead() {


  //DHT22
  h = dht.readHumidity();
  t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    //Serial.println(F("Failed to read from DHT sensor!"));
    //temp_str = String(t);
    //temp_str.toCharArray(temp, temp_str.length() + 1);
    client.publish("ventilator/print", "DHT No reading");
    delay(100);
    return;
  }

  //MSQTT
  /*temp_str = String(press);
    temp_str.toCharArray(temp, temp_str.length() + 1);
    client.publish("press280", temp);
    delay(100);*/

  temp_str = String(t);
  temp_str.toCharArray(temp, temp_str.length() + 1);
  client.publish("ventilator/temp", temp);
  delay(100);

  temp_str = String(h);
  temp_str.toCharArray(temp, temp_str.length() + 1);
  client.publish("ventilator/hum", temp);
  delay(100);


}
void loop() {
  client.loop();
  currentMillis = millis();
  if (WiFi.status() != WL_CONNECTED) {
    setup_wifi();
  }
  if (!client.connected()) {
    reconnect();
  }

  ArduinoOTA.handle();
  // Serial.println(" ALA BALA");

  if (currentMillis - startMillis >= period)  //test whether the period has elapsed
  {
    anRead();
    startMillis = millis();
  }

  if (ventilatoron <= h && ventilatorwork == false) {
    ventilator_on();
  }

  if (ventilatoroff >= h && ventilatorwork == true) {
    ventilator_off();
  }
}

The ishue is how to distinguish from which topic is the message?
The comparition is in callback function

usually on an ESP8266 we would use D3. Are you sure 3 is the GPIO where your DHT is connected to? There is no direct correspondance between pin names and GPIOs.

which ESP do you have? why can't you connect the DHT elsewhere? printing exactly what you get would go a long way in debugging starting with

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();
}

I'm reprograming sonoff basic device with ESP8285 chip. The pins that are free to use are RX and TX. Thats why i use RX GPIO3. The DHT22 is working fine with this setup. I think that the problem with this device is some limitation of the memory compare with ESP8266 that i ususali use, and that make dificulties when i try to compare the topic name. Is there a way to do that without to use string?

I'm debuging it via msqtt cos i cannot use serial comunication(DHT22 data > gpio3 RX. When i recieve the topic i resend it back to the server and the names are ok.

how do you upload your code ?

just unplug the DHT and remove the code that is linked to the DHT and just fake the values. Once all work you'll be able to reconnect the DHT