BH1750 upgrades (#2725)
* BH1750 upgrades Moved the definitions into the main usermods_list.cpp instead of having a section to copy across. Added Home Assistant Discovery topic for light sensor. This is toggleable from the usermod menu. * Configure pin, other enhancements, readme Implemented pin manager Made pins configurable at runtime Improved info screen outputs Added F() around strings Updated readme * Resolve conflict * Merge branch 'main' * Missing comma Co-authored-by: Christian Schwinne <dev.aircoookie@gmail.com> Co-authored-by: Christian Schwinne <cschwinne@gmail.com>
This commit is contained in:
parent
7cac609c06
commit
30a029c19f
@ -1,16 +0,0 @@
|
||||
; Options
|
||||
; -------
|
||||
; USERMOD_BH1750 - define this to have this user mod included wled00\usermods_list.cpp
|
||||
; USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL - the max number of milliseconds between measurements, defaults to 10000ms
|
||||
; USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL - the min number of milliseconds between measurements, defaults to 500ms
|
||||
; USERMOD_BH1750_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 10 seconds
|
||||
; USERMOD_BH1750_OFFSET_VALUE - the offset value to report on, defaults to 1
|
||||
;
|
||||
[env:usermod_BH1750_d1_mini]
|
||||
extends = env:d1_mini
|
||||
build_flags =
|
||||
${common.build_flags_esp8266}
|
||||
-D USERMOD_BH1750
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
claws/BH1750 @ ^1.2.0
|
@ -3,22 +3,47 @@
|
||||
This usermod will read from an ambient light sensor like the BH1750 sensor.
|
||||
The luminance is displayed both in the Info section of the web UI as well as published to the `/luminance` MQTT topic if enabled.
|
||||
|
||||
## Installation
|
||||
## Dependencies
|
||||
- Libraries
|
||||
- `claws/BH1750 @^1.2.0`
|
||||
- This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`).
|
||||
- Data is published over MQTT - make sure you've enabled the MQTT sync interface.
|
||||
|
||||
Copy the example `platformio_override.ini` to the root directory. This file should be placed in the same directory as `platformio.ini`.
|
||||
## Compiliation
|
||||
|
||||
### Define Your Options
|
||||
To enable, compile with `USERMOD_BH1750` defined (e.g. in `platformio_override.ini`)
|
||||
```ini
|
||||
[env:usermod_BH1750_d1_mini]
|
||||
extends = env:d1_mini
|
||||
build_flags =
|
||||
${common.build_flags_esp8266}
|
||||
-D USERMOD_BH1750
|
||||
lib_deps =
|
||||
${esp8266.lib_deps}
|
||||
claws/BH1750 @ ^1.2.0
|
||||
```
|
||||
|
||||
* `USERMOD_BH1750` - define this to have this user mod included wled00\usermods_list.cpp
|
||||
### Configuration Options
|
||||
The following settings can be set at compile-time but are configurable on the usermod menu (except First Measurement time):
|
||||
* `USERMOD_BH1750_MAX_MEASUREMENT_INTERVAL` - the max number of milliseconds between measurements, defaults to 10000ms
|
||||
* `USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL` - the min number of milliseconds between measurements, defaults to 500ms
|
||||
* `USERMOD_BH1750_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 10 seconds
|
||||
* `USERMOD_BH1750_OFFSET_VALUE` - the offset value to report on, defaults to 1
|
||||
* `USERMOD_BH1750_FIRST_MEASUREMENT_AT` - the number of milliseconds after boot to take first measurement, defaults to 10 seconds
|
||||
|
||||
All parameters can be configured at runtime using Usermods settings page.
|
||||
In addition, on the Usermod screen allows you to:
|
||||
- enable/disable the usermod
|
||||
- Enable Home Assistant Discovery of usermod
|
||||
- Configure the SCL/SDA pins
|
||||
|
||||
### PlatformIO requirements
|
||||
|
||||
If you are using `platformio_override.ini`, you should be able to refresh the task list and see your custom task, for example `env:usermod_BH1750_d1_mini`.
|
||||
## API
|
||||
The following method is available to interact with the usermod from other code modules:
|
||||
- `getIlluminance` read the brightness from the sensor
|
||||
|
||||
## Change Log
|
||||
Jul 2022
|
||||
- Added Home Assistant Discovery
|
||||
- Implemented PinManager to register pins
|
||||
- Made pins configurable in usermod menu
|
||||
- Added API call to read illuminance from other modules
|
||||
- Enhanced info-screen outputs
|
||||
- Updated `readme.md`
|
@ -1,3 +1,6 @@
|
||||
// force the compiler to show a warning to confirm that this file is included
|
||||
#warning **** Included USERMOD_BH1750 ****
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
@ -47,6 +50,24 @@ private:
|
||||
static const char _maxReadInterval[];
|
||||
static const char _minReadInterval[];
|
||||
static const char _offset[];
|
||||
static const char _HomeAssistantDiscovery[];
|
||||
|
||||
// set the default pins based on the architecture, these get overridden by Usermod menu settings
|
||||
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
||||
#define HW_PIN_SCL 22
|
||||
#define HW_PIN_SDA 21
|
||||
#else // ESP8266 boards
|
||||
#define HW_PIN_SCL 5
|
||||
#define HW_PIN_SDA 4
|
||||
#endif
|
||||
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;
|
||||
bool sensorFound = false;
|
||||
|
||||
// Home Assistant and MQTT
|
||||
String mqttLuminanceTopic = F("");
|
||||
bool mqttInitialized = false;
|
||||
bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages
|
||||
|
||||
BH1750 lightMeter;
|
||||
float lastLux = -1000;
|
||||
@ -56,11 +77,58 @@ private:
|
||||
return isnan(prevValue) || newValue <= prevValue - maxDiff || newValue >= prevValue + maxDiff || (newValue == 0.0 && prevValue > 0.0);
|
||||
}
|
||||
|
||||
// set up Home Assistant discovery entries
|
||||
void _mqttInitialize()
|
||||
{
|
||||
mqttLuminanceTopic = String(mqttDeviceTopic) + F("/brightness");
|
||||
|
||||
if (HomeAssistantDiscovery) _createMqttSensor(F("Brightness"), mqttLuminanceTopic, F("Illuminance"), F(" lx"));
|
||||
}
|
||||
|
||||
// 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(F("homeassistant/sensor/")) + mqttClientID + F("/") + name + F("/config");
|
||||
|
||||
StaticJsonDocument<600> doc;
|
||||
|
||||
doc[F("name")] = String(serverDescription) + F(" ") + name;
|
||||
doc[F("state_topic")] = topic;
|
||||
doc[F("unique_id")] = String(mqttClientID) + name;
|
||||
if (unitOfMeasurement != "")
|
||||
doc[F("unit_of_measurement")] = unitOfMeasurement;
|
||||
if (deviceClass != "")
|
||||
doc[F("device_class")] = deviceClass;
|
||||
doc[F("expire_after")] = 1800;
|
||||
|
||||
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;
|
||||
|
||||
String temp;
|
||||
serializeJson(doc, temp);
|
||||
DEBUG_PRINTLN(t);
|
||||
DEBUG_PRINTLN(temp);
|
||||
|
||||
mqtt->publish(t.c_str(), 0, true, temp.c_str());
|
||||
}
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
Wire.begin();
|
||||
lightMeter.begin();
|
||||
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_BH1750; // 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)) return;
|
||||
|
||||
Wire.begin(ioPin[1], ioPin[0]);
|
||||
|
||||
sensorFound = lightMeter.begin();
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
void loop()
|
||||
@ -90,18 +158,25 @@ public:
|
||||
lastSend = millis();
|
||||
if (WLED_MQTT_CONNECTED)
|
||||
{
|
||||
char subuf[45];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat_P(subuf, PSTR("/luminance"));
|
||||
mqtt->publish(subuf, 0, true, String(lux).c_str());
|
||||
if (!mqttInitialized)
|
||||
{
|
||||
_mqttInitialize();
|
||||
mqttInitialized = true;
|
||||
}
|
||||
mqtt->publish(mqttLuminanceTopic.c_str(), 0, true, String(lux).c_str());
|
||||
DEBUG_PRINTLN(F("Brightness: ") + String(lux) + F("lx"));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINTLN("Missing MQTT connection. Not publishing data");
|
||||
DEBUG_PRINTLN(F("Missing MQTT connection. Not publishing data"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline float getIlluminance() {
|
||||
return (float)lastLux;
|
||||
}
|
||||
|
||||
void addToJsonInfo(JsonObject &root)
|
||||
{
|
||||
JsonObject user = root[F("u")];
|
||||
@ -109,28 +184,23 @@ public:
|
||||
user = root.createNestedObject(F("u"));
|
||||
|
||||
JsonArray lux_json = user.createNestedArray(F("Luminance"));
|
||||
|
||||
if (!getLuminanceComplete)
|
||||
{
|
||||
if (!sensorFound) {
|
||||
// if no sensor
|
||||
lux_json.add(F("BH1750 "));
|
||||
lux_json.add(F("Not Found"));
|
||||
} else if (!getLuminanceComplete) {
|
||||
// if we haven't read the sensor yet, let the user know
|
||||
// that we are still waiting for the first measurement
|
||||
lux_json.add((USERMOD_BH1750_FIRST_MEASUREMENT_AT - millis()) / 1000);
|
||||
lux_json.add(F(" sec until read"));
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
lux_json.add(lastLux);
|
||||
lux_json.add(F(" lx"));
|
||||
}
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_BH1750;
|
||||
}
|
||||
|
||||
/**
|
||||
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
||||
*/
|
||||
// (called from set.cpp) stores persistent properties to cfg.json
|
||||
void addToConfig(JsonObject &root)
|
||||
{
|
||||
// we add JSON object.
|
||||
@ -138,35 +208,68 @@ public:
|
||||
top[FPSTR(_enabled)] = !disabled;
|
||||
top[FPSTR(_maxReadInterval)] = maxReadingInterval;
|
||||
top[FPSTR(_minReadInterval)] = minReadingInterval;
|
||||
top[FPSTR(_HomeAssistantDiscovery)] = HomeAssistantDiscovery;
|
||||
top[FPSTR(_offset)] = offset;
|
||||
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("Photoresistor config saved."));
|
||||
DEBUG_PRINTLN(F("BH1750 config saved."));
|
||||
}
|
||||
|
||||
/**
|
||||
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
||||
*/
|
||||
// called before setup() to populate properties from values stored in cfg.json
|
||||
bool readFromConfig(JsonObject &root)
|
||||
{
|
||||
int8_t newPin[2]; for (byte i=0; i<2; i++) newPin[i] = ioPin[i]; // prepare to note changed pins
|
||||
|
||||
// we look for JSON object.
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
if (top.isNull())
|
||||
{
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
DEBUG_PRINT(F("BH1750"));
|
||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||
return false;
|
||||
}
|
||||
bool configComplete = !top.isNull();
|
||||
|
||||
configComplete &= getJsonValue(top[FPSTR(_enabled)], disabled, false);
|
||||
configComplete &= getJsonValue(top[FPSTR(_maxReadInterval)], maxReadingInterval, 10000); //ms
|
||||
configComplete &= getJsonValue(top[FPSTR(_minReadInterval)], minReadingInterval, 500); //ms
|
||||
configComplete &= getJsonValue(top[FPSTR(_HomeAssistantDiscovery)], HomeAssistantDiscovery, false);
|
||||
configComplete &= getJsonValue(top[FPSTR(_offset)], offset, 1);
|
||||
for (byte i=0; i<2; i++) configComplete &= getJsonValue(top[F("pin")][i], newPin[i], ioPin[i]);
|
||||
|
||||
disabled = !(top[FPSTR(_enabled)] | !disabled);
|
||||
maxReadingInterval = (top[FPSTR(_maxReadInterval)] | maxReadingInterval); // ms
|
||||
minReadingInterval = (top[FPSTR(_minReadInterval)] | minReadingInterval); // ms
|
||||
offset = top[FPSTR(_offset)] | offset;
|
||||
DEBUG_PRINT(FPSTR(_name));
|
||||
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."));
|
||||
|
||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||
return true;
|
||||
// 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_BH1750;
|
||||
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();
|
||||
}
|
||||
|
||||
return configComplete;
|
||||
|
||||
}
|
||||
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_BH1750;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// strings to reduce flash memory usage (used more than twice)
|
||||
@ -174,4 +277,5 @@ const char Usermod_BH1750::_name[] PROGMEM = "BH1750";
|
||||
const char Usermod_BH1750::_enabled[] PROGMEM = "enabled";
|
||||
const char Usermod_BH1750::_maxReadInterval[] PROGMEM = "max-read-interval-ms";
|
||||
const char Usermod_BH1750::_minReadInterval[] PROGMEM = "min-read-interval-ms";
|
||||
const char Usermod_BH1750::_HomeAssistantDiscovery[] PROGMEM = "HomeAssistantDiscoveryLux";
|
||||
const char Usermod_BH1750::_offset[] PROGMEM = "offset-lx";
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* Register your v2 usermods here!
|
||||
*/
|
||||
#ifdef USERMOD_BH1750
|
||||
#include "../usermods/BH1750_v2/usermod_BH1750.h"
|
||||
#endif
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
#ifdef USERMOD_BH1750
|
||||
usermods.add(new Usermod_BH1750());
|
||||
#endif
|
||||
}
|
@ -56,6 +56,7 @@ enum struct PinOwner : uint8_t {
|
||||
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
||||
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA, // 0x17 // Usermod "quinled-an-penta.h"
|
||||
UM_BME280 = USERMOD_ID_BME280, // 0x18 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||
UM_BH1750 = USERMOD_ID_BH1750, // 0x19 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE // 0x1E // Usermod "audio_reactive.h"
|
||||
};
|
||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||
|
@ -30,9 +30,11 @@
|
||||
#ifdef USERMOD_BUZZER
|
||||
#include "../usermods/buzzer/usermod_v2_buzzer.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SENSORSTOMQTT
|
||||
#include "../usermods/sensors_to_mqtt/usermod_v2_SensorsToMqtt.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PIRSWITCH
|
||||
#include "../usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h"
|
||||
#endif
|
||||
@ -41,10 +43,15 @@
|
||||
#include "../usermods/usermod_v2_mode_sort/usermod_v2_mode_sort.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BH1750
|
||||
#include "../usermods/BH1750_v2/usermod_BH1750.h"
|
||||
#endif
|
||||
|
||||
// BME280 v2 usermod. Define "USERMOD_BME280" in my_config.h
|
||||
#ifdef USERMOD_BME280
|
||||
#include "../usermods/BME280_v2/usermod_bme280.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
#ifdef USE_ALT_DISPlAY
|
||||
#include "../usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h"
|
||||
@ -52,6 +59,7 @@
|
||||
#include "../usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ROTARY_ENCODER_UI
|
||||
#ifdef USE_ALT_DISPlAY
|
||||
#include "../usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h"
|
||||
@ -59,6 +67,7 @@
|
||||
#include "../usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUTO_SAVE
|
||||
#include "../usermods/usermod_v2_auto_save/usermod_v2_auto_save.h"
|
||||
#endif
|
||||
@ -159,7 +168,6 @@ void registerUsermods()
|
||||
* \/ \/ \/
|
||||
*/
|
||||
//usermods.add(new MyExampleUsermod());
|
||||
|
||||
#ifdef USERMOD_BATTERY_STATUS_BASIC
|
||||
usermods.add(new UsermodBatteryBasic());
|
||||
#endif
|
||||
@ -180,12 +188,18 @@ void registerUsermods()
|
||||
usermods.add(new BuzzerUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BH1750
|
||||
usermods.add(new Usermod_BH1750());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BME280
|
||||
usermods.add(new UsermodBME280());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SENSORSTOMQTT
|
||||
usermods.add(new UserMod_SensorsToMQTT());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PIRSWITCH
|
||||
usermods.add(new PIRsensorSwitch());
|
||||
#endif
|
||||
@ -193,12 +207,15 @@ void registerUsermods()
|
||||
#ifdef USERMOD_MODE_SORT
|
||||
usermods.add(new ModeSortUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||
usermods.add(new FourLineDisplayUsermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_ROTARY_ENCODER_UI
|
||||
usermods.add(new RotaryEncoderUIUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_AUTO_SAVE
|
||||
usermods.add(new AutoSaveUsermod()); // can use USERMOD_FOUR_LINE_DISPLAY
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user