Publish onto Mosquitto broker running on laptop - arduino

I have followed the steps outlined in the following link to install and run the Mosquitto broker on my laptop.
https://sivatechworld.wordpress.com/2015/06/11/step-by-step-installing-and-configuring-mosquitto-with-windows-7/
I have tested the publishing and subscription events using command line i.e, the mosquitto_pub and mosquitto_sub commands and they worked fine!
I want to publish to this broker running on my laptop (listening to port 1883 - confirmed using the netstat-an command) using an Arduino which is using the functions from "PubSubClient" library.
For the server's IP address in the Arduino Publish sketch, I have given the IP address of my laptop itself which it gets when it connects to my home network. Following is the publisher code:
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#define CLIENTID "Arsen"
const char topic[] = "tem";
#define POLLINTERVAL 120000
void callback(char* topic, byte* payload, unsigned int length){
//Do nothing as we are publishing ONLY.
}
byte mac [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED} ;
IPAddress server(192, 168, 0, 10);
EthernetClient ethClient;
PubSubClient arduinoClient(server,1883, callback, ethClient) ;
unsigned long boardTime = 0 ;
float sensedTemperature = 0;
char charTemp [6];
int connRC = 0;
void setup(void) {
Serial.begin(9600);
//Connect to the MQTT server - test.mosquitto.org
beginConnection() ;
}
//Initialise MQTT connection
void beginConnection() {
Serial.begin(9600);
Ethernet.begin(mac) ; //using the address assigned through DHCP
do{
int connRC = arduinoClient.connect(CLIENTID);
}while(connRC==1);
Serial.println("We are connected finally");
delay(5000);
Serial.println(arduinoClient.state());
}
void loop(void) {
boardTime = millis();
if ((boardTime % POLLINTERVAL) == 0) {
getTemp();
dtostrf(sensedTemperature,5,2,charTemp);
boolean rec = arduinoClient.publish(topic, charTemp);
Serial.println(rec);
Serial.println("Successfully published");
}
arduinoClient.loop();
}
void getTemp() {
// Send the command to get temperatures
delay(100);
sensedTemperature = analogRead(2); //temperature sensor at analog pin 2 on Arduino.
Serial.println(sensedTemperature);
delay(150);
}
The subscriber code is:
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <EthernetServer.h>
#include <EthernetClient.h>
#include <Dns.h>
#include <Dhcp.h>
#include <SPI.h>
#include <PubSubClient.h>
#define PIN 13
//MQTT Definition
#define CLIENTID "Aract"
#define TOPICNAME "tem"
byte mac [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED} ;
IPAddress server(192,168,0,5); // Mosquitto Server
int connRC = 0;
//Handle message from mosquitto and set LEDs
void callback(char* topic, byte* payload, unsigned int length) {
int i=0; char buffer [length];
for(i=0;i<length;i++) {
buffer [i] = char((payload[i]));
}
String payLoadData = buffer;
Serial.println(payLoadData);
setled(payLoadData);
}
//Our MQTT client
EthernetClient ethclient;
PubSubClient arduinoClient(server, 1883, callback, ethclient) ;
void setup() {
//Connect to the MQTT server - test.mosquitto.org
beginConnection() ;
}
//Initialise MQTT connection
void beginConnection() {
Serial.begin(9600);
Ethernet.begin(mac) ;
do{
connRC = arduinoClient.connect(CLIENTID) ;
delay(2000);
}while(connRC==1);
delay(3000);
Serial.println(arduinoClient.state());
if (connRC==1) {
boolean rec = arduinoClient.subscribe(TOPICNAME) ;
Serial.println(rec);
Serial.println("Successfully Subscribed");
} else {
Serial.println("connRC") ;
}
}
void loop()
{
arduinoClient.loop() ;
}
void setled(String s)
{
int temperature;
temperature = s.toInt();
Serial.println(temperature);
if (temperature >= 200){
digitalWrite(PIN, HIGH);
}
else{
digitalWrite(PIN, LOW);
}
}
The Ethernet shield is working well as it successfully executed the example programs. The state function returns "zero" which implies that the board is connecting to the network. However, the publish command returns a boolean value "rec" which is giving false. I want to know as to why this process is being unsuccessful all the time?
The verbose option (-v) along with Mosquitto on command line throws up an unknown error instead of showing the logged details. How to overcome this problem or what exactly is wrong in my technique?

I had faced the same problem and I got the solution as this...
Just go to the services running in your PC and stop the mosquitto-broker, now open the cmd and change the directory to the place where mosuitto files were located (in my case it is "cd C:\Program Files (x86)\mosquitto") and then enter this command mosquitto -v, now just left that window like that (If u closed then it won't work)...
It really worked and the reason why its not working in before case is, when we started moquitto-broker service then its not opening ports for IPv4 and here is the reference "Mosquitto Error"

Related

Can't connect ESP32 to MQTT

I have been trying to connect my ESP32 with HiveMQ MQTT broker url. It connects when I use free public MQTT broker like broker.hivemq.com, but when I use my url which I got after registering in HiveMQ, it doesn't connect. It returns error with code 2.
I have used this MQTT broker url with windows MQTT client app and it works fine but it doesn't work with ESP32.
#include <WiFi.h>
#include <PubSubClient.h>
// WiFi
const char *ssid = "********"; // Enter your WiFi name
const char *password = "********"; // Enter WiFi password
// MQTT Broker
const char *mqtt_broker = "591c2cacc87d4e248d106212ae6e0d4f.s2.eu.hivemq.cloud";
const char *topic = "esp32/test";
const char *mqtt_username = "*******";
const char *mqtt_password = "*******";
const int mqtt_port = 8883;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
// Set software serial baud to 115200;
Serial.begin(115200);
// connecting to a WiFi network
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
//connecting to a mqtt broker
client.setServer(mqtt_broker, mqtt_port);
client.setCallback(callback);
while (!client.connected()) {
String client_id = "esp32-client-";
client_id += String(WiFi.macAddress());
Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Public emqx mqtt broker connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// publish and subscribe
client.publish(topic, "Hi EMQ X I'm ESP32 ^^");
client.subscribe(topic);
}
void callback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char) payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void loop() {
client.loop();
}
In the comments, #hcheung said:
When you use MQTT over TLS (port 8883), you need to use WiFiClientSecure.h and add the root CA of broker.hivemq.com to your sketch. Refer to WiFiClientSecure on how to do it.
You can get the root CA of your HiveMQ broker with the following OpenSSL method:
openssl s_client -connect hivemq-broker-host:8883 -showcerts
Change hivemq-broker-host with your MQTT host.
Using a combination of Farhan's example and a few other examples I found elsewhere, I was able to get this to work.
First, open a terminal run the command from Johnny Boy's answer (This assumes you have openssl installed. If not, install it.
openssl s_client -connect YOUR_URL.hivemq.cloud:8883 -showcerts
You'll get three certificates. They look like this
-----BEGIN CERTIFICATE----- MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
...Lots more characters that I'll omit for brevity...
-----END CERTIFICATE-----
The third certificate is the one you want. Copy this certificate out of your terminal (including the BEGIN and END CERTIFICATE parts). Paste the cert into your ESP32 code as a const char variable, such as:
const char *ROOT_CERT = "-----BEGIN CERTIFICATE-----\n"
"MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
... etc..
Using the WiFiClientSecure library mentioned in the comments, use the setCACert function to utilize your certificate. The rest of the code looks pretty close to what Farhan had. In my example, a few of the variables, including the ROOT_CERT variable from above, were defined in another file (WifiCredentials.h):
#include <PubSubClient.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <WiFiUdp.h>
#include "WifiCredentials.h"
#include <WiFiClientSecure.h>
*********/
Helpful References:
* https://randomnerdtutorials.com/esp32-web-server-arduino-ide/
*
*********/
WiFiClientSecure wifiClient;
PubSubClient mqttClient(wifiClient);
char *mqttServer = "YOUR_URL.hivemq.cloud";
int mqttPort = 8883;
const char *mqtt_password = "password_I_setup_at_hivemq";
const char *mqtt_username = "username_I-setup_at_hivemq";
void setup() {
Serial.begin(9600);
// Connect to Wi-Fi network
Serial.print("Connecting to ");
Serial.println(WifiSSID);
WiFi.begin(WifiSSID, WifiPassword);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("...Still Connecting");
}
Serial.println("");
Serial.println("WiFi connected.");
wifiClient.setCACert(ROOT_CERT);
}
void loop(){
if (!mqttClient.connected()) {
mqttClient.setServer(mqttServer, mqttPort);
// set the callback function
mqttClient.setCallback(callback);
Serial.println("Connecting to MQTT Broker...");
while (!mqttClient.connected()) {
Serial.println("Reconnecting to MQTT Broker..");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (mqttClient.connect(clientId.c_str(), mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT BRoker!.");
// subscribe to topic
mqttClient.subscribe("/transactions/device1");
mqttClient.publish("/transactions/device1", "testing hello");
} else {
Serial.print("failed with state ");
Serial.print(mqttClient.state());
delay(2000);
}
}
}
mqttClient.loop();
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Callback - ");
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
}
Connect a tool like MQTT Dash to your HiveMQ instance, open a serial monitor, and test your code.

Arduino PubSubClient fail to connect to Mosquitto

I'm trying to complete my brewing system with Arduino, Raspberry, mqtt, MySql, Php.
I want to switch from sending data via serial port to ethernet+MQTT.
When I try to publish-subscribe with PubSubClient everything goes well. But whenever I try to put the DallasTemperature begin() function it can't connect anymore to the broker.
As soon as I remove the instruction sensors.begin(); it restarts and works perfectly.
Any of you knows why the hell is acting like this?
Here the code:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#define ONE_WIRE_BUS 10
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature Sensors(&oneWire);
// Pins
const int photocellPin = 1; // the cell and 10K pulldown are connected to a1
// Variables
String lightC;
unsigned long time;
char message_buffer[100];
// Network Settings
// MAC address of ethernet shield
// Look for it on a sticket at the bottom of the shield.
// Old Arduino Ethernet Shields or clones may not have a dedicated MAC address. Set any hex values here.
byte MAC_ADDRESS[] = { 0xFE, 0xED, 0xDE, 0xAD, 0xBE, 0xED };
// IP address of MQTT server
byte MQTT_SERVER[] = { 192, 168, 2, 46 }; // 10, 192, 191, 77 { 192, 168, 1, 115 };
// Handles messages arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Messaggio ricevuto [");
Serial.print(topic);
Serial.print("]");
for (int i = 0; i < length; i++) {
char receivedChar = (char)payload[i];
Serial.print(receivedChar);
}
Serial.println();
}
EthernetClient ethClient;
PubSubClient client(MQTT_SERVER, 1883, callback, ethClient);
IPAddress ip(192, 168, 2, 177);
void setup()
{
// Initilize serial link for debugging
Serial.begin(9600);
Ethernet.begin(MAC_ADDRESS, ip);
delay(2000);
// initialize the digital pin's as an output.
Serial.println("connected...");
Sensors.begin();
Serial.println("initialized..."); // Just for checking
}
void loop()
{
if (!client.connected()) {
reconnect();
}
lightC = dtostrf(analogRead(photocellPin), 5, 2, message_buffer); // TMP36 sensor calibration
Serial.println(lightC);
delay(2000);
// Publish sensor reading every X milliseconds
if (millis() > (time + 60000)) {
time = millis();
client.publish("fromarduino", (char*)lightC.c_str());
}
// MQTT client loop processing
client.loop();
}
void reconnect()
{
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("mb-arduino")) {
Serial.println("MQTT connected");
client.publish("fromarduino/alive", "I'm alive!");
client.subscribe("toarduino");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
It always returns error rc=-2.

Blink Led using MQTT in arduino

I have to implement a prototyping scenario that blink LED in the arduino with MQTT protocol. I already tried with several MQTT libraries but non of them not work perfectly. Connection to the MQTT broker working successfully but when I publish the message with topic which I set in arduino not blink the LED. Arduno have to publish a message when it successfully connect but this publishing part also not working
this is my code
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Set the MAC address
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 100);
IPAddress server(192, 168, 1, 20);
// Set what PINs our Led's are connected to
int redPin = 13;
//int greenPin = 6;
//int bluePin = 7;
// Set a generic code that will trigger our Blue Led
// think of this as a set of codes for automation you might write
byte triggerRed[13] = "12345";
// handles messages that are returned from the broker on our subscribed channel
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("New message from broker on topic:");
Serial.println(topic);
Serial.print("Payload:");
Serial.write(payload, length);
// Check and see if our payload matches our simple trigger test
if ((length == 5) & (memcmp(payload, triggerRed, 5) == 0) )
{
//blink(redPin);
}
}
EthernetClient ethClient;
PubSubClient client(ethClient);
// Fire up our PubSub client
//PubSubClient client(server, 1883, callback);
void setup()
{
// Open serial communications
Serial.begin(9600);
client.setServer(server, 1883);
client.setCallback(callback);
// Setup our Leds
pinMode(redPin, OUTPUT);
// pinMode(greenPin, OUTPUT);
// pinMode(bluePin, OUTPUT);
// attempt a DHCP connection
Serial.println("Attempting to get an IP address using DHCP:");
if (!Ethernet.begin(mac))
{
// if DHCP fails, start with a hard-coded address:
Serial.println("failed to get an IP address using DHCP, trying manually");
Ethernet.begin(mac, ip);
}
Serial.print("My address:");
Serial.println(Ethernet.localIP());
// Connect to Broker, give it arduino as the name
if (client.connect("arduino")) {
// Good, we connected turn on the red led
digitalWrite(redPin, HIGH);
// Publish a message to the status topic
client.publish("status","Arduino is now online");
// Listen for messages on the control topic
client.subscribe("ultra");
}
}
void loop()
{
client.loop();
}
// Anything with flashing lights.
void blink(int targetLed)
{
digitalWrite(redPin, HIGH);
}
how can I fix this ?
Put connection routine in a loop and try with test.mosquitto.org first.
Here is code that works for me (Ethernet shield hardware):
definitions:
#define CLIENT_NAME "myclientname"
#define TOPIC "mytopic"
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 105);
IPAddress server(85, 119, 83, 194);// test.mosquitto.org
#define MQTT_PORT 1883
IPAddress myDns(8, 8, 8, 8);
EthernetClient ethClient;
PubSubClient client(ethClient);
setup:
client.setServer(server, MQTT_PORT);
client.setCallback(callback);
Ethernet.begin(mac);
loop:
if (!client.connected()) {
reconnect();
}
client.loop();
reconnect routine
void reconnect() {
if (millis() - reconnectionTimer >reconnection_period){// Loop until we're reconnected
reconnectionTimer = millis();
if (!client.connected()) {
// Attempt to connect
if (client.connect(CLIENT_NAME)) {
client.subscribe(TOPIC);
}
else {
Serial.print(client.state());
Serial3.print(client.state());
}
}
}
}
update for blink:
void blink(){
digitalWrite(led, LOW);
delay(500);
digitalWrite(led, HIGH);
}
I lost a lot of time because i had the problem with the mqtt server. ensure that your server is using mqtt protocol, because i was using ws protocol and any library that I tried doesn't works with this protocol

mqtt error void callback/subscribed on arduino

I'm testing with my arduino and MQTT cloud.
For the publish everything goes well, the arduino publishes "hello world"
But with the void callback function nothing happens.
With my MQTT.fx client, I'm subscribed to the topics "status" and "commando".
At the "status" I see that the arduino is a live.
When I publish with my MQTT.fx client to the topic "commando".
I can see it arrived in my client, but not in the serial monitor of the arduino.
Why is the void callback function not used?
#include <SPI.h>
#include <PubSubClient.h>
#include <Ethernet.h>
#define server "m20.cloudmqtt.com"
int port = 13365;
// Update these with values suitable for your network.
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 120 };
unsigned long time;
char message_buff[100];
EthernetClient ethClient;
PubSubClient client(server, port, callback, ethClient);
void setup()
{
// init serial link for debugging
Serial.begin(115200);
Ethernet.begin(mac, ip);
if (client.connect("arduino-MQTT","test","test")) {
client.publish("/arduino/status/","hello world");
client.subscribe("/arduino/commando/");
Serial.println("Connected");
}
if (Ethernet.begin(mac) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
return;
}
}
void loop()
{
// MQTT client loop processing
client.loop();
}
void callback(char* topic, byte* payload, unsigned int length) {
if (strcmp(topic, "/arduino/commando/") == 0) {
String msg = toString(payload, length);
Serial.println(msg);
}else{
Serial.println("arduino topic not found");
}
}
//
// toString function
//
String toString(byte* payload, unsigned int length) {
int i = 0;
char buff[length + 1];
for (i = 0; i < length; i++) {
buff[i] = payload[i];
}
buff[i] = '\0';
String msg = String(buff);
return msg;
}
I have just tested your code with RSMB broker and it works. I do not have DHCP on my computer so I had to comment out DHCP handling code - Ethernet.begin(mac). I think that's where your bug is. Because:
You assign static IP to your Ethernet
Connect to mqtt broker, and subscribe to a topic
Query DHCP for a new IP. Probably at this point your Arduino gets a different IP than statically configured and the broker cannot reach your Arduino any more to publish subscribed topic.
Fix your Ethernet handling code. I like this formula:
// Start the Ethernet connection:
Serial.println(F("Querying DHCP"));
if ( Ethernet.begin( mac ) == 0 ) {
Serial.println(F("DHCP failed, fallback to static IP"));
// When DHCP fails, fallback to static configuration ;
Ethernet.begin( mac, ip ) ;
}
printIp() ;
And printIp function:
void printIp() {
// Print local IP address
Serial.print(F("My IP "));
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print('.');
}
}

Arduino Knolleary PubSubClient will publish messages but can't receive them

I am using the Knolleary PubSubClient to make a connection to my MQTT server. I have been able to successfully authenticate and make a connection after not much work. I can even publish messages to topics. However, the issue I am having is that I can subscribe to topics and get no error, but when I publish to that topic (from mosquitto on my Mac) the callback does not get called and the message to the subscribe topic does not appear to be received. I have tried running a mosquitto subscription to the same topic at the same time, and that does receive the published message. Not sure if there is a problem in my callback code or what is going on here. Any help would be appreciated. Arduino code is below:
/*
Basic MQTT example
- connects to an MQTT server
- publishes "hello world" to the topic "outTopic"
- subscribes to the topic "inTopic"
*/
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte server[] = { 10, 2, 63, 123 };
byte ip[] = { 192, 168, 1, 10 };
void callback(char* topic, byte* payload, unsigned int length) {
Serial.println(topic);
//convert byte to char
payload[length] = '\0';
String strPayload = String((char*)payload);
Serial.println(strPayload);
//int valoc = strPayload.lastIndexOf(',');
//String val = strPayload.substring(valoc+1);
//Serial.println(val);
}
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
void setup()
{
Serial.begin(19200);
Serial.println("==STARTING==");
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
//delay(500);
boolean con = client.connect("1", "3snzzon5dyade:abc", "OBSCURED_FOR_SEC");
while(con != 1){
Serial.println("no con-while");
con = client.connect("1", "3snzzon5dyade:abc", "OBSCURED_FOR_SEC");
}
//Serial.println(con);
if(con){
Serial.println("got con");
client.publish("testq","hello world");
client.subscribe("testq");
}else Serial.println("no con");
}
void loop()
{
client.loop();
}
Like I said, I can see everything working properly with mosquitto. I have even tried matching up client_ids with no luck. Any help or ideas would be greatly appreciated.
your subscribe topic "testq" must be in an array like
char testq[] = {'t', 'e', 's', 't', 'q', '\0'};
be sure to finisht your array with an ,'\0'
Then you subscribe with:
client.subscribe(testq);

Resources