IoT and MQTT

Ok, my previous blog entry outlined how to make the NodeMCU board a lot more useful by adding the DHT22 sensor which captured temperature and humidity. This is nice but does require a serial connection between my Linux machine and the NodeMCU board to make the information measured visible. Requiring a hardwired serial cable to establish connectivity made this prototype a lot less useful in the world of IoT. The objective of this blog post is to 'Cut the Serial Cord' and go wireless. Here is where the ESP8266 chipset shines with its integrated wifi capability. Lets see whether it can become a full blown, enterprise grade IoT device.

This blog post builds upon the scripts created in the previous blog post by adding wireless communication using the MQTT protocol and corresponding NodeMCU module.

MQ Telemetry Transport (MQTT) is an open source machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium. -- MQTT.org

As far as IoT protocols go, MQTT is not the only kid on the block, others protocols worth mentioning: HTTP, WebSocket, XMPP and CoAP. If interested in learning more about these protocols, I recommend the article by Micrium, People Internet vs. Device Internet. As far as IOT goes I favor MQTT as it was designed to deliver reliable messaging over unreliable networks. More information on the origins of MQTT (formerly MQ Telemetry Transport) can be found here. In this blog post discusses how to enable communication using this protocol.

Mosquitto

The essence of the MQTT protocol is the publish/subscribe (pub/sub) pattern which is an alternative to the traditional client-server model. The main difference is that in a client-server model, the client directly communicates with the end point where as in a pub/sub model such direct link does not exist. Instead a clients who is sending a message (the publisher) is decoupled from another client(s) who is receiving the message (the subscriber). A third component: the broker is known by publisher(s) and subscriber(s) and filters all incoming messages and distributes them accordingly. The MQTT protocol resembles a hub-and-spoke model.

When reviewing he NodeMCU mqtt module documentation it is mentioned that the client adheres to version 3.1.1. of the MQTT protocol. As these protocols are not backward compatible a message broker which is configured for this version is mandatory for establishing connectivity with the device.

For the purposes of this blog I have opted for Mosquitto, an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 3.1 and 3.1.1. This section describes the steps to deploy the message broker locally on an GalliumOS/Ubuntu Linux environment. Alternatively online message broker services are available such as the Mosquitto Test Sever or HiveMQ.

The latest Mosquitto message broker can be installed from the Mosquitto PPA which is actively being maintained by Roger Light, the founder of the Mosquitto broker. First order of business is to add the untrusted PPA as software source to the package manager, install the necesarry software packages and validate the broker is up and running.

#Add Mosquitto PPA as untrusted software repository
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa  
sudo apt-get update

#Install various Mosquitto packages
#Mosquitto message broker
sudo apt-get install mosquitto  
#Mosquitto client development libraries
sudo apt-get install libmosquitto-dev  
#Mosquitto terminal client
sudo apt-get install mosquitto-clients

#Validate Mosquitto broker is running
sudo service mosquitto status  

If the script executed successful you should see an active mosquitto service as depicted in screenshot below. Note that the status message mentions mosquitto MQTT v3.1 message broker. This does not mean that protocol version 3.1.1 as the latest version of MQTT support both protocols.

In order to test the message broker we can open a terminal window and enter the following command mosquitto_sub -t "mqtt-test" -v. This command subscribes the terminal session as a client to the topic mqtt-test.

In a second terminal session enter the command mosquitto_pub -t "mqtt-test" -m "Hello MQTT World!". This terminal session acts as a publishing client and publishes the message 'Hello MQTT World!' to the topic mqtt-test. If the message broker is working successfully the message published should be visible to the subscriber client terminal session.

Code

The NodeMCU firmware has a module available to establish a MQTT client. The code snippets below fully utilize the functions provided by this module. In addition, the wifi module is used to connect the ESP8266 SoC onto the internet.

config.lua

The config.lua file is extended with several additional variables and constants required for MQTT connectivity.

--wifi module
wifi_ssid = "YOUR NETWORK"  
wifi_password = "YOUR PASSWORD"

--mqtt module
mqtt_broker_ip = "YOUR LOCALHOST IP"  
mqtt_broker_port = 1883  
mqtt_username = ""  
mqtt_password = ""  
mqtt_client_id = ""

--dht module
dht_pin = 2  -- Pin connected to DHT22 sensor  
dht_temp_calc = 0  -- Calculated temperature  
dht_humi_calc = 0  -- Calculated humidity  
mqtt_temp = 0      -- Temperature for publication  
mqtt_humi = 0      -- Humidity for publication

--sensor reading interval
dsleep_time = 60000 --sleep time in us

-- Status Message
print("Global variables loaded")  

mqtt.lua

This script is an extension for the dht22.lua script. A line of code is added that creates the MQTT client for the ESP8266 device which will connect to the message broker identifying itself by the ESP chip ID: m = mqtt.Client(node.chipid(), 120, mqtt_username, mqtt_password).

An additional function is added that establishes the connection and publishes the temperature and humidity captured by the sensor: func_mqtt_pub(). This function executes 3 commands:

  • m:connect - creates the connection between the MQTT and the message broker
  • m:publish - publishes the values measured by the DHT22 sensor to the topics ESP8266/temp and ESP8266/humi.
  • node.dsleep - enters deep sleep mode, wakes up when timed out.
-- Load global user-defined variables
dofile("config.lua")

-- Connect to the wifi network using wifi module
wifi.setmode(wifi.STATION)  
wifi.sta.config(wifi_ssid, wifi_password)  
wifi.sta.connect()

-- Establish MQTT client
m = mqtt.Client(node.chipid(), 120, mqtt_username, mqtt_password)

-- Read out DHT22 sensor using dht module
function func_read_dht()  
  status, temp, humi, temp_dec, humi_dec = dht.read(2)
  if( status == dht.OK ) then
-- Integer firmware using this example
    print("DHT Temperature: "..math.floor(temp).."."..temp_dec.." C")
    mqtt_temp = math.floor(temp).."."..temp_dec
    print("DHT Humidity: "..math.floor(humi).."."..humi_dec.." %")
    mqtt_humi = math.floor(humi).."."..humi_dec
-- Float firmware using this example
--    print("DHT Temperature: "..temp.." C")
--    print("DHT Humidity: "..humi.." %")
  elseif( dht_status == dht.ERROR_CHECKSUM ) then          
    print( "DHT Checksum error" )
  elseif( dht_status == dht.ERROR_TIMEOUT ) then
    print( "DHT Time out" )
  end
end

-- Publish temperature readings and activate deep sleep
function func_mqtt_pub()  
  m:connect(mqtt_broker_ip, mqtt_broker_port, 0, function(client) print("Connected to MQTT broker")
    m:publish("ESP8266/temp",mqtt_temp,0,0, function(client) print("Temp message published")
      m:publish("ESP8266/humi",mqtt_humi,0,0, function(client) print("Humi message published")
        print("Going into deep sleep mode for "..(dsleep_time/1000).." seconds.")
        node.dsleep(dsleep_time*1000)
      end)
    end)
  end)
end

-- Capture and publish sensor reading and enter deep sleep
function func_exec_loop()  
  if wifi.sta.status() == 5 then  --STA_GOTIP
    print("Connected to "..wifi.sta.getip())
    func_read_dht() --Retrieve sensor data
    func_mqtt_pub() --Publish MQTT messages and go to sleep
    tmr.stop(1) --Exit loop
  else
    print("Still connecting...")
  end
end

tmr.alarm(1,500,tmr.ALARM_AUTO,function() func_exec_loop() end)  

The init.lua script should be modified to execute the newly created mqtt script by modifying the following command: FileToExecute="mqtt.lua". Once all the scripts have been uploaded to the NodeMCU device its demo time. Disconnect the serial cable from your laptop and insert it into a wall socket using a 3.3V/5V USB power adapter.

On the machine which contains the Mosquitto message broker open a terminal window and subscribe to the ESP8266/# topics: mosquitto_sub -t "ESP8266/#" -v. The # symbol is considered a wildcard thus subscribing to both the ESP8266/temp and the ESP8266/humi topics. If everything went well the temperature and humidity are received by the local client's wireless through the MQTT protocol subscription!

As you can see MQTT is a powerful protocol, easily scalable and reliable - a perfect protocol for IoT appliance. Unfortunately this protocol is not (yet) supported by the Hana Cloud Platform ("HCP"). Next installment will focus on the HTML and WebSocket protocols and establish connectivity with the HCP.

Tiest van Gool

Boulder, CO

comments powered by Disqus