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

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

Related

Arduino Ethernet parsing XML

I'm using an Arduino Uno and ethernet shield to pull xml data from OpenWeatherMap.org. I have the api link and a key, and it all works fine on the web browser. My code is below, however when I get to reading the response from the GET command, all i get is "ΓΏ", not anything I would expect.
I can connect to the arduino when using it as a server, and I can ping it from command prompt so I know it is on the network and the board is not at fault, so it must be something with my code. I have followed the tutorial on the arduino site and loaded the example to GET data, but this also does not work, all I get is a "did not connect" message.
Can someone please look over my code and see what I am doing wrong?
EDIT: I have added the extra loop to print all the xml data, however the program still gets stuck on the while(!client.available());. If i comment it out, I get to the "waiting for server response" but never any further than that. I have checked that the arduino si on the same subnet mask as all the other devices in the network.
// Based on:
// Read Yahoo Weather API XML
// 03.09.2012
// http://forum.arduino.cc/index.php?topic=121992.0
//
#include <SPI.h>
#include <Ethernet.h>
#include <TextFinder.h>
int cityID=2644487; //Lincoln, UK
byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02};
byte ip[] = {192, 168, 1, 89};
byte gateway[] = {192, 168, 1, 254};
byte subnet[] = {255, 255, 255, 0};
//Open weather map xml
char server[] = "http://api.openweathermap.org";
int port = 80; //usually 80 for http.
char APIkey[33] = "HIDDENAPIKEY";
EthernetClient client;
char temperature[30];
void setup()
{
pinMode(10, OUTPUT);
digitalWrite(10,HIGH);
Serial.begin(9600);
Serial.println("Initialising...");
// Start Ethernet
if(!Ethernet.begin(mac)){//if DHCP does not automatically connect
Serial.println("Invalid Connection");
}
Serial.println("");
Serial.print("Connecting to OWM server using cityID: ");
Serial.println(cityID);
Serial.print("Using API key: ");
Serial.println(APIkey);
if (client.connect(server,port))
{
client.println("GET /data/2.5/weather?id=2644487&appid=HIDDENAPIKEY&mode=xml&units=metric HTTP/1.1");
client.println("HOST: api.openweathermap.org");
client.println();
Serial.println("Connected to XML data.");
while(!client.available()); //wait for client data to be available
Serial.println("Waiting for server response...");
while(client.available()){
char c = client.read();
Serial.println(c);
}
}
}
void loop()
{
}
For start, your Host header is wrong, use only domain name:
client.println("HOST: api.openweathermap.org");
Second problem I see here is that you do not read entire response from server but only one char.
You have to wait for response data to be available, after that read all the data and parse it or print at start.
This part is wrong:
char c = client.read();
Serial.println(c);
Should be something similar to:
while (!client.available()); //Wait client data to be available
while (client.available()) { //Print all the data
char c = client.read();
Serial.println(c);
}

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

Publish onto Mosquitto broker running on laptop

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"

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('.');
}
}

Unable to connect to MQTT Server

I am using knolleary library to connect the Arduino UNO board to MQTT server. For broker I am using test.mosquitto.org (85.119.83.194) but I am not able to connect.
Here is my code:
/*
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, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 10, 2, 63, 123};
byte ip[] = { 85, 119, 83, 194 };
void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
Serial.println("Message received");
}
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
void setup()
{
Ethernet.begin(mac, ip);
Serial.begin(9600);
Serial.println("Ethernet Begin");
if (client.connect("arduinoClient")) {
Serial.println("Client connected");
client.subscribe("/notification/turnlighton");
}
else{
Serial.println("Client not connected");
}
}
void loop()
{
client.loop();
}
client.connect("arduinoClient") return false and "Client not connected" message is printed Serial Monitor.
I am not sure what should be the value of
byte server[] = { 10, 2, 63, 123};
As an alternate I also tried to connect to the Really Simple Message Broker (RSMB) in intranet. Still I get same message.
Can any one help in here?
Thanks in advance
SRS
You have it around the wrong way;
byte server[] is your mqtt server's ip address, in your case test.mosquitto.org (85.119.83.194)
byte ip[] is the static ip address you want the arduino to have on your network.
The other thing to check is that you can connect using a cli client to test.mosquitto.org as it is sometimes down I find.
Have a look at my temperature publishing code, https://github.com/matbor/arduinoTemps2mqtt it might give you a few hints as it was modified from that original example that comes with PubSubClient. In my one I just have the arduino running off DHCP.

Resources