Year of the X Festival: IoT in less than a day!

Today I attended the Year of the X Innovation Festival and happened to sit in a workshop run by Iteratec titled IoT in less than a day. What I love about Year of the X festivals is, that there is a general you can touch this attitude to the workshops and demos. This workshop was no exception! The company sent a team of over five developers and designers. They brought all kind of sensors ranging from a motion detector to an ultra-sonic distance sensor. There were also plenty of actors, for example, a self-built matrix display and an Internet-connected blender (mixing smoothies in the company colors). 😂

During the workshop, attendees were invited to throw some IoT ideas into an online collaboration tool challenging the team to build a few of those in less than a day. An IoT challenge? I re-arranged my agenda to make some room! A couple of minutes later I found myself in the back office were the friendly Iteratec guys helped me to get started.

The Idea

I have a DHT22 temperature and humidity sensor connected to a RaspberryPi in my lab at home. The data is pulled once a minute by Prometheus (a time series database) and occasionally visualized using Grafana (a graphing frontend for monitoring data).

A very different approach was shown in the workshop. All sensors published their data to a central message broker and actors (or other sensors) could subscribe to the messages. I wanted to learn that and decided to connect a DHT22 sensor to a message broker via a NodeMCU. A platform I had my struggles with before. 😩

The Approach

The NodeMCU Platform can conveniently be programmed using the standard Arduino IDE which makes it easy to get started. There are libraries for all the common tasks. In fact, the hardest part was to get the UART interface working with macOS. 🙈 After that, the plan was as follows:

  • Connect to the wifi
  • Connect to the message broker
  • Read DHT22 sensor
  • Publish sensor data to message broker
  • Wait a couple of seconds and go back to Read DHT22 sensor

With a little help here and there (snprintf() on Arduino ignores the %f pattern and ignores floats!) I got everything working in a couple of hours. It was really great that the workshop organizers had brought almost an entire lab in boxes. 👍

As message broker I used shiftr.io, a free message broker that has a nice visualization. It was very helpful to see if and what messages were send from where to where. I can recommend this service!

The Result

Serial console output of the NodeMCU:

Message broker visualization:

The NodeMCU and connected DHT22 sensor.

The Code

#include <ESP8266WiFi.h>
#include <MQTTClient.h>
#include "DHT.h"

const char *wifi_ssid     = "wifi";
const char *wifi_password = "secret";

const char *mqtt_server   = "broker.shiftr.io";
const char *mqtt_id       = "my_first_node";
const char *mqtt_user     = "login";
const char *mqtt_password = "secret";

const int  dht_pin        = D6;

WiFiClient net;
MQTTClient client;
DHT dht(dht_pin, DHT22);

void setup() {
  Serial.begin(115200);

  // wifi
  Serial.print("wifi: ssid=");
  Serial.println(wifi_ssid);
  Serial.print("wifi: password=");
  Serial.println(wifi_password);
  Serial.print("wifi: connecting");
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("wifi: ip_addr=");
  Serial.println(WiFi.localIP());
  Serial.println("wifi: done!");

  // message broker connection
  client.begin(mqtt_server, net);
  connect();
}

void connect() {
  Serial.print("mqtt: server=");
  Serial.println(mqtt_server);
  Serial.print("mqtt: id=");
  Serial.println(mqtt_id);
  Serial.print("mqtt: user=");
  Serial.println(mqtt_user);
  Serial.print("mqtt: password=");
  Serial.println(mqtt_password);
  Serial.print("mqtt: connecting");
  while (!client.connect(mqtt_id, mqtt_user, mqtt_password)) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println();
  Serial.println("mqtt: done!");
  client.subscribe("commands");
}

void loop() {
  // vars
  float temperature = 0.0;
  float humidity = 0.0;
  String message;

  client.loop();
  delay(10); // stability fix
  if(!client.connected()) {
    connect();
  }


  temperature = dht.readTemperature();
  humidity = dht.readHumidity();
  message  = "temperature=";
  message += String(temperature, 1);
  message += " ";
  message += "humidity=";
  message += String(humidity, 1);  Serial.print("message_out: ");
  Serial.println(message);
  client.publish("sensors", message);

  delay(3000);
}

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
  Serial.print("message_in: topic=");
  Serial.print(topic);
  Serial.print(" payload='");
  Serial.print(payload);
  Serial.println("'");
}