ESP32 and NODE RED MQTT

I need help.
I am doing a thesis project.
and I need help with the following:
I have my NODE RED interface made locally

which sends an on-off data and this is received by an IBM CLOUD server.
This data arrives at NODE RED on a server in the cloud, as shown below.


and this data that I receive from the NODE RED in the cloud I need to use it to turn on or off a led in an ESP32 module.
I tried the MQTT protocol but I can’t read the data that my server sends me.
I also tried to connect directly to the server to read the data in JSON format but I also don’t know how to read it in the ARDUINO IDE



#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h> 

//-------- your wifi -----------

const char* ssid = "CELERITY_MONTALVAN";
const char* password = "1722510060B.";

#define ORG "5hjcib" 
#define DEVICE_TYPE "raspberry1" 
#define DEVICE_ID "comunicacioniot" 
#define TOKEN "123456789Bf" 
//-------- Bluemix information to build up MQTT message -------

char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
char pubTopic[] = "iot-2/evt/status/fmt/json";
char subTopic[] = "iot-2/cmd/test/fmt/String";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;

WiFiClient wifiClient;
PubSubClient client(server, 1883, NULL, wifiClient);

const char ledpin3 = 4;

void receivedCallback(char* pubTopic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println (pubTopic);

  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  /* we got '1' -> on */
  if ((char)payload[0] == '1') {
    digitalWrite(ledpin3, HIGH); 
  } else {
    /* we got '0' -> on */
    digitalWrite(ledpin3, LOW);
  }
}

void setup() {
    Serial.begin(115200);
    Serial.println();
    pinMode(ledpin3, OUTPUT);
    Serial.print("Connecting to "); 
    Serial.print(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    } 
    Serial.println("");
    
    Serial.print("WiFi connected, IP address: "); 
    Serial.println(WiFi.localIP());

    if (!client.connected()) {
        Serial.print("Reconnecting client to ");
        Serial.println(server);
        while (!client.connect(clientId, authMethod, token)) {
            Serial.print(".");
            delay(500);
        }
        client.setCallback(receivedCallback);
        if (client.subscribe(subTopic)) {
            Serial.println("subscribe to cmd OK");
        } else {
            Serial.println("subscribe to cmd FAILED");
        }
        Serial.println("Bluemix connected");
    }
}

void loop() {
client.loop();
 if (client.publish(pubTopic, (char*) payload.c_str())) {
            Serial.println("Publish ok");
        } else {
            Serial.println("Publish failed");
        }
    }
}

The code is a small idea of what I want to do for a single led, and then add it for a total of 5 leds

The guys over at the node red answer guy place refused to help you out?

the problem is that the NODE RED is sending the data from the cloud to some subscriber but the main problem is in the arduino program. since I do not know how to read that data or how to correctly subscribe to read the data either from the IBM WATSON server or the ones that NODE RED CLOUD sends me, any of the 2 would help me to activate the LEDs and with that some RELAYS

those are the data that arrives and that I need to see them in arduino to perform a certain action

Do you get the topic to print out in the callback?

Do you get a message indicating that the subscribe went through?

Have you used an external program like MQTT.fx to make the same connection to the MQTT server that you are expecting the ESP32 to make?

Here is my WiFI connect code:

void connectToWiFi()
{
  int TryCount = 0;
  while ( WiFi.status() != WL_CONNECTED )
  {
    TryCount++;
    WiFi.disconnect();
    WiFi.begin( SSID, PASSWORD );
    vTaskDelay( 2500 );
    if ( TryCount == 10 )
    {
      ESP.restart();
    }
  }
  WiFi.onEvent( WiFiEvent );
}

Notice the WiFI.disconnect()( before the connect? The disconntct does 2 things. 1, if connected, disconnect. And the other thing do is to reset the WiFi stack.

Here is my MQTT connect code

void connectToMQTT()
{
  byte mac[5]; // create client ID from mac address
  WiFi.macAddress(mac); // get mac address
  String clientID = String(mac[0]) + String(mac[4]) ; // use mac address to create clientID
  while ( !MQTTclient.connected() )
  {
    MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password );
    vTaskDelay( 250 );
  }
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( topicOK );
  //MQTTclient.subscribe( mqtt_topic );
} //void connectToMQTT()

Notice the code creates its own client ID ,so you don’t have to.

Here is my MQTT keep alive task

void MQTTkeepalive( void *pvParameters )
{
  sema_MQTT_KeepAlive   = xSemaphoreCreateBinary();
  xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
  MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = 250; //delay for ms
  for (;;)
  {
    //check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
    if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // !!!!!whiles MQTTlient.loop() is running no other mqtt operations should be in process!!!!!
      MQTTclient.loop();
      xSemaphoreGive( sema_MQTT_KeepAlive );
    }
    else {
      if ( !(wifiClient.connected()) || !(WiFi.status() == WL_CONNECTED) )
      {
        connectToWiFi();
      }
      connectToMQTT();
    }
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
  }
  vTaskDelete ( NULL );
}

The task, has an important setting you might want to consider making, MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection.

Oh, here is my MQTT callback.

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)
////

You might want to consider adding the IRAM_ATTR to your callback for faster operations.

thanks for your reply.

Everything you mention to me is already done. as it’s shown in the following.

char subTopic = “iot-2/cmd/test/fmt/String”;

this part I don’t understand where it comes from “iot-2 / cmd / test / fmt / String” or what it is for. or I need to change to the topic that my node red server sends me. which I do not know where to see what topic sends me.
Knowing the topic and when the ESP32 reads the message that it was sent, it would be easy to show it on the serial monitor and assign an action to that message.

That appears to be 2 test topics that can be subscribed to for processing. Most likely to assist he programmer with troubleshooting.

I would recommend that if you know your BROKER’s info you replace the info in that script with your Broker’s info.

Is that a real username and password in your posts?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.