MQTT NodeMCU servo can react only on decimal array payload - mqtt

I'm creating a fish feeder with SG90 servo and NodeMCU
I used this sketch:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Servo.h>
// Update these with values suitable for your network.
const char* ssid = "your_wifi_hotspot";
const char* password = "your_wifi_password";
const char* mqtt_server = "broker.mqttdashboard.com";
//const char* mqtt_server = "iot.eclipse.org";
Servo myservo; // create servo object to control a servo
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(100);
// We start by connecting to a WiFi network
Serial.print("Connecting to ");
Serial.println(ssid);
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("Command from MQTT broker is : [");
Serial.print(topic);
for(int i=0;i<length;i++)
{
if((int)payload[i]>194||(int)payload[i]<0)
break;
myservo.write((int)payload[i]); // tell servo to go to position in variable '(int)payload[i]'
}
}//end callback
void reconnect() {
// Loop until we're reconnected
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 you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
if (client.connect(clientId.c_str()))
{
Serial.println("connected");
//once connected to MQTT broker, subscribe command if any
client.subscribe("OsoyooCommand");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
myservo.attach(D1); // attaches the servo on pin D1 to the servo object
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
The servo is working when I use MQTTBox in order to send a payload as "Decimal Array", it is however is giving me a hard time when I send payload as JSON string.
If I send "Decimal Array" 1 it does turn Servo to position 1, however if I simply send 1 as a payload as a string it moves Servo to position 49.
If I send payload as 2 it moves to position 50.
If I send payload as 10 then position is 4948
looks like position of 1 and position of 0 at the same time.
My ultimate goal is to send those payloads via HomeAssistant which are sent as string or JSON, however I don't find a correct solution at the moment.
I would highly appreciate any help or solution.

MQTT payloads are UTF-8 encoded so the Arduino PubSubClient library treats the payload as an array of uint8_t.
If you want to send and receive JSON then you can use the ArduinoJson library to parse a JSON payload. So assuming a JSON payload like:
{
"position": 123
}
Then you can implement a callback such as:
#include <ArduinoJson.h>
// Assuming a fixed sized JSON buffer
StaticJsonBuffer<200> jsonBuffer;
void callback(char* topic, byte* payload, unsigned int length)
{
JsonObject& root = jsonBuffer.parseObject(payload);
if (root.success() && root.is<JsonObject>())
{
int position = root.as<JsonObject>().get<int>("position");
myservo.write(position);
}
}

Looks like the motor is taking the position of the ASCII equivalent of the number when you send it as a string.
i.e.
ASCII equivalent of the character '1' in 49 in decimal
ASCII equivalent of the character '2' in 50 in decimal
Try sending the character 'a', the motor will go to 97.
If you want to send a string, you will have to change the following code:
for(int i=0;i<length;i++)
{
if((int)payload[i]>194||(int)payload[i]<0)
break;
myservo.write((int)payload[i]); // tell servo to go to position in variable '(int)payload[i]'
}
to:
int location=String((char*)payload).toInt()
if((location>194)||(location<0))
return;
myservo.write(location);

Related

ESP NOW failing using WIFI_AP_STA and WiFi.begin but working without the WiFi.begin

I am using code derived from Rui Santos https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
I am using ESP NOW to send readings from an ESP32 sender to an ESP32 receiver then using the ESP32 receiver to send an html message to a ESP32 web server. Per Rui's instructions I need to start WiFi with WIFI_AP_STA to allow both wifi connection methods.
The sender and receiver code is below.
If I run the code as is, i.e. the receiver setup as WIFI_AP_STA but with the WiFi.begin line commented out, I get a sender status of:
Send success, and a receive status of:Receive status. SO there is no problem sending an ESP NOW message from the sender to the receiver (also works with WIFI_STA).
If I use WIFI_AP_STA and uncomment the line in the receiver "WiFi.begin(SSIS, PASSWORD)" so that I can send a message to the ESP32 web server, I get a send status of:Send fail, and a receive status of:Receive status with failed send. The send fails but the receive is still successful. Same fail if I use WIFI_AP. It seems that in WIFI_AP_STA mode with a WiFi.begin, the receiver sends an incorrect status back to the sender.
In summary, on the receiver, using wifi mode WIFI_AP_STA without a WiFi.begin, works for sending an ESP NOW message from sender to receiver, as it should.
Using wifi mode WIFI_AP_STA and WiFi.begin on the receiver, the sender fails when sending an ESP NOW message. When I implement the web code the web html message send works. However the issue can be reproduced using the simplified code below.
Using WiFi#2.0.0.
I've run out of ideas, is anyone able to point me at further investigation areas?
My sender code is:
#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
// Rui Santos https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
uint8_t broadcastAddress[] = {0x24, 0x6F, 0x28, 0xAA, 0x84, 0x10};
typedef struct struct_message
{
char ESP32NowText[33];
} struct_message;
struct_message ESP32NowMessage;
//
String text = "AAA000010000200003000040000500006";
esp_now_peer_info_t peerInfo;
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
{
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK)
{
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
Serial.println("Failed to add peer");
return;
}
}
void loop()
{
strncpy(ESP32NowMessage.ESP32NowText, text.c_str(), text.length());
Serial.println("Msg to send:" + String(ESP32NowMessage.ESP32NowText));
Serial.println("Snd Len:" + String(sizeof(ESP32NowMessage)));
// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&ESP32NowMessage, sizeof(ESP32NowMessage));
if (result == ESP_OK)
{
Serial.println("Sent with success");
}
else
{
Serial.println("Error sending the data");
}
delay(2000);
}
My receiver code is:
#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
// Rui Santos https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
typedef struct struct_message
{
char ESP32NowValues[33];
} struct_message;
struct_message ESP32NowMessage;
// callback function that will be executed when data is received
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len)
{
memcpy(&ESP32NowMessage, incomingData, sizeof(ESP32NowMessage));
Serial.println("Bytes received: " + String(len));
Serial.println("Values:" + String(ESP32NowMessage.ESP32NowValues));
Serial.println("---------------------------------------");
}
const char WiFiSSID[] = "SSID";
const char WiFiPassword[] = "PASSWORD";
//
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_AP_STA);
// WiFi.begin(WiFiSSID, WiFiPassword);
// Init ESP-NOW
if (esp_now_init() != ESP_OK)
{
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_recv_cb(OnDataRecv);
}
void loop()
{
}

Send data from NodeMcu(ESP266) to ESP32 using esp now?

I am trying to send some data from a Nodemcu(esp8266) to ESP32. I am trying to use espnow for that purpose, but I am really stuck, I cant merge the Master and Slave for both the boards, I find the codes to be far different I tried some modifications and I can send data from the Nodemcu but can't receive it on the ESP32. I am trying to send two analog values for a Gesture control car.
The master code or the controller code running on the Nodemcu is given below
#include <ESP8266WiFi.h>
#include <espnow.h>
#define MUX_A D4
#define MUX_B D3
#define MUX_C D2
#define ANALOG_INPUT A0
#define CHANNEL 4
extern "C" {
}
uint8_t remoteMac[] = {0x24, 0x6F, 0x28, 0xB6, 0x24, 0x49};
struct __attribute__((packed)) DataStruct {
//char text[32];
int x;
int y;
unsigned long time;
};
DataStruct myData;
unsigned long lastSentMillis;
unsigned long sendIntervalMillis = 1000;
unsigned long sentMicros;
unsigned long ackMicros;
int xAxis;
int yAxis;
int zAxis;
void InitESPNow() {
WiFi.disconnect();
if (esp_now_init()==0) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
// Retry InitESPNow, add a counte and then restart?
// InitESPNow();
// or Simply Restart
ESP.restart();
}
}
void sendData() {
if (millis() - lastSentMillis >= sendIntervalMillis) {
lastSentMillis += sendIntervalMillis;
myData.time = millis();
uint8_t bs[sizeof(myData)];
memcpy(bs, &myData, sizeof(myData));
sentMicros = micros();
esp_now_send(NULL, bs, sizeof(myData)); // NULL means send to all peers
Serial.println("sent data");
Serial.println(myData.x);
Serial.println(myData.y);
}
}
void sendCallBackFunction(uint8_t* mac, uint8_t sendStatus) {
ackMicros = micros();
Serial.print("Trip micros "); Serial.println(ackMicros - sentMicros);
Serial.printf("Send status = %i", sendStatus);
Serial.println();
Serial.println();
}
void setup() {
Serial.begin(115200); Serial.println();
Serial.println("Starting EspnowController.ino");
WiFi.mode(WIFI_STA); // Station mode for esp-now controller
WiFi.disconnect();
Serial.printf("This mac: %s, ", WiFi.macAddress().c_str());
Serial.printf("slave mac: %02x%02x%02x%02x%02x%02x", remoteMac[0], remoteMac[1], remoteMac[2], remoteMac[3], remoteMac[4], remoteMac[5]);
Serial.printf(", channel: %i\n",CHANNEL);
InitESPNow();
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_add_peer(remoteMac, ESP_NOW_ROLE_SLAVE, CHANNEL, NULL, 0);
esp_now_register_send_cb(sendCallBackFunction);
Serial.print("Message ");
pinMode(MUX_A, OUTPUT);
pinMode(MUX_B, OUTPUT);
pinMode(MUX_C, OUTPUT);
Serial.println("Setup finished");
}
void changeMux(int c, int b, int a) {
digitalWrite(MUX_A, a);
digitalWrite(MUX_B, b);
digitalWrite(MUX_C, c);
}
void loop() {
changeMux(LOW, LOW, LOW);
xAxis = analogRead(ANALOG_INPUT); //Value of the sensor connected to pin 0 of IC
changeMux(LOW, LOW, HIGH);
yAxis = analogRead(ANALOG_INPUT); //Value of the sensor connected to pin 1 of IC
changeMux(LOW, HIGH, LOW);
zAxis = analogRead(ANALOG_INPUT); //Value of the sensor connected to pin 2 of IC
changeMux(LOW, HIGH, LOW);
myData.x= xAxis;
myData.y= yAxis;
sendData();
delay(500);
}
The slave code running on the ESP32 is given below
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#define CHANNEL 4
uint8_t mac[] = {0x36, 0x33, 0x33, 0x33, 0x33, 0x33};
struct __attribute__((packed)) DataStruct {
//char text[32];
int x;
int y;
unsigned long time;
};
DataStruct myData;
// Init ESP Now with fallback
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP);
// configure device AP mode
// This is the mac address of the Slave in AP Mode
esp_wifi_set_mac(ESP_IF_WIFI_STA, &mac[0]);
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Init ESPNow with a fallback logic
if (esp_now_init()!=0) {
Serial.println("*** ESP_Now init failed");
while(true) {};
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
Serial.print("Aheloiioi");
}
// callback when data is recv from Master
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
memcpy(&myData, data, sizeof(myData));
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Recv from: "); Serial.println(macStr);
Serial.print("Last Packet Recv Data: "); Serial.println(myData.x); Serial.println(myData.y);
Serial.println("");
}
void loop() {
// Chill
}
This is the only output I get on the ESP32
ESPNow/Basic/Slave Example
AP MAC: 24:6F:28:B6:24:49
Aheloiioi
While this is the output on Nodemcu
Starting EspnowController.ino
This mac: BC:DD:C2:B5:E3:2B, slave mac: 246f28b62449, channel: 4
ESPNow Init Success
Message Setup finished
sent data
10
8
Trip micros 7320
Send status = 1
sent data
9
8
Trip micros 6817
Send status = 1
sent data
10
9
Trip micros 6731
Send status = 1
and it continues
If there are any other methods to send data, please do mention
I never use esp_now before so I didn't test it myself, but I think this has nothing to do with the library or esp32, it is just a minor mistake of c++ usage.
On your sendData() function of your esp8266, you did this:
uint8_t bs[sizeof(myData)];
memcpy(bs, &myData, sizeof(myData));
sentMicros = micros();
esp_now_send(NULL, bs, sizeof(myData));
The bs has a type of uint8_t and is an array, and you try to copy the data that has a type of struct myData into the array. And you then try to pass the array into the esp_now_send(). I quickly took a look at the esp_now_send() function prototype definition, the esp_now_send() need to pass in the address (which has a type of uint8_t) of your data structure myData.
I don't know know why you need to do the memcpy, but I think it will easier and simply to just directly pass in the pointer of myData into the function call.
void sendData() {
if (millis() - lastSentMillis >= sendIntervalMillis) {
lastSentMillis += sendIntervalMillis;
myData.time = millis();
esp_now_send(NULL, (uint8_t *)&myData, sizeof(myData)); // NULL means send to all peers
Serial.println("sent data");
Serial.println(myData.x);
Serial.println(myData.y);
}
}
Please let me know if this work?

ESP8266 Subscribe to AWS IOT topic

Hi I need to create a lambda function which will access the AWS thing and publish MQTT message, I'd like to get the published message on the ESP8266 which was connected to the thing as well, and controlled turn on/off the LED on ESP8266. So far I have uploaded the private.der, cert.der and ca.der to the ESP8266 absolutely, but it couldn't subscribed AWS IOT, please point me in the right tips then please share.
Code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#define OUT_TOPIC "$aws/things/devices/shadow/update"
#define IN_TOPIC "$aws/things/devices/shadow/update/delta"
const char* ssid = "sid";
const char* password = "password";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
const char* AWS_endpoint = "endpoint.amazonaws.com";//MQTT broker ip
const char* json = "{\"state\":{\"reported\":{\"led\":\"off\"}}}";
StaticJsonDocument<1024> doc;
WiFiClientSecure espClient;
PubSubClient mqttClient(espClient);//set MQTT port number to 8883 as per standard
PubSubClient client(AWS_endpoint, 8883, espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);// We start by connecting to a WiFi network
espClient.setBufferSizes(512, 512);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
timeClient.begin();
while(!timeClient.update()){
timeClient.forceUpdate();
}
espClient.setX509Time(timeClient.getEpochTime());
int qos = 0;//Maximum size of data that can be communicated
Serial.println(MQTT_MAX_PACKET_SIZE);
if(mqttClient.subscribe(IN_TOPIC, qos)){
Serial.println("Subscribed.");
Serial.println("Success!!");
}
deserializeJson(doc, json);
JsonObject obj = doc.as<JsonObject>();
if(mqttClient.publish(OUT_TOPIC, json)){
Serial.println("Published!!");
}
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
setup_wifi();
delay(1000);
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
//replace cert.crt eith your uploaded file name
File cert = SPIFFS.open("/cert.der", "r");
if (!cert) {
Serial.println("Failed to open cert file");
}
else
Serial.println("Success to open cert file");
delay(1000);
if (espClient.loadCertificate(cert))
Serial.println("cert loaded");
else
Serial.println("cert not loaded");
// Load private key file
File private_key = SPIFFS.open("/private.der", "r");//replace private eith your uploaded file name
if (!private_key) {
Serial.println("Failed to open private cert file");
}
else
Serial.println("Success to open private cert file");
delay(1000);
if (espClient.loadPrivateKey(private_key))
Serial.println("private key loaded");
else
Serial.println("private key not loaded");
// Load CA file
File ca = SPIFFS.open("/ca.der", "r");
//replace ca eith your uploaded file name
if (!ca) {
Serial.println("Failed to open ca ");
}
else
Serial.println("Success to open ca");
delay(1000);
if(espClient.loadCACert(ca))
Serial.println("ca loaded");
else
Serial.println("ca failed");
Serial.print("Heap: ");
Serial.println(ESP.getFreeHeap());
}
void callback (char* topic, byte* payload, unsigned int length) {
Serial.println("Received. topic=");
Serial.println(topic);
char subsc[length];
for(int i=0; i<length; i++){
subsc [i]=(char)payload[i];
subsc [length]='\0';
Serial.print(subsc);
}
Serial.print("\n");
digitalWrite(LED_BUILTIN, HIGH);
}
void mqttLoop() {
mqttClient.loop();
delay(100);
//digitalWrite(LED_pin, LOW);
digitalWrite(LED_BUILTIN, LOW);
Serial.print(".");
}
void loop() {
It looks like you're using the older forms of WiFiClientSecure certificate handling. I'll assume that's working OK and you're able to establish an SSL connection.
Your IN_TOPIC needs to be updated slightly to: $aws/things/<name-of-your-thing>/shadow/update/accepted (where hopefully you know what <name-of-your-thing> is). You can get this from the thing shadow on your AWS console.
Similarly AWS_endpoint needs updating: it should be of the form <random-stuff-specific-to-you>.iot.<region>.amazonaws.com. You can also find it from the same place as the MQTT topics.
You only want one instance of PubSubClient. I'll assume you delete client and keep mqttClient. You'll need to update the instantiation to include the AWS endpoint and port as you have done for client.
Before calling mqttClient.subscribe(...) you need to register the callback:
mqttClient.setCallback(::callback);
then connect to AWS:
mqttClient.connect("some-unique-name");
Finally, you need to edit PubSubClient.h (look for it in Arduino/libraries/PubSubClient/src) to update MQTT_MAX_PACKET_SIZE. The default is 128 and I've found that too small with AWS's messages. I've made mine 1024:
#define MQTT_MAX_PACKET_SIZE 1024
and that appears ample.
Once that compiles and runs you'll start seeing callback(...) called with the topics you've subscribed to and you can implement the function to do whatever you need.
The PubSubClient doesn't do much error reporting to help diagnose what's going on. I'm currently refactoring it a bit and including more diagnostic information and will eventually issue a pull request. Let me know if you'd like my hacked version before I get that far.

MQTT subscription

Can someone help me with this code?
The goal is to trigger a Led when the value of the payload is > 1000.
It is a MQTT subscribtion code based on the esp8266mqtt PubSub client example. I will use it for a subscribyion of a topic from a CO2sensor
I've tried to modify a part of it but I think it has yo do something with the kind of datatype or a wrong condition?
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char *ssid = "xxx";
const char *password = "xxx";
const char *mqtt_server = "xxxx";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
int led = D4;
void setup_wifi()
{
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
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();
// Switch on the LED if value of C02 is above 1000
i = atoi (payload); //convert string to integer
if ( i > 1000) // comparison
{
digitalWrite(led, HIGH); // Turn the LED on
}
else
{
digitalWrite(led, LOW); // Turn the LED off
}
}
void reconnect()
{
// Loop until we're reconnected
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("outTopic", "Test");
// ... and resubscribe
client.subscribe("my/sensors/co2");
}
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(led, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
}
Kind regards
Hi, This is what I publish:
void pubMessage() {
char message[16];
snprintf(message, sizeof(message), "%d", co2);
client.publish("my/sensors/co2", message);
delay(30000);
First you are casting the first byte of payload to a char.
Since it's just the first byte, it has a max value of 256.
Second you are comparing that 1 bytes value to the string '1000'
Without knowing exactly what you are publishing it is very hard to tell you how to fix it.
If you are publishing a string representing the number then you will need to parse it first with atoi() then do the comparison to the integer 1000 not the string.
If it is a byte value then you will need to read the correct value from the incoming byte array before doing the comparison.

I can not subscribe with ESP8266-ESP32 in IBM Watson IOT

I want to subscribe to the "iot-2/evt/status/fmt/json" topic with ESP8266 on IBM Watson IOT. The connection is established but it is disconnecting again. So, reconnecting the MQTT client to … and subscribe to iot-2 / cmd / + / fmt / + OK. This cycle continues. Why is the connection broken?
My ESP8266 code is as follows.
I used an ESP8266-12E NodeMCU, I’ve created an Android app for the publisher.
/*
Basic ESP8266 MQTT example
This sketch demonstrates the capabilities of the pubsub library in combination
with the ESP8266 board/library.
It connects to an MQTT server then:
- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not binary
- If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
else switch it off
It will reconnect to the server if the connection is lost using a blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
achieve the same result without blocking the main loop.
To install the ESP8266 board, (using Arduino 1.6.4+):
- Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
- Select your ESP8266 in "Tools -> Board"
*/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
//#include <ESP8266HTTPClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
//ZYxel
#define ssid "......."
#define password ".................."
//GES ARGE
#define ssid2 "..............." // WiFi SSID
#define password2 "............." // WiFi password
#define spi_ss_pin SS
#define ORG "............"
#define DEVICE_TYPE "........."
#define DEVICE_ID "..........."
#define TOKEN "................"
//-------- Customise the above values --------
char server[] = ORG ".messaging.internetofthings.ibmcloud.com";
int mqttPort=1883;
const char topic[] = "iot-2/cmd/status/fmt/json"; //"iot-2/cmd/status/fmt/json";
char authMethod[] = "use-token-auth";
char token[] = TOKEN;
char clientId[] = "d:" ORG ":" DEVICE_TYPE ":" DEVICE_ID;
WiFiClient wifiClient;
void callback(char* topic, byte* payload, unsigned int payloadLength) ;
PubSubClient client(server, 1883, callback, wifiClient);
void setup() {
Serial.begin(115200);
Serial.println();
wifiConnect();
mqttConnect();
}
void loop() {
if (!client.loop()) {
mqttConnect();
}
}
void wifiConnect() {
Serial.print("Connecting to "); Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("nWiFi connected, IP address: "); Serial.println(WiFi.localIP());
}
void mqttConnect() {
if (!client.connected()) {
Serial.print("Reconnecting MQTT client to "); Serial.println(server);
while (!client.connect(clientId, authMethod, token)) {
Serial.print(".");
delay(500);
}
initManagedDevice();
Serial.println();
}
}
void initManagedDevice() {
if (client.subscribe(topic)) {
Serial.println("subscribe to cmd OK");
} else {
Serial.println("subscribe to cmd FAILED");
}
}
void callback(char* topic, byte* payload, unsigned int payloadLength) {
Serial.print("callback invoked for topic: "); Serial.println(topic);
for (int i = 0; i < payloadLength; i++) {
Serial.print((char)payload[i]);
}
}
A device ("use-token-auth" authentication type) cannot subscribe to a topic like "iot-2/evt/status/fmt/json" only "iot-2/cmd/status/fmt/json" is allowed.
What you need to do is to generate an API key and token and authenticate as an application:
The following example shows a typical API key:
a-orgId-a84ps90Ajs
The following example shows a typical authentication token:
MP$08VKz!8rXwnR-Q*
When you make an MQTT connection by using an API key, ensure that the following guidelines are applied:
The MQTT client ID is in the format: a:orgId:appId
The MQTT user name is the API key (for example, a-orgId-a84ps90Ajs)
The MQTT password is the authentication token (for example, MP$08VKz!8rXwnR-Q*)
After that you can subscribe to topic like iot-2/type/device_type/id/device_id/evt/event_id/fmt/format_string. So it should be:
iot-2/type/yourDeviceType/id/yourDeviceId/evt/status/fmt/json
You can use the same for commands: this how the topic should look like
iot-2/type/device_type/id/device_id/cmd/command_id/fmt/format_string

Resources