diff --git a/docs/DeviceProfiles/lilygo_ttgo_t-internet_poe.json b/docs/DeviceProfiles/lilygo_ttgo_t-internet_poe.json index 0bc2857c..538f3000 100644 --- a/docs/DeviceProfiles/lilygo_ttgo_t-internet_poe.json +++ b/docs/DeviceProfiles/lilygo_ttgo_t-internet_poe.json @@ -18,5 +18,50 @@ "type": 0, "clk_mode": 3 } + }, + { + "name": "LILYGO TTGO T-Internet-POE, nrf24 direct solder", + "nrf24": { + "miso": 12, + "mosi": 4, + "clk": 15, + "irq": 33, + "en": 14, + "cs": 2 + }, + "eth": { + "enabled": true, + "phy_addr": 0, + "power": -1, + "mdc": 23, + "mdio": 18, + "type": 0, + "clk_mode": 3 + } + }, + { + "name": "LILYGO TTGO T-Internet-POE, nrf24 direct solder, SSD1306", + "nrf24": { + "miso": 12, + "mosi": 4, + "clk": 15, + "irq": 33, + "en": 14, + "cs": 2 + }, + "eth": { + "enabled": true, + "phy_addr": 0, + "power": -1, + "mdc": 23, + "mdio": 18, + "type": 0, + "clk_mode": 3 + }, + "display": { + "type": 2, + "data": 16, + "clk": 32 + } } ] \ No newline at end of file diff --git a/include/Display_Graphic.h b/include/Display_Graphic.h index ac0512df..9fe202c4 100644 --- a/include/Display_Graphic.h +++ b/include/Display_Graphic.h @@ -19,6 +19,7 @@ public: void init(DisplayType_t type, uint8_t data, uint8_t clk, uint8_t cs, uint8_t reset); void loop(); void setContrast(uint8_t contrast); + void setStatus(bool turnOn); void setOrientation(uint8_t rotation = DISPLAY_ROTATION); void setLanguage(uint8_t language); void setStartupDisplay(); @@ -33,6 +34,8 @@ private: U8G2* _display; + bool _displayTurnedOn; + DisplayType_t _display_type = DisplayType_t::None; uint8_t _display_language = DISPLAY_LANGUAGE; uint8_t _mExtra; diff --git a/include/Led_Single.h b/include/Led_Single.h index 22fc87a2..a5c601bd 100644 --- a/include/Led_Single.h +++ b/include/Led_Single.h @@ -19,6 +19,9 @@ public: void init(); void loop(); + void turnAllOff(); + void turnAllOn(); + private: enum class LedState_t { On, @@ -27,6 +30,7 @@ private: }; LedState_t _ledState[PINMAPPING_LED_COUNT]; + LedState_t _allState; TimeoutHelper _updateTimeout; TimeoutHelper _blinkTimeout; uint8_t _ledActive = 0; diff --git a/include/Utils.h b/include/Utils.h index 33887ff9..6de962b0 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -8,4 +8,5 @@ public: static uint32_t getChipId(); static uint64_t generateDtuSerial(); static int getTimezoneOffset(); + static void restartDtu(); }; diff --git a/lib/Hoymiles/src/Hoymiles.cpp b/lib/Hoymiles/src/Hoymiles.cpp index e5e6e4dd..a5f468b5 100644 --- a/lib/Hoymiles/src/Hoymiles.cpp +++ b/lib/Hoymiles/src/Hoymiles.cpp @@ -91,9 +91,21 @@ void HoymilesClass::loop() } // Fetch dev info (but first fetch stats) - if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) { - _messageOutput->println("Request device info"); - iv->sendDevInfoRequest(); + if (iv->Statistics()->getLastUpdate() > 0) { + bool invalidDevInfo = !iv->DevInfo()->containsValidData() + && iv->DevInfo()->getLastUpdateAll() > 0 + && iv->DevInfo()->getLastUpdateSimple() > 0; + + if (invalidDevInfo) { + _messageOutput->println("DevInfo: No Valid Data"); + } + + if ((iv->DevInfo()->getLastUpdateAll() == 0) + || (iv->DevInfo()->getLastUpdateSimple() == 0) + || invalidDevInfo) { + _messageOutput->println("Request device info"); + iv->sendDevInfoRequest(); + } } if (++inverterPos >= getNumInverters()) { diff --git a/lib/Hoymiles/src/parser/DevInfoParser.cpp b/lib/Hoymiles/src/parser/DevInfoParser.cpp index 44fe59e1..eab3a303 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.cpp +++ b/lib/Hoymiles/src/parser/DevInfoParser.cpp @@ -196,6 +196,16 @@ String DevInfoParser::getHwModelName() return devInfo[idx].modelName; } +bool DevInfoParser::containsValidData() +{ + time_t t = getFwBuildDateTime(); + + struct tm info; + localtime_r(&t, &info); + + return info.tm_year > (2016 - 1900); +} + uint8_t DevInfoParser::getDevIdx() { uint8_t ret = 0xff; diff --git a/lib/Hoymiles/src/parser/DevInfoParser.h b/lib/Hoymiles/src/parser/DevInfoParser.h index 18c3d7c8..b18bc8a1 100644 --- a/lib/Hoymiles/src/parser/DevInfoParser.h +++ b/lib/Hoymiles/src/parser/DevInfoParser.h @@ -33,6 +33,8 @@ public: uint16_t getMaxPower(); String getHwModelName(); + bool containsValidData(); + private: time_t timegm(struct tm* tm); uint8_t getDevIdx(); diff --git a/src/Display_Graphic.cpp b/src/Display_Graphic.cpp index 972b3bc2..26991cb5 100644 --- a/src/Display_Graphic.cpp +++ b/src/Display_Graphic.cpp @@ -47,6 +47,7 @@ void DisplayGraphicClass::init(DisplayType_t type, uint8_t data, uint8_t clk, ui _display = constructor(reset, clk, data, cs); _display->begin(); setContrast(DISPLAY_CONTRAST); + setStatus(true); } } @@ -139,10 +140,11 @@ void DisplayGraphicClass::loop() if ((millis() - _lastDisplayUpdate) > _period) { _display->clearBuffer(); + bool displayPowerSave = false; //=====> Actual Production ========== if (Datastore.getIsAtLeastOneReachable()) { - _display->setPowerSave(false); + displayPowerSave = false; if (Datastore.getTotalAcPowerEnabled() > 999) { snprintf(_fmtText, sizeof(_fmtText), i18n_current_power_kw[_display_language], (Datastore.getTotalAcPowerEnabled() / 1000)); } else { @@ -158,7 +160,7 @@ void DisplayGraphicClass::loop() printText(i18n_offline[_display_language], 0); // check if it's time to enter power saving mode if (millis() - _previousMillis >= (_interval * 2)) { - _display->setPowerSave(enablePowerSafe); + displayPowerSave = enablePowerSafe; } } //<======================= @@ -184,6 +186,12 @@ void DisplayGraphicClass::loop() _mExtra++; _lastDisplayUpdate = millis(); + + if (!_displayTurnedOn) { + displayPowerSave = true; + } + + _display->setPowerSave(displayPowerSave); } } @@ -195,4 +203,9 @@ void DisplayGraphicClass::setContrast(uint8_t contrast) _display->setContrast(contrast * 2.55f); } +void DisplayGraphicClass::setStatus(bool turnOn) +{ + _displayTurnedOn = turnOn; +} + DisplayGraphicClass Display; \ No newline at end of file diff --git a/src/Led_Single.cpp b/src/Led_Single.cpp index 17690fe0..7ce6637f 100644 --- a/src/Led_Single.cpp +++ b/src/Led_Single.cpp @@ -20,6 +20,7 @@ void LedSingleClass::init() { _blinkTimeout.set(500); _updateTimeout.set(LEDSINGLE_UPDATE_INTERVAL); + turnAllOn(); for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) { auto& pin = PinMapping.get(); @@ -40,7 +41,7 @@ void LedSingleClass::loop() return; } - if (_updateTimeout.occured()) { + if (_updateTimeout.occured() && _allState == LedState_t::On) { const CONFIG_T& config = Configuration.get(); // Update network status @@ -68,6 +69,9 @@ void LedSingleClass::loop() } _updateTimeout.reset(); + } else if (_updateTimeout.occured() && _allState == LedState_t::Off) { + _ledState[0] = LedState_t::Off; + _ledState[1] = LedState_t::Off; } for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) { @@ -93,3 +97,13 @@ void LedSingleClass::loop() } } } + +void LedSingleClass::turnAllOff() +{ + _allState = LedState_t::Off; +} + +void LedSingleClass::turnAllOn() +{ + _allState = LedState_t::On; +} diff --git a/src/Utils.cpp b/src/Utils.cpp index db8363ad..2e59d856 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -3,6 +3,8 @@ * Copyright (C) 2022 - 2023 Thomas Basler and others */ #include "Utils.h" +#include "Display_Graphic.h" +#include "Led_Single.h" #include uint32_t Utils::getChipId() @@ -52,4 +54,14 @@ int Utils::getTimezoneOffset() gmt = mktime(ptm); return static_cast(difftime(rawtime, gmt)); -} \ No newline at end of file +} + +void Utils::restartDtu() +{ + LedSingle.turnAllOff(); + Display.setStatus(false); + yield(); + delay(1000); + yield(); + ESP.restart(); +} diff --git a/src/WebApi_config.cpp b/src/WebApi_config.cpp index d936be58..08b86d65 100644 --- a/src/WebApi_config.cpp +++ b/src/WebApi_config.cpp @@ -4,6 +4,7 @@ */ #include "WebApi_config.h" #include "Configuration.h" +#include "Utils.h" #include "WebApi.h" #include "WebApi_errors.h" #include @@ -114,7 +115,7 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request) request->send(response); LittleFS.remove(CONFIG_FILENAME); - ESP.restart(); + Utils::restartDtu(); } void WebApiConfigClass::onConfigListGet(AsyncWebServerRequest* request) @@ -157,10 +158,7 @@ void WebApiConfigClass::onConfigUploadFinish(AsyncWebServerRequest* request) response->addHeader("Connection", "close"); response->addHeader("Access-Control-Allow-Origin", "*"); request->send(response); - yield(); - delay(1000); - yield(); - ESP.restart(); + Utils::restartDtu(); } void WebApiConfigClass::onConfigUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final) diff --git a/src/WebApi_device.cpp b/src/WebApi_device.cpp index ab7d7bfb..521e799e 100644 --- a/src/WebApi_device.cpp +++ b/src/WebApi_device.cpp @@ -6,6 +6,7 @@ #include "Configuration.h" #include "Display_Graphic.h" #include "PinMapping.h" +#include "Utils.h" #include "WebApi.h" #include "WebApi_errors.h" #include "helper.h" @@ -185,9 +186,6 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request) request->send(response); if (performRestart) { - yield(); - delay(1000); - yield(); - ESP.restart(); + Utils::restartDtu(); } } \ No newline at end of file diff --git a/src/WebApi_firmware.cpp b/src/WebApi_firmware.cpp index 798264a0..62cf5615 100644 --- a/src/WebApi_firmware.cpp +++ b/src/WebApi_firmware.cpp @@ -5,6 +5,7 @@ #include "WebApi_firmware.h" #include "Configuration.h" #include "Update.h" +#include "Utils.h" #include "WebApi.h" #include "helper.h" #include @@ -42,10 +43,7 @@ void WebApiFirmwareClass::onFirmwareUpdateFinish(AsyncWebServerRequest* request) response->addHeader("Connection", "close"); response->addHeader("Access-Control-Allow-Origin", "*"); request->send(response); - yield(); - delay(1000); - yield(); - ESP.restart(); + Utils::restartDtu(); } void WebApiFirmwareClass::onFirmwareUpdateUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final) diff --git a/src/WebApi_maintenance.cpp b/src/WebApi_maintenance.cpp index b59ed34e..ed2d6867 100644 --- a/src/WebApi_maintenance.cpp +++ b/src/WebApi_maintenance.cpp @@ -4,6 +4,7 @@ */ #include "WebApi_maintenance.h" +#include "Utils.h" #include "WebApi.h" #include "WebApi_errors.h" #include @@ -75,10 +76,7 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request) response->setLength(); request->send(response); - yield(); - delay(1000); - yield(); - ESP.restart(); + Utils::restartDtu(); } else { retMsg["message"] = "Reboot cancled!"; retMsg["code"] = WebApiError::MaintenanceRebootCancled; diff --git a/webapp/package.json b/webapp/package.json index d4d9b246..31f237aa 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -26,18 +26,18 @@ "@rushstack/eslint-patch": "^1.3.3", "@tsconfig/node18": "^18.2.1", "@types/bootstrap": "^5.2.6", - "@types/node": "^20.5.1", - "@types/sortablejs": "^1.15.1", + "@types/node": "^20.5.7", + "@types/sortablejs": "^1.15.2", "@types/spark-md5": "^3.0.2", "@vitejs/plugin-vue": "^4.3.3", "@vue/eslint-config-typescript": "^11.0.3", "@vue/tsconfig": "^0.4.0", - "eslint": "^8.47.0", + "eslint": "^8.48.0", "eslint-plugin-vue": "^9.17.0", "npm-run-all": "^4.1.5", "sass": "^1.64.2", "terser": "^5.19.2", - "typescript": "^5.1.6", + "typescript": "^5.2.2", "vite": "^4.4.9", "vite-plugin-compression": "^0.5.1", "vite-plugin-css-injected-by-js": "^3.3.0", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 14593bac..ae7a4028 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -166,10 +166,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@^8.47.0": - version "8.47.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.47.0.tgz#5478fdf443ff8158f9de171c704ae45308696c7d" - integrity sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og== +"@eslint/js@8.48.0": + version "8.48.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.48.0.tgz#642633964e217905436033a2bd08bf322849b7fb" + integrity sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw== "@humanwhocodes/config-array@^0.11.10": version "0.11.10" @@ -382,20 +382,20 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== -"@types/node@^20.5.1": - version "20.5.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.1.tgz#178d58ee7e4834152b0e8b4d30cbfab578b9bb30" - integrity sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg== +"@types/node@^20.5.7": + version "20.5.7" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377" + integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA== "@types/semver@^7.3.12": version "7.3.13" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== -"@types/sortablejs@^1.15.1": - version "1.15.1" - resolved "https://registry.yarnpkg.com/@types/sortablejs/-/sortablejs-1.15.1.tgz#123abafbe936f754fee5eb5b49009ce1f1075aa5" - integrity sha512-g/JwBNToh6oCTAwNS8UGVmjO7NLDKsejVhvE4x1eWiPTC3uCuNsa/TD4ssvX3du+MLiM+SHPNDuijp8y76JzLQ== +"@types/sortablejs@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@types/sortablejs/-/sortablejs-1.15.2.tgz#d51e5ecac00a9782aa256c1401309ce1c4031ba2" + integrity sha512-mOIv/EnPMzAZAVbuh9uGjOZ1BBdimP9Y6IPGntsvQJtko5yapSDKB7GwB3AOlF5N3bkpk4sBwQRpS3aEkiUbaA== "@types/spark-md5@^3.0.2": version "3.0.2" @@ -1168,15 +1168,15 @@ eslint-visitor-keys@^3.4.3: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.47.0: - version "8.47.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.47.0.tgz#c95f9b935463fb4fad7005e626c7621052e90806" - integrity sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q== +eslint@^8.48.0: + version "8.48.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.48.0.tgz#bf9998ba520063907ba7bfe4c480dc8be03c2155" + integrity sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.2" - "@eslint/js" "^8.47.0" + "@eslint/js" "8.48.0" "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -2469,10 +2469,10 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -typescript@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" - integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== ufo@^1.1.2: version "1.1.2"