Usermod BME280 Enhancements
I added a Usermod interface for key settings. I used a PinArray for the SDA/SCL pins, but you can't name these individually. I have also made a display to show the temperature/humidity values in the web interface's Info screen. I had to change the definition of those items in order to allow these new functions to work. I have not noticed any negative side effects to this change. At the moment, I've not figured out how to make Celsius/Farenheit toggleable due to the way the #define setup works. Finally, I have added a routine to publish MQTT Discovery Topics for Home Assistant (toggleable in the Usermod screen). I've been testing this on the only suitable device I have for a few months and haven't noticed any problems.
This commit is contained in:
parent
a8908238d5
commit
e12f7b67e5
@ -1,3 +1,6 @@
|
|||||||
|
// force the compiler to show a warning to confirm that this file is included
|
||||||
|
#warning **** Included USERMOD_BME280 version 2.0 ****
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
@ -11,32 +14,13 @@ class UsermodBME280 : public Usermod
|
|||||||
private:
|
private:
|
||||||
// User-defined configuration
|
// User-defined configuration
|
||||||
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit
|
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit
|
||||||
#define TemperatureDecimals 1 // Number of decimal places in published temperaure values
|
unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values
|
||||||
#define HumidityDecimals 2 // Number of decimal places in published humidity values
|
unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values
|
||||||
#define PressureDecimals 2 // Number of decimal places in published pressure values
|
unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values
|
||||||
#define TemperatureInterval 5 // Interval to measure temperature (and humidity, dew point if available) in seconds
|
unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
|
||||||
#define PressureInterval 300 // Interval to measure pressure in seconds
|
unsigned long PressureInterval = 300; // Interval to measure pressure in seconds
|
||||||
#define PublishAlways 0 // Publish values even when they have not changed
|
bool PublishAlways = false; // Publish values even when they have not changed
|
||||||
|
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
|
||||||
// Sanity checks
|
|
||||||
#if !defined(TemperatureDecimals) || TemperatureDecimals < 0
|
|
||||||
#define TemperatureDecimals 0
|
|
||||||
#endif
|
|
||||||
#if !defined(HumidityDecimals) || HumidityDecimals < 0
|
|
||||||
#define HumidityDecimals 0
|
|
||||||
#endif
|
|
||||||
#if !defined(PressureDecimals) || PressureDecimals < 0
|
|
||||||
#define PressureDecimals 0
|
|
||||||
#endif
|
|
||||||
#if !defined(TemperatureInterval) || TemperatureInterval < 0
|
|
||||||
#define TemperatureInterval 1
|
|
||||||
#endif
|
|
||||||
#if !defined(PressureInterval) || PressureInterval < 0
|
|
||||||
#define PressureInterval TemperatureInterval
|
|
||||||
#endif
|
|
||||||
#if !defined(PublishAlways)
|
|
||||||
#define PublishAlways 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
||||||
uint8_t SCL_PIN = 22;
|
uint8_t SCL_PIN = 22;
|
||||||
@ -82,6 +66,14 @@ private:
|
|||||||
float lastDewPoint;
|
float lastDewPoint;
|
||||||
float lastPressure;
|
float lastPressure;
|
||||||
|
|
||||||
|
// MQTT topic strings for publishing Home Assistant discovery topics
|
||||||
|
bool mqttInitialized = false;
|
||||||
|
String mqttTemperatureTopic = "";
|
||||||
|
String mqttHumidityTopic = "";
|
||||||
|
String mqttPressureTopic = "";
|
||||||
|
String mqttHeatIndexTopic = "";
|
||||||
|
String mqttDewPointTopic = "";
|
||||||
|
|
||||||
// Store packet IDs of MQTT publications
|
// Store packet IDs of MQTT publications
|
||||||
uint16_t mqttTemperaturePub = 0;
|
uint16_t mqttTemperaturePub = 0;
|
||||||
uint16_t mqttPressurePub = 0;
|
uint16_t mqttPressurePub = 0;
|
||||||
@ -110,6 +102,55 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Procedure to define all MQTT Topics
|
||||||
|
void _mqttInitialize()
|
||||||
|
{
|
||||||
|
mqttTemperatureTopic = String(mqttDeviceTopic) + "/temperature";
|
||||||
|
mqttPressureTopic = String(mqttDeviceTopic) + "/pressure";
|
||||||
|
mqttHumidityTopic = String(mqttDeviceTopic) + "/humidity";
|
||||||
|
mqttHeatIndexTopic = String(mqttDeviceTopic) + "/heat_index";
|
||||||
|
mqttDewPointTopic = String(mqttDeviceTopic) + "/dew_point";
|
||||||
|
|
||||||
|
String t = String("homeassistant/sensor/") + mqttClientID + "/temperature/config";
|
||||||
|
|
||||||
|
_createMqttSensor("Temperature", mqttTemperatureTopic, "temperature", "°C");
|
||||||
|
_createMqttSensor("Pressure", mqttPressureTopic, "pressure", "hPa");
|
||||||
|
_createMqttSensor("Humidity", mqttHumidityTopic, "humidity", "%");
|
||||||
|
_createMqttSensor("HeatIndex", mqttHeatIndexTopic, "temperature", "°C");
|
||||||
|
_createMqttSensor("DewPoint", mqttDewPointTopic, "temperature", "°C");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
|
||||||
|
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
|
||||||
|
{
|
||||||
|
String t = String("homeassistant/sensor/") + mqttClientID + "/" + name + "/config";
|
||||||
|
|
||||||
|
StaticJsonDocument<600> doc;
|
||||||
|
|
||||||
|
doc["name"] = String(serverDescription) + " " + 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["name"] = serverDescription;
|
||||||
|
device["identifiers"] = "wled-sensor-" + String(mqttClientID);
|
||||||
|
device["manufacturer"] = "WLED";
|
||||||
|
device["model"] = "FOSS";
|
||||||
|
device["sw_version"] = versionString;
|
||||||
|
|
||||||
|
String temp;
|
||||||
|
serializeJson(doc, temp);
|
||||||
|
Serial.println(t);
|
||||||
|
Serial.println(temp);
|
||||||
|
|
||||||
|
mqtt->publish(t.c_str(), 0, true, temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
@ -143,7 +184,7 @@ public:
|
|||||||
{
|
{
|
||||||
// BME280 sensor MQTT publishing
|
// BME280 sensor MQTT publishing
|
||||||
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
|
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
|
||||||
if (sensorType != 0 && mqtt != nullptr)
|
if (sensorType != 0 && WLED_MQTT_CONNECTED)
|
||||||
{
|
{
|
||||||
// Timer to fetch new temperature, humidity and pressure data at intervals
|
// Timer to fetch new temperature, humidity and pressure data at intervals
|
||||||
timer = millis();
|
timer = millis();
|
||||||
@ -157,6 +198,12 @@ public:
|
|||||||
float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
|
float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
|
||||||
float humidity, heatIndex, dewPoint;
|
float humidity, heatIndex, dewPoint;
|
||||||
|
|
||||||
|
if (WLED_MQTT_CONNECTED && !mqttInitialized && HomeAssistantDiscovery)
|
||||||
|
{
|
||||||
|
_mqttInitialize();
|
||||||
|
mqttInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If temperature has changed since last measure, create string populated with device topic
|
// If temperature has changed since last measure, create string populated with device topic
|
||||||
// from the UI and values read from sensor, then publish to broker
|
// from the UI and values read from sensor, then publish to broker
|
||||||
if (temperature != lastTemperature || PublishAlways)
|
if (temperature != lastTemperature || PublishAlways)
|
||||||
@ -213,4 +260,86 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publish Sensor Information to Info Page
|
||||||
|
void addToJsonInfo(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
if (sensorType==0) //No Sensor
|
||||||
|
{
|
||||||
|
// if we sensor not detected, let the user know
|
||||||
|
JsonArray temperature_json = user.createNestedArray("BME/BMP280 Sensor");
|
||||||
|
temperature_json.add(F("Not Found"));
|
||||||
|
}
|
||||||
|
else if (sensorType==2) //BMP280
|
||||||
|
{
|
||||||
|
|
||||||
|
JsonArray temperature_json = user.createNestedArray("Temperature");
|
||||||
|
JsonArray pressure_json = user.createNestedArray("Pressure");
|
||||||
|
temperature_json.add(sensorTemperature);
|
||||||
|
temperature_json.add(F("°C"));
|
||||||
|
pressure_json.add(sensorPressure);
|
||||||
|
pressure_json.add(F("°C"));
|
||||||
|
}
|
||||||
|
else if (sensorType==1) //BME280
|
||||||
|
{
|
||||||
|
JsonArray temperature_json = user.createNestedArray("Temperature");
|
||||||
|
JsonArray humidity_json = user.createNestedArray("Humidity");
|
||||||
|
JsonArray pressure_json = user.createNestedArray("Pressure");
|
||||||
|
JsonArray heatindex_json = user.createNestedArray("Heat Index");
|
||||||
|
JsonArray dewpoint_json = user.createNestedArray("Dew Point");
|
||||||
|
temperature_json.add(sensorTemperature);
|
||||||
|
temperature_json.add(F("°C"));
|
||||||
|
humidity_json.add(sensorHumidity);
|
||||||
|
humidity_json.add(F("%"));
|
||||||
|
pressure_json.add(sensorPressure);
|
||||||
|
pressure_json.add(F("°C"));
|
||||||
|
heatindex_json.add(sensorHeatIndex);
|
||||||
|
heatindex_json.add(F("°C"));
|
||||||
|
dewpoint_json.add(sensorDewPoint);
|
||||||
|
dewpoint_json.add(F("°C"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Usermod Config Settings
|
||||||
|
void addToConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject("BME280/BMP280");
|
||||||
|
top["TemperatureDecimals"] = TemperatureDecimals;
|
||||||
|
top["HumidityDecimals"] = HumidityDecimals;
|
||||||
|
top["PressureDecimals"] = PressureDecimals;
|
||||||
|
top["TemperatureInterval"] = TemperatureInterval;
|
||||||
|
top["PublishAlways"] = PublishAlways;
|
||||||
|
top["HomeAssistantDiscovery"] = HomeAssistantDiscovery;
|
||||||
|
JsonArray pinArray = top.createNestedArray("pin-sda-scl");
|
||||||
|
pinArray.add(SDA_PIN);
|
||||||
|
pinArray.add(SCL_PIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Usermod Config Settings
|
||||||
|
bool readFromConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
|
||||||
|
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
||||||
|
|
||||||
|
JsonObject top = root["BME280/BMP280"];
|
||||||
|
|
||||||
|
bool configComplete = !top.isNull();
|
||||||
|
|
||||||
|
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
|
||||||
|
configComplete &= getJsonValue(top["TemperatureDecimals"], TemperatureDecimals, 1);
|
||||||
|
configComplete &= getJsonValue(top["HumidityDecimals"], HumidityDecimals, 0);
|
||||||
|
configComplete &= getJsonValue(top["PressureDecimals"], PressureDecimals, 0);
|
||||||
|
configComplete &= getJsonValue(top["TemperatureInterval"], TemperatureInterval, 30);
|
||||||
|
configComplete &= getJsonValue(top["PublishAlways"], PublishAlways, false);
|
||||||
|
configComplete &= getJsonValue(top["HomeAssistantDiscovery"], HomeAssistantDiscovery, false);
|
||||||
|
configComplete &= getJsonValue(top["pin-sda-scl"][0], SDA_PIN, 21); //SDA
|
||||||
|
configComplete &= getJsonValue(top["pin-sda-scl"][1], SCL_PIN, 22); //SCL
|
||||||
|
|
||||||
|
return configComplete;
|
||||||
|
}
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user