BME280 fixes and optimisations

- MQTT not required
- minor string optimisations
- added enable option
This commit is contained in:
Blaz Kristan 2022-11-25 16:45:21 +01:00
parent 906c7a8ea1
commit 8e30e4925c

View File

@ -16,14 +16,15 @@ private:
// NOTE: Do not implement any compile-time variables, anything the user needs to configure // NOTE: Do not implement any compile-time variables, anything the user needs to configure
// should be configurable from the Usermod menu using the methods below // should be configurable from the Usermod menu using the methods below
// key settings set via usermod menu // key settings set via usermod menu
unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values uint8_t TemperatureDecimals = 0; // Number of decimal places in published temperaure values
unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values uint8_t HumidityDecimals = 0; // Number of decimal places in published humidity values
unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values uint8_t PressureDecimals = 0; // Number of decimal places in published pressure values
unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds uint16_t TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
unsigned long PressureInterval = 300; // Interval to measure pressure in seconds uint16_t PressureInterval = 300; // Interval to measure pressure in seconds
bool PublishAlways = false; // Publish values even when they have not changed bool PublishAlways = false; // Publish values even when they have not changed
bool UseCelsius = true; // Use Celsius for Reporting bool UseCelsius = true; // Use Celsius for Reporting
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
bool enabled = true;
// set the default pins based on the architecture, these get overridden by Usermod menu settings // set the default pins based on the architecture, these get overridden by Usermod menu settings
#ifdef ESP8266 #ifdef ESP8266
@ -70,15 +71,10 @@ private:
// MQTT topic strings for publishing Home Assistant discovery topics // MQTT topic strings for publishing Home Assistant discovery topics
bool mqttInitialized = false; bool mqttInitialized = false;
String mqttTemperatureTopic = "";
String mqttHumidityTopic = "";
String mqttPressureTopic = "";
String mqttHeatIndexTopic = "";
String mqttDewPointTopic = "";
// Store packet IDs of MQTT publications // strings to reduce flash memory usage (used more than twice)
uint16_t mqttTemperaturePub = 0; static const char _name[];
uint16_t mqttPressurePub = 0; static const char _enabled[];
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu) // Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
void UpdateBME280Data(int SensorType) void UpdateBME280Data(int SensorType)
@ -95,7 +91,7 @@ private:
sensorTemperature = _temperature; sensorTemperature = _temperature;
sensorHumidity = _humidity; sensorHumidity = _humidity;
sensorPressure = _pressure; sensorPressure = _pressure;
tempScale = "°C"; tempScale = F("°C");
if (sensorType == 1) if (sensorType == 1)
{ {
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit); sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
@ -111,7 +107,7 @@ private:
sensorTemperature = _temperature; sensorTemperature = _temperature;
sensorHumidity = _humidity; sensorHumidity = _humidity;
sensorPressure = _pressure; sensorPressure = _pressure;
tempScale = "°F"; tempScale = F("°F");
if (sensorType == 1) if (sensorType == 1)
{ {
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit); sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
@ -123,18 +119,23 @@ private:
// Procedure to define all MQTT discovery Topics // Procedure to define all MQTT discovery Topics
void _mqttInitialize() void _mqttInitialize()
{ {
mqttTemperatureTopic = String(mqttDeviceTopic) + F("/temperature"); char mqttTemperatureTopic[128];
mqttPressureTopic = String(mqttDeviceTopic) + F("/pressure"); char mqttHumidityTopic[128];
mqttHumidityTopic = String(mqttDeviceTopic) + F("/humidity"); char mqttPressureTopic[128];
mqttHeatIndexTopic = String(mqttDeviceTopic) + F("/heat_index"); char mqttHeatIndexTopic[128];
mqttDewPointTopic = String(mqttDeviceTopic) + F("/dew_point"); char mqttDewPointTopic[128];
snprintf_P(mqttTemperatureTopic, 127, PSTR("%s/temperature"), mqttDeviceTopic);
snprintf_P(mqttPressureTopic, 127, PSTR("%s/pressure"), mqttDeviceTopic);
snprintf_P(mqttHumidityTopic, 127, PSTR("%s/humidity"), mqttDeviceTopic);
snprintf_P(mqttHeatIndexTopic, 127, PSTR("%s/heat_index"), mqttDeviceTopic);
snprintf_P(mqttDewPointTopic, 127, PSTR("%s/dew_point"), mqttDeviceTopic);
if (HomeAssistantDiscovery) { if (HomeAssistantDiscovery) {
_createMqttSensor(F("Temperature"), mqttTemperatureTopic, F("temperature"), tempScale); _createMqttSensor(F("Temperature"), mqttTemperatureTopic, "temperature", tempScale);
_createMqttSensor(F("Pressure"), mqttPressureTopic, F("pressure"), F("hPa")); _createMqttSensor(F("Pressure"), mqttPressureTopic, "pressure", F("hPa"));
_createMqttSensor(F("Humidity"), mqttHumidityTopic, F("humidity"), F("%")); _createMqttSensor(F("Humidity"), mqttHumidityTopic, "humidity", F("%"));
_createMqttSensor(F("HeatIndex"), mqttHeatIndexTopic, F("temperature"), tempScale); _createMqttSensor(F("HeatIndex"), mqttHeatIndexTopic, "temperature", tempScale);
_createMqttSensor(F("DewPoint"), mqttDewPointTopic, F("temperature"), tempScale); _createMqttSensor(F("DewPoint"), mqttDewPointTopic, "temperature", tempScale);
} }
} }
@ -169,6 +170,15 @@ private:
mqtt->publish(t.c_str(), 0, true, temp.c_str()); mqtt->publish(t.c_str(), 0, true, temp.c_str());
} }
void publishMqtt(const char *topic, const char* state) {
//Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED){
char subuf[128];
snprintf_P(subuf, 127, PSTR("%s/%s"), mqttDeviceTopic, topic);
mqtt->publish(subuf, 0, false, state);
}
}
public: public:
void setup() void setup()
{ {
@ -183,7 +193,7 @@ public:
if (!bme.begin()) if (!bme.begin())
{ {
sensorType = 0; sensorType = 0;
DEBUG_PRINTLN(F("Could not find BME280I2C sensor!")); DEBUG_PRINTLN(F("Could not find BME280 I2C sensor!"));
} }
else else
{ {
@ -207,14 +217,16 @@ public:
void loop() void loop()
{ {
if (!enabled || strip.isUpdating()) return;
// 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 Connected, otherwise it will crash the MCU
if (sensorType != 0 && WLED_MQTT_CONNECTED) if (sensorType != 0)
{ {
// 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();
if (timer - lastTemperatureMeasure >= TemperatureInterval * 1000 || mqttTemperaturePub == 0) if (timer - lastTemperatureMeasure >= TemperatureInterval * 1000)
{ {
lastTemperatureMeasure = timer; lastTemperatureMeasure = timer;
@ -223,18 +235,11 @@ public:
float temperature = roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); float temperature = roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
float humidity, heatIndex, dewPoint; float humidity, heatIndex, dewPoint;
if (WLED_MQTT_CONNECTED && !mqttInitialized)
{
_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)
{ {
String topic = String(mqttDeviceTopic) + "/temperature"; publishMqtt("temperature", String(temperature, TemperatureDecimals).c_str());
mqttTemperaturePub = mqtt->publish(topic.c_str(), 0, false, String(temperature, TemperatureDecimals).c_str());
} }
lastTemperature = temperature; // Update last sensor temperature for next loop lastTemperature = temperature; // Update last sensor temperature for next loop
@ -247,20 +252,17 @@ public:
if (humidity != lastHumidity || PublishAlways) if (humidity != lastHumidity || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + F("/humidity"); publishMqtt("humidity", String(humidity, HumidityDecimals).c_str());
mqtt->publish(topic.c_str(), 0, false, String(humidity, HumidityDecimals).c_str());
} }
if (heatIndex != lastHeatIndex || PublishAlways) if (heatIndex != lastHeatIndex || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + F("/heat_index"); publishMqtt("heat_index", String(heatIndex, TemperatureDecimals).c_str());
mqtt->publish(topic.c_str(), 0, false, String(heatIndex, TemperatureDecimals).c_str());
} }
if (dewPoint != lastDewPoint || PublishAlways) if (dewPoint != lastDewPoint || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + F("/dew_point"); publishMqtt("dew_point", String(dewPoint, TemperatureDecimals).c_str());
mqtt->publish(topic.c_str(), 0, false, String(dewPoint, TemperatureDecimals).c_str());
} }
lastHumidity = humidity; lastHumidity = humidity;
@ -269,7 +271,7 @@ public:
} }
} }
if (timer - lastPressureMeasure >= PressureInterval * 1000 || mqttPressurePub == 0) if (timer - lastPressureMeasure >= PressureInterval * 1000)
{ {
lastPressureMeasure = timer; lastPressureMeasure = timer;
@ -277,15 +279,23 @@ public:
if (pressure != lastPressure || PublishAlways) if (pressure != lastPressure || PublishAlways)
{ {
String topic = String(mqttDeviceTopic) + F("/pressure"); publishMqtt("pressure", String(pressure, PressureDecimals).c_str());
mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(pressure, PressureDecimals).c_str());
} }
lastPressure = pressure; lastPressure = pressure;
} }
} }
} }
void onMqttConnect(bool sessionPresent)
{
if (WLED_MQTT_CONNECTED && !mqttInitialized)
{
_mqttInitialize();
mqttInitialized = true;
}
}
/* /*
* API calls te enable data exchange between WLED modules * API calls te enable data exchange between WLED modules
*/ */
@ -294,9 +304,9 @@ public:
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} else { } else {
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32; return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
} }
} }
inline float getTemperatureF() { inline float getTemperatureF() {
if (UseCelsius) { if (UseCelsius) {
return ((float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f; return ((float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
@ -304,12 +314,15 @@ public:
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} }
} }
inline float getHumidity() { inline float getHumidity() {
return (float)roundf(sensorHumidity * powf(10, HumidityDecimals)); return (float)roundf(sensorHumidity * powf(10, HumidityDecimals));
} }
inline float getPressure() { inline float getPressure() {
return (float)roundf(sensorPressure * powf(10, PressureDecimals)); return (float)roundf(sensorPressure * powf(10, PressureDecimals));
} }
inline float getDewPointC() { inline float getDewPointC() {
if (UseCelsius) { if (UseCelsius) {
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
@ -317,6 +330,7 @@ public:
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32; return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
} }
} }
inline float getDewPointF() { inline float getDewPointF() {
if (UseCelsius) { if (UseCelsius) {
return ((float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f; return ((float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
@ -324,13 +338,16 @@ public:
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} }
} }
inline float getHeatIndexC() { inline float getHeatIndexC() {
if (UseCelsius) { if (UseCelsius) {
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals); return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
} else { } else {
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32; return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
} }
}inline float getHeatIndexF() { }
inline float getHeatIndexF() {
if (UseCelsius) { if (UseCelsius) {
return ((float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f; return ((float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
} else { } else {
@ -384,7 +401,8 @@ public:
// Save Usermod Config Settings // Save Usermod Config Settings
void addToConfig(JsonObject& root) void addToConfig(JsonObject& root)
{ {
JsonObject top = root.createNestedObject(F("BME280/BMP280")); JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
top[F("TemperatureDecimals")] = TemperatureDecimals; top[F("TemperatureDecimals")] = TemperatureDecimals;
top[F("HumidityDecimals")] = HumidityDecimals; top[F("HumidityDecimals")] = HumidityDecimals;
top[F("PressureDecimals")] = PressureDecimals; top[F("PressureDecimals")] = PressureDecimals;
@ -405,17 +423,17 @@ public:
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor // 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) // 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)
int8_t newPin[2]; for (byte i=0; i<2; i++) newPin[i] = ioPin[i]; // prepare to note changed pins int8_t newPin[2]; for (byte i=0; i<2; i++) newPin[i] = ioPin[i]; // prepare to note changed pins
JsonObject top = root[F("BME280/BMP280")]; JsonObject top = root[FPSTR(_name)];
if (top.isNull()) { if (top.isNull()) {
DEBUG_PRINT(F("BME280/BMP280")); DEBUG_PRINT(F(_name));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false; return false;
} }
bool configComplete = !top.isNull(); bool configComplete = !top.isNull();
configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled);
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing // A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1); configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1);
configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0); configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0);
@ -427,7 +445,7 @@ public:
configComplete &= getJsonValue(top[F("HomeAssistantDiscovery")], HomeAssistantDiscovery, false); configComplete &= getJsonValue(top[F("HomeAssistantDiscovery")], HomeAssistantDiscovery, false);
for (byte i=0; i<2; i++) configComplete &= getJsonValue(top[F("pin")][i], newPin[i], ioPin[i]); for (byte i=0; i<2; i++) configComplete &= getJsonValue(top[F("pin")][i], newPin[i], ioPin[i]);
DEBUG_PRINT(FPSTR(F("BME280/BMP280"))); DEBUG_PRINT(FPSTR(_name));
if (!initDone) { if (!initDone) {
// first run: reading from cfg.json // first run: reading from cfg.json
for (byte i=0; i<2; i++) ioPin[i] = newPin[i]; for (byte i=0; i<2; i++) ioPin[i] = newPin[i];
@ -454,4 +472,7 @@ public:
uint16_t getId() { uint16_t getId() {
return USERMOD_ID_BME280; return USERMOD_ID_BME280;
} }
}; };
const char UsermodBME280::_name[] PROGMEM = "BME280/BMP280";
const char UsermodBME280::_enabled[] PROGMEM = "enabled";