mirror of
https://github.com/wled/WLED.git
synced 2025-04-25 23:37:18 +00:00
Address comments
This commit is contained in:
parent
68f6b3452e
commit
f71d839009
@ -94,6 +94,9 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
|
|||||||
; -D USERMOD_AUTO_SAVE
|
; -D USERMOD_AUTO_SAVE
|
||||||
; -D AUTOSAVE_AFTER_SEC=90
|
; -D AUTOSAVE_AFTER_SEC=90
|
||||||
;
|
;
|
||||||
|
; Use AHT10/AHT15/AHT20 usermod
|
||||||
|
; -D USERMOD_AHT10
|
||||||
|
;
|
||||||
; Use 4 Line Display usermod with SPI display
|
; Use 4 Line Display usermod with SPI display
|
||||||
; -D USERMOD_FOUR_LINE_DISPLAY
|
; -D USERMOD_FOUR_LINE_DISPLAY
|
||||||
; -D USE_ALT_DISPlAY # mandatory
|
; -D USE_ALT_DISPlAY # mandatory
|
||||||
|
@ -17,6 +17,9 @@ Dependencies, These must be added under `lib_deps` in your `platform.ini` (or `p
|
|||||||
- `enjoyneering/AHT10@~1.1.0` (by [enjoyneering](https://registry.platformio.org/libraries/enjoyneering/AHT10))
|
- `enjoyneering/AHT10@~1.1.0` (by [enjoyneering](https://registry.platformio.org/libraries/enjoyneering/AHT10))
|
||||||
- `Wire`
|
- `Wire`
|
||||||
|
|
||||||
|
## Author
|
||||||
|
[@LordMike](https://github.com/LordMike)
|
||||||
|
|
||||||
# Compiling
|
# Compiling
|
||||||
|
|
||||||
To enable, compile with `USERMOD_AHT10` defined (e.g. in `platformio_override.ini`)
|
To enable, compile with `USERMOD_AHT10` defined (e.g. in `platformio_override.ini`)
|
||||||
|
@ -5,197 +5,209 @@
|
|||||||
|
|
||||||
#define AHT10_SUCCESS 1
|
#define AHT10_SUCCESS 1
|
||||||
|
|
||||||
class UsermodAHT10 : public Usermod {
|
class UsermodAHT10 : public Usermod
|
||||||
private:
|
{
|
||||||
static const char _name[];
|
private:
|
||||||
|
static const char _name[];
|
||||||
|
|
||||||
unsigned long _lastLoopCheck = 0;
|
unsigned long _lastLoopCheck = 0;
|
||||||
bool _initDone = false;
|
bool _initDone = false;
|
||||||
|
|
||||||
// Settings. Some of these are stored in a different format than they're user settings - so we don't have to convert at runtime
|
// Settings. Some of these are stored in a different format than they're user settings - so we don't have to convert at runtime
|
||||||
bool _enabled = false;
|
bool _enabled = false;
|
||||||
uint8_t _i2cAddress = AHT10_ADDRESS_0X38;
|
uint8_t _i2cAddress = AHT10_ADDRESS_0X38;
|
||||||
ASAIR_I2C_SENSOR _ahtType = AHT10_SENSOR;
|
ASAIR_I2C_SENSOR _ahtType = AHT10_SENSOR;
|
||||||
uint16_t _checkInterval = 60000; // milliseconds, user settings is in seconds
|
uint16_t _checkInterval = 60000; // milliseconds, user settings is in seconds
|
||||||
float _decimalFactor = 100; // a power of 10 factor. 1 would be no change, 10 is one decimal, 100 is two etc. User sees a power of 10 (0, 1, 2, ..)
|
float _decimalFactor = 100; // a power of 10 factor. 1 would be no change, 10 is one decimal, 100 is two etc. User sees a power of 10 (0, 1, 2, ..)
|
||||||
|
|
||||||
uint8_t _lastStatus = 0;
|
uint8_t _lastStatus = 0;
|
||||||
float _lastHumidity = 0;
|
float _lastHumidity = 0;
|
||||||
float _lastTemperature = 0;
|
float _lastTemperature = 0;
|
||||||
|
|
||||||
AHT10* _aht = nullptr;
|
AHT10* _aht = nullptr;
|
||||||
|
|
||||||
float truncateDecimals(float val) {
|
float truncateDecimals(float val)
|
||||||
return roundf(val * _decimalFactor) / _decimalFactor;
|
{
|
||||||
|
return roundf(val * _decimalFactor) / _decimalFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeAht()
|
||||||
|
{
|
||||||
|
if (_aht != nullptr)
|
||||||
|
{
|
||||||
|
delete _aht;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeAht() {
|
_aht = new AHT10(_i2cAddress, _ahtType);
|
||||||
if (_aht != nullptr) {
|
|
||||||
delete _aht;
|
_lastStatus = 0;
|
||||||
|
_lastHumidity = 0;
|
||||||
|
_lastTemperature = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~UsermodAHT10()
|
||||||
|
{
|
||||||
|
delete _aht;
|
||||||
|
_aht = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
initializeAht();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// if usermod is disabled or called during strip updating just exit
|
||||||
|
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
||||||
|
if (!_enabled || strip.isUpdating())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// do your magic here
|
||||||
|
unsigned long currentTime = millis();
|
||||||
|
|
||||||
|
if (currentTime - _lastLoopCheck < _checkInterval)
|
||||||
|
return;
|
||||||
|
_lastLoopCheck = currentTime;
|
||||||
|
|
||||||
|
_lastStatus = _aht->readRawData();
|
||||||
|
|
||||||
|
if (_lastStatus == AHT10_ERROR)
|
||||||
|
{
|
||||||
|
// Perform softReset and retry
|
||||||
|
DEBUG_PRINTLN("AHTxx returned error, doing softReset");
|
||||||
|
if (!_aht->softReset())
|
||||||
|
{
|
||||||
|
DEBUG_PRINTLN("softReset failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_aht = new AHT10(_i2cAddress, _ahtType);
|
_lastStatus = _aht->readRawData();
|
||||||
|
|
||||||
_lastStatus = 0;
|
|
||||||
_lastHumidity = 0;
|
|
||||||
_lastTemperature = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~UsermodAHT10() {
|
if (_lastStatus == AHT10_SUCCESS)
|
||||||
delete _aht;
|
{
|
||||||
_aht = nullptr;
|
float temperature = truncateDecimals(_aht->readTemperature(AHT10_USE_READ_DATA));
|
||||||
|
float humidity = truncateDecimals(_aht->readHumidity(AHT10_USE_READ_DATA));
|
||||||
|
|
||||||
|
// Push to MQTT
|
||||||
|
|
||||||
|
// Store
|
||||||
|
_lastHumidity = humidity;
|
||||||
|
_lastTemperature = temperature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_AHT10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToJsonInfo(JsonObject& root) override
|
||||||
|
{
|
||||||
|
// if "u" object does not exist yet wee need to create it
|
||||||
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
#ifdef USERMOD_AHT10_DEBUG
|
||||||
|
JsonArray temp = user.createNestedArray(F("status"));
|
||||||
|
temp.add(_lastLoopCheck);
|
||||||
|
temp.add(F(" / "));
|
||||||
|
temp.add(_lastStatus);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
JsonArray jsonTemp = user.createNestedArray(F("AHT Temperature"));
|
||||||
|
JsonArray jsonHumidity = user.createNestedArray(F("AHT Humidity"));
|
||||||
|
|
||||||
|
if (_lastLoopCheck == 0)
|
||||||
|
{
|
||||||
|
// Before first run
|
||||||
|
jsonTemp.add(F("Not read yet"));
|
||||||
|
jsonHumidity.add(F("Not read yet"));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
if (_lastStatus != AHT10_SUCCESS)
|
||||||
void setup() {
|
{
|
||||||
|
jsonTemp.add(F("An error occurred"));
|
||||||
|
jsonHumidity.add(F("An error occurred"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonTemp.add(_lastTemperature);
|
||||||
|
jsonTemp.add(F("°C"));
|
||||||
|
|
||||||
|
jsonHumidity.add(_lastHumidity);
|
||||||
|
jsonHumidity.add(F("%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||||
|
top[F("Enabled")] = _enabled;
|
||||||
|
top[F("I2CAddress")] = static_cast<uint8_t>(_i2cAddress);
|
||||||
|
top[F("SensorType")] = _ahtType;
|
||||||
|
top[F("CheckInterval")] = _checkInterval / 1000;
|
||||||
|
top[F("Decimals")] = log10f(_decimalFactor);
|
||||||
|
|
||||||
|
DEBUG_PRINTLN(F("AHT10 config saved."));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readFromConfig(JsonObject& root) override
|
||||||
|
{
|
||||||
|
// 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[FPSTR(_name)];
|
||||||
|
|
||||||
|
bool configComplete = !top.isNull();
|
||||||
|
if (!configComplete)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
configComplete &= getJsonValue(top[F("Enabled")], _enabled);
|
||||||
|
configComplete &= getJsonValue(top[F("I2CAddress")], _i2cAddress);
|
||||||
|
configComplete &= getJsonValue(top[F("CheckInterval")], _checkInterval);
|
||||||
|
if (configComplete)
|
||||||
|
{
|
||||||
|
if (1 <= _checkInterval && _checkInterval <= 600)
|
||||||
|
_checkInterval *= 1000;
|
||||||
|
else
|
||||||
|
// Invalid input
|
||||||
|
_checkInterval = 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
configComplete &= getJsonValue(top[F("Decimals")], _decimalFactor);
|
||||||
|
if (configComplete)
|
||||||
|
{
|
||||||
|
if (0 <= _decimalFactor && _decimalFactor <= 5)
|
||||||
|
_decimalFactor = pow10f(_decimalFactor);
|
||||||
|
else
|
||||||
|
// Invalid input
|
||||||
|
_decimalFactor = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tmpAhtType;
|
||||||
|
configComplete &= getJsonValue(top[F("SensorType")], tmpAhtType);
|
||||||
|
if (configComplete)
|
||||||
|
{
|
||||||
|
if (0 <= tmpAhtType && tmpAhtType <= 2)
|
||||||
|
_ahtType = static_cast<ASAIR_I2C_SENSOR>(tmpAhtType);
|
||||||
|
else
|
||||||
|
// Invalid input
|
||||||
|
_ahtType = ASAIR_I2C_SENSOR::AHT10_SENSOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_initDone)
|
||||||
|
{
|
||||||
|
// Reloading config
|
||||||
initializeAht();
|
initializeAht();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
_initDone = true;
|
||||||
// if usermod is disabled or called during strip updating just exit
|
return configComplete;
|
||||||
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
}
|
||||||
if (!_enabled || strip.isUpdating())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// do your magic here
|
|
||||||
unsigned long currentTime = millis();
|
|
||||||
|
|
||||||
if (currentTime - _lastLoopCheck < _checkInterval)
|
|
||||||
return;
|
|
||||||
_lastLoopCheck = currentTime;
|
|
||||||
|
|
||||||
_lastStatus = _aht->readRawData();
|
|
||||||
|
|
||||||
if (_lastStatus == AHT10_ERROR)
|
|
||||||
{
|
|
||||||
// Perform softReset and retry
|
|
||||||
DEBUG_PRINTLN("AHTxx returned error, doing softReset");
|
|
||||||
if (!_aht->softReset())
|
|
||||||
{
|
|
||||||
DEBUG_PRINTLN("softReset failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastStatus = _aht->readRawData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_lastStatus == AHT10_SUCCESS)
|
|
||||||
{
|
|
||||||
float temperature = truncateDecimals(_aht->readTemperature(AHT10_USE_READ_DATA));
|
|
||||||
float humidity = truncateDecimals(_aht->readHumidity(AHT10_USE_READ_DATA));
|
|
||||||
|
|
||||||
// Push to MQTT
|
|
||||||
|
|
||||||
// Store
|
|
||||||
_lastHumidity = humidity;
|
|
||||||
_lastTemperature = temperature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToJsonInfo(JsonObject& root) override
|
|
||||||
{
|
|
||||||
// if "u" object does not exist yet wee need to create it
|
|
||||||
JsonObject user = root["u"];
|
|
||||||
if (user.isNull())
|
|
||||||
user = root.createNestedObject("u");
|
|
||||||
|
|
||||||
#ifdef USERMOD_AHT10_DEBUG
|
|
||||||
JsonArray temp = user.createNestedArray(F("status"));
|
|
||||||
temp.add(_lastLoopCheck);
|
|
||||||
temp.add(F(" / "));
|
|
||||||
temp.add(_lastStatus);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JsonArray jsonTemp = user.createNestedArray(F("AHT Temperature"));
|
|
||||||
JsonArray jsonHumidity = user.createNestedArray(F("AHT Humidity"));
|
|
||||||
|
|
||||||
if (_lastLoopCheck == 0)
|
|
||||||
{
|
|
||||||
// Before first run
|
|
||||||
jsonTemp.add(F("Not read yet"));
|
|
||||||
jsonHumidity.add(F("Not read yet"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_lastStatus != AHT10_SUCCESS)
|
|
||||||
{
|
|
||||||
jsonTemp.add(F("An error occurred"));
|
|
||||||
jsonHumidity.add(F("An error occurred"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonTemp.add(_lastTemperature);
|
|
||||||
jsonTemp.add(F("°C"));
|
|
||||||
|
|
||||||
jsonHumidity.add(_lastHumidity);
|
|
||||||
jsonHumidity.add(F("%"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addToConfig(JsonObject& root)
|
|
||||||
{
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
|
||||||
top[F("Enabled")] = _enabled;
|
|
||||||
top[F("I2CAddress")] = static_cast<uint8_t>(_i2cAddress);
|
|
||||||
top[F("SensorType")] = _ahtType;
|
|
||||||
top[F("CheckInterval")] = _checkInterval / 1000;
|
|
||||||
top[F("Decimals")] = log10f(_decimalFactor);
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("AHT10 config saved."));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool readFromConfig(JsonObject& root) override
|
|
||||||
{
|
|
||||||
// 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[FPSTR(_name)];
|
|
||||||
|
|
||||||
bool configComplete = !top.isNull();
|
|
||||||
if (!configComplete)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
configComplete &= getJsonValue(top["Enabled"], _enabled);
|
|
||||||
configComplete &= getJsonValue(top["I2CAddress"], _i2cAddress);
|
|
||||||
configComplete &= getJsonValue(top["CheckInterval"], _checkInterval);
|
|
||||||
if (configComplete)
|
|
||||||
{
|
|
||||||
if (1 <= _checkInterval && _checkInterval <= 600)
|
|
||||||
_checkInterval *= 1000;
|
|
||||||
else
|
|
||||||
// Invalid input
|
|
||||||
_checkInterval = 60000;
|
|
||||||
}
|
|
||||||
|
|
||||||
configComplete &= getJsonValue(top["Decimals"], _decimalFactor);
|
|
||||||
if (configComplete)
|
|
||||||
{
|
|
||||||
if (0 <= _decimalFactor && _decimalFactor <= 5)
|
|
||||||
_decimalFactor = pow10f(_decimalFactor);
|
|
||||||
else
|
|
||||||
// Invalid input
|
|
||||||
_decimalFactor = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tmpAhtType;
|
|
||||||
configComplete &= getJsonValue(top["SensorType"], tmpAhtType);
|
|
||||||
if (configComplete)
|
|
||||||
{
|
|
||||||
if (0 <= tmpAhtType && tmpAhtType <= 2)
|
|
||||||
_ahtType = static_cast<ASAIR_I2C_SENSOR>(tmpAhtType);
|
|
||||||
else
|
|
||||||
// Invalid input
|
|
||||||
_ahtType = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_initDone)
|
|
||||||
{
|
|
||||||
// Reloading config
|
|
||||||
initializeAht();
|
|
||||||
}
|
|
||||||
|
|
||||||
_initDone = true;
|
|
||||||
return configComplete;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const char UsermodAHT10::_name[] PROGMEM = "AHTxx";
|
const char UsermodAHT10::_name[] PROGMEM = "AHTxx";
|
@ -178,6 +178,7 @@
|
|||||||
#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h"
|
#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h"
|
||||||
#define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h"
|
#define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h"
|
||||||
#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h"
|
#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h"
|
||||||
|
#define USERMOD_ID_AHT10 49 //Usermod "usermod_aht10.h"
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
|
Loading…
x
Reference in New Issue
Block a user