DHT22 sensor and MQTT

After a lot of faffing around I’ve managed to get the DHT22 sensor showing up in WLED.
What I’m now stuck on is how to retrieve the Temperature and Humidity readings into Home Assistant.

From the looks of it, the usermod SensorstoMQTT is only for the Dallas sensors.

Any pointers would be much appreciated.

The only way to do it is to rewrite usermod for DHT22

I have been playing around with taking code from the sensors2mqtt code and adapting it to suit a DHT11.
It seems to work.
#pragma once
#include “wled.h”
#include <dht_nonblocking.h>
#include <Arduino.h>
#include <Wire.h>

// USERMOD_DHT_DHTTYPE:
// 11 // DHT 11
// 21 // DHT 21
// 22 // DHT 22 (AM2302), AM2321 *** default
#ifndef USERMOD_DHT_DHTTYPE
#define USERMOD_DHT_DHTTYPE 11
#endif

#if USERMOD_DHT_DHTTYPE == 11
#define DHTTYPE DHT_TYPE_11
#elif USERMOD_DHT_DHTTYPE == 21
#define DHTTYPE DHT_TYPE_21
#elif USERMOD_DHT_DHTTYPE == 22
#define DHTTYPE DHT_TYPE_22
#endif

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// NOTE: Pin defaults below are for QuinLed Dig-Uno’s Q2 on the board
// Connect pin 4 (on the right) of the sensor to GROUND
// NOTE: If using a bare sensor (AM*), Connect a 10K resistor from pin 2
// (data) to pin 1 (power) of the sensor. DHT* boards have the pullup already

#ifdef USERMOD_DHT_PIN
#define DHTPIN USERMOD_DHT_PIN
#else
#ifdef ARDUINO_ARCH_ESP32
#define DHTPIN 21
#else //ESP8266 boards
#define DHTPIN 5
#endif
#endif

// the frequency to check sensor, 1 minute
#ifndef USERMOD_DHT_MEASUREMENT_INTERVAL
#define USERMOD_DHT_MEASUREMENT_INTERVAL 600000
#endif

// how many seconds after boot to take first measurement, 90 seconds
// 90 gives enough time to OTA update firmware if this crashses
#ifndef USERMOD_DHT_FIRST_MEASUREMENT_AT
#define USERMOD_DHT_FIRST_MEASUREMENT_AT 90000
#endif

// from COOLDOWN_TIME in dht_nonblocking.cpp
#define DHT_TIMEOUT_TIME 5000

DHT_nonblocking dht_sensor(DHTPIN, DHTTYPE);

class UsermodDHT : public Usermod {
private:
unsigned long nextReadTime = 0;
unsigned long lastReadTime = 0;
float humidity, temperature = 0;
bool initializing = true;
bool disabled = false;

bool initialized = false;
bool mqttInitialized = false;
float SensorHumidity = 0;
float SensorTemperature = 0;
String mqttTemperatureTopic = "";
String mqttHumidityTopic = "";
unsigned long nextMeasure = 0;
unsigned long tempTimer = millis();

void _initialize()
{
// initialized = bmp.begin(BMP280_ADDRESS_ALT);
// bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. /
// Adafruit_BMP280::SAMPLING_X16, /
Temp. oversampling /
// Adafruit_BMP280::SAMPLING_X16, /
Pressure oversampling /
// Adafruit_BMP280::FILTER_X16, /
Filtering. /
// Adafruit_BMP280::STANDBY_MS_2000); /
Refresh values every 20 seconds */

Serial.print("initialized");

}

void _mqttInitialize()
{
mqttTemperatureTopic = String(mqttDeviceTopic) + “/temperature”;
mqttHumidityTopic = String(mqttDeviceTopic) + “/humidity”;
String t = String(“homeassistant/sensor/”) + mqttClientID + “/temperature/config”;
_createMqttSensor(“temperature”, mqttTemperatureTopic, “temperature”, “°C”);
_createMqttSensor(“humidity”, mqttHumidityTopic, “humidity”, “%”);
dht_sensor.measure(&temperature, &humidity);
SensorTemperature = temperature;
SensorHumidity = humidity;
mqtt->publish(mqttTemperatureTopic.c_str(), 0, true, String(SensorTemperature).c_str());
mqtt->publish(mqttHumidityTopic.c_str(), 0, true, String(SensorHumidity).c_str());
}

void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
{
String t = String(“homeassistant/sensor/”) + mqttClientID + “/” + name + “/config”;

StaticJsonDocument<300> doc;

doc["name"] = name;
doc["state_topic"] = topic;
doc["unique_id"] = String(mqttClientID) + name;
if (unitOfMeasurement != "")
  doc["unit_of_measurement"] = unitOfMeasurement;
if (deviceClass != "")
  doc["device_class"] = deviceClass;
doc["expire_after"] = 1800;

JsonObject device = doc.createNestedObject("device"); // attach the sensor to the same device
device["identifiers"] = String("wled-sensor-DHT-") + mqttClientID;
device["manufacturer"] = "Aircoookie";
device["model"] = "WLED-DHT";
device["sw_version"] = VERSION;
device["name"] = mqttClientID;

String temp;
serializeJson(doc, temp);
Serial.println(t);
Serial.println(temp);

mqtt->publish(t.c_str(), 0, true, temp.c_str());

}

/*

static bool measure_environment( float *temperature, float *humidity )
{
static unsigned long measurement_timestamp = millis( );

if( millis( ) - measurement_timestamp > 3000ul )
{
if( dht_sensor.measure( temperature, humidity ) == true )
{
measurement_timestamp = millis( );
return( true );
}
}

return( false );
}

float temperature;
float humidity;
if( measure_environment( &temperature, &humidity ) == true )
{
Serial.print( "T = " );
Serial.print( temperature, 1 );
Serial.print( " deg. C, H = " );
Serial.print( humidity, 1 );
Serial.println( “%” );
}
else
{
Serial.println(“nope.”);
}

*/

void _updateSensorData()
{

dht_sensor.measure(&temperature, &humidity);
SensorTemperature = temperature;
SensorHumidity = humidity;
// dht_sensor.measure(&temperature, &humidity);

// Serial.printf("%f c,%f %\n",SensorTemperature, SensorHumidity);
}

public:
void setup() {

  nextReadTime = millis() + USERMOD_DHT_FIRST_MEASUREMENT_AT;
  lastReadTime = millis();

   Serial.println("Starting!");
 Serial.println("Initializing sensors.. ");
_initialize();
 
}

// gets called every time WiFi is (re-)connected.
void connected()
{
nextMeasure = millis() + 5000; // Schedule next measure in 5 seconds
}

void loop() {

// unsigned long tempTimer = millis();
if (tempTimer > nextMeasure)
{
nextMeasure = tempTimer + 60000; // Schedule next measure in 60 seconds
}
// if (!initialized)
// {
// Serial.println(“Error! Sensors not initialized in loop()!”);
// _initialize();
// return; // lets try again next loop
// }
if (mqtt != nullptr && mqtt->connected())
{
if (!mqttInitialized)
{
_mqttInitialize();
mqttInitialized = true;
}
// Update sensor data
_updateSensorData();
// Create string populated with user defined device topic from the UI,
// and the read temperature, humidity and pressure.
// Then publish to MQTT server.
mqtt->publish(mqttTemperatureTopic.c_str(), 0, true, String(SensorTemperature).c_str());
mqtt->publish(mqttHumidityTopic.c_str(), 0, true, String(SensorHumidity).c_str());
}

else
{
// Serial.println(“Missing MQTT connection. Not publishing data”);
// mqttInitialized = false;
}

  if (disabled) {
    return;
  }
  if (millis() < nextReadTime) {
    return;
  }

 unsigned long tempTimer = millis();
  unsigned long dcalc = millis();
 

  float tempC;
  float humidityH;
  if (dht_sensor.measure(&tempC, &humidity)) {
    temperature = tempC;
    humidityH = humidity;
    nextReadTime = millis() + USERMOD_DHT_MEASUREMENT_INTERVAL;
    lastReadTime = millis();
    initializing = false;

    Serial.printf("%f c,%f %\n",temperature, humidity);

    if (mqtt != nullptr && mqtt->connected())
  {

//    mqtt->publish(mqttTemperatureTopic.c_str(), 0, true, String(temperature).c_str());

// mqtt->publish(mqttHumidityTopic.c_str(), 0, true, String(humidity).c_str());
}

  }     
  if (((millis() - lastReadTime) > 10*USERMOD_DHT_MEASUREMENT_INTERVAL)) {
    disabled = false;
  }

if (tempTimer > nextMeasure)
{
nextMeasure = tempTimer + 60000; // Schedule next measure in 60 seconds
// if (!initialized)
// {
// Serial.println(“Error! Sensors not initialized in loop()!”);
// _initialize();
// return; // lets try again next loop
// }
if (mqtt != nullptr && mqtt->connected())
{
if (!mqttInitialized)
{
_mqttInitialize();
mqttInitialized = true;
}
// Update sensor data
// _updateSensorData();

float tempC;
if (dht_sensor.measure(&tempC, &humidity)) {
#ifdef USERMOD_DHT_CELSIUS
temperature = tempC;
#else
temperature = tempC * 9 / 5 + 32;
#endif
Serial.println(“Reading 2…\n”);
nextReadTime = millis() + USERMOD_DHT_MEASUREMENT_INTERVAL;
lastReadTime = millis();
initializing = false;
}
if (((millis() - lastReadTime) > 10*USERMOD_DHT_MEASUREMENT_INTERVAL)) {
disabled = false;
}
// Create string populated with user defined device topic from the UI,
// and the read temperature, humidity and pressure.
// Then publish to MQTT server.
mqtt->publish(mqttTemperatureTopic.c_str(), 0, true, String(temperature).c_str());
mqtt->publish(mqttHumidityTopic.c_str(), 0, true, String(humidity).c_str());
}

else
{
Serial.println(“Missing MQTT connection. Not publishing data”);
mqttInitialized = false;
}

}

}
void addToJsonInfo(JsonObject& root) {
if (disabled) {
return;
}
JsonObject user = root[“u”];
if (user.isNull()) user = root.createNestedObject(“u”);
JsonArray temp = user.createNestedArray(“Temperature”);
JsonArray hum = user.createNestedArray(“Humidity”);

  if (initializing) {
    // if we haven't read the sensor yet, let the user know
    // that we are still waiting for the first measurement
    temp.add((nextReadTime - millis()) / 1000);
    temp.add(" sec until read");
    hum.add((nextReadTime - millis()) / 1000);
    hum.add(" sec until read");
    return;
  }

  hum.add(humidity);
  hum.add("%");

  temp.add(temperature);
  #ifdef USERMOD_DHT_CELSIUS
  temp.add("°C");
  #else
  temp.add("°F");
  #endif
}

uint16_t getId()
{
  return USERMOD_ID_DHT;
}

};

I think everybody appreciates your job but better to share with all users by posting your changes as pull request to main GitHub repository.

I managed to get the DHT info into MQTT by editing the DHT mod and adding the code at the bottom at the end of “void addToJsonInfo{}” before the closing curly bracket.

I think the temperature mods could use a tidy up and consolidation. There are currently 3 mods relating to temperature (DHT, Temperature and sensors_to_mqtt). Makes sense to have all of this in one mod and use build flags to set pins, sensor types, etc

    if (WLED_MQTT_CONNECTED)
    {
      char subuf[64];
      strcpy(subuf, mqttDeviceTopic);
      strcat_P(subuf, PSTR("/humidity"));
      mqtt->publish(subuf, 0, false, String(humidity).c_str());
      strcpy(subuf, mqttDeviceTopic);
      strcat_P(subuf, PSTR("/temperature"));
      mqtt->publish(subuf, 0, false, String(temperature).c_str());
      strcat_P(subuf, PSTR("_f"));
      mqtt->publish(subuf, 0, false, String((float)temperature * 1.8f + 32).c_str());
    }

Hi All,
I’m not much of a coder and was only trying to assist with what was working for me.
I wanted to have the DHT11 values visible in the info screen and the MQTT data posted to Home Assistant in the MQTT category as I could not see anything appearing in the Wled category,

Perhaps I’m missing something about how to get the values to appear , but like all of us, I’m still learning.

1 Like