2022-07-19 15:27:15 +02:00
// force the compiler to show a warning to confirm that this file is included
# warning **** Included USERMOD_BME280 version 2.0 ****
2020-12-25 21:17:30 +01:00
# pragma once
# include "wled.h"
# include <Arduino.h>
# include <Wire.h>
# include <BME280I2C.h> // BME280 sensor
# include <EnvironmentCalculations.h> // BME280 extended measurements
class UsermodBME280 : public Usermod
{
private :
2022-07-20 14:06:27 +02:00
// 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
// key settings set via usermod menu
unsigned long TemperatureDecimals = 0 ; // Number of decimal places in published temperaure values
unsigned long HumidityDecimals = 0 ; // Number of decimal places in published humidity values
unsigned long 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
unsigned long PressureInterval = 300 ; // Interval to measure pressure in seconds
bool PublishAlways = false ; // Publish values even when they have not changed
bool UseCelsius = true ; // Use Celsius for Reporting
bool HomeAssistantDiscovery = false ; // Publish Home Assistant Device Information
// set the default pins based on the architecture, these get overridden by Usermod menu settings
# ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
2022-07-21 10:48:37 +02:00
# define HW_PIN_SCL 22
# define HW_PIN_SDA 21
2022-07-20 14:06:27 +02:00
# else // ESP8266 boards
2022-07-21 10:48:37 +02:00
# define HW_PIN_SCL 5
# define HW_PIN_SDA 4
2022-07-20 14:06:27 +02:00
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
# endif
2022-07-21 10:48:37 +02:00
int8_t ioPin [ 2 ] = { HW_PIN_SCL , HW_PIN_SDA } ; // I2C pins: SCL, SDA...defaults to Arch hardware pins but overridden at setup()
bool initDone = false ;
2020-12-25 21:17:30 +01:00
// BME280 sensor settings
BME280I2C : : Settings settings {
BME280 : : OSR_X16 , // Temperature oversampling x16
BME280 : : OSR_X16 , // Humidity oversampling x16
BME280 : : OSR_X16 , // Pressure oversampling x16
// Defaults
BME280 : : Mode_Forced ,
BME280 : : StandbyTime_1000ms ,
BME280 : : Filter_Off ,
BME280 : : SpiEnable_False ,
BME280I2C : : I2CAddr_0x76 // I2C address. I2C specific. Default 0x76
} ;
BME280I2C bme { settings } ;
2021-04-12 10:31:59 +02:00
uint8_t sensorType ;
2020-12-25 21:17:30 +01:00
// Measurement timers
long timer ;
long lastTemperatureMeasure = 0 ;
long lastPressureMeasure = 0 ;
// Current sensor values
2021-04-12 10:31:59 +02:00
float sensorTemperature ;
float sensorHumidity ;
float sensorHeatIndex ;
float sensorDewPoint ;
float sensorPressure ;
2022-07-20 14:06:27 +02:00
String tempScale ;
2020-12-25 21:17:30 +01:00
// Track previous sensor values
float lastTemperature ;
float lastHumidity ;
float lastHeatIndex ;
float lastDewPoint ;
float lastPressure ;
2022-07-19 15:27:15 +02:00
// MQTT topic strings for publishing Home Assistant discovery topics
bool mqttInitialized = false ;
String mqttTemperatureTopic = " " ;
String mqttHumidityTopic = " " ;
String mqttPressureTopic = " " ;
String mqttHeatIndexTopic = " " ;
String mqttDewPointTopic = " " ;
2020-12-25 21:17:30 +01:00
// Store packet IDs of MQTT publications
uint16_t mqttTemperaturePub = 0 ;
uint16_t mqttPressurePub = 0 ;
2022-07-20 14:06:27 +02:00
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
2020-12-25 21:17:30 +01:00
void UpdateBME280Data ( int SensorType )
{
float _temperature , _humidity , _pressure ;
2022-07-20 14:06:27 +02:00
if ( UseCelsius ) {
2020-12-25 21:17:30 +01:00
BME280 : : TempUnit tempUnit ( BME280 : : TempUnit_Celsius ) ;
EnvironmentCalculations : : TempUnit envTempUnit ( EnvironmentCalculations : : TempUnit_Celsius ) ;
2022-07-20 14:06:27 +02:00
BME280 : : PresUnit presUnit ( BME280 : : PresUnit_hPa ) ;
bme . read ( _pressure , _temperature , _humidity , tempUnit , presUnit ) ;
sensorTemperature = _temperature ;
sensorHumidity = _humidity ;
sensorPressure = _pressure ;
tempScale = " °C " ;
if ( sensorType = = 1 )
{
sensorHeatIndex = EnvironmentCalculations : : HeatIndex ( _temperature , _humidity , envTempUnit ) ;
sensorDewPoint = EnvironmentCalculations : : DewPoint ( _temperature , _humidity , envTempUnit ) ;
}
} else {
2020-12-25 21:17:30 +01:00
BME280 : : TempUnit tempUnit ( BME280 : : TempUnit_Fahrenheit ) ;
EnvironmentCalculations : : TempUnit envTempUnit ( EnvironmentCalculations : : TempUnit_Fahrenheit ) ;
2022-07-20 14:06:27 +02:00
BME280 : : PresUnit presUnit ( BME280 : : PresUnit_hPa ) ;
2020-12-25 21:17:30 +01:00
2022-07-20 14:06:27 +02:00
bme . read ( _pressure , _temperature , _humidity , tempUnit , presUnit ) ;
2020-12-25 21:17:30 +01:00
2022-07-20 14:06:27 +02:00
sensorTemperature = _temperature ;
sensorHumidity = _humidity ;
sensorPressure = _pressure ;
tempScale = " °F " ;
if ( sensorType = = 1 )
{
sensorHeatIndex = EnvironmentCalculations : : HeatIndex ( _temperature , _humidity , envTempUnit ) ;
sensorDewPoint = EnvironmentCalculations : : DewPoint ( _temperature , _humidity , envTempUnit ) ;
}
2020-12-25 21:17:30 +01:00
}
}
2022-07-20 14:06:27 +02:00
// Procedure to define all MQTT discovery Topics
2022-07-19 15:27:15 +02:00
void _mqttInitialize ( )
{
2022-07-21 18:38:07 +02:00
mqttTemperatureTopic = String ( mqttDeviceTopic ) + F ( " /temperature " ) ;
mqttPressureTopic = String ( mqttDeviceTopic ) + F ( " /pressure " ) ;
mqttHumidityTopic = String ( mqttDeviceTopic ) + F ( " /humidity " ) ;
mqttHeatIndexTopic = String ( mqttDeviceTopic ) + F ( " /heat_index " ) ;
mqttDewPointTopic = String ( mqttDeviceTopic ) + F ( " /dew_point " ) ;
2022-07-19 15:27:15 +02:00
2022-07-20 14:06:27 +02:00
if ( HomeAssistantDiscovery ) {
2022-07-21 10:48:37 +02:00
_createMqttSensor ( F ( " Temperature " ) , mqttTemperatureTopic , F ( " temperature " ) , tempScale ) ;
_createMqttSensor ( F ( " Pressure " ) , mqttPressureTopic , F ( " pressure " ) , F ( " hPa " ) ) ;
_createMqttSensor ( F ( " Humidity " ) , mqttHumidityTopic , F ( " humidity " ) , F ( " % " ) ) ;
_createMqttSensor ( F ( " HeatIndex " ) , mqttHeatIndexTopic , F ( " temperature " ) , tempScale ) ;
_createMqttSensor ( F ( " DewPoint " ) , mqttDewPointTopic , F ( " temperature " ) , tempScale ) ;
2022-07-20 14:06:27 +02:00
}
2022-07-19 15:27:15 +02:00
}
// 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 )
{
2022-07-21 18:38:07 +02:00
String t = String ( F ( " homeassistant/sensor/ " ) ) + mqttClientID + F ( " / " ) + name + F ( " /config " ) ;
2022-07-19 15:27:15 +02:00
StaticJsonDocument < 600 > doc ;
2022-07-21 10:48:37 +02:00
doc [ F ( " name " ) ] = String ( serverDescription ) + " " + name ;
doc [ F ( " state_topic " ) ] = topic ;
doc [ F ( " unique_id " ) ] = String ( mqttClientID ) + name ;
2022-07-19 15:27:15 +02:00
if ( unitOfMeasurement ! = " " )
2022-07-21 10:48:37 +02:00
doc [ F ( " unit_of_measurement " ) ] = unitOfMeasurement ;
2022-07-19 15:27:15 +02:00
if ( deviceClass ! = " " )
2022-07-21 10:48:37 +02:00
doc [ F ( " device_class " ) ] = deviceClass ;
doc [ F ( " expire_after " ) ] = 1800 ;
2022-07-19 15:27:15 +02:00
2022-07-21 10:48:37 +02:00
JsonObject device = doc . createNestedObject ( F ( " device " ) ) ; // attach the sensor to the same device
device [ F ( " name " ) ] = serverDescription ;
device [ F ( " identifiers " ) ] = " wled-sensor- " + String ( mqttClientID ) ;
device [ F ( " manufacturer " ) ] = F ( " WLED " ) ;
device [ F ( " model " ) ] = F ( " FOSS " ) ;
device [ F ( " sw_version " ) ] = versionString ;
2022-07-19 15:27:15 +02:00
String temp ;
serializeJson ( doc , temp ) ;
2022-07-21 18:38:07 +02:00
DEBUG_PRINTLN ( t ) ;
DEBUG_PRINTLN ( temp ) ;
2022-07-19 15:27:15 +02:00
mqtt - > publish ( t . c_str ( ) , 0 , true , temp . c_str ( ) ) ;
}
2020-12-25 21:17:30 +01:00
public :
void setup ( )
{
2022-07-21 10:48:37 +02:00
bool HW_Pins_Used = ( ioPin [ 0 ] = = HW_PIN_SCL & & ioPin [ 1 ] = = HW_PIN_SDA ) ; // note whether architecture-based hardware SCL/SDA pins used
PinOwner po = PinOwner : : UM_BME280 ; // defaults to being pinowner for SCL/SDA pins
PinManagerPinType pins [ 2 ] = { { ioPin [ 0 ] , true } , { ioPin [ 1 ] , true } } ; // allocate pins
if ( HW_Pins_Used ) po = PinOwner : : HW_I2C ; // allow multiple allocations of HW I2C bus pins
if ( ! pinManager . allocateMultiplePins ( pins , 2 , po ) ) { sensorType = 0 ; return ; }
Wire . begin ( ioPin [ 1 ] , ioPin [ 0 ] ) ;
2020-12-25 21:17:30 +01:00
if ( ! bme . begin ( ) )
{
2021-04-12 10:31:59 +02:00
sensorType = 0 ;
2022-07-21 18:38:07 +02:00
DEBUG_PRINTLN ( F ( " Could not find BME280I2C sensor! " ) ) ;
2020-12-25 21:17:30 +01:00
}
else
{
switch ( bme . chipModel ( ) )
{
case BME280 : : ChipModel_BME280 :
2021-04-12 10:31:59 +02:00
sensorType = 1 ;
2022-07-21 18:38:07 +02:00
DEBUG_PRINTLN ( F ( " Found BME280 sensor! Success. " ) ) ;
2020-12-25 21:17:30 +01:00
break ;
case BME280 : : ChipModel_BMP280 :
2021-04-12 10:31:59 +02:00
sensorType = 2 ;
2022-07-21 18:38:07 +02:00
DEBUG_PRINTLN ( F ( " Found BMP280 sensor! No Humidity available. " ) ) ;
2020-12-25 21:17:30 +01:00
break ;
default :
2021-04-12 10:31:59 +02:00
sensorType = 0 ;
2022-07-21 18:38:07 +02:00
DEBUG_PRINTLN ( F ( " Found UNKNOWN sensor! Error! " ) ) ;
2020-12-25 21:17:30 +01:00
}
}
2022-07-21 10:48:37 +02:00
initDone = true ;
2020-12-25 21:17:30 +01:00
}
void loop ( )
{
// BME280 sensor MQTT publishing
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
2022-07-19 15:27:15 +02:00
if ( sensorType ! = 0 & & WLED_MQTT_CONNECTED )
2020-12-25 21:17:30 +01:00
{
// Timer to fetch new temperature, humidity and pressure data at intervals
timer = millis ( ) ;
if ( timer - lastTemperatureMeasure > = TemperatureInterval * 1000 | | mqttTemperaturePub = = 0 )
{
lastTemperatureMeasure = timer ;
2021-04-12 10:31:59 +02:00
UpdateBME280Data ( sensorType ) ;
2020-12-25 21:17:30 +01:00
2022-07-21 18:38:07 +02:00
float temperature = roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2021-04-12 10:31:59 +02:00
float humidity , heatIndex , dewPoint ;
2020-12-25 21:17:30 +01:00
2022-07-20 14:06:27 +02:00
if ( WLED_MQTT_CONNECTED & & ! mqttInitialized )
2022-07-19 15:27:15 +02:00
{
_mqttInitialize ( ) ;
mqttInitialized = true ;
}
2020-12-25 21:17:30 +01:00
// 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
2021-04-12 10:31:59 +02:00
if ( temperature ! = lastTemperature | | PublishAlways )
2020-12-25 21:17:30 +01:00
{
String topic = String ( mqttDeviceTopic ) + " /temperature " ;
2021-04-12 10:31:59 +02:00
mqttTemperaturePub = mqtt - > publish ( topic . c_str ( ) , 0 , false , String ( temperature , TemperatureDecimals ) . c_str ( ) ) ;
2020-12-25 21:17:30 +01:00
}
2021-04-12 10:31:59 +02:00
lastTemperature = temperature ; // Update last sensor temperature for next loop
2020-12-25 21:17:30 +01:00
2021-04-12 10:31:59 +02:00
if ( sensorType = = 1 ) // Only if sensor is a BME280
2020-12-25 21:17:30 +01:00
{
2022-07-21 18:38:07 +02:00
humidity = roundf ( sensorHumidity * powf ( 10 , HumidityDecimals ) ) / powf ( 10 , HumidityDecimals ) ;
heatIndex = roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
dewPoint = roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2020-12-25 21:17:30 +01:00
2021-04-12 10:31:59 +02:00
if ( humidity ! = lastHumidity | | PublishAlways )
2020-12-25 21:17:30 +01:00
{
2022-07-21 18:38:07 +02:00
String topic = String ( mqttDeviceTopic ) + F ( " /humidity " ) ;
2021-04-12 10:31:59 +02:00
mqtt - > publish ( topic . c_str ( ) , 0 , false , String ( humidity , HumidityDecimals ) . c_str ( ) ) ;
2020-12-25 21:17:30 +01:00
}
2021-04-12 10:31:59 +02:00
if ( heatIndex ! = lastHeatIndex | | PublishAlways )
2020-12-25 21:17:30 +01:00
{
2022-07-21 18:38:07 +02:00
String topic = String ( mqttDeviceTopic ) + F ( " /heat_index " ) ;
2021-04-12 10:31:59 +02:00
mqtt - > publish ( topic . c_str ( ) , 0 , false , String ( heatIndex , TemperatureDecimals ) . c_str ( ) ) ;
2020-12-25 21:17:30 +01:00
}
2021-04-12 10:31:59 +02:00
if ( dewPoint ! = lastDewPoint | | PublishAlways )
2020-12-25 21:17:30 +01:00
{
2022-07-21 18:38:07 +02:00
String topic = String ( mqttDeviceTopic ) + F ( " /dew_point " ) ;
2021-04-12 10:31:59 +02:00
mqtt - > publish ( topic . c_str ( ) , 0 , false , String ( dewPoint , TemperatureDecimals ) . c_str ( ) ) ;
2020-12-25 21:17:30 +01:00
}
2021-04-12 10:31:59 +02:00
lastHumidity = humidity ;
lastHeatIndex = heatIndex ;
lastDewPoint = dewPoint ;
2020-12-25 21:17:30 +01:00
}
}
if ( timer - lastPressureMeasure > = PressureInterval * 1000 | | mqttPressurePub = = 0 )
{
lastPressureMeasure = timer ;
2022-07-21 18:38:07 +02:00
float pressure = roundf ( sensorPressure * powf ( 10 , PressureDecimals ) ) / powf ( 10 , PressureDecimals ) ;
2020-12-25 21:17:30 +01:00
2021-04-12 10:31:59 +02:00
if ( pressure ! = lastPressure | | PublishAlways )
2020-12-25 21:17:30 +01:00
{
2022-07-21 18:38:07 +02:00
String topic = String ( mqttDeviceTopic ) + F ( " /pressure " ) ;
2021-04-12 10:31:59 +02:00
mqttPressurePub = mqtt - > publish ( topic . c_str ( ) , 0 , true , String ( pressure , PressureDecimals ) . c_str ( ) ) ;
2020-12-25 21:17:30 +01:00
}
2021-04-12 10:31:59 +02:00
lastPressure = pressure ;
2020-12-25 21:17:30 +01:00
}
}
}
2022-07-19 22:47:56 +02:00
/*
* API calls te enable data exchange between WLED modules
*/
inline float getTemperatureC ( ) {
2022-07-20 14:06:27 +02:00
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) * 1.8f + 32 ;
2022-07-20 14:06:27 +02:00
}
2022-07-19 22:47:56 +02:00
}
inline float getTemperatureF ( ) {
2022-07-20 14:06:27 +02:00
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( ( float ) roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) - 32 ) * 0.56f ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
}
2022-07-19 22:47:56 +02:00
}
inline float getHumidity ( ) {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorHumidity * powf ( 10 , HumidityDecimals ) ) ;
2022-07-19 22:47:56 +02:00
}
inline float getPressure ( ) {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorPressure * powf ( 10 , PressureDecimals ) ) ;
2022-07-19 22:47:56 +02:00
}
2022-07-20 14:06:27 +02:00
inline float getDewPointC ( ) {
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) * 1.8f + 32 ;
2022-07-20 14:06:27 +02:00
}
}
inline float getDewPointF ( ) {
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( ( float ) roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) - 32 ) * 0.56f ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
}
2022-07-19 22:47:56 +02:00
}
2022-07-20 14:06:27 +02:00
inline float getHeatIndexC ( ) {
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) * 1.8f + 32 ;
2022-07-20 14:06:27 +02:00
}
} inline float getHeatIndexF ( ) {
if ( UseCelsius ) {
2022-07-21 18:38:07 +02:00
return ( ( float ) roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) - 32 ) * 0.56f ;
2022-07-20 14:06:27 +02:00
} else {
2022-07-21 18:38:07 +02:00
return ( float ) roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ;
2022-07-20 14:06:27 +02:00
}
2022-07-19 22:47:56 +02:00
}
2022-07-19 15:27:15 +02:00
// Publish Sensor Information to Info Page
void addToJsonInfo ( JsonObject & root )
{
JsonObject user = root [ F ( " u " ) ] ;
2022-07-19 22:47:56 +02:00
if ( user . isNull ( ) ) user = root . createNestedObject ( F ( " u " ) ) ;
2022-07-19 15:27:15 +02:00
if ( sensorType = = 0 ) //No Sensor
{
// if we sensor not detected, let the user know
2022-07-21 10:48:37 +02:00
JsonArray temperature_json = user . createNestedArray ( F ( " BME/BMP280 Sensor " ) ) ;
2022-07-19 15:27:15 +02:00
temperature_json . add ( F ( " Not Found " ) ) ;
}
else if ( sensorType = = 2 ) //BMP280
{
2022-07-21 18:38:07 +02:00
JsonArray temperature_json = user . createNestedArray ( F ( " Temperature " ) ) ;
JsonArray pressure_json = user . createNestedArray ( F ( " Pressure " ) ) ;
temperature_json . add ( roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) ) ;
2022-07-20 14:06:27 +02:00
temperature_json . add ( tempScale ) ;
2022-07-21 18:38:07 +02:00
pressure_json . add ( roundf ( sensorPressure * powf ( 10 , PressureDecimals ) ) ) ;
2022-07-19 23:15:26 +02:00
pressure_json . add ( F ( " hPa " ) ) ;
2022-07-19 15:27:15 +02:00
}
else if ( sensorType = = 1 ) //BME280
{
2022-07-21 18:38:07 +02:00
JsonArray temperature_json = user . createNestedArray ( F ( " Temperature " ) ) ;
JsonArray humidity_json = user . createNestedArray ( F ( " Humidity " ) ) ;
JsonArray pressure_json = user . createNestedArray ( F ( " Pressure " ) ) ;
JsonArray heatindex_json = user . createNestedArray ( F ( " Heat Index " ) ) ;
JsonArray dewpoint_json = user . createNestedArray ( F ( " Dew Point " ) ) ;
temperature_json . add ( roundf ( sensorTemperature * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ) ;
2022-07-20 14:06:27 +02:00
temperature_json . add ( tempScale ) ;
2022-07-21 18:38:07 +02:00
humidity_json . add ( roundf ( sensorHumidity * powf ( 10 , HumidityDecimals ) ) ) ;
2022-07-19 15:27:15 +02:00
humidity_json . add ( F ( " % " ) ) ;
2022-07-21 18:38:07 +02:00
pressure_json . add ( roundf ( sensorPressure * powf ( 10 , PressureDecimals ) ) ) ;
2022-07-19 22:47:56 +02:00
pressure_json . add ( F ( " hPa " ) ) ;
2022-07-21 18:38:07 +02:00
heatindex_json . add ( roundf ( sensorHeatIndex * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ) ;
2022-07-20 14:06:27 +02:00
heatindex_json . add ( tempScale ) ;
2022-07-21 18:38:07 +02:00
dewpoint_json . add ( roundf ( sensorDewPoint * powf ( 10 , TemperatureDecimals ) ) / powf ( 10 , TemperatureDecimals ) ) ;
2022-07-20 14:06:27 +02:00
dewpoint_json . add ( tempScale ) ;
2022-07-19 15:27:15 +02:00
}
return ;
}
// Save Usermod Config Settings
void addToConfig ( JsonObject & root )
{
2022-07-21 10:48:37 +02:00
JsonObject top = root . createNestedObject ( F ( " BME280/BMP280 " ) ) ;
top [ F ( " TemperatureDecimals " ) ] = TemperatureDecimals ;
top [ F ( " HumidityDecimals " ) ] = HumidityDecimals ;
top [ F ( " PressureDecimals " ) ] = PressureDecimals ;
top [ F ( " TemperatureInterval " ) ] = TemperatureInterval ;
top [ F ( " PressureInterval " ) ] = PressureInterval ;
top [ F ( " PublishAlways " ) ] = PublishAlways ;
top [ F ( " UseCelsius " ) ] = UseCelsius ;
top [ F ( " HomeAssistantDiscovery " ) ] = HomeAssistantDiscovery ;
JsonArray io_pin = top . createNestedArray ( F ( " pin " ) ) ;
for ( byte i = 0 ; i < 2 ; i + + ) io_pin . add ( ioPin [ i ] ) ;
top [ F ( " help4Pins " ) ] = F ( " SCL,SDA " ) ; // help for Settings page
DEBUG_PRINTLN ( F ( " BME280 config saved. " ) ) ;
2022-07-19 15:27:15 +02:00
}
// 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)
2022-07-21 10:48:37 +02:00
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 " ) ] ;
if ( top . isNull ( ) ) {
DEBUG_PRINT ( F ( " BME280/BMP280 " ) ) ;
DEBUG_PRINTLN ( F ( " : No config found. (Using defaults.) " ) ) ;
return false ;
}
2022-07-19 15:27:15 +02:00
bool configComplete = ! top . isNull ( ) ;
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
2022-07-21 10:48:37 +02:00
configComplete & = getJsonValue ( top [ F ( " TemperatureDecimals " ) ] , TemperatureDecimals , 1 ) ;
configComplete & = getJsonValue ( top [ F ( " HumidityDecimals " ) ] , HumidityDecimals , 0 ) ;
configComplete & = getJsonValue ( top [ F ( " PressureDecimals " ) ] , PressureDecimals , 0 ) ;
configComplete & = getJsonValue ( top [ F ( " TemperatureInterval " ) ] , TemperatureInterval , 30 ) ;
configComplete & = getJsonValue ( top [ F ( " PressureInterval " ) ] , PressureInterval , 30 ) ;
configComplete & = getJsonValue ( top [ F ( " PublishAlways " ) ] , PublishAlways , false ) ;
configComplete & = getJsonValue ( top [ F ( " UseCelsius " ) ] , UseCelsius , true ) ;
configComplete & = getJsonValue ( top [ F ( " HomeAssistantDiscovery " ) ] , HomeAssistantDiscovery , false ) ;
for ( byte i = 0 ; i < 2 ; i + + ) configComplete & = getJsonValue ( top [ F ( " pin " ) ] [ i ] , newPin [ i ] , ioPin [ i ] ) ;
DEBUG_PRINT ( FPSTR ( F ( " BME280/BMP280 " ) ) ) ;
if ( ! initDone ) {
// first run: reading from cfg.json
for ( byte i = 0 ; i < 2 ; i + + ) ioPin [ i ] = newPin [ i ] ;
DEBUG_PRINTLN ( F ( " config loaded. " ) ) ;
} else {
DEBUG_PRINTLN ( F ( " config (re)loaded. " ) ) ;
// changing parameters from settings page
bool pinsChanged = false ;
for ( byte i = 0 ; i < 2 ; i + + ) if ( ioPin [ i ] ! = newPin [ i ] ) { pinsChanged = true ; break ; } // check if any pins changed
if ( pinsChanged ) { //if pins changed, deallocate old pins and allocate new ones
PinOwner po = PinOwner : : UM_BME280 ;
if ( ioPin [ 0 ] = = HW_PIN_SCL & & ioPin [ 1 ] = = HW_PIN_SDA ) po = PinOwner : : HW_I2C ; // allow multiple allocations of HW I2C bus pins
pinManager . deallocateMultiplePins ( ( const uint8_t * ) ioPin , 2 , po ) ; // deallocate pins
for ( byte i = 0 ; i < 2 ; i + + ) ioPin [ i ] = newPin [ i ] ;
setup ( ) ;
}
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return ! top [ F ( " pin " ) ] . isNull ( ) ;
}
2022-07-19 15:27:15 +02:00
return configComplete ;
}
2022-07-21 10:48:37 +02:00
uint16_t getId ( ) {
return USERMOD_ID_BME280 ;
}
2020-12-25 21:17:30 +01:00
} ;