From f71d839009fc5e539572318fa0983e29da881c5f Mon Sep 17 00:00:00 2001 From: Michael Bisbjerg Date: Tue, 14 May 2024 17:54:43 +0200 Subject: [PATCH] Address comments --- platformio_override.sample.ini | 3 + usermods/AHT10_v2/README.md | 3 + usermods/AHT10_v2/usermod_aht10.h | 364 +++++++++++++++--------------- wled00/const.h | 1 + 4 files changed, 195 insertions(+), 176 deletions(-) diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index 05bd1983e..14508de72 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -94,6 +94,9 @@ build_flags = ${common.build_flags} ${esp8266.build_flags} ; -D USERMOD_AUTO_SAVE ; -D AUTOSAVE_AFTER_SEC=90 ; +; Use AHT10/AHT15/AHT20 usermod +; -D USERMOD_AHT10 +; ; Use 4 Line Display usermod with SPI display ; -D USERMOD_FOUR_LINE_DISPLAY ; -D USE_ALT_DISPlAY # mandatory diff --git a/usermods/AHT10_v2/README.md b/usermods/AHT10_v2/README.md index e6f16ddc4..650a59532 100644 --- a/usermods/AHT10_v2/README.md +++ b/usermods/AHT10_v2/README.md @@ -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)) - `Wire` +## Author +[@LordMike](https://github.com/LordMike) + # Compiling To enable, compile with `USERMOD_AHT10` defined (e.g. in `platformio_override.ini`) diff --git a/usermods/AHT10_v2/usermod_aht10.h b/usermods/AHT10_v2/usermod_aht10.h index d6e44a87b..984905a21 100644 --- a/usermods/AHT10_v2/usermod_aht10.h +++ b/usermods/AHT10_v2/usermod_aht10.h @@ -5,197 +5,209 @@ #define AHT10_SUCCESS 1 -class UsermodAHT10 : public Usermod { - private: - static const char _name[]; +class UsermodAHT10 : public Usermod +{ +private: + static const char _name[]; - unsigned long _lastLoopCheck = 0; - bool _initDone = false; + unsigned long _lastLoopCheck = 0; + 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 - bool _enabled = false; - uint8_t _i2cAddress = AHT10_ADDRESS_0X38; - ASAIR_I2C_SENSOR _ahtType = AHT10_SENSOR; - 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, ..) + // 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; + uint8_t _i2cAddress = AHT10_ADDRESS_0X38; + ASAIR_I2C_SENSOR _ahtType = AHT10_SENSOR; + 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, ..) - uint8_t _lastStatus = 0; - float _lastHumidity = 0; - float _lastTemperature = 0; + uint8_t _lastStatus = 0; + float _lastHumidity = 0; + float _lastTemperature = 0; - AHT10* _aht = nullptr; + AHT10* _aht = nullptr; - float truncateDecimals(float val) { - return roundf(val * _decimalFactor) / _decimalFactor; + float truncateDecimals(float val) + { + return roundf(val * _decimalFactor) / _decimalFactor; + } + + void initializeAht() + { + if (_aht != nullptr) + { + delete _aht; } - void initializeAht() { - if (_aht != nullptr) { - delete _aht; + _aht = new AHT10(_i2cAddress, _ahtType); + + _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 = 0; - _lastHumidity = 0; - _lastTemperature = 0; + _lastStatus = _aht->readRawData(); } - ~UsermodAHT10() { - delete _aht; - _aht = nullptr; + 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; + } + } + + 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: - void setup() { + 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(_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(tmpAhtType); + else + // Invalid input + _ahtType = ASAIR_I2C_SENSOR::AHT10_SENSOR; + } + + if (_initDone) + { + // Reloading config 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; - } - - _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(_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(tmpAhtType); - else - // Invalid input - _ahtType = 0; - } - - if (_initDone) - { - // Reloading config - initializeAht(); - } - - _initDone = true; - return configComplete; - } + _initDone = true; + return configComplete; + } }; -const char UsermodAHT10::_name[] PROGMEM = "AHTxx"; \ No newline at end of file +const char UsermodAHT10::_name[] PROGMEM = "AHTxx"; \ No newline at end of file diff --git a/wled00/const.h b/wled00/const.h index a44e67598..5173afd24 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -178,6 +178,7 @@ #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_MAX17048 48 //Usermod "usermod_max17048.h" +#define USERMOD_ID_AHT10 49 //Usermod "usermod_aht10.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot