Open THDEW opened 8 years ago
I got a little more question, if i set connection in Arduino and doing different task than publish or subscribe. Will it disconnect automatically?
Hi, you'll have to provide a clearer description, with code, of what works and doesn't work for you. What hardware are you using?
The client will remain connected as long as you call the client.loop function regularly. Otherwise the server will disconnect the client due to inactivity.
Problem Message : Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Hardware _: Arduino Uno + Ethernet Shield _Software : Arduino IDE (1.6.7) , PubSubClient 2.6.0
// Update these with values suitable for your network. byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; IPAddress ip(172, 16, 0, 100); IPAddress server(85,119,83,194); // test.mosquitto.org
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(); }
EthernetClient ethClient; PubSubClient client(ethClient);
void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("arduinoClientUNIQUE")) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopicUNIQUE","hello world"); // ... and resubscribe client.subscribe("inTopicUNIQUE"); } 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() { Serial.begin(57600);
client.setServer(server, 1883); client.setCallback(callback);
Ethernet.begin(mac, ip); // Allow the hardware to sort itself out delay(1500); }
void loop() { if (!client.connected()) { reconnect(); } client.loop(); }
@shrobon Have you tried verifying your basic setup using the File->Examples->Ethernet->WebClient
example? Just to ensure the hardware and the network connection is all okay.
@knolleary , Yes I have tried doing that . The WebClient works perfectly well .
@knolleary . You can close the issue . There were a couple of problems from my end . You can include this in your readme since many stumble with this problem . Firstly , while using the WebClient , i was getting a DHCP address . Here in this sketch , i overlooked the IP address completely. Secondly i made the client name Unique . This solved the issue . Connects and publishes like a charm now ! Thanks
@shrobon well, I can't close this issue as @THDEW raised it and we have no indication of whether they have resolved their issue. But I think you're quite right that hardcoded IP vs DHCP is definitely something I must remember to mention when this type of issue gets raised. Thanks!
hi there sorry for reviving this post but i have been with this problem for 2 weeks ! and here i read that there is a webclient example i try it but doesnt works for me :(
i add an screenshot to show you what happen, i am using an arduino ethernet on a DHCP network but when i try to use the webclient example always fail...
can someone help my with that ? or tell me where i can find some help ?
PD: sorry for my bad english LOOOTS OF THANKS FOR YOU POST GIVE ME HOPE !!
@panzho it looks like your board isn't even getting an IP address, so you're problem probably has nothing to do with PubSubClient. Did you try just running this example sketch? Crawl before you walk, walk before you run :-)
@vicatcu yeah thanks for your answer i use that example and i remember that my network is not a dhcp network, i am on a static ip network ! (sorry about that :P ) now the example give me back the ip of my arduino in the monitor serie 9600 but i already have problems with my mqtt sketch `//https://www.baldengineer.com/mqtt-tutorial.html
LiquidCrystal lcd(9, 8, 6, 5, 3, 2);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xDA, 0xA0 };
byte server[] = { 10,1,4,36 };
//byte ip[] = { 10, 2, 23, 163 };
IPAddress ip(10, 2, 23, 163); IPAddress myDns(10,1,1, 45); IPAddress gateway(10, 2, 23, 254); IPAddress subnet(255, 255, 255, 0);
EthernetClient ethClient;
//PubSubClient client(server , 1883 , callback ,ethClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Payload: ");
Serial.write(payload, length);
Serial.println();
//clear LCD screen
lcd.clear();
//set cursor position on the LCD at column 0, line 0 then display Office Temp
lcd.setCursor(0,0);
lcd.print("mqtt");
//set cursor position on the LCD at column 0, line 1
lcd.setCursor(0,1);
//write the payload to the LCD display
lcd.write(payload, length);
}
PubSubClient client(server, 1883, callback, ethClient);
void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("intentando conexion MQTT..."); // Attempt to connect if (client.connect("ardu")) { Serial.println("conectado"); // ... and subscribe to topic client.subscribe("mqtt/2"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" nuevo intento en 5 seg"); // Wait 5 seconds before retrying delay(5000); } } }
void setup(){ Serial.begin(9600); Ethernet.begin(mac, ip ,gateway, subnet); client.setClient(ethClient); client.setServer(server, 1883); client.setCallback(callback);
//Print Arduino IP address to serial for debugging
Serial.print("IP = ");
Serial.println(Ethernet.localIP());
lcd.begin(16, 2);
lcd.print("mqtt Siquei");
lcd.setCursor(0,1);
lcd.print(Ethernet.localIP());
if(4>3){ Serial.println("calando ifes"); } client.connect("ardu", "arduino", "arduino"); //client.connect("arduino", "arduino", "arduino"); if (client.connect("ardu", "arduino", "arduino")) {
client.publish("mqtt/2","LCD Display Online");
Serial.println("conexion exitosa");
client.subscribe("mqtt/2");
} if (client.connect("arduino")==false) {
client.publish("mqtt/2","LCD Display Online");
Serial.println("fallo la conexion");
client.subscribe("mqtt/2");
}
}
void loop() { if (!client.connected()) { reconnect(); } client.loop(); }
` this is my code, you can take it for your sketch if you want (i get it from many tutorials including this guy code :P ) what do you say about it ? where is wrong ?
@panzho if you monitor the traffic coming from your Arduino Ethernet (e.g. using WireShark or something) I bet things would become clear. I would guess wildly that the IP address of your server is wrong - double check it, and try reversing the octets in your sketch.
@vicatcu thanks for your patience i know my english is horrible i dont know how but i change lots of things on my network and my sketch code and now IS WORKING!
this little part of my life... its called happiness xD
i think the problem was that i was trying to connect to a dhcp network but my network is a static one
the code for that is
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xDA, 0xA0 }; IPAddress ip(10, 2, 23, 163); IPAddress myDns(10,1,1, 45); IPAddress gateway(10, 2, 23, 254); IPAddress subnet(255, 255, 255, 0); IPAddress server(10, 1, 4, 36);
Ethernet.begin(mac, ip, myDns, gateway, subnet); this if for STATIC ip networks
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xDA, 0xA0 }; byte ip[]{10, 2, 23, 163};
ethernet.begin(mac,ip); this one is for DHCP networks ethernet.begin(mac); this one for dhcp networks too
@panzho i have the same problem u had and i am running my broker on a raspberry pi how can i solve it i am very new to this so can u take it step by step
Dont Use: byte server[] = { 10,1,4,36 };
USE: IPAddress server(10, 1, 4, 36);
IN: client.setServer(server, 1883);
Worked for me.
This seems to be a common problem when using ESP8266 + Mosquitto broker.
I also had a perfectly working set-up with multiple ESPs and they suddenly started showing the same "failed rc=-2" error (WifiClient can not connect to the broker) out of nowhere. Once this error starts showing, there is seemingly no way to recover. I even tried different MQTT libraries and ESP platforms.
The solution is very unexpected but simple:
Explicitly add a
WiFi.mode(WIFI_STA);
before
Wifi.connect(....);
I could not believe it myself. But it actually fixed the problem across ALL my MQT sensors. There simply seems to be an invalid state of the network stack that prevents PubSub's WifiClient to connect.
@hotkeymuc interesting - good discovery thanks. Need to find somewhere to capture this as I'm sure it'll come up!
@knolleary Please add hotkeymuc's solution somewhere visible (in the (esp8266/32) examples perhaps?)! I ran into the same issue with the ESP32, and after hours of debugging found this thread. My problem was solved instantly.
nice job, that solved my problem too.
I add the command
WiFi.mode(WIFI_STA);
just before
if (client.connect(..................)) {
and it did the job. Now, it is working like a charm !!!!!!
Thanks
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
#define WIFI_SSID "Home"
#define WIFI_PASS "testing1"
IPAddress server(198, 162, 43, 27);
String s = "";
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();
}
WiFiClient ethClient;
PubSubClient client(ethClient);
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
WiFi.mode(WIFI_STA);//added here
if (client.connect("NodeMCU")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("test/topic","hello world");
// ... and resubscribe
client.subscribe("test/inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void WiFi_Connect(){
WiFi.mode(WIFI_STA); //added here
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(s+" connected with IP: "+WiFi.localIP());
}
void setup()
{
Serial.begin(9600);
delay(5000);
Serial.println("Setup");
Serial.println("Setserver "+server);
client.setServer(server, 1883);
Serial.println("Setcallback");
client.setCallback(callback);
WiFi_Connect();
// Allow the hardware to sort itself out
delay(1500);
}
void loop()
{
Serial.println("Loop");
if (!client.connected()) {
Serial.println("Reconnect");
reconnect();
}
client.loop();
}
Console response Setup Setcallback ....... connected with IP: 1703520448 Loop Reconnect Attempting MQTT connection...failed, rc=-2 try again in 5 seconds Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
still facing issue after adding WiFi.mode(WIFI_STA);
@knolleary I've just got involved with ESP and had the same issue with connecting to the MQTT server. I was using Mosquitto on the local machine. Cloud MQTT was working fine as was Mos testing server.
I thought I might have needed to somehow 'register' topics before I subcribed to them as I am new to all things IoT. I was trying AT Command Tester and bunch of other things trying to track the issue. I spent far too long trying to track down info for this without realizing I shouldn't be using "127.0.0.1" or "Localhost" on port 1883 but that I should be using the IP of the local machine.
I'd be willing wager a fizzy drink that there are more than a few people who receive the -2 error have the same issue.
const char* ssid = "********"; //put your wifi ssid here
const char* password = "********"; //put your wifi password here.
const char* mqtt_server = "192.168.0.1"; //const char* mqtt_server = "add local machine's IP Address here and not 127.0.0.1 or Localhost";
I am not able to connect to the mqtt server I have made in Window. localhost with the port 1883. The code is down below. No matter how man times I try. It doesn't connect with the broker.
// WiFi card example
char ssid[] = "Faizan_Qadir"; // your SSID char pass[] = "c8fabbe2"; // your SSID Password char server[] = "localhost"; WiFiClient client; PubSubClient mqttClient(client); // Use this for WiFi instead of EthernetClient void wifi() { delay(100); // Begin WiFi section // Serial.printf("\nConnecting to %s", ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
// print out info about the connection:
Serial.println("\nConnected to network");
Serial.println(ssid);
Serial.print("My IP address is: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Allow the hardware to sort itself out delay(1500); mqttClient.setServer(server, 1883);
if (mqttClient.connect("myClientID")) { // connection succeeded Serial.println("\nConnected Succeeded"); } else {
Serial.println("\nFailed");
mqttClient.state();
// connection failed
// mqttClient.state() will provide more information
// on why it failed.
}
} void setup() { Serial.begin(115200); wifi(); reconnect(); }
void loop()
{
mqttClient.loop(); } ![Uploading Capture.PNG…]()
nice job, that solved my problem too.
I add the command WiFi.mode(WIFI_STA);
just before if (client.connect(..................)) {
and it did the job. Now, it is working like a charm !!!!!!
Thanks
It's 2022 and this is still the fix. Thanks!
same here today. only this works: nodemcu v3
WiFi.mode(WIFI_STA);//added here
hello every one, i have the same problem but I don't know where to add it can comeone help?
#include <WiFiNINA.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <SparkFunLSM6DS3.h>
/* You need to go into this file and change this line from:
#define MQTT_MAX_PACKET_SIZE 128
to:
#define MQTT_MAX_PACKET_SIZE 2048
*/
#include <PubSubClient.h>
#include "./sha256.h"
#include "./base64.h"
#include "./parson.h"
#include "./morse_code.h"
#include "./utils.h"
#include "./configure.h"
//Create a instance of class LSM6DS3
LSM6DS3 onboardIMU(SPI_MODE, 30);
bool wifiConnected = false;
bool mqttConnected = false;
String iothubHost;
String deviceId;
String sharedAccessKey;
WiFiSSLClient wifiClient;
PubSubClient *mqtt_client = NULL;
int requestId = 0;
int twinRequestId = -1;
#define TELEMETRY_SEND_INTERVAL 5000 // telemetry data sent every 5 seconds
#define PROPERTY_SEND_INTERVAL 15000 // property data sent every 15 seconds
#define SENSOR_READ_INTERVAL 2500 // read sensors every 2.5 seconds
long lastTelemetryMillis = 0;
long lastPropertyMillis = 0;
long lastSensorReadMillis = 0;
// telemetry data values
enum xyz {X, Y, Z};
float tempValue = 0.0;
float gyroValue[3] = {0.0, 0.0, 0.0};
float accelValue[3] = {0.0, 0.0, 0.0};
// die property value
int dieNumberValue = 1;
// grab the current time from internet time service
unsigned long getNow()
{
IPAddress address(129, 6, 15, 28); // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[NTP_PACKET_SIZE];
WiFiUDP Udp;
Udp.begin(2390);
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123);
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
// wait to see if a reply is available
int waitCount = 0;
while (waitCount < 20) {
delay(500);
waitCount++;
if (Udp.parsePacket() ) {
Udp.read(packetBuffer, NTP_PACKET_SIZE);
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
unsigned long secsSince1900 = highWord << 16 | lowWord;
Udp.stop();
return (secsSince1900 - 2208988800UL);
}
}
return 0;
}
// IoT Hub MQTT publish topics
static const char IOT_EVENT_TOPIC[] = "devices/{device_id}/messages/events/";
static const char IOT_TWIN_REPORTED_PROPERTY[] = "$iothub/twin/PATCH/properties/reported/?$rid={request_id}";
static const char IOT_TWIN_REQUEST_TWIN_TOPIC[] = "$iothub/twin/GET/?$rid={request_id}";
static const char IOT_DIRECT_METHOD_RESPONSE_TOPIC[] = "$iothub/methods/res/{status}/?$rid={request_id}";
// IoT Hub MQTT subscribe topics
static const char IOT_TWIN_RESULT_TOPIC[] = "$iothub/twin/res/#";
static const char IOT_TWIN_DESIRED_PATCH_TOPIC[] = "$iothub/twin/PATCH/properties/desired/#";
static const char IOT_C2D_TOPIC[] = "devices/{device_id}/messages/devicebound/#";
static const char IOT_DIRECT_MESSAGE_TOPIC[] = "$iothub/methods/POST/#";
// split the connection string into it's composite pieces
void splitConnectionString() {
String connStr = (String)iotConnStr;
int hostIndex = connStr.indexOf("HostName=");
int deviceIdIndex = connStr.indexOf(F(";DeviceId="));
int sharedAccessKeyIndex = connStr.indexOf(";SharedAccessKey=");
iothubHost = connStr.substring(hostIndex + 9, deviceIdIndex);
deviceId = connStr.substring(deviceIdIndex + 10, sharedAccessKeyIndex);
sharedAccessKey = connStr.substring(sharedAccessKeyIndex + 17);
}
// acknowledge the receipt of a setting back to Azure IoT Central (makes the setting status turn green)
void acknowledgeSetting(const char* propertyKey, const char* propertyValue, int version) {
// for IoT Central need to return acknowledgement
const static char* responseTemplate = "{\"%s\":{\"value\":%s,\"statusCode\":%d,\"status\":\"%s\",\"desiredVersion\":%d}}";
char payload[1024];
sprintf(payload, responseTemplate, propertyKey, propertyValue, 200, "completed", version);
Serial.println(payload);
String topic = (String)IOT_TWIN_REPORTED_PROPERTY;
char buff[20];
topic.replace("{request_id}", itoa(requestId, buff, 10));
mqtt_client->publish(topic.c_str(), payload);
requestId++;
}
// process direct method requests
void handleDirectMethod(String topicStr, String payloadStr) {
String msgId = topicStr.substring(topicStr.indexOf("$RID=") + 5);
String methodName = topicStr.substring(topicStr.indexOf("$IOTHUB/METHODS/POST/") + 21, topicStr.indexOf("/?$"));
Serial_printf("Direct method call:\n\tMethod Name: %s\n\tParameters: %s\n", methodName.c_str(), payloadStr.c_str());
if (strcmp(methodName.c_str(), "ECHO") == 0) {
// acknowledge receipt of the command
String response_topic = (String)IOT_DIRECT_METHOD_RESPONSE_TOPIC;
char buff[20];
response_topic.replace("{request_id}", msgId);
response_topic.replace("{status}", "200"); //OK
mqtt_client->publish(response_topic.c_str(), "");
// output the message as morse code
JSON_Value *root_value = json_parse_string(payloadStr.c_str());
JSON_Object *root_obj = json_value_get_object(root_value);
const char* msg = json_object_get_string(root_obj, "displayedValue");
morse_encodeAndFlash(msg);
json_value_free(root_value);
}
}
// process Cloud to Device (C2D) requests
void handleCloud2DeviceMessage(String topicStr, String payloadStr) {
Serial_printf("Twin property change:\n\tPayload: %s\n", payloadStr.c_str());
}
// process twin property (settings in IoT Central language) changes
void handleTwinPropertyChange(String topicStr, String payloadStr) {
// read the property values sent using JSON parser
JSON_Value *root_value = json_parse_string(payloadStr.c_str());
JSON_Object *root_obj = json_value_get_object(root_value);
const char* propertyKey = json_object_get_name(root_obj, 0);
double propertyValue;
double version;
if (strcmp(propertyKey, "fanSpeed") == 0) {
JSON_Object* valObj = json_object_get_object(root_obj, propertyKey);
propertyValue = json_object_get_number(valObj, "value");
version = json_object_get_number(root_obj, "$version");
char propertyValueStr[8];
itoa(propertyValue, propertyValueStr, 10);
Serial_printf("Fan Speed setting change received with value: %s\n", propertyValueStr);
acknowledgeSetting(propertyKey, propertyValueStr, version);
}
json_value_free(root_value);
}
// callback for MQTT subscriptions
void callback(char* topic, byte* payload, unsigned int length) {
String topicStr = (String)topic;
topicStr.toUpperCase();
payload[length] = '\0';
String payloadStr = (String)((char*)payload);
if (topicStr.startsWith("$IOTHUB/METHODS/POST/")) { // direct method callback
handleDirectMethod(topicStr, payloadStr);
} else if (topicStr.indexOf("/MESSAGES/DEVICEBOUND/") > -1) { // cloud to device message
handleCloud2DeviceMessage(topicStr, payloadStr);
} else if (topicStr.startsWith("$IOTHUB/TWIN/PATCH/PROPERTIES/DESIRED")) { // digital twin desired property change
handleTwinPropertyChange(topicStr, payloadStr);
} else if (topicStr.startsWith("$IOTHUB/TWIN/RES")) { // digital twin response
int result = atoi(topicStr.substring(topicStr.indexOf("/RES/") + 5, topicStr.indexOf("/?$")).c_str());
int msgId = atoi(topicStr.substring(topicStr.indexOf("$RID=") + 5, topicStr.indexOf("$VERSION=") - 1).c_str());
if (msgId == twinRequestId) {
// twin request processing
twinRequestId = -1;
// output limited to 512 bytes so this output may be truncated
Serial_printf("Current state of device twin:\n%s", payloadStr.c_str());
if (length > 512)
Serial.println(" ...");
else
Serial.println();
} else {
if (result >= 200 && result < 300) {
Serial_printf("--> IoT Hub acknowledges successful receipt of twin property: %d\n", msgId);
} else {
Serial_printf("--> IoT Hub could not process twin property: %d, error: %d\n", msgId, result);
}
}
} else { // unknown message
Serial_printf("Unknown message arrived [%s]\nPayload contains: %s", topic, payloadStr.c_str());
}
}
// connect to Azure IoT Hub via MQTT
void connectMQTT(String deviceId, String username, String password) {
mqtt_client->disconnect();
Serial.println("Starting IoT Hub connection");
int retry = 0;
while(retry < 10 && !mqtt_client->connected()) {
if (mqtt_client->connect(deviceId.c_str(), username.c_str(), password.c_str())) {
Serial.println("===> mqtt connected");
mqttConnected = true;
} else {
Serial.print("---> mqtt failed, rc=");
Serial.println(mqtt_client->state());
delay(2000);
retry++;
}
}
}
// create an IoT Hub SAS token for authentication
String createIotHubSASToken(char *key, String url, long expire){
url.toLowerCase();
String stringToSign = url + "\n" + String(expire);
int keyLength = strlen(key);
int decodedKeyLength = base64_dec_len(key, keyLength);
char decodedKey[decodedKeyLength];
base64_decode(decodedKey, key, keyLength);
Sha256 *sha256 = new Sha256();
sha256->initHmac((const uint8_t*)decodedKey, (size_t)decodedKeyLength);
sha256->print(stringToSign);
char* sign = (char*) sha256->resultHmac();
int encodedSignLen = base64_enc_len(HASH_LENGTH);
char encodedSign[encodedSignLen];
base64_encode(encodedSign, sign, HASH_LENGTH);
delete(sha256);
return "SharedAccessSignature sr=" + url + "&sig=" + urlEncode((const char*)encodedSign) + "&se=" + String(expire);
}
// reads the value from the onboard LSM6DS3 sensor
void readSensors() {
// random die roll
dieNumberValue = random(1, 7);
// read LSM6DS3 sensor values
tempValue = onboardIMU.readTempC();
accelValue[X] = onboardIMU.readRawAccelX();
accelValue[Y] = onboardIMU.readRawAccelY();
accelValue[Z] = onboardIMU.readRawAccelZ();
gyroValue[X] = onboardIMU.readRawGyroX();
gyroValue[Y] = onboardIMU.readRawGyroY();
gyroValue[Z] = onboardIMU.readRawGyroZ();
}
// arduino setup function called once at device startup
void setup()
{
Serial.begin(115200);
if( onboardIMU.begin() != 0 ) {
Serial.println("Error initializing the on device IMU");
}
// attempt to connect to Wifi network:
Serial.print("WiFi Firmware version is ");
Serial.println(WiFi.firmwareVersion());
int status = WL_IDLE_STATUS;
Serial_printf("Attempting to connect to Wi-Fi SSID: %s ", wifi_ssid);
status = WiFi.begin(wifi_ssid, wifi_password);
while ( status != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println();
splitConnectionString();
// create SAS token and user name for connecting to MQTT broker
String url = iothubHost + urlEncode(String("/devices/" + deviceId).c_str());
char *devKey = (char *)sharedAccessKey.c_str();
long expire = getNow() + 864000;
String sasToken = createIotHubSASToken(devKey, url, expire);
String username = iothubHost + "/" + deviceId + "/api-version=2016-11-14";
// connect to the IoT Hub MQTT broker
wifiClient.connect(iothubHost.c_str(), 8883);
mqtt_client = new PubSubClient(iothubHost.c_str(), 8883, wifiClient);
connectMQTT(deviceId, username, sasToken);
mqtt_client->setCallback(callback);
// // add subscriptions
mqtt_client->subscribe(IOT_TWIN_RESULT_TOPIC); // twin results
mqtt_client->subscribe(IOT_TWIN_DESIRED_PATCH_TOPIC); // twin desired properties
String c2dMessageTopic = IOT_C2D_TOPIC;
c2dMessageTopic.replace("{device_id}", deviceId);
mqtt_client->subscribe(c2dMessageTopic.c_str()); // cloud to device messages
mqtt_client->subscribe(IOT_DIRECT_MESSAGE_TOPIC); // direct messages
// request full digital twin update
String topic = (String)IOT_TWIN_REQUEST_TWIN_TOPIC;
char buff[20];
topic.replace("{request_id}", itoa(requestId, buff, 10));
twinRequestId = requestId;
requestId++;
mqtt_client->publish(topic.c_str(), "");
// initialize timers
lastTelemetryMillis = millis();
lastPropertyMillis = millis();
}
// arduino message loop - do not do anything in here that will block the loop
void loop()
{
if (mqtt_client->connected()) {
// give the MQTT handler time to do it's thing
mqtt_client->loop();
// read the sensor values
if (millis() - lastSensorReadMillis > SENSOR_READ_INTERVAL) {
readSensors();
lastSensorReadMillis = millis();
}
// send telemetry values every 5 seconds
if (millis() - lastTelemetryMillis > TELEMETRY_SEND_INTERVAL) {
Serial.println("Sending telemetry ...");
String topic = (String)IOT_EVENT_TOPIC;
topic.replace("{device_id}", deviceId);
//char buff[10];
String payload = "{\"temp\": {temp}, \"accelerometerX\": {accelerometerX}, \"accelerometerY\": {accelerometerY}, \"accelerometerZ\": {accelerometerZ}, \"gyroscopeX\": {gyroscopeX}, \"gyroscopeY\": {gyroscopeY}, \"gyroscopeZ\": {gyroscopeZ}}";
payload.replace("{temp}", String(tempValue));
payload.replace("{accelerometerX}", String(accelValue[X]));
payload.replace("{accelerometerY}", String(accelValue[Y]));
payload.replace("{accelerometerZ}", String(accelValue[Z]));
payload.replace("{gyroscopeX}", String(gyroValue[X]));
payload.replace("{gyroscopeY}", String(gyroValue[Y]));
payload.replace("{gyroscopeZ}", String(gyroValue[Z]));
Serial_printf("\t%s\n", payload.c_str());
mqtt_client->publish(topic.c_str(), payload.c_str());
lastTelemetryMillis = millis();
}
// send a property update every 15 seconds
if (millis() - lastPropertyMillis > PROPERTY_SEND_INTERVAL) {
Serial.println("Sending digital twin property ...");
String topic = (String)IOT_TWIN_REPORTED_PROPERTY;
char buff[20];
topic.replace("{request_id}", itoa(requestId, buff, 10));
String payload = "{\"dieNumber\": {dieNumberValue}}";
payload.replace("{dieNumberValue}", itoa(dieNumberValue, buff, 10));
mqtt_client->publish(topic.c_str(), payload.c_str());
requestId++;
lastPropertyMillis = millis();
}
}
}
This seems to be a common problem when using ESP8266 + Mosquitto broker.
I also had a perfectly working set-up with multiple ESPs and they suddenly started showing the same "failed rc=-2" error (WifiClient can not connect to the broker) out of nowhere. Once this error starts showing, there is seemingly no way to recover. I even tried different MQTT libraries and ESP platforms.
The solution is very unexpected but simple:
Explicitly add a
WiFi.mode(WIFI_STA);
before
Wifi.connect(....);
I could not believe it myself. But it actually fixed the problem across ALL my MQT sensors. There simply seems to be an invalid state of the network stack that prevents PubSub's WifiClient to connect.
Hi,
In my code, I added the line
Wifi.mode(WIFI_STA);
But Same error persists. My MQTT server is actively running on port 1883. And Also I connected to the wifi.
This is my code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "test";
const char* password = "test123";
// MQTT broker credentials (set to NULL if not required)
const char* MQTT_username = "root";
const char* MQTT_password = "toor";
const char* mqtt_server = "192.168.1.106";
WiFiClient espClient;
PubSubClient client(espClient);
long now = millis();
long lastMeasure = 0;
void setup_wifi() {
delay(10);
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.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());
}
void callback(String topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
if (topic == "esp32/output") {
Serial.print("Changing LED to ");
if (messageTemp == "on") {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("On");
} else if (messageTemp == "off") {
digitalWrite(LED_BUILTIN, LOW);
Serial.print("Off");
}
}
Serial.println();
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
WiFi.mode(WIFI_STA);
if (client.connect("ESP8266Client", MQTT_username, MQTT_password)) {
Serial.println("connected");
// Subscribe or resubscribe to a topic
client.subscribe("esp32/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
long randomNumber;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
WiFi.mode(WIFI_STA);
Serial.begin(9600);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
randomSeed(analogRead(0));
}
void loop() {
if (!client.connected()) {
reconnect();
}
if (!client.loop()) {
WiFi.mode(WIFI_STA);
client.connect("ESP8266Client", MQTT_username, MQTT_password);
}
now = millis();
if (now - lastMeasure > 30000) {
lastMeasure = now;
randomNumber = random(100);
client.publish("esp32/random", String(randomNumber).c_str());
Serial.println("Random Number");
Serial.print(randomNumber);
}
}
Kindly help me resolve this issue. Thanks in advance!
I always fail to connect when I implement your basic example with my code. This will happen when I put put reconnect method in the void loop but when I tried to change the position to void setup(), it's work but not perfectly which mean when I put in different position in void setup(), somehow it make my program freeze. BTW, I put small delay before it will connect to and the code that I get is -2 which mean the connection fail. Do u have any suggestion?