I'm using Arduino Uno and Wi-Fi shield. I'm trying to implement MQTT protocol for communication and I tried two libraries for Arduino. First one is Knolleary's PubSubClient: http://pubsubclient.knolleary.net/ . I modified original example a little bit to use WiFi module instead of ethernet. Sending works but not every time (sometimes, the message is sent and sometimes not). But receiving via callback function doesn't work at all.
Here is my code:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the desired topic
- subscribes to the desired topic
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// If you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
As you can see, I'm using http://test.mosquitto.org/ for testing. I'm also using mosquitto on Ubuntu where I'm subscribed to the same topic and from where (another terminal window) I'm publishing to the same topic. Here is the picture of both windows:
As you can see, "hello world" message from Arduino is received successfully (but not every time), and when I publish "bla" message from another window, it's successfully received on mosquitto (on image) but NOT on Arduino. Is there something wrong with my code or? I found similar problem here: Arduino Knolleary PubSubClient will publish messages but can't receive them
It's worth noticing that it keeps getting reconnected all the time. As you can see, in loop() I put a part of code which will connect and subscribe again if connection is lost. On Serial Monitor I get "INFO: Reconnected!" message every 2-3 seconds.
Adafruit library
Then I tried the Adafruit library, but it won't connect at all! I tried with test.mosquitto.org and with io.adafruit.com from their example, but I just keep getting "Connection failed!" error. I tried making many changes and combinations but no luck so far. Once I managed to get "Failed to subscribe" instead of "Connection failed" but this was only once and next time with the same code I get "Connection failed" again.
Here's my code:
/*
Basic MQTT example with Authentication
- connects to an MQTT server, providing username
and password
- publishes "hello world" to the topic "outTopic"
- subscribes to the topic "inTopic"
*/
#include <WiFi.h>
#include <PubSubClient.h>
char ssid[] = "[DELETED]"; // your network SSID (name)
char pass[] = "[DELETED]"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
// Update these with values suitable for your network.
IPAddress server(85, 119, 83, 194);
WiFiClient WifiClient;
void callbackFunc(char* topic, byte* payload, unsigned int length) {
Serial.println("test message received");
/*Serial.println();
Serial.println("=============== MESSAGE RECEIVED ================================");
Serial.print("Topic: ");
Serial.print(topic);
Serial.println();
Serial.println((const char *) payload);*/
}
PubSubClient client(server, 1883, callbackFunc, WifiClient);
void setup()
{
delay(2000);
Serial.begin(9600);
Serial.println("Starting....");
Serial.println("Initializing Wifi...");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
}
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if (status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// Ff you are connected, print out success message
else
Serial.println("Connected to network");
if (client.connect("arduinoClient")) {
Serial.println("Connected to server! Sending message...");
client.publish("randy/test","hello world");
client.subscribe("randy/test");
Serial.println("Sent!");
}
else
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
}
void loop()
{
client.loop();
delay(1000);
if (!client.connected())
{
if(!client.connect("arduinoClient"))
{
Serial.println("ERROR: Cannot connect to MQTT server!");
Serial.println(client.state());
}
else
{
client.subscribe("randy/test");
Serial.println("INFO: reconnected!");
}
}
}
Any idea what's wrong with those libraries or my code?
As mentioned in the comments
When using example code on public brokers make sure you change the client id to something random as the odds of clashing with somebody else are pretty high. Because client ids have to be unique else they will cause a reconnection storm
Related
i trying to acheive some home automation with esp 32. my project is like following
i have several end points with esp 8266 acting likes slave switches sending Id datas to an esp 32 who is my gateway.
both slaves (esp8266) and master gateway (esp 32, are communicating
with espnow library
the gateway should be connected to an mqtt server ( rasperry pi) who
dispatches automation command depending on endpoint Id.
For now i succesfully have communication between esp8266 slaves and esp 32 gateway
i also have succesfully setted my rasperry pi as mqtt broker with home automation command
But i'm blocked when i need to add wifi connection and mqtt messaging to my ESP 32 gateway
My code on the esp32 gateway is
#include <esp_now.h>
#include <WiFi.h>
#include <PubSubClient.h>
#define LED 2
int myData;
char ssid[] = "my ssid";
char password[] = "mypass";
char mqtt_server[] = "192.168.1.55";
WiFiClient espClient;
PubSubClient MQTTclient(espClient);
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
Serial.print("Bytes received: ");
Serial.println(len);
Serial.print("data: ");
Serial.println(myData);
/*
if(myData == 1){
String reponse="device1";
MQTTclient.publish("homecommand",reponse.c_str());
}
*/
for (int t=0; t<3; t++)
{
digitalWrite(LED,HIGH);
delay(50);
digitalWrite(LED,LOW);
delay(50);
}
}
void MQTTconnect() {
while (!MQTTclient.connected()) {
Serial.print("Attente MQTT connection...");
String clientId = "TestClient-";
clientId += String(random(0xffff), HEX);
// test connexion
if (MQTTclient.connect(clientId.c_str(),"","")) {
Serial.println("connected");
} else { // si echec affichage erreur
Serial.print("ECHEC, rc=");
Serial.print(MQTTclient.state());
Serial.println(" nouvelle tentative dans 5 secondes");
delay(5000);
}
}
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
pinMode(LED,OUTPUT);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(OnDataRecv);
/*
Serial.println("Connect to Wifi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("Connected");
MQTTclient.setServer(mqtt_server, 1883);
if (!MQTTclient.connected()) {
MQTTconnect();
}*/
}
void loop() {
// put your main code here, to run repeatedly:
}
The code works well, when i trigger one of my slaves i receive the message print it in serial an blink 3 times
But when i uncomment the part about connecting to my home router and my mqtt broker i lost the 'On DataRecv' callback
So my question is "Is it possible to have an Esp working as espnow gateway to gather messages and at the same time being connected to my home router for mqtt publishing ?"
If yes i would appreciate some help to implement it.
Thanks a lot.
Swap
WiFi.mode(WIFI_STA);
for
WiFi.mode(WIFI_AP_STA);
re:
https://www.electrosoftcloud.com/en/esp32-wifi-and-esp-now-simultaneously/
My problem:
I have a Raspberry Pi, and I have installed the Mosquitto MQTT broker on it. My objective is to make 2 MQTT clients communicate over the Mosquitto broker, so I have installed the code below on two ESP8266 (WeMos D1 mini)
and I have created this MQTT command: mosquitto_pub -h 192.168.1.20 -t /wassim/led -m "on".
So, when I connect only one ESP client, I see the message "on" in the serial monitor. But when I connect the second ESP client, I can't see any message on the serial monitor... (But if on the terminal of the Raspberry, then I can see everything. On the clients I can't see anything). The code:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <MQTTClient.h>
float temp;
float lm;
String aw="";
const char* host = "192.168.1.20";
const char* ssid = "THOMSON1121";
const char* password = "Wassim";
WiFiClient net;
MQTTClient mqtt;
void connect();
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Booting...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
mqtt.begin(host, net);
connect();
if(mqtt.subscribe("/wassim/led")) {
Serial.println("Subscription Valid !");
}
Serial.println("Setup completed...");
}
void loop() {
if (!mqtt.connected()) {
connect();
}
mqtt.loop();
delay(3000);
}
void connect() {
while(WiFi.waitForConnectResult() != WL_CONNECTED) {
WiFi.begin(ssid, password);
Serial.println("WiFi connection failed. Retry.");
}
Serial.print("Wifi connection successful - IP-Address: ");
Serial.println(WiFi.localIP());
while (!mqtt.connect(host)) {
Serial.print(".");
}
Serial.println("MQTT connected!");
}
void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
Serial.print("incoming: ");
Serial.print(topic);
Serial.print(" - ");
Serial.print(payload);
Serial.println();
}
The change from one client to another is if(mqtt.subscribe("/wassim/tmp")).
MQTT is a 'message bus' application....in order to have multiple 'subscribers' receive the same message that is being put on the bus by a 'publisher', they both have to subscribe to the same topic...or at least enough of the topic + wildcard...in order to get sent that published message. You only have one of your two clients listening to the topic that your 'mosquitto_pub' command is sending out. For it to receive, you either specify the full topic (mqtt.subscribe("/wassim/led")), or a wildcard to pick up all the 'wassim' messages sent out (mqtt.subscribe("/wassim/#")).
The problem is that I want to execute the code below, but when ESP8266 is shut down, then I start it again, everything is gone.
So, is there a solution that I can make this ESP8266 work the same controlled by my Arduino Uno.
My program blow is to control the GPIO2 through web browser.
Thanks a lot to all of you!!
My Codes:
#include <ESP8266WiFi.h>
#include <aREST.h>
// Create aREST instance
aREST rest = aREST();
// WiFi parameters
const char* ssid = "Protect Big Dragon 4";
const char* password = "18717772056";
// The port to listen for incoming TCP connections
#define LISTEN_PORT 80
// Create an instance of the server
WiFiServer server(LISTEN_PORT);
void setup(void)
{
// Start Serial
Serial.begin(115200);
// Give name and ID to device
rest.set_id("2");
rest.set_name("lamp_control");
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
void loop() {
// Handle REST calls
WiFiClient client = server.available();
if (!client) {
return;
}
while(!client.available()){
delay(1);
}
rest.handle(client);
}
So your ESP8266 loses your code when it is rebooted.
Sounds like the memory is faulty.
Try a different ESP8266 and let us know what occurs.
#include "SPI.h"
#include “WiFiEsp.h”
#include <WiFiEspClient.h>
#include “SoftwareSerial.h”
#include <PubSubClient.h>
#include <WiFiEspUdp.h>
float temp=0;
int tempPin = 0;
int isClientConnected = 0;
char data[80];
char ssid[] = “SSID”; // your network SSID (name)
char pass[] = “PASSWORD”; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio’s status
char deviceName = “ArduinoClient1”;
IPAddress server(xxx,xxx,xxx,xxx); //MQTT server IP
IPAddress ip(192,168,43,200);
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("-");
}
// Emulate Serial1 on pins 6/7 if not present
WiFiEspClient espClient;
PubSubClient client(espClient);
SoftwareSerial Serial1(6,7); // RX, TX
void setup(){
Serial.begin(9600);
Serial1.begin(9600);
WiFi.init(&Serial1);
WiFi.config(ip);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
while (true);
}
while ( status != WL_CONNECTED) {
Serial.print("Attemptingonnect to WPA SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
Serial.print("WiFius : ");
Serial.println(status);
}
//connect to MQTT server
client.setServer(server, 1883);
client.setCallback(callback);
isClientConnected = client.connect(deviceName);
Serial.println("+++++++");
Serial.print("isClientConnected;
Serial.println(isClientConnected);
Serial.print("client.state");
Serial.println(client.state());
if (isClientConnected) {
Serial.println("Connected…..");
client.publish("status","Welcome to ISG");
client.subscribe("isg/demoPublish/rpi/ardTempWarn");
//Not able to recieve for this subscribed topic on Arduino Uno Only if I
//print it returns 1
}
}
void loop() {
temp = (5.0 * analogRead(tempPin) * 100.0) / 1024;
Serial.print(" temp : " );
Serial.println(temp);
Serial.print("client.connected);
Serial.println(client.connected());
if (!client.connected()) {
reconnect();
}
client.publish("isg/demoPublish/ard1/tempLM35",String(temp).c_str());
// able to receive data at other
// clients like RPI,Web using Mosquitto broker
client.loop();
delay(5000);
}
void reconnect() {
Serial.println("Device is trying to connect to server ");
while (!client.connected()) {
if (client.connect(deviceName)) {
} else {
delay(5000);
}
}
}
I am using Arduino Uno R3 and ESP8266-01 as wifi connector.
I have to read temperature data and send to Mosquitto ,MongoDB and Raspberry Pi and receive a data on specific condition for that i have subscribed a topic in Arduino.
I am able to receive data from Arduino to all other clients but I am not able to receive data on Subscribed topic in Arduino. But all other deviced like MongoDB able to receive data from Raspberry Pi.
I have used Arduino Uno R3, ESP8266-01 devices and liberary for to connect and send/receive data WiFiEsp.h, WiFiEspClient.h, WiFiEspUdp.h, SoftwareSerial.h, PubSubClient.h
client.subscribe("topic"); returns 1
Also callback function implemented but not able to get call.
So can any one help me why I am not getting subscribed topic message in Arduino?
I have follow https://sonyarouje.com/2016/03/15/mqtt-communication-with-arduino-using-esp8266-esp-01/#comment-111773
The library that you are using has bug in callback hence it would be better that you use other library my preference would be
https://github.com/vshymanskyy/TinyGSM
this library include almost all variants of SIM800(A,C,L,H,808), variants of SIM900(A,D,908,968), ESP8266 (mounted on arduino), Ethernet shield etc. It worked for me, as same issue bugged me for almost 1-2 weeks but latter was able to receive all subscribed message irrespective of mode of communication(GSM,Ethernet,WiFi)
I have recently bought an arduino wifi shield(Atmal chip 32UC3A1512-U), which I connected with
my Arduino Mega ADK R3 board)...It is getting connected to my wifi network, But when I run the
SimpleWebServer Example provided in the library to on/off the LED is not working. The code is given below...
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "belkin.E33"; // your network SSID (name)
char pass[] = "abc123cde456"; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(80);
void setup() {
Serial.begin(9600); // initialize serial communication
pinMode(9, OUTPUT); // set the LED pin mode
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
while(true); // don't continue
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid); // print the network name (SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin(); // start the web server on port 80
printWifiStatus(); // you're connected now, so print out the status
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("new client"); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("Click here turn the LED on pin 9 on<br>");
client.print("Click here turn the LED on pin 9 off<br>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
}
else { // if you got a newline, then clear currentLine:
currentLine = "";
}
}
else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(9, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(9, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
// print where to go in a browser:
Serial.print("To see this page in action, open a browser to http://");
Serial.println(ip);
}
The result that I am getting in the serial monitor is
Attempting to connect to Network named: belkin.E33
SSID: belkin.E33
IP Address: 192.168.2.5
strength (RSSI):-56 dBm
To see this page in action, open a browser to http://192.168.2.5
But When I am opening the browser with the specified IP address, It is showing
Could not Connect to 192.168.2.5
I have tried this in mozilla and chrome from my ubuntu machine...also tried from some other machines in the same network but with the same result. But when I am pinging to 192.168.2.5 it is pinging...What went wrong??? . My friend adviced to change the firmware...Is it an issue,bcas as told earlier simple examples for establishing the connection are working...Please guide me
I've got the same problem after upgrading Arduino IDE to lastest version (v2) from v1.0.8 which is doing fine with the wifi shield tests (client and server).
Going to try the nightly build now and see if it's fixed.
Edit: Yeap, Nightly build solves this issue.