
{"id":42,"date":"2017-04-04T17:47:46","date_gmt":"2017-04-04T06:47:46","guid":{"rendered":"http:\/\/bakke.online\/?p=42"},"modified":"2017-04-04T17:47:46","modified_gmt":"2017-04-04T06:47:46","slug":"adding-persisted-messages-to-adafruits-mqtt-library","status":"publish","type":"post","link":"https:\/\/www.bakke.online\/index.php\/2017\/04\/04\/adding-persisted-messages-to-adafruits-mqtt-library\/","title":{"rendered":"Adding retained messages to Adafruit&#039;s MQTT library"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-43\" src=\"https:\/\/www.bakke.online\/wp-content\/uploads\/2017\/04\/20170325_230800.jpg\" alt=\"\" width=\"1200\" height=\"858\" \/><\/p>\n<p>Recently, when building a weather station based on <a href=\"https:\/\/learn.adafruit.com\/adafruit-huzzah-esp8266-breakout\/overview\">Adafruit&#8217;s Huzzah ESP8266<\/a> breakout board, I needed the ability to send messages that should be retained on the MQTT server.<\/p>\n<p>I am using <a href=\"https:\/\/mosquitto.org\/\">mosquitto<\/a> on my home server, acting as a message broker. \u00a0My weather stations send messages to it and these are then forwarded to the subscribers who have signed up for them. \u00a0At the moment, these subscribers are a weather logging system, a current weather display panel on the different computers at home, and, occasionally, a command-line client used for troubleshooting.<\/p>\n<p>As the weather stations are battery powered, they will not run always on, always connected, but they wake up every few minutes, check the weather, and transmit the results to the MQTT server before they go to sleep again.<\/p>\n<p>Any subscribers will receive these messages as soon as they are sent. \u00a0However, when a subscriber starts running and connects to the MQTT server, it will not receive any messages until the relevant weather station sends one. \u00a0By default, there&#8217;s no concept of the most recent values. \u00a0This is kind of inconvenient for the weather panel application on the computers, as they will not show any values until the next time the weather station wakes up. \u00a0Depending on the battery levels and configuration, that could be quite a while&#8230;<\/p>\n<p><!--more-->To do that, MQTT supports retained messages. \u00a0These are messages that have a special flag set which tells the server they can be retained. \u00a0A subscriber that connects will then get the most recent retained message as soon as the connection has been established, and then receive updates whenever the weather station sends them through.<\/p>\n<p>Adafruit&#8217;s MQTT library makes the MQTT communication bit incredibly easy, but unfortunately it does not support retained messages out of the box as of the time of writing. \u00a0There are a number of pull-requests for this feature on their github page, so it is possible this situation will change. \u00a0For the same reason, I have not requested a pull of my changes.<\/p>\n<p>I decided to add this feature to a forked version of their library, mainly as an exercise and also to learn the inner workings of the library better. \u00a0MQTT is an open standard and the documentation for the protocol can be found on the <a href=\"http:\/\/docs.oasis-open.org\/mqtt\/mqtt\/v3.1.1\/os\/mqtt-v3.1.1-os.html\">OASIS <\/a>server.<\/p>\n<p>My forked version can be found on github, at\u00a0<a href=\"https:\/\/github.com\/erikbakke\/Adafruit_MQTT_Library\">https:\/\/github.com\/erikbakke\/Adafruit_MQTT_Library<\/a>.<\/p>\n<h3>In Adafruit_MQTT.h<\/h3>\n<p>Let&#8217;s start with the class declarations in the header file Adafruit_MQTT.h. \u00a0In the Adafruit_MQTT class there are two main publish methods, one which takes a string payload, and one which takes a pointer to binary data as well as the length of the binary data buffer. \u00a0I added a new uint8_t parameter to control whether the published message should be retained:<\/p>\n<pre><span class=\"pl-k\">bool<\/span> <span class=\"pl-en\">publish<\/span>(<span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic, <span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *payload, <span class=\"pl-c1\">uint8_t<\/span> qos = <span class=\"pl-c1\">0<\/span><span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x\"> retain = <\/span><span class=\"pl-c1 x x-last\">0<\/span><\/span>);\n<span class=\"pl-k\">bool<\/span> <span class=\"pl-en\">publish<\/span>(<span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic, <span class=\"pl-c1\">uint8_t<\/span> *payload, <span class=\"pl-c1\">uint16_t<\/span> bLen, <span class=\"pl-c1\">uint8_t<\/span> qos = <span class=\"pl-c1\">0<\/span><span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x\"> retain = <\/span><span class=\"pl-c1 x x-last\">0<\/span><\/span>);<\/pre>\n<p>These methods build the actual MQTT packet data and then pass this to publishPacket(), which is where the control header fields get added and the packet sent to the server. \u00a0As the retain flag is in one of these header fields, I also needed to add the flag as a parameter here.<\/p>\n<pre><span class=\"pl-c1\">uint16_t<\/span> <span class=\"pl-en\">publishPacket<\/span>(<span class=\"pl-c1\">uint8_t<\/span> *packet, <span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic, <span class=\"pl-c1\">uint8_t<\/span> *payload, <span class=\"pl-c1\">uint16_t<\/span> bLen, <span class=\"pl-c1\">uint8_t<\/span> qos<span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x x-last\"> retain<\/span><\/span>);<\/pre>\n<p>In the Adafruit_MQTT_Publish class, the retain parameter is added to the constructor class, so the behaviour can be controlled per\u00a0feed.<\/p>\n<pre><span class=\"pl-en\">Adafruit_MQTT_Publish<\/span>(Adafruit_MQTT *mqttserver, <span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *feed, <span class=\"pl-c1\">uint8_t<\/span> qos = <span class=\"pl-c1\">0<\/span><span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x\"> retain = <\/span><span class=\"pl-c1 x x-last\">0<\/span><\/span>);<\/pre>\n<p>This needs to be backed by a member variable, which I added to the bottom of the class declaration.<\/p>\n<pre><span style=\"color: #ff0000;\"><span class=\"pl-c1\">uint8_t<\/span> retain;<\/span><\/pre>\n<p>That&#8217;s it for the class declarations\u00a0so let&#8217;s move on to the definitions, which are found in the Adafruit_MQTT.cpp file.<\/p>\n<h3>In Adafruit_MQTT.cpp<\/h3>\n<p>In Adafruit_MQTT, the const char* based publish() method is modified to take the retain parameter and pass it on to the binary buffer based method.<\/p>\n<pre><span class=\"pl-k\">bool<\/span> <span class=\"pl-en\">Adafruit_MQTT::publish<\/span>(<span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic, <span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *data, <span class=\"pl-c1\">uint8_t<\/span> qos<span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x x-last\"> retain<\/span><\/span>) {\n\n<span class=\"pl-k\">\u00a0 \u00a0 return<\/span> <span class=\"pl-c1\">publish<\/span>(topic, (<span class=\"pl-c1\">uint8_t<\/span>*)(data), <span class=\"pl-c1\">strlen<\/span>(data), qos<span class=\"x x-first x-last\" style=\"color: #ff0000;\">, retain<\/span>);\n}<\/pre>\n<p>That constructor is also modified to take the additional parameter and\u00a0pass it to the publishPacket() method.<\/p>\n<pre><span class=\"pl-k\">bool<\/span> <span class=\"pl-en\">Adafruit_MQTT::publish<\/span>(<span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic, <span class=\"pl-c1\">uint8_t<\/span> *data, <span class=\"pl-c1\">uint16_t<\/span> bLen, <span class=\"pl-c1\">uint8_t<\/span> qos<span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x x-last\"> retain<\/span><\/span>) {\n <span class=\"pl-c1\">\u00a0 \u00a0 uint16_t<\/span> len = <span class=\"pl-c1\">publishPacket<\/span>(buffer, topic, data, bLen, qos<span class=\"x x-first x-last\" style=\"color: #ff0000;\">, retain<\/span>);\n\n<span class=\"pl-k\">\u00a0 \u00a0 if<\/span> (!<span class=\"pl-c1\">sendPacket<\/span>(buffer, len))\n<span class=\"pl-k\">\u00a0 \u00a0 \u00a0 \u00a0 return<\/span> <span class=\"pl-c1\">false<\/span>;\n...<\/pre>\n<p>publishPacket(), in turn, takes that parameter&#8230;<\/p>\n<pre><span class=\"pl-c1\">uint16_t<\/span> <span class=\"pl-en\">Adafruit_MQTT::publishPacket<\/span>(<span class=\"pl-c1\">uint8_t<\/span> *packet, <span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *topic,\n<span class=\"pl-c1\">                                      uint8_t<\/span> *data, <span class=\"pl-c1\">uint16_t<\/span> bLen, <span class=\"pl-c1\">uint8_t<\/span> qos<span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x x-last\"> retain<\/span><\/span>) {<\/pre>\n<p>&#8230;and puts it into the header field.<\/p>\n<pre><span class=\"pl-c\">\/\/<\/span> Now you can start generating the packet!\np[<span class=\"pl-c1\">0<\/span>] = MQTT_CTRL_PUBLISH &lt;&lt; <span class=\"pl-c1\">4<\/span> | qos &lt;&lt; <span class=\"pl-c1\">1<\/span><span class=\"x x-first x-last\" style=\"color: #ff0000;\"> | retain<\/span>;\np++;<\/pre>\n<p>In the Adafruit_MQTT_Publish class, the constructor has been modified to take the new retain parameter and stuff it into a member variable.<\/p>\n<pre><span class=\"pl-en\">Adafruit_MQTT_Publish::Adafruit_MQTT_Publish<\/span>(Adafruit_MQTT *mqttserver,\n<span class=\"pl-k\">const<\/span> <span class=\"pl-k\">char<\/span> *feed, <span class=\"pl-c1\">uint8_t<\/span> q<span style=\"color: #ff0000;\"><span class=\"x x-first\">, <\/span><span class=\"pl-c1 x\">uint8_t<\/span><span class=\"x x-last\"> r<\/span><\/span>) {\n    mqtt = mqttserver;\n    topic = feed;\n    qos = q;\n    <span style=\"color: #ff0000;\">retain = r;<\/span>\n}<\/pre>\n<p>Next, each of the publish() methods are modified to pass the retain flag to mqtt-&gt;publish().<\/p>\n<pre><span class=\"pl-k\">return<\/span> mqtt-&gt;<span class=\"pl-c1\">publish<\/span>(topic, payload, qos<span class=\"x x-first x-last\" style=\"color: #ff0000;\">, retain<\/span>);<\/pre>\n<p>Or a more detailed example, which has been adapted from one of Adafruit&#8217;s MQTT library examples:<\/p>\n<pre><span style=\"color: #33cccc;\">void<\/span> MQTT_uploadToServer( <span style=\"color: #33cccc;\">float<\/span> temp, <span style=\"color: #33cccc;\">float<\/span> humidity, <span style=\"color: #33cccc;\">float<\/span> voltage )\n{\n  <span style=\"color: #ff6600;\">WiFiClient<\/span> client;\n  <span style=\"color: #33cccc;\">float<\/span> temp = -500; <span style=\"color: #999999;\">\/\/ Use this as a flag, as -500 degrees is physically impossible, it is below absolute zero<\/span>\n  <span style=\"color: #33cccc;\">int8_t<\/span> ret;\n\n<span style=\"color: #ff6600;\"><strong>  Adafruit_MQTT_Client<\/strong><\/span> mqtt( &amp;client, MQTT_SERVER, MQTT_SERVERPORT, MQTT_USERNAME, MQTT_PASSWD );\n  <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span> publish_temp = <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span>( &amp;mqtt, MQTT_USERNAME \"<span style=\"color: #008080;\">\/feeds\/<\/span>\" MQTT_NAME \"<span style=\"color: #008080;\">\/temp<\/span>\", MQTT_QOS_0, 1 );\n  <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span> publish_humidity = <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span>( &amp;mqtt, MQTT_USERNAME \"<span style=\"color: #008080;\">\/feeds\/<\/span>\" MQTT_NAME \"<span style=\"color: #008080;\">\/humidity<\/span>\", MQTT_QOS_0, 1 );\n  <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span> publish_voltage = <span style=\"color: #ff6600;\"><strong>Adafruit_MQTT_Publish<\/strong><\/span>( &amp;mqtt, MQTT_USERNAME \"<span style=\"color: #008080;\">\/feeds\/<\/span>\" MQTT_NAME \"<span style=\"color: #008080;\">\/voltage<\/span>\", MQTT_QOS_0, 1 );\n\n  <span style=\"color: #ff6600;\"><strong>Serial<\/strong><\/span>.<span style=\"color: #ff6600;\">print<\/span>(\"<span style=\"color: #008080;\">Connecting to MQTT...<\/span> \");\n\n  <span style=\"color: #33cccc;\">uint8_t<\/span> retries = 3;\n  <span style=\"color: #808000;\">while<\/span> ((ret = mqtt.<span style=\"color: #ff6600;\">connect<\/span>()) != 0) { <span style=\"color: #999999;\">\/\/ connect will return 0 for connected<\/span>\n    <span style=\"color: #ff6600;\"><strong>Serial<\/strong><\/span>.<span style=\"color: #ff6600;\">println<\/span>(mqtt.<span style=\"color: #ff6600;\">connectErrorString<\/span>(ret));\n    <span style=\"color: #ff6600;\"><strong>Serial<\/strong><\/span>.<span style=\"color: #ff6600;\">println<\/span>(\"<span style=\"color: #008080;\">Retrying MQTT connection in 5 seconds...<\/span>\");\n    mqtt.<span style=\"color: #ff6600;\">disconnect<\/span>();\n    <span style=\"color: #ff6600;\">delay<\/span>(5000); <span style=\"color: #999999;\">\/\/ wait 5 seconds<\/span>\n    retries--;\n    <span style=\"color: #808000;\">if<\/span> (retries == 0) {\n      <span style=\"color: #999999;\">\/\/ basically die and wait for WDT to reset me<\/span>\n      <span style=\"color: #808000;\">while<\/span> (1);\n    }\n  }\n  <span style=\"color: #ff6600;\"><strong>Serial<\/strong><\/span>.<span style=\"color: #ff6600;\">println<\/span>(\"<span style=\"color: #008080;\">MQTT Connected!<\/span>\");\n\n  <span style=\"color: #808000;\">if<\/span>( !isnan( temp ) )\n  {\n    publish_temp.<span style=\"color: #ff6600;\">publish<\/span>( temp );\n  }\n  <span style=\"color: #808000;\">if<\/span>( !isnan( humidity ) )\n  {\n    publish_humidity.<span style=\"color: #ff6600;\">publish<\/span>( humidity );\n  }\n  <span style=\"color: #808000;\">if<\/span>( !isnan( voltage ) )\n  {\n    publish_voltage.<span style=\"color: #ff6600;\">publish<\/span>( voltage );\n  }\n\n  mqtt.<span style=\"color: #ff6600;\">disconnect<\/span>();\n}<\/pre>\n<p>If the example code doesn&#8217;t compile, make sure your copy of the MQTT library supports the additional retain flag.<\/p>\n<h3>In closing<\/h3>\n<p>The library can be used in the same way as the official Adafruit library, and it is 100% source compatible. \u00a0Unless you explicitly add an r-parameter value of 1 when creating the Adafruit_MQTT_Publish feed object, the library will behave exactly as the standard one. \u00a0Pass a value of 1, however, and the MQTT server will persist the message, eliminating the startup delay for subscribers to the topic.<\/p>\n<p>My changes can be found on <a href=\"https:\/\/github.com\/erikbakke\/Adafruit_MQTT_Library\">github<\/a>, and a diff of my changes relative to the official version are <a href=\"https:\/\/github.com\/adafruit\/Adafruit_MQTT_Library\/compare\/master...erikbakke:master\">here<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, when building a weather station based on Adafruit&#8217;s Huzzah ESP8266 breakout board, I needed the ability to send messages that should be retained on the MQTT server. I am using mosquitto on my home server, acting as a message broker. \u00a0My weather stations send messages to it and these are then forwarded to the &hellip; <a href=\"https:\/\/www.bakke.online\/index.php\/2017\/04\/04\/adding-persisted-messages-to-adafruits-mqtt-library\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Adding retained messages to Adafruit&#039;s MQTT library&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,1],"tags":[8,9,10],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-arduino","category-uncategorized","tag-arduino","tag-esp8266","tag-mqtt"],"_links":{"self":[{"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/comments?post=42"}],"version-history":[{"count":0,"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/posts\/42\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/media?parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/categories?post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bakke.online\/index.php\/wp-json\/wp\/v2\/tags?post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}