diff --git a/src/CHANGES.md b/src/CHANGES.md index 31162471..d4969697 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -7,6 +7,10 @@ * fix protection mask #1352 * merge PR: Add Watchdog for ESP32 #1367 * merge PR: ETH support for CMT2300A - HMS/HMT #1356 +* full refresh of ePaper after booting #1107 +* add optional custom link #1199 +* pinout has an own subgroup in `/settings` +* grid profile will be displayed as hex in every case #1199 ## 0.8.57 - 2024-01-15 * merge PR: fix immediate clearing of display after sunset #1364 diff --git a/src/config/config.h b/src/config/config.h index b783a62b..a633f3af 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -253,7 +253,9 @@ // reconnect delay #define MQTT_RECONNECT_DELAY 5000 - +// maximum custom link length +#define MAX_CUSTOM_LINK_LEN 100 +#define MAX_CUSTOM_LINK_TEXT_LEN 32 // syslog settings #ifdef ENABLE_SYSLOG #define SYSLOG_HOST "" diff --git a/src/config/settings.h b/src/config/settings.h index 0e690ede..db545e38 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -184,6 +184,8 @@ typedef struct { typedef struct { display_t display; + char customLink[MAX_CUSTOM_LINK_LEN]; + char customLinkText[MAX_CUSTOM_LINK_TEXT_LEN]; } plugins_t; typedef struct { @@ -716,6 +718,8 @@ class settings { disp[F("busy")] = mCfg.plugin.display.disp_busy; disp[F("dc")] = mCfg.plugin.display.disp_dc; disp[F("pirPin")] = mCfg.plugin.display.pirPin; + obj[F("cst_lnk")] = mCfg.plugin.customLink; + obj[F("cst_lnk_txt")] = mCfg.plugin.customLinkText; } else { JsonObject disp = obj["disp"]; getVal(disp, F("type"), &mCfg.plugin.display.type); @@ -734,6 +738,8 @@ class settings { getVal(disp, F("busy"), &mCfg.plugin.display.disp_busy); getVal(disp, F("dc"), &mCfg.plugin.display.disp_dc); getVal(disp, F("pirPin"), &mCfg.plugin.display.pirPin); + getChar(obj, F("cst_lnk"), mCfg.plugin.customLink, MAX_CUSTOM_LINK_LEN); + getChar(obj, F("cst_lnk_txt"), mCfg.plugin.customLinkText, MAX_CUSTOM_LINK_TEXT_LEN); } } diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp index d12da365..36d7a901 100644 --- a/src/plugins/Display/Display_ePaper.cpp +++ b/src/plugins/Display/Display_ePaper.cpp @@ -26,8 +26,8 @@ DisplayEPaper::DisplayEPaper() { void DisplayEPaper::init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _BUSY, uint8_t _SCK, uint8_t _MOSI, uint32_t *utcTs, const char *version) { mUtcTs = utcTs; - mRefreshState = RefreshStatus::LOGO; - mSecondCnt = 0; + mRefreshState = RefreshStatus::BLACK; + mSecondCnt = 2; if (type == 10) { Serial.begin(115200); @@ -63,6 +63,7 @@ void DisplayEPaper::fullRefresh() { void DisplayEPaper::refreshLoop() { switch(mRefreshState) { case RefreshStatus::LOGO: + mFirst = false; _display->fillScreen(GxEPD_BLACK); _display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE); mNextRefreshState = RefreshStatus::PARTITIALS; @@ -79,7 +80,7 @@ void DisplayEPaper::refreshLoop() { if(mSecondCnt == 0) { _display->fillScreen(GxEPD_WHITE); mNextRefreshState = RefreshStatus::PARTITIALS; - mRefreshState = RefreshStatus::WAIT; + mRefreshState = (mFirst) ? RefreshStatus::LOGO : RefreshStatus::WAIT; } break; diff --git a/src/plugins/Display/Display_ePaper.h b/src/plugins/Display/Display_ePaper.h index 0e077601..14dd8564 100644 --- a/src/plugins/Display/Display_ePaper.h +++ b/src/plugins/Display/Display_ePaper.h @@ -58,6 +58,7 @@ class DisplayEPaper { const char* _version; RefreshStatus mRefreshState, mNextRefreshState; uint8_t mSecondCnt; + bool mFirst = true; }; #endif // ESP32 diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 8053c6e2..6a9e1e2b 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -258,6 +258,8 @@ class RestApi { obj[F("menu_prot")] = mApp->getProtection(request); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0); + obj[F("cst_lnk")] = String(mConfig->plugin.customLink); + obj[F("cst_lnk_txt")] = String(mConfig->plugin.customLinkText); #if defined(ESP32) obj[F("esp_type")] = F("ESP32"); @@ -354,7 +356,6 @@ class RestApi { obj[F("pending")] = (bool)mApp->getSavePending(); obj[F("success")] = (bool)mApp->getLastSaveSucceed(); obj[F("reboot")] = (bool)mApp->getShouldReboot(); - obj[F("refresh_url")] = "/"; #if defined(ETHERNET) && defined(CONFIG_IDF_TARGET_ESP32S3) obj[F("reload")] = 5; #else diff --git a/src/web/html/api.js b/src/web/html/api.js index 3b8b266d..83a009a5 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -84,10 +84,18 @@ function topnav() { } function parseNav(obj) { - for(i = 0; i < 12; i++) { + for(i = 0; i < 13; i++) { if(i == 2) continue; var l = document.getElementById("nav"+i); + if(12 == i) { + if(obj.cst_lnk.length > 0) { + l.href = obj.cst_lnk + l.innerHTML = obj.cst_lnk_txt + l.classList.remove("hide"); + } + continue; + } if(window.location.pathname == "/" + l.href.substring(0, l.href.indexOf("?")).split('/').pop()) { if((i != 8 )&& (i != 9)) l.classList.add("active"); diff --git a/src/web/html/includes/nav.html b/src/web/html/includes/nav.html index 4cd62d4a..447bf411 100644 --- a/src/web/html/includes/nav.html +++ b/src/web/html/includes/nav.html @@ -17,6 +17,7 @@ REST API {#NAV_DOCUMENTATION} {#NAV_ABOUT} + Custom Link Login Logout diff --git a/src/web/html/save.html b/src/web/html/save.html index bfc9a12a..d972a2ab 100644 --- a/src/web/html/save.html +++ b/src/web/html/save.html @@ -32,10 +32,10 @@ meta.httpEquiv = "refresh" if(!obj.reboot) { html = "{#SUCCESS_SAVED_RELOAD}"; - meta.content = 3; + meta.content = "2; URL=/setup" } else { html = "{#SUCCESS_SAVED_REBOOT} " + obj.reload + " {#SECONDS}."; - meta.content = obj.reload + "; URL=/"; + meta.content = obj.reload + "; URL=/" } document.getElementsByTagName('head')[0].appendChild(meta); } else { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 961e8805..127adce2 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -9,54 +9,51 @@
-
-
- {#DEVICE_NAME} -
-
{#DEVICE_NAME}
-
-
-
-
{#REBOOT_AT_MIDNIGHT}
-
-
-
-
{#DARK_MODE}
-
-
{#DARK_MODE_NOTE}
-
-
-
- {#PINOUT_CONFIGURATION} -

Status LEDs

-
- -

{#RADIO} (NRF24L01+)

-
- -

{#RADIO} (CMT2300A)

-
- -

{#SERIAL_CONSOLE}

-
-
{#LOG_PRINT_INVERTER_DATA}
-
-
-
-
{#LOG_SERIAL_DEBUG}
-
-
-
-
{#LOG_PRIVACY_MODE}
-
-
-
-
{#LOG_PRINT_TRACES}
-
-
-
+
+ {#SYSTEM_CONFIG} +
+
{#DEVICE_NAME}
+
+
+
+
{#REBOOT_AT_MIDNIGHT}
+
+
+
+
{#DARK_MODE}
+
+
{#DARK_MODE_NOTE}
+
+
+
{#CUSTOM_LINK}
+
+
+
+
{#CUSTOM_LINK_TEXT}
+
+
+
+
+ {#SERIAL_CONSOLE} +
+
{#LOG_PRINT_INVERTER_DATA}
+
+
+
+
{#LOG_SERIAL_DEBUG}
+
+
+
+
{#LOG_PRIVACY_MODE}
+
+
+
+
{#LOG_PRINT_TRACES}
+
+
+
@@ -137,172 +134,188 @@
-
- {#INVERTER} -
-
-
{#INTERVAL} [s]
-
-
-
-
{#INV_GAP} [ms]
-
-
-
-
{#INV_RESET_MIDNIGHT}
-
-
-
-
{#INV_PAUSE_SUNSET}
-
-
-
-
{#INV_RESET_NOT_AVAIL}
-
-
-
-
{#INV_RESET_MAX_MIDNIGHT}
-
-
-
-
{#INV_START_WITHOUT_TIME}
-
-
-
-
{#INV_READ_GRID_PROFILE}
-
-
-
-
{#INV_YIELD_EFF}
-
-
-
+
+ {#INVERTER} +
+
+
{#INTERVAL} [s]
+
+
+
+
{#INV_GAP} [ms]
+
+
+
+
{#INV_RESET_MIDNIGHT}
+
+
+
+
{#INV_PAUSE_SUNSET}
+
+
+
+
{#INV_RESET_NOT_AVAIL}
+
+
+
+
{#INV_RESET_MAX_MIDNIGHT}
+
+
+
+
{#INV_START_WITHOUT_TIME}
+
+
+
+
{#INV_READ_GRID_PROFILE}
+
+
+
+
{#INV_YIELD_EFF}
+
+
+
-
- NTP Server -
-
NTP Server / IP
-
-
-
-
NTP Port
-
-
-
-
{#NTP_INTERVAL}
-
-
-
-
{#NTP_SET_SYS_TIME}
-
- -
- +
+ NTP Server +
+
NTP Server / IP
+
-
-
-
{#NTP_SYS_TIME}
-
-
-
+
+
NTP Port
+
+
+
+
{#NTP_INTERVAL}
+
+
+
+
{#NTP_SET_SYS_TIME}
+
+ +
+ +
+
+
+
{#NTP_SYS_TIME}
+
+
+
-
- {#SUNRISE_SUNSET} -
-
{#LATITUDE}
-
-
-
-
{#LONGITUDE}
-
-
-
-
{#OFFSET_SUNRISE}
-
-
-
-
{#OFFSET_SUNSET}
-
-
-
+
+ {#SUNRISE_SUNSET} +
+
{#LATITUDE}
+
+
+
+
{#LONGITUDE}
+
+
+
+
{#OFFSET_SUNRISE}
+
+
+
+
{#OFFSET_SUNSET}
+
+
+
-
- MQTT -
-
Broker / Server IP
-
-
-
-
Port
-
-
-
-
Client Id (optional)
-
-
-
-
{#MQTT_USER}
-
-
-
-
{#MQTT_PASSWORD}
-
-
-
-
Topic
-
-
-

{#MQTT_NOTE}

-
-
{#INTERVAL}
-
-
-
-
Discovery Config (homeassistant)
-
- - +
+ MQTT +
+
Broker / Server IP
+
-
-
+
+
Port
+
+
+
+
Client Id (optional)
+
+
+
+
{#MQTT_USER}
+
+
+
+
{#MQTT_PASSWORD}
+
+
+
+
Topic
+
+
+

{#MQTT_NOTE}

+
+
{#INTERVAL}
+
+
+
+
Discovery Config (homeassistant)
+
+ + +
+
+ +
+ + +
+
+ {#PINOUT_CONFIG} +

Status LEDs

+
+ +

{#RADIO} (NRF24L01+)

+
+ +

{#RADIO} (CMT2300A)

+
+ +
-
- {#DISPLAY_CONFIG} -
-
-
-
{#DISP_OFF_INV}
-
-
-
-
-
{#DISP_LUMINANCE}
-
-
-

{#DISP_PINOUT}

-
-
-
-

{#GRAPH_OPTIONS}

-
+
+ {#DISPLAY_CONFIG} +
+
-
{#GRAPH_SHOW_RATIO}
-
+
{#DISP_OFF_INV}
+
-
-
+
+
+
{#DISP_LUMINANCE}
+
+
+

{#DISP_PINOUT}

+
+
+
+

{#GRAPH_OPTIONS}

+
+
+
{#GRAPH_SHOW_RATIO}
+
+
+
+
@@ -644,6 +657,11 @@ parseESP(obj); parseRssi(obj); + if(0 != obj.cst_lnk.length) { + document.getElementsByName("cstLnk")[0].value = obj.cst_lnk + document.getElementsByName("cstLnkTxt")[0].value = obj.cst_lnk_txt + } + ts = obj["ts_now"]; window.setInterval("tick()", 1000); } diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index b99501f3..3b90a028 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -366,7 +366,6 @@ } else { content.push(ml("div", {class: "row"}, ml("div", {class: "col"}, ml("h5", {}, "{#UNKNOWN_PROFILE}")))) content.push(ml("div", {class: "row"}, ml("div", {class: "col"}, ml("p", {}, "{#OPEN_ISSUE}.")))) - content.push(ml("div", {class: "row"}, ml("div", {class: "col my-2"}, ml("pre", {}, obj.grid)))) } } else { content.push(ml("div", {class: "row"}, @@ -377,6 +376,8 @@ content.push(parseGridGroup(glob)) } } + if(0 != obj.grid.length) + content.push(ml("div", {class: "row"}, ml("div", {class: "col my-2"}, ml("pre", {}, obj.grid)))) modal("{#PROFILE_MODAL}: " + obj.name, ml("div", {}, ml("div", {class: "col mb-2"}, [...content]))) }) diff --git a/src/web/lang.json b/src/web/lang.json index d5fca4fe..f0c5dbd0 100644 --- a/src/web/lang.json +++ b/src/web/lang.json @@ -149,7 +149,17 @@ "de": "(der Browser-Cache muss geleert oder STRG + F5 gedrückt werden, um diese Einstellung zu aktivieren)" }, { - "token": "PINOUT_CONFIGURATION", + "token": "CUSTOM_LINK", + "en": "Custom link (leave empty to hide element in navigation)", + "de": "benutzerspezifischer Link (leer lassen, um Element in Navigation auszublenden)" + }, + { + "token": "CUSTOM_LINK_TEXT", + "en": "Custom link Text", + "de": "Beschriftung des Links" + }, + { + "token": "PINOUT_CONFIG", "en": "Pinout Configuration", "de": "Anschlusseinstellungen" }, diff --git a/src/web/web.h b/src/web/web.h index 46b93d5c..13f1f4ae 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -482,6 +482,15 @@ class Web { mConfig->sys.darkMode = (request->arg("darkMode") == "on"); mConfig->sys.schedReboot = (request->arg("schedReboot") == "on"); + + if (request->arg("cstLnk") != "") { + request->arg("cstLnk").toCharArray(mConfig->plugin.customLink, MAX_CUSTOM_LINK_LEN); + request->arg("cstLnkTxt").toCharArray(mConfig->plugin.customLinkText, MAX_CUSTOM_LINK_TEXT_LEN); + } else { + mConfig->plugin.customLink[0] = '\0'; + mConfig->plugin.customLinkText[0] = '\0'; + } + // protection if (request->arg("adminpwd") != "{PWD}") { request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);