MQTT and the Wemos D1 Mini

• Category: IoT

I recently bought up a bunch of the esp8266 based Wemos D1 Mini micro-controllers. These things are great! I managed to find them online here in Thailand for the measily price of ~5usd a pop. Not only that, I also got a few relay and temp/humidity shields to go along with it.

Photo

Weather and MQTT all the things!

I'm working on a small Python project dealing with graphing data, and instead of finding random datasets online, I figured it'd be fun to procure this data myself. Since I've recently been installing a a bunch of Sonoff's around the house (using Theo Arendst's firmware for MQTT functionality, but I'll save that for another post), I figured this could also somehow tie the weather data in with some OpenHAB rules.

For this, I am simply using the Wemos and the Temp/Humidity shield (which is basically a AM2302/DTH22 sensor directly wired to pin D4 on the shield) and some basically code using Adafruit's DHT Library as well as knowlleary's PubSubClient Library, both of which can be installed using the Arduino IDE's package manager.

Here is the dead simple sketch

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

const char* ssid        = "........";
const char* password    = "........";

char* server            = "........";
char* temp_topic        = "sensor/outside/temp";
char* humid_topic       = "sensor/outside/humid";
char* hellotopic        = "hello_topic";

#define DHTPIN D4     // D4 for the Wemos Temp Shield
#define DHTTYPE DHT22   
#define REPORT_INTERVAL 28 // Time between readings

byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; // Change if needed

String clientName;
DHT dht(DHTPIN, DHTTYPE, 15);
WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);

void setup() {
  Serial.begin(38400);
  Serial.println("DHTxx test!");
  delay(20);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  clientName += "esp8266-weather";
  WiFi.macAddress(mac);

  Serial.print("Connecting to ");
  Serial.print(server);

  if (client.connect((char*) clientName.c_str())) {
    Serial.println("Connected to MQTT broker");

    if (client.publish(hellotopic, "hello from ESP8266")) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");
    }
  }
  else {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
  }

  dht.begin();
}

void loop() {

  float h = dht.readHumidity();
  float t = dht.readTemperature();
  float f = dht.readTemperature(true);

  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" \*C ");
  Serial.print(f);
  Serial.print(" \*F\t");

  String str_temp = "";
  str_temp+=t;
  String str_hmd = "";
  str_hmd+=h;

  sendTemperature(str_temp,temp_topic);
  delay(2000);
  sendTemperature(str_hmd,humid_topic);

  int cnt = REPORT_INTERVAL;

  while (cnt--)
    delay(1000);
}


void sendTemperature(String payload, char* pubtopic) {
  if (!client.connected()) {
    if (client.connect((char*) clientName.c_str())) {
      Serial.println("Connected to MQTT broker again");
    }
    else {
      Serial.println("MQTT Connection Failed. Resetting...");
      abort();
    }
  }

  if (client.connected()) {
    Serial.print("Sending payload: ");
    Serial.println(payload);

    if (client.publish(pubtopic, (char*) payload.c_str())) {
      Serial.println("Publish ok");
    }
    else {
      Serial.println("Publish failed");
    }
  }
}

In conclusion

This will publish the temp and humidity to the MQTT under 2 separate topics, temp_topic and humid_topic -- You could modify the code have it pass one message in the MQTT payload JSON formatted, including both the temp and humidity in a single topic, something akin to

String reading = "{\"Humidity\":";
reading += h;
reading += ",\"Temperature\":";
reading += t;
reading += "}";

however, for my needs, I wanted the 2 topics to be separate. However, if you were to do this, you would easily be able to decode the JSON in OpenHAB or even some of the MQTT libraries for Python.

Caveats

This has been running for a few days now, and luckily I haven't had to implement some kind of a Watchdog Timer, however, I've had a few failed readings from the DHT22 shield, which I'd be willing to put down to the fact that it's a cheap piece of hardware. But hey, at $5, you wont see me complaining! :)