<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adrian Benavides</title>
    <description>The latest articles on DEV Community by Adrian Benavides (@adrib).</description>
    <link>https://dev.to/adrib</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F113611%2F5648a8a8-8ff0-4e9d-9114-d3d5fc09c6b5.png</url>
      <title>DEV Community: Adrian Benavides</title>
      <link>https://dev.to/adrib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrib"/>
    <language>en</language>
    <item>
      <title>GPS Live Tracking With Balena, Neo-6M, And LoRa!</title>
      <dc:creator>Adrian Benavides</dc:creator>
      <pubDate>Thu, 10 Oct 2019 17:33:11 +0000</pubDate>
      <link>https://dev.to/adrib/gps-live-tracking-with-balena-neo-6m-and-lora-3f8m</link>
      <guid>https://dev.to/adrib/gps-live-tracking-with-balena-neo-6m-and-lora-3f8m</guid>
      <description>&lt;p&gt;Originally &lt;a href="https://kokonatt.com/embedded/gps-live-tracking"&gt;published on my blog here&lt;/a&gt; and full &lt;a href="https://github.com/adrianbenavides/gps-tracker"&gt;code on github&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table Of Contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Project overview&lt;/li&gt;
&lt;li&gt;Using the Neo-6M&lt;/li&gt;
&lt;li&gt;Using the LoRa-02&lt;/li&gt;
&lt;li&gt;Visualization with Balena and Grafana&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  What's this about? A quick project overview&lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Whenever I need inspiration on new IoT projects ideas to work on I phone my colleague Ramiro and in less than 10 minutes we have 4 or 5 ideas on the table.&lt;/p&gt;

&lt;p&gt;During our last conversation, he told me about an idea he had that caught my attention. "If your bike or motorbike were stolen, wouldn't it be nice to be able to know in that precise instant where it is, or what was its last known position?".&lt;/p&gt;

&lt;p&gt;Imagine having a &lt;strong&gt;small device that you could use to track any of your most valuable things&lt;/strong&gt;: your bike, your laptop, your backpack, even your wallet. Or at least, small enough to carry it yourself in your pocket or your jacket.&lt;/p&gt;

&lt;p&gt;I spent a couple of days thinking about this concept, about how I could develop it, what technologies to use, what devices, etc. At that moment, the only thing I had clear was that I wanted this device to be autonomous and therefore not dependent on being able to connect to a WiFi network or use a SIM card for data communication.&lt;/p&gt;

&lt;p&gt;After looking at several options I ended up deciding that I was going to use a radiofrequency module to transmit my GPS position to a receiver that I would have connected to a Raspberry Pi in my house, where I could process and visualize the data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VOJhhZqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f1145931ebc35ddf98f1e_gps-trakcker-project-architecture.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VOJhhZqh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f1145931ebc35ddf98f1e_gps-trakcker-project-architecture.png" alt="gps-trakcker-project-architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now, let's build it!&lt;/p&gt;

&lt;h1&gt;
  
  
  Reading GPS data with an ESP8266 and the Neo-6M&lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Neo-8M odyssey
&lt;/h2&gt;

&lt;p&gt;This whole project revolves around monitoring my GPS position remotely. It is clear then that the main piece, the only sensor, will be the GPS module.&lt;/p&gt;

&lt;p&gt;Well, looking for examples of how to read GPS data using an Arduino board, I saw that almost everyone used the same module: the Ublox Neo-6M. So when I went to Aliexpress to buy a unit I saw that there were two more models available, the Neo-7M and the Neo-8M. My first and only thought was: "The newer the better, I don't care if I haven't seen any examples using the Neo-8M, that's the one I'm going to buy. I'll figure out how to work with it later". WRONG!&lt;/p&gt;

&lt;p&gt;After two weeks of waiting, the package finally arrives, I hook it up to my ESP8266... it doesn't work, there is no way to receive data no matter what I do. I change to Windows 10, I connect the Neo-8M to try debugging it with the u-center software and nothing, for some reason it didn't work.&lt;/p&gt;

&lt;p&gt;Just considering the idea that I would have to wait another two weeks to receive it, made me rethink whether to discard the project and get on with something else. So I went out for a walk and on my way home I convinced myself to buy the Neo-6M and that, in the meantime, it would be a good idea to work on the visualization. And so I did.&lt;/p&gt;

&lt;p&gt;But first, let's check how you can use a Neo-6M with an ESP8266.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting GPS data out of the Neo-6M
&lt;/h2&gt;

&lt;p&gt;This module is quite simple to use. Apart from the power pins, it has two more pins to transmit and receive data. You have to be careful with this though, because you have to connect the RX pin of the Neo-6M to the pin of your board that you have configured as TX, and the TX of the Neo-6M to the pin configured as RX of the board.&lt;/p&gt;

&lt;p&gt;What I mean is that &lt;strong&gt;we are not using the built-in RX/TX pins&lt;/strong&gt; of the board, but rather we will configure a couple of digital pins (D2 and D3) to interface with the Neo-6M.&lt;/p&gt;

&lt;p&gt;It is much easier to express this with an image:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TFPImUhE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f111e931ebc7e7df98ed8_neo6m-esp8266-wiring_bb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TFPImUhE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f111e931ebc7e7df98ed8_neo6m-esp8266-wiring_bb.png" alt="neo6m-esp8266-wiring"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see below, we will use the &lt;strong&gt;SoftwareSerial&lt;/strong&gt; library to read the Neo-6M data and the &lt;strong&gt;TinyGPS++&lt;/strong&gt; library to parse the readings. You can see a &lt;a href="https://lastminuteengineers.com/neo6m-gps-arduino-tutorial/"&gt;full lastminuteengineers.com tutorial on how Neo-6M works here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;# check out the full code at: https://github.com/adrianbenavides/arduino-helpers
&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TinyGPSPlus&lt;/span&gt; &lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TinyGPSPlus&lt;/span&gt; &lt;span class="n"&gt;emptyGpsParser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SoftwareSerial&lt;/span&gt; &lt;span class="nf"&gt;gpsSerial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NEO6M_RX_PIN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NEO6M_TX_PIN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Neo6m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Setting up Neo-6M GPS module... "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;gpsSerial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NEO6M_BAUD&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"done"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;TinyGPSPlus&lt;/span&gt; &lt;span class="n"&gt;Neo6m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsSerial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsSerial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;emptyGpsParser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Neo6m&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TinyGPSPlus&lt;/span&gt; &lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Latitude: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Longitude: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Altitude: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gpsParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;altitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;meters&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Location: Not Available"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Communicating two nodes with radio frequency using the LoRa-02&lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  LoRa-02 wiring with an ESP8266 and the MISO/MOSI nightmare
&lt;/h2&gt;

&lt;p&gt;Now that we have our GPS module working, it is time to work on the transmission of this data for later analysis and visualization.&lt;/p&gt;

&lt;p&gt;Remember that we will carry the GPS sensor connected to a battery and that we are working under the limitation of not being able to connect to the internet or use a SIM card to transmit data.&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;Ra-02 LoRa&lt;/strong&gt; (Long-range Radio) module comes into play. Developed by &lt;a href="https://www.ai-thinker.com/product/overview"&gt;Ai-Thinker, the manufacturer behind the ESP modules&lt;/a&gt;, this radio frequency module improves the previous version providing a larger bandwidth, increasing interference resistance, minimizing current consumption, and increasing security. The LoRa-02 mounts an SX1278 IC and works on a 433MHz frequency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1egsxdaK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.smart-prototyping.com/image/data/5_community/WIFI/101769%2520Ra-02/1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1egsxdaK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://www.smart-prototyping.com/image/data/5_community/WIFI/101769%2520Ra-02/1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before jumping into code, I would like to tell you a couple of details about the wiring of this module, something that took me several hours of desperation to resolve... largely because of my ignorance and lack of experience, as you will soon see.&lt;/p&gt;

&lt;p&gt;One example after another, I couldn't find a single well-documented one that used an ESP8266 in any of its variants. So I tried to make the simplest example work: setting up the module and send a message... but I just couldn't, something was wrong and I didn't know what it was.&lt;/p&gt;

&lt;p&gt;After a considerable period of monkey testing, I had the first good idea of the day: "man, let's take a look at the pinouts of the LoRa and the ESP8266 modules to see if we are missing something". It didn't take me too long to realize the problem: the MISO and MOSI pins of the LoRa module must be connected to the MISO and MOSI pins of the microcontroller. Makes sense right? Believe it or not, I haven't seen ANYONE specifying this "little" detail in any of the examples, implying that the pins used are arbitrary when in fact they are not.&lt;/p&gt;

&lt;p&gt;In case you need it, here are the pins that you want to use:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;NodeMcu&lt;/th&gt;
&lt;th&gt;UNO, Nano&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PIN_SPI_SCK&lt;/td&gt;
&lt;td&gt;(14) -&amp;gt; D5&lt;/td&gt;
&lt;td&gt;D13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PIN_SPI_MISO&lt;/td&gt;
&lt;td&gt;(12) -&amp;gt; D6&lt;/td&gt;
&lt;td&gt;D12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PIN_SPI_MOSI&lt;/td&gt;
&lt;td&gt;(13) -&amp;gt; D7&lt;/td&gt;
&lt;td&gt;D11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PIN_SPI_SS&lt;/td&gt;
&lt;td&gt;(15) -&amp;gt; D8&lt;/td&gt;
&lt;td&gt;D10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And here is the complete wiring:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--trzPokP3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f111d8733b536bb60cfde_lora-esp8266-wiring_bb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--trzPokP3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9f111d8733b536bb60cfde_lora-esp8266-wiring_bb.png" alt="esp8266-lora02-wiring"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Sending and receiving data with the LoRa-02
&lt;/h2&gt;

&lt;p&gt;To work with the SX1278, we have a couple of libraries.&lt;/p&gt;

&lt;p&gt;The first one I found was &lt;a href="https://github.com/sandeepmistry/arduino-LoRa"&gt;Arduino LoRa&lt;/a&gt;, which I didn't get to test, as it doesn't specify what arduino-like boards it supports and I didn't feel like I would be in the mood to find it out by myself.&lt;/p&gt;

&lt;p&gt;After searching a little further I found what it seems to be the standard library to work with radio frequency modules: the &lt;a href="http://www.airspayce.com/mikem/arduino/RadioHead/"&gt;Radio Head library&lt;/a&gt;. It offers a &lt;strong&gt;wide set of interfaces for different radio modules&lt;/strong&gt;, including support for the SX1278 with the class &lt;a href="http://www.airspayce.com/mikem/arduino/RadioHead/classRH__RF95.html"&gt;RH_RG95&lt;/a&gt;. The only problem is that it's not distributed through GitHub, but don't worry, the guys at &lt;a href="https://github.com/adafruit/RadioHead"&gt;Adafruit have us covered with a github'ified version&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Working with the Radio Head library is pretty straightforward: a simple method to set up the module with some configuration options and a couple of methods to receive and send messages.&lt;/p&gt;

&lt;p&gt;Again, here are a couple of tricky details that I found interesting to highlight: &lt;br&gt;
    1. The maximum message length is 255 characters&lt;br&gt;
    2. The message passed to the &lt;code&gt;send()&lt;/code&gt; method must be of type &lt;code&gt;uint8_t&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As I did in the &lt;a href="https://kokonatt.com/embedded/mqtt-with-esp8266"&gt;previous project where I experimented with the MQTT protocol&lt;/a&gt;, I've created a wrapper to avoid having the GPS code and LoRa cluttering the &lt;code&gt;main.cpp&lt;/code&gt; file, making it easier to read. &lt;a href="https://github.com/adrianbenavides/arduino-helpers/blob/master/src/lora.cpp"&gt;You can check the complete code here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;# check out the full code at: https://github.com/adrianbenavides/arduino-helpers
&lt;/span&gt;&lt;span class="n"&gt;RH_RF95&lt;/span&gt; &lt;span class="nf"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PIN_SPI_SS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RFM95_INT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;rf95_buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RH_RF95_MAX_MESSAGE_LEN&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;rf95_buf_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rf95_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;LoRa&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setFrequency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RF95_FREQ&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"setFrequency failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LoRa&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rf95_buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;rf95_buf_len&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Serial&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LoRa - No message received"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;rf95_buf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;LoRa&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;messageLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messageLength&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;messageLength&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;rf95&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitPacketSent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Mounting the GPS receiver!
&lt;/h2&gt;

&lt;p&gt;It turned out to be a bit bigger than I expected but, you know, it's a prototype...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vJdgbS3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecfe8733b5093d5f8601_gps-tracker-mounting-1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJdgbS3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecfe8733b5093d5f8601_gps-tracker-mounting-1.jpeg" alt="gps-tracker-mounting-1"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UVNyvZ2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecfe8733b57f9a5f85ff_gps-tracker-mounting-2.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UVNyvZ2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecfe8733b57f9a5f85ff_gps-tracker-mounting-2.jpeg" alt="gps-tracker-mounting-2"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rgsRTF8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecff8733b53e575f8602_gps-tracker-mounting-3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rgsRTF8_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://uploads-ssl.webflow.com/5d0320c393cf98e9a472b352/5d9eecff8733b53e575f8602_gps-tracker-mounting-3.jpeg" alt="gps-tracker-mounting-3"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Data aggregation and visualization with Balena and MQTT&lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  Customizing the Balena Sense project to handle any sensor data
&lt;/h2&gt;

&lt;p&gt;In this section, I'm going to detail how to leverage the power of &lt;a href="https://balena.io"&gt;Balena&lt;/a&gt; to create an &lt;strong&gt;MQTT gateway with a customized data visualization using grafana&lt;/strong&gt;. The power this ecosystem gives to IoT developers is awesome, especially because it saves you from creating the frontend, database, and visualization engine. And that's a LOT of boilerplate and saved time.&lt;/p&gt;

&lt;p&gt;To tell telegraf that it must listen to MQTT messages we need to add the following code to the &lt;code&gt;telegraf.conf&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;inputs.mqtt_consumer&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
  &lt;span class="c1"&gt;## MQTT broker URLs to be used.&lt;/span&gt;
  &lt;span class="c1"&gt;## The format should be scheme://host:port, schema can be tcp, ssl, or ws.&lt;/span&gt;
  &lt;span class="s"&gt;servers = ["tcp://mqtt:1883"]&lt;/span&gt;

  &lt;span class="s"&gt;## Topics that will be subscribed to.&lt;/span&gt;
  &lt;span class="s"&gt;topics = [&lt;/span&gt;
    &lt;span class="s"&gt;"sensor/#",&lt;/span&gt;
  &lt;span class="s"&gt;]&lt;/span&gt;

  &lt;span class="s"&gt;## Data format to consume.&lt;/span&gt;
  &lt;span class="s"&gt;## Each data format has its own unique set of configuration options, read&lt;/span&gt;
  &lt;span class="s"&gt;## more about them here&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;## https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md&lt;/span&gt;
  &lt;span class="s"&gt;data_format = "influx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;data_format&lt;/code&gt; key is set to "influx", which is the default InfluxDB format, also known as &lt;strong&gt;line protocol&lt;/strong&gt;. An example of a valid message would be: &lt;code&gt;gps lat=41.1234,lng=2.4321&lt;/code&gt;, where &lt;strong&gt;gps&lt;/strong&gt; defines the influxdb table and the rest of the message the columns and values to be assigned. &lt;a href="https://docs.influxdata.com/influxdb/v1.7/write_protocols/line_protocol_tutorial/"&gt;Here is the official documentation of this data format&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As for the provisioned dashboards, you can remove the default Balena Sense dashboard, which is defined in the &lt;code&gt;grafana/provisioning/dashboards&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Finally, &lt;strong&gt;if you need to install any additional grafana plugins&lt;/strong&gt;, &lt;a href="https://grafana.com/grafana/plugins/pr0ps-trackmap-panel"&gt;like the trackmap-panel I'm using in this project&lt;/a&gt;, you can add them in the &lt;code&gt;balena-mqtt-gateway/grafana/entry.sh&lt;/code&gt; file, right before initializing the grafana server.&lt;/p&gt;

&lt;p&gt;For further information on how to set up a balena project using a raspberry pi, &lt;a href="https://www.balena.io/os/docs/raspberrypi3/getting-started/"&gt;check out their official documentation here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPS data visualization with grafana
&lt;/h2&gt;

&lt;p&gt;At this point, we have every physical piece of the system doing its job, sending, receiving and processing GPS data.&lt;/p&gt;

&lt;p&gt;The only thing that is left to do is set up the visualization. To do this we will be using the map plugin I mentioned earlier, and luckily for us, &lt;strong&gt;it works out of the box&lt;/strong&gt; with the provided query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"location"&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;timeFilter&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is what we'll see in the grafana dashboard if the whole system is working properly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/MDaAwg4EPjvb7O1XY7/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/MDaAwg4EPjvb7O1XY7/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;It took me a while, but it's working just as I expected! Frankly, I have enjoyed a lot and I have learned a lot of new things working on this project. The satisfaction of seeing a remote device interacting with an RPi that I have in my room is indescribable.&lt;/p&gt;

&lt;p&gt;Sometimes, I can't help myself but think about electronics and communication technologies as if it were black magic. Actually, I think is exactly this "childish" feeling that pushes me to keep experimenting and keep looking for new ideas to implement.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this guide, see you next time!&lt;/p&gt;

</description>
      <category>embedded</category>
      <category>arduino</category>
      <category>balena</category>
    </item>
    <item>
      <title>Exploring MQTT With The ESP8266</title>
      <dc:creator>Adrian Benavides</dc:creator>
      <pubDate>Thu, 19 Sep 2019 21:40:12 +0000</pubDate>
      <link>https://dev.to/adrib/exploring-mqtt-with-the-esp8266-5c56</link>
      <guid>https://dev.to/adrib/exploring-mqtt-with-the-esp8266-5c56</guid>
      <description>&lt;p&gt;In any IoT project, we have a number of unique requirements and restrictions. The communication strategy to connect devices and send data between them is critically important. &lt;/p&gt;

&lt;p&gt;In this guide, we will explore a powerful, simple and lightweight messaging protocol over the wire: MQTT.&lt;/p&gt;

&lt;p&gt;Originally &lt;a href="https://kokonatt.com/embedded/mqtt-with-esp8266" rel="noopener noreferrer"&gt;published on my blog here&lt;/a&gt; and full &lt;a href="https://github.com/adrianbenavides/esp8266-mqtt-experiments" rel="noopener noreferrer"&gt;code on github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;MQTT Basics&lt;/li&gt;
&lt;li&gt;Dev Environment&lt;/li&gt;
&lt;li&gt;ESP8266 Filesystem&lt;/li&gt;
&lt;li&gt;Communicating Two Devices&lt;/li&gt;
&lt;li&gt;Tracking Devices Status&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's The MQTT Protocol?&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In the embedded world, we assume that the end-devices are going to work under a variety of processing capacity, energy or &lt;strong&gt;communication constraints&lt;/strong&gt;. And specifically on the subject that concerns us in this post, how we are going to implement the communications of our system is going to have a direct implication on the consumption of resources and energy of the devices. &lt;/p&gt;

&lt;p&gt;In this guide we are going to explore MQTT, a lightweight communication protocol &lt;strong&gt;over TCP&lt;/strong&gt; invented in 1999 by Andy Stanford-Clark from IBM and Arlen Nipper from Arcom, initially designed for battery-operated devices to supervise oil pipelines. Later in 2010, IBM released it as a royalty-free protocol. In 2014, OASIS announced that the MQTT v.3.1.1 had become an OASIS standard and a lot of MQTT clients were developed for all programming languages.&lt;/p&gt;

&lt;p&gt;The most commonly used broker is the &lt;strong&gt;Eclipse's Mosquitto library&lt;/strong&gt;: an open-source implementation of the MQTT v3.1 and v.3.1.1 standards providing a lightweight method to transport messages, enabling the pub/sub pattern for low power sensors, mobile devices, embedded computers, and microcontrollers. You can install the Mosquitto broker on your PC as well as on any embedded system with Linux support, such as the Raspberry Pi. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuploads-ssl.webflow.com%2F5d0320c393cf98e9a472b352%2F5d6f418cee72d933e1a8d093_mqtt-protocol.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuploads-ssl.webflow.com%2F5d0320c393cf98e9a472b352%2F5d6f418cee72d933e1a8d093_mqtt-protocol.jpg" alt="mqtt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Main Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Data agnostic: you can use it to send &lt;strong&gt;sensor data, images or even OTA&lt;/strong&gt; (over the air) updates &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lightweight and bandwidth efficient&lt;/strong&gt;: the smallest frame is only 2 bytes long &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Per-queue &lt;strong&gt;QoS&lt;/strong&gt; levels &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Runs on &lt;strong&gt;top of the TCP/IP stack&lt;/strong&gt;, so you can use it to encrypt the data with TLS/SSL and to have a secure connection between clients &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple to develop&lt;/strong&gt;: clients exist for all operating systems and programming languages &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Central broker: different devices can communicate with each other without having to worry about compatibility &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Session awareness: provides an &lt;strong&gt;identity-based&lt;/strong&gt; approach for subscriptions &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexible subscription topics using &lt;strong&gt;single-level and multi-level wildcards&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Basic Terminology
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broker&lt;/strong&gt;: the software application that &lt;strong&gt;receives&lt;/strong&gt; messages from &lt;strong&gt;publishing clients&lt;/strong&gt; and &lt;strong&gt;routes&lt;/strong&gt; the messages to the appropriate subscribed clients &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: a device that can publish messages to a topic or subscribe to messages from a topic &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Topic&lt;/strong&gt;: an identifier (a string) used by the broker to filter messages for each connected clients. It is sent by clients to the broker in a subscribe request to express the desire in receiving messages published by other clients. It is sent by the clients when publishing messages to any other client that subscribed on the same topic &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Publish&lt;/strong&gt;: the action of sending a message from a client to the broker &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subscribe&lt;/strong&gt;: the action of informing the broker about an interest in receiving future messages published by other clients on that topic. A client can subscribe to multiple topics &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unsubscribe&lt;/strong&gt;: the action of informing the broker that a client doesn't want to receive messages of the specified topic &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, before jumping into the meat of this guide, let's make sure first that we are on the same page with our development tools. &lt;/p&gt;

&lt;h2&gt;
  
  
  Set Up For The Experiments&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MQTT Broker With Raspberry Pi And BalenaOS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.balena.io%2Fstatic%2Fplatform-963e4c5aa84a4220819f3518c043e662.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.balena.io%2Fstatic%2Fplatform-963e4c5aa84a4220819f3518c043e662.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I said before, Mosquitto can be installed on any PC (Windows, MacOS and Linux), so if you don't have any RPi at hand you can install Mosquitto locally and use the static IP of your computer. &lt;/p&gt;

&lt;p&gt;In my case, I am working on a mini home-automation project in which I need to integrate several devices, show data in a webapp and analyze that data to execute certain actions. As you can see, a full development stack is involved here (database, a backend, a frontend) and for this kind of setup there is nothing better than working with containers. Did anyone say Docker? &lt;/p&gt;

&lt;p&gt;How can we use &lt;strong&gt;Docker on a Raspberry Pi with automated deployments&lt;/strong&gt;, without having to waste hours configuring Raspbian? &lt;a href="https://www.balena.io/" rel="noopener noreferrer"&gt;This is one of the things you can achieve with Balena&lt;/a&gt;. And before you ask: yes, it's free, but "only" for your first 10 devices... &lt;/p&gt;

&lt;p&gt;Here's a short video of the process to create a new Balena app (it took me around &lt;strong&gt;15 minutes from start to finish&lt;/strong&gt;): &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/XBpQIf1NkNzWGUEs13/source.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/XBpQIf1NkNzWGUEs13/source.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, in the upper right corner, you can check out your newly created balena remote git repository. Click on the "?" button to see how to configure your project or &lt;a href="https://www.balena.io/docs/learn/getting-started/raspberrypi3/nodejs/#deploy-code" rel="noopener noreferrer"&gt;check the docs here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now, time to set up the MQTT broker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new github project and add &lt;a href="https://github.com/adrianbenavides/mqtt-balena/" rel="noopener noreferrer"&gt;this docker-compose.yml file&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add your balena remote endpoint we saw earlier in the dashboard &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Push your changes first to github and then to balena &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Done! Within a couple of minutes, you will see in the balena dashboard how the mosquitto container is created and started &lt;/p&gt;

&lt;h3&gt;
  
  
  ESP8266 Development Environment
&lt;/h3&gt;

&lt;p&gt;I'd recommend you to use Linux because it offers a number of advantages over Mac or Windows that can help you avoid certain frustrations. For example, in a standard Ubuntu installation, I have been able to work with Arduino boards, ESPs and even STMs &lt;strong&gt;without having to worry about installing a single driver&lt;/strong&gt;. And believe me: that it's pure pleasure. &lt;/p&gt;

&lt;p&gt;In any case, keep in mind that sometimes it is inevitable to go through Windows since there is some specific vendor development software that is only available for this operating system. So, always check your requirements and make sure you know beforehand what software do you need to work with your devices. &lt;/p&gt;

&lt;p&gt;For the experiments conducted in this guide we don't need anything fancy so, luckily, we can stay on Linux. &lt;/p&gt;

&lt;h4&gt;
  
  
  PlatformIO + VS Code (or Atom)
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuploads-ssl.webflow.com%2F5d0320c393cf98e9a472b352%2F5d708f1c6d5a3832b1dafc32_platformio-vscode-p-800.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuploads-ssl.webflow.com%2F5d0320c393cf98e9a472b352%2F5d708f1c6d5a3832b1dafc32_platformio-vscode-p-800.png" alt="platformio-vscode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Forget about using the Arduino IDE. It's anything but functional and practical. It lacks every functionality that makes up a good IDE. &lt;/p&gt;

&lt;p&gt;Luckily, we have PlatformIO, an extension for VS Code and Atom that turns these fantastic editors into authentic IDEs for our embed experiments. &lt;/p&gt;

&lt;p&gt;From the docs: "It takes care of toolchains, debuggers, frameworks that work on most popular platforms like Windows, Mac and Linux. It supports more than 500 development boards along with more than 30 development platforms and 15 frameworks." &lt;/p&gt;

&lt;p&gt;It also allows you to manage your libraries and keep them updated as well as debugging your code easily. &lt;/p&gt;

&lt;p&gt;What are you waiting for? Go ahead and &lt;a href="https://docs.platformio.org/en/latest/ide/vscode.html#ide-vscode" rel="noopener noreferrer"&gt;install it right now&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Next thing you want to do is download a couple of libraries: PubSubClient and ArduinoJson. Or you could simply clone the repository of this guide. &lt;/p&gt;

&lt;p&gt;And now, let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  The ESP8266 Filesystem: Storing WiFi Credentials Into Flash Memory&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Since I will be working with several ESP8266 for a while on different projects, I thought it would be a good idea to take some time to preconfigure the modules and &lt;strong&gt;forget about hard-coding my wifi network credentials&lt;/strong&gt; in the scripts and then put dummy text before uploading the project to github. I'm sure I would end up pushing the password and never notice. &lt;/p&gt;

&lt;p&gt;Getting this with an ESP8266 is quite simple with the help of the &lt;strong&gt;SPIFFS and ArduinoJson&lt;/strong&gt; libraries. To encapsulate the basic functionalities related to our device (network connection and flash memory management) I have created a small class called NodeMcu. &lt;/p&gt;

&lt;p&gt;As you can see, one of the constructors accepts a single argument with which we will pass the stringified Json that we want to persist in memory. In the setup() method it will try to recover the data from the memory or it will fail if it doesn't find the right data to connect to the local network. &lt;/p&gt;

&lt;p&gt;Apart from this NodeMcu wrapper, I have also created another one to work with MQTT in a more direct and clean way, with all the external libraries included. Make sure to check out the full code here. &lt;/p&gt;

&lt;p&gt;Now that we have our boards properly configured, we can move on to the first experiment. &lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Two Devices With MQTT&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this first experiment we are going to focus on the core functionality of the MQTT protocol: &lt;strong&gt;publish/listen to messages to/from a topic&lt;/strong&gt;, and use this to toggle an LED. As a trigger to send the messages I have used 2-way switches, not very suitable for prototypes as you can see in the GIF below, but much cooler the typical flat buttons of four pins that are usually used in most of the tutorials. &lt;/p&gt;

&lt;p&gt;The workflow is simple: when we press the button of the device on the left, it will toggle the LED from the right; and vice versa. The only trap is that each device listens to all the messages that are published, so we need to filter out the self-published messages to avoid acting on itself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/kgChxhGQCxsC7U6pSL/source.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/kgChxhGQCxsC7U6pSL/source.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detecting Disconnected Devices With Last Will Messages&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;One of the most interesting features of the MQTT protocol is that the broker &lt;strong&gt;keeps track of the connection&lt;/strong&gt; between itself and all the connected clients. The broker knows at all times when one of its clients has disconnected. How? Very simple: it continuously pings its clients and when one of them stops responding for a certain period of time (timeout), it assumes that it has been disconnected. &lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;timeout&lt;/strong&gt; is defined by the client when it sends the initial connection request to the broker, so it is totally configurable by the client. In this connection request is where we can also include the parameters for the &lt;strong&gt;Last Will and Testament (LWT) message&lt;/strong&gt; which includes: the payload, which topic to publish it, the QoS, and whether the message should be retained or not. &lt;/p&gt;

&lt;p&gt;And here appears a new feature of MQTT: &lt;strong&gt;retaining a message&lt;/strong&gt;. This allows us to tell the broker that, whenever we send a "retain" flagged message to a topic, it should store it and keep it safe. Now, when a new client subscribes to that topic, it will receive that retained message. Think it as a &lt;strong&gt;welcome note&lt;/strong&gt; for newcomers. &lt;/p&gt;

&lt;p&gt;We can &lt;strong&gt;combine these two MQTT functionalities&lt;/strong&gt; to track the status of our devices, and this is what we are going to do in this experiment. Of course, the PubSubClient library offers us the API to easily work with LWT messages on our Arduino-like boards. &lt;/p&gt;

&lt;p&gt;This is the standard algorithm used to manage LWT messages (credits to knolleary from stackoverflow): &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When a client connects, it publishes a RETAINED message to a topic unique to it ("clients/&lt;em&gt;clientId&lt;/em&gt;/status") with a payload of 1 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It also, on connect, sets an LWT message to be published to the same topic, but with a payload of 0. This should also be a RETAINED message &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a client disconnects cleanly, it publishes a RETAINED message to the same topic with a payload of 0 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a client disconnects abruptly (ping fails for the defined timeout), the broker will publish the LWT message as the new RETAINED message &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/adrianbenavides/esp8266-mqtt-experiments/tree/master/mqtt-2-last-will" rel="noopener noreferrer"&gt;Here you have the code used&lt;/a&gt; and here &lt;a href="https://www.hivemq.com/mqtt-essentials/" rel="noopener noreferrer"&gt;more details about LWT from HiveMQ&lt;/a&gt; (parts 8 and 9). &lt;/p&gt;

&lt;p&gt;The wiring for this experiment is just the same as before but without the buttons.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Uttc74Bj8d3VWOI5Jp/source.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Uttc74Bj8d3VWOI5Jp/source.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up!
&lt;/h2&gt;

&lt;p&gt;In this guide, we have worked with one of the most widely used variants of ESP8266 (NodeMcu) to implement some of the basic concepts of the MQTT communication protocol. &lt;/p&gt;

&lt;p&gt;We have also seen how to use the internal storage of our module to store configuration files and speed up the development of our prototypes. &lt;/p&gt;

&lt;p&gt;Now you could apply the techniques we have learned here in some real project you may have in mind, implementing an efficient and straightforward communication system to send, for example, data from our sensors to a local server for later analysis. &lt;/p&gt;

&lt;p&gt;MQTT is much more than what we have seen here today, but I hope that at the very least these experiments have helped you understand the core concepts of this protocol and how to use them. Keep experimenting and learning! &lt;/p&gt;

</description>
      <category>embedded</category>
      <category>arduino</category>
    </item>
  </channel>
</rss>
