Moved to http://pubsubclient.knolleary.net/

  1. ilium007 • June 23, 2012

    (Nick says: three quick-fire comments collapsed down into one)

    Cheers !! I have a had a play with all of the above but I am not sure what the line:

    payload[length] = '';

    is saying.

    Also, when I run the first example I get the error:

    “invalid conversion from ‘byte*’ to ‘const char*’

    This is what I have done with my callback function:

    void callback(char* topic, byte* payload, unsigned int length)
    {
      lcd.clear();
      lcd.setCursor(0,0);
      
      if ((payload[0])==80 && (payload[1])==80)
      {
        lcd.print("PUMP:");
        if (payload[2]==48 && payload[3]==49)
        {
          lcd.print("ON");
          //turn on the pump here; set digital pin high to trigger SSR
    
        }
        else if (payload[2]==48 && payload[3]==48)
        {
          lcd.print("OFF");
          //turn off the pump here; set digital pin low to trigger SSR
        }
        else
        {
          lcd.print("NA");
        }
      }
      delay(5000);
      lcd.clear();
    }
    

    I am not sure if this is the best way to handle a very simple MQ type message protocol. ANy suggestions welcome. I am trying to write a simple protocol that I will use to measure water in my various water tanks and then turn on/off pumps and open/close solenoid valves as necessary.

    I should have added. At present to turn on a pump I would send a message:

    PP01

    to turn off:

    PP00

  2. nickJune 23, 2012

    ilium007,
    that first example should have been strncmp((char*)payload,"foo",3) – it needs the explicit cast to the right type.

    The payload[length] = ''; line is actually payload[length] = '\0';. This sets the byte immediately after the payload to the null byte – which allows payload to be treated as a null-terminated string.

    I would change your if statements to be something like:

    if (length == 4 && strncmp((char*)payload,"PP01",4)==0) {
      // turn pump on
    } else if (length == 4 && strncmp((char*)payload,"PP00",4)==0) {
      // turn pump off
    }
    // etc
    

    That said, I would suggest changing your topic structure slightly. Rather than have a single topic for all commands you want to send to the arduino, use a different topic for each device connected. For example:

    foo/pump1
    foo/solenoid1
    foo/pump2
    ...
    

    You can then subscribe to foo/#. You would then publish a simple ‘0’ or ‘1’ to the appropriate topic to signify off or on. You may even publish the messages with the ‘retained’ flag set, so that if the Arduino loses its connection and reconnects, it’ll get back the last known state of all the devices when it resubscribes.

    Following this approach means the callback would be something like:

    //Note the use of strcmp rather than strncmp
    // this is because topic is already a null-terminated
    // string.
    if (strcmp(topic,"foo/pump2")==0) { 
     if (payload[0] == '0') {
      // Turn off
     } else if (payload[0] == '1') {
      // Turn on
     }
    } // etc
    

    (Wrap your code in <pre></pre> tags)

    ((I’m going to collapse your comments down to a single one))

    (((I should probably create a mailing-list of something for this sort of discussion, to save space here)))

  3. ilium007 • June 24, 2012

    OK thanks. This has got me tearing my hair out ! I wasn’t brought up on C programming and I am having a hell of a time working out what data type I need to get these values in to publish to the MQTT queue from the Arduino.

    I have a Maxbotix sensor which I am getting a pulse width value (long) and converting into an int value through division to get a distance in cm. I assumed it would be easy to get this data type onto the queue via the publish method. I see it takes a topic as an array of characters but again I am stuck on the payload. It takes a byte array as the payload, as in, a NON null terminated array of bytes. How do I go from the int value to a byte array.

    Thanks

  4. ilium007 • June 24, 2012

    My bad – I have just re-read the API reference and I now see that the publish method can take a char* for topic (I’m cool with that) and a char* for payload. I just need to get my int into a char*

    I am sure this is dead simple – I just don’t know how to do it ! I have run out of pins on my EtherTen and I can’t run Ethernet, my maxbotix sensor, LCD shield and serial. Serial has had to lose out to the LCD so now my only method of debugging my code is via LCD and MQTT !

  5. nickJune 24, 2012

    ilium007 – check out the itoa C function:

    char payload[10];
    int i=1234; 
    itoa(i, payload, 10);
    
  6. ilium007 • June 24, 2012

    Invalid conversion from long int to char*

    I didnt even know there was a data type of ‘long int’

    This is my code:
    for(int i = 0; i < arraySize; i++)
    {
    digitalWrite(swPin, HIGH); //bring high for 21us to start MaxSonar ranging
    delayMicroseconds(39);
    digitalWrite(swPin, LOW);
    pulse = pulseIn(pwPin, HIGH);
    cm = pulse/58; //58uS per cm
    //rangeValue[i] = pulse/58;

    char payload[10];
    itoa(cm, payload, 10);

    mqttClient.publish("tanks/status",cm);

    delay(10);
    }

    I am trying to output the distance measurement in the MQTT message. pulse is initiated as ‘long’, cm is an int

  7. nickJune 24, 2012

    There’s lots of information on converting types on google… suggest you have a look there for now. Rather than debug your code here, I’ll mail you tomorrow.

  8. ilium007 • June 24, 2012

    Apologies. Thanks for the help so far.

  9. infohoundJuly 13, 2012

    Hi Nick. Thanks for writing and distributing this MQTT library for Arduino. Is there any way that you could post a quick Arduino example of how to print a received message (from a subscribed topic) using the callback function? I’ve reviewed the comments and documentation and am able to connect and publish messages, but just haven’t been able to quite figure this out. Thanks in advance for your time and help.

  10. nickJuly 13, 2012

    infohound, do you mean print the payload to Serial?

    Here are a couple examples that ought to work:

    // See caveats of this approach in comment #50
    void callback(char* topic, byte* payload, unsigned int length) {
      // As long as length isn't too big, we can add a null to the payload:
      payload[length] = '\0';
      String strPayload = String((char*)payload);
      Serial.println(strPayload);
    }
    
    void callback(char* topic, byte* payload, unsigned int length) {
      for (int i=0; i<length; i++) {
        Serial.print((char)payload[i]);
      }
      Serial.println();
    }
    
  11. infohoundJuly 14, 2012

    Thanks Nick, but unfortunately neither of those worked. I had tried the first suggestion when reading the comments previously and just tried it again (along w/ the other) after your response. Unfortunately, I still can’t get it to work. I can successfully connect, subscribe and publish messages but can’t seem to receive them. I keep getting an “Error: Connection timed out” message from the Mosquitto broker that I’m using to publish. Other clients are able to receive the published messages but I haven’t been able to figure this out. Thanks again for your help and I’ll keep plugging away at it. If you happen to think of something that may help please let me know. Thanks again.

  12. infohoundJuly 14, 2012

    Scratch that! I just got it. Thanks again for your help Nick!

  13. Des • August 9, 2012

    Is this likely to work easily with other Wifi shields? e.g.
    http://bit.ly/OUByca

    Thanks!

  14. nickAugust 12, 2012

    Hi Des – it should work with any WiFi shield whose library extends the Arduino Ethernet client library. Following that link to RobotShop.com, I couldn’t find any details on what libraries their shields use, so I cannot say for certain.

  15. Johan • August 14, 2012

    Hi Nick,

    Thanks alot for the effort, do you know whether your library supports the ethernet ENC28J60 chipset?

  16. nickAugust 14, 2012

    Hi Johan, there is a fork on github that claims support for that chipset (as is found on the Nanode, for example) – but I have to admit I haven’t kept up to date with where it has got to. https://github.com/njh/NanodeMQTT/

  17. Johan • August 14, 2012

    @Nick, thanks for the reply, I’ll give it a shot.

  18. Johan • August 14, 2012

    Hi Nick, tried, but Nanode with MQTT has severe space implications on my ATMega328. Is there no change that it might word with the EtherCard libaries that support ENC28J60? https://github.com/jcw/ethercard?

  19. nickAugust 15, 2012

    Hi Johan. The simple difference between the ENC28J60 hardware and the WizNet hardware used in the official shield is that WizNet implements the TCP layer of the networking stack for you, where as with the ENC28J60, you have to implement TCP yourself on the ATMega328.

    EtherCard, and older libraries for the ENC*, were intended for the simple request-response exchanges in HTTP. This meant their TCP implementation did not need to worry about multiple packet exchanges, or connections that lasted more than this simple exchange.

    MQTT requires a sustained TCP session, so requires more of TCP to be implemented.

    I see in the README for EtherCard there is experimental support for streamed data. Depending where that has got to and how reliable that is, then it might be feasible to port my library to use that as the underlying network layer. But that wouldn’t be a simple drop-in replacement and would require quite a lot of work.

    If at some point the EtherCard library was wrapped in a library that was API compatible with the official Ethernet library, then it would be easier to port.

  20. Josh Hawley • August 29, 2012

    Hey Nick,
    Whenever I publish from the Arduino I receive the message ~10 times on my client. I am attempting to publish sensor data so it can be viewed by other devices. Any ideas on a good process that I can use to narrow down where the message is getting duplicated?

    Setup:
    Moquitto MQTT Broker 1.0.2 cygwin (http://mosquitto.org)
    MqttDotNet library for .Net (http://sourceforge.net/projects/mqttdotnet/)
    Arduino Uno R3 with and Arduino Ethernet Shield
    This library as of 8/26/2012.

  21. nickAugust 30, 2012

    Hi Josh. I would start by grabbing something like IA92 (http://mqtt.org/wiki/doku.php/ia92) to subscribe to the topic. Using a second subscriber will confirm if the duplicate messages are coming from the publisher (arduino) or are an issue with the subscriber (.NET client).

    If IA92 also receives the 10 messages, then the issue is on the arduino side. The next thing to check is the logic in your code. Add some tracing (ie Serial.println) to verify how many times your code is really calling publish. If it is genuinely only calling publish once, then it starts to get a bit more involved. At that point, I’d use something like Wireshark to look at the network traffic to see what is happening at the MQTT level.

    Hope that helps – if you want to follow up, drop me an email (nick at this domain).

  22. Andrew TothOctober 9, 2012

    Nick,

    Nice work! Have this running on a Nanode connected to an LED message board vis RS232. Mode connectedness to come.

    Enjoying the projects on your site. Thanks for all your efforts.

  23. soilboy • October 22, 2012

    Hi

    Has anybody got this library to work with cosm? I have the same issue as Alessandro a few months ago but not sure If he had any comments.

    I can publish fine to a public broker but NOT cosm.

    Cheers

  24. nickOctober 23, 2012

    Hi Soilboy – I have just successfully connected to cosm and subscribed to a feed – so it is possible. I think the problem Alessandro, and presumably you, are hitting is to do with the maximum packet size the client supports.

    Cosm allows you to specify your api in two different ways; either as the username or prefixed to the topic.

    If you prefix it to the topic, then every publish you receive will include the full api key (as the full topic is included in the packet). The additional 48 characters of API key may be pushing the packet size over the limit.

    I found that by specifying the api key as the username, rather than prefixing it, then the messages arrived as expected. This does mean you cannot use different api keys for each topic you may want access to from the arduino.

    The alternative is to increase the value of MQTT_MAX_PACKET_SIZE in PubSubClient.h.

    Hope that helps.

  25. nickOctober 27, 2012

    Following up my last comment, although I could connect, it was always a fairly unstable connection. I’ll write a post soon, but if you want to use this library with Cosm, you should grab the latest version from github – not the current ‘released’ version (1.8). The Cosm broker does not like MQTT packets being split over multiple TCP packets – which this library was doing. I have changed the code to not do this and now the connection is solid.

  26. pingback from Updated Arduino Client for MQTT « knollearyNovember 11, 2012

  27. Josh Hawley • November 19, 2012

    What are the defaults for the smaller overloads on publish()? I assume that the length is calculated from the array that is passed in? Is retain set on or off by default? I looked in the API documentation, but it did not specify the default values.

  28. nickNovember 19, 2012

    Hi Josh – thanks for the question; Retain is false, and the payload is assumed to be a null-terminated string so its length can be determined. I’ve updated the API docs.

  29. Franz Garsombke • February 5, 2013

    Thanks for a great and useful framework!

    I was wondering if this framework works with the RedFly-Shield?

    https://github.com/watterott/RedFly-Shield
    http://www.watterott.com/en/Arduino-RedFly-Shield

    Thanks again.

    Franz Garsombke

  30. nickFebruary 5, 2013

    Hi Franz. I’m not aware of anyone using that shield with the library. I’ve had a quick look at its library and it looks like it implements the appropriate Client interface for it to work – but I’d want to try it out to be sure. I’m currently without a development environment thanks to a catastrophic attempt to upgrade Ubuntu on my laptop – once it’s back on its feet, I’ll have a closer look.

  31. Franz Garsombke • February 5, 2013

    Thanks for checking into the library Nick. I just received the RedFly (from Germany!) and have somebody soldering it up. I will let you know if it works or not. Your framework works perfectly with the Ethernet Shield.

    I’ve had a few catastrophic upgrades ๐Ÿ™‚ Now I never upgrade Ubuntu, and just start clean ๐Ÿ™‚

    Take care.

    Franz

  32. Franz Garsombke • February 13, 2013

    Finally got the RedFly shield working. For some reason the RedFlyClient class extends Server which doesn’t make much sense to me.

    https://github.com/watterott/RedFly-Shield/blob/master/src/libraries/RedFly/RedFlyClient.h

    The PubSubClient input parameter is ‘Client’ so of course there is no matching function call. Doh!

    So, my guess is that it will not work without modifications to one of the libraries.

  33. Nuno • April 13, 2013

    Hi!

    I’m working with an Arduino project and I would like to abstract the communication layer using this MQTT library. I did not see in any place whether the library works or not with a bluetooth shield instead an ethernet. Where I can find more information?

    Thanks!

  34. nickApril 13, 2013

    Hi, I don’t know anyone using the library with a bluetooth shield, but the communication layer is already abstracted out so it should be possible. The library uses the Client interface for handling the network connection – by default it uses EthernetClient, but you can pass your own instance in one of the constructors. If you have, or can write, a library that uses that interface, it should work.

  35. Nuno • April 30, 2013

    Hi Nick,
    Thank you for your answer. To clarify, I don’t have a bluetooth shield like I said, I’m working with a bluetooth modem like this: https://www.sparkfun.com/products/10393 Basically the pins RX/TX are connected to the Arduino board.
    Right now, I have a mini-library called “SerialClient” that it’s an encapsulation of a SoftwareSerial object with the Client interface. I’m using a SoftwareSerial object to have the hardwareSerial for debugging purposes.
    With this solution I still have a problem because the bluetooth modem is seen as a SerialPort in my computer. I also developed a proxy to forward all bytes from the serial port (bluetooth) to the final MQTT server.

    It works very well, now I can finally talk with my project through a MQTT server ๐Ÿ™‚ Or if you want, it’s easy to switch to the HardwareSerial and this way the Arduino can be connected using the USB cable.

    Later I can publish the mini-library in Github if it’s useful to anyone.

    Thank you!

  36. David RyanJune 27, 2013

    Has anyone had much success with large messages publishing with publish_P? I’m trying to publish a message 2400 bytes. I’m using Serial1 to connect to a RN-XV WiFly module. I’m wondering if the default speed of 9600 is too slow and _client->write is over running the buffer?

    Thanks,
    David.

  37. David RyanJune 27, 2013

    I think I just answered my own question. I added a small delay between writing bytes in publish_P and it sent successfully.

    for (i=0;iwrite((char)pgm_read_byte_near(payload + i));
    delay(3);
    }

    Is there a better way of implementing this?

  38. nickJune 28, 2013

    Hi David, that’s a bit odd. I’m AFK at the moment… I’ll have a play when I’m back next week.

  39. Jerry • June 30, 2013

    I downloaded the latest Arduino Client Library from GitHub, its PubSubClient v1.9.1. Then I tried publishing to the Xively MQTT bridge. The problem is the topic name required by Xively is over-writing memory as the topic name is too long. For example,
    1. String topic = “test/foo/bar”; // Works
    2. String topic = “C11cF7Y3ahRP0X1h2T0j/v2/feeds/465951493.json”; // Works, max 20 char string
    3. String topic = ” C134cF7Y3aRP0X1h2T0j9Z7HCAecHc3901e2ZYHkKA5dkXQR/v2/feeds/465951493.json”; // FAILS due to 48 (first) alphanumeric field

    Xively MQTT bridge requires topic #3, but the first part is 48 chars and is over-writing memory in the Arduino PubSubClient library. Can someone please fix this? Thanks in advance!

  40. nickJune 30, 2013

    Hi Jerry,

    If you scroll back to comment #74 you’ll see this discussed. Either specify the 48 char API key as the username on connect (so you don’t need to include it in the topic of each publish) or increase the internal buffer size used to hold the packet in PubSubClient.h.

  41. Jerry • June 30, 2013

    An answer already give, perfect! It works well now in Xively. Here’s what worked for me …
    a. Used Port 1883 as Port 8883 would not authenticate with API_KEY
    b. Used API_KEY as Username, NULL as password on connect
    c. Topic had to start with ‘/’, e.g. “/v2/feeds/465951493.json”; as opposed to Xively docs which say “…subscribe to โ€˜API_KEY/v2/feeds/504.jsonโ€™.”
    d. Didn’t need to change PubSubClient.h MQTT_MAX_PACKET_SIZE

    P.S. I scrolled through the post, better if I had searched for a keyword instead …

  42. John Lee • July 12, 2013

    I’m new to arduino. Has anyone tried connecting to MQTT by using a arduino WiFi shield? Is there any guides for me to edit it to make it compatible for arduino WiFi shield?

  43. nickJuly 12, 2013

    Hi John, you’ll see the Arduino WiFi shield is listed above in the Compatible Hardware section. I haven’t tried it personally, but it should just work by passing a WiFiClient instance to the PubSubClient constructor once the WiFi shield is connected to the network.

  44. John Lee • July 15, 2013

    Hi nick,

    Thank you for the guidelines. It can work with the arduino Wifi shield, but the arduino IDE required to be ver 1.0.2 instead of the new 1.0.5.

  45. nickJuly 15, 2013

    Hi John – that’s interesting. I’ll have a look at 1.0.5 and see what’s broken.

  46. Marcel • October 14, 2013

    A very promising development for the ENC28J60 board. It is a plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields.

    You can find it at https://github.com/ntruchsess/arduino_uip

    I could get the basic example running by just replacing ‘UIPEthernet.h’ instead of ‘Ethernet.h’

    I must add that for now it was not stable enough to run long, so I need to dig into the details of why stops after 1 or 2 messages

  47. Marcel • October 14, 2013

    seems like it is working after all. Hence as far as I can see the library at https://github.com/ntruchsess/arduino_uip works perfectly together.

    This makes room for very low cost arduino MQTT sensors!

  48. Tony Petchy • November 12, 2013

    Are there any plans to update the client library to include QOS of 1. Or, is this software considered mature and there is not going to be any major additions or improvements.

  49. nickNovember 12, 2013

    Hi Tony,

    funnily enough, there’s a pull request waiting for me to test that will allow the client to subscribe and receive QoS 1 messages.

    It does not add support for sending QoS 1, nor anything to do with QoS 2. These are not in the plan for this client as there is no reliable storage on the arduino, so we cannot provide proper QoS 1 or 2 semantics.

  50. Tony Petchy • November 14, 2013

    How long does the spec require the information be stored for QoS 1?

    What I need to do is make sure the data has been successfully transmitted and received. I do not have to verify anyone actually consumed the data, I just have to know it is/was available (that sounds like QoS 1). I guess I could subscribe to the topic and wait for the broker to send it back to me.

  51. leave a comment

    You must be logged in to post a comment.