Browse Source

0.8.58

* 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
pull/1373/head
lumapu 1 year ago
parent
commit
c3a2ad0a97
  1. 4
      src/CHANGES.md
  2. 4
      src/config/config.h
  3. 6
      src/config/settings.h
  4. 7
      src/plugins/Display/Display_ePaper.cpp
  5. 1
      src/plugins/Display/Display_ePaper.h
  6. 3
      src/web/RestApi.h
  7. 10
      src/web/html/api.js
  8. 1
      src/web/html/includes/nav.html
  9. 4
      src/web/html/save.html
  10. 46
      src/web/html/setup.html
  11. 3
      src/web/html/visualization.html
  12. 12
      src/web/lang.json
  13. 9
      src/web/web.h

4
src/CHANGES.md

@ -7,6 +7,10 @@
* fix protection mask #1352 * fix protection mask #1352
* merge PR: Add Watchdog for ESP32 #1367 * merge PR: Add Watchdog for ESP32 #1367
* merge PR: ETH support for CMT2300A - HMS/HMT #1356 * 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 ## 0.8.57 - 2024-01-15
* merge PR: fix immediate clearing of display after sunset #1364 * merge PR: fix immediate clearing of display after sunset #1364

4
src/config/config.h

@ -253,7 +253,9 @@
// reconnect delay // reconnect delay
#define MQTT_RECONNECT_DELAY 5000 #define MQTT_RECONNECT_DELAY 5000
// maximum custom link length
#define MAX_CUSTOM_LINK_LEN 100
#define MAX_CUSTOM_LINK_TEXT_LEN 32
// syslog settings // syslog settings
#ifdef ENABLE_SYSLOG #ifdef ENABLE_SYSLOG
#define SYSLOG_HOST "<hostname-or-ip-address-of-syslog-server>" #define SYSLOG_HOST "<hostname-or-ip-address-of-syslog-server>"

6
src/config/settings.h

@ -184,6 +184,8 @@ typedef struct {
typedef struct { typedef struct {
display_t display; display_t display;
char customLink[MAX_CUSTOM_LINK_LEN];
char customLinkText[MAX_CUSTOM_LINK_TEXT_LEN];
} plugins_t; } plugins_t;
typedef struct { typedef struct {
@ -716,6 +718,8 @@ class settings {
disp[F("busy")] = mCfg.plugin.display.disp_busy; disp[F("busy")] = mCfg.plugin.display.disp_busy;
disp[F("dc")] = mCfg.plugin.display.disp_dc; disp[F("dc")] = mCfg.plugin.display.disp_dc;
disp[F("pirPin")] = mCfg.plugin.display.pirPin; disp[F("pirPin")] = mCfg.plugin.display.pirPin;
obj[F("cst_lnk")] = mCfg.plugin.customLink;
obj[F("cst_lnk_txt")] = mCfg.plugin.customLinkText;
} else { } else {
JsonObject disp = obj["disp"]; JsonObject disp = obj["disp"];
getVal<uint8_t>(disp, F("type"), &mCfg.plugin.display.type); getVal<uint8_t>(disp, F("type"), &mCfg.plugin.display.type);
@ -734,6 +738,8 @@ class settings {
getVal<uint8_t>(disp, F("busy"), &mCfg.plugin.display.disp_busy); getVal<uint8_t>(disp, F("busy"), &mCfg.plugin.display.disp_busy);
getVal<uint8_t>(disp, F("dc"), &mCfg.plugin.display.disp_dc); getVal<uint8_t>(disp, F("dc"), &mCfg.plugin.display.disp_dc);
getVal<uint8_t>(disp, F("pirPin"), &mCfg.plugin.display.pirPin); getVal<uint8_t>(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);
} }
} }

7
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) { 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; mUtcTs = utcTs;
mRefreshState = RefreshStatus::LOGO; mRefreshState = RefreshStatus::BLACK;
mSecondCnt = 0; mSecondCnt = 2;
if (type == 10) { if (type == 10) {
Serial.begin(115200); Serial.begin(115200);
@ -63,6 +63,7 @@ void DisplayEPaper::fullRefresh() {
void DisplayEPaper::refreshLoop() { void DisplayEPaper::refreshLoop() {
switch(mRefreshState) { switch(mRefreshState) {
case RefreshStatus::LOGO: case RefreshStatus::LOGO:
mFirst = false;
_display->fillScreen(GxEPD_BLACK); _display->fillScreen(GxEPD_BLACK);
_display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE); _display->drawBitmap(0, 0, logo, 200, 200, GxEPD_WHITE);
mNextRefreshState = RefreshStatus::PARTITIALS; mNextRefreshState = RefreshStatus::PARTITIALS;
@ -79,7 +80,7 @@ void DisplayEPaper::refreshLoop() {
if(mSecondCnt == 0) { if(mSecondCnt == 0) {
_display->fillScreen(GxEPD_WHITE); _display->fillScreen(GxEPD_WHITE);
mNextRefreshState = RefreshStatus::PARTITIALS; mNextRefreshState = RefreshStatus::PARTITIALS;
mRefreshState = RefreshStatus::WAIT; mRefreshState = (mFirst) ? RefreshStatus::LOGO : RefreshStatus::WAIT;
} }
break; break;

1
src/plugins/Display/Display_ePaper.h

@ -58,6 +58,7 @@ class DisplayEPaper {
const char* _version; const char* _version;
RefreshStatus mRefreshState, mNextRefreshState; RefreshStatus mRefreshState, mNextRefreshState;
uint8_t mSecondCnt; uint8_t mSecondCnt;
bool mFirst = true;
}; };
#endif // ESP32 #endif // ESP32

3
src/web/RestApi.h

@ -258,6 +258,8 @@ class RestApi {
obj[F("menu_prot")] = mApp->getProtection(request); obj[F("menu_prot")] = mApp->getProtection(request);
obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask );
obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0); 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) #if defined(ESP32)
obj[F("esp_type")] = F("ESP32"); obj[F("esp_type")] = F("ESP32");
@ -354,7 +356,6 @@ class RestApi {
obj[F("pending")] = (bool)mApp->getSavePending(); obj[F("pending")] = (bool)mApp->getSavePending();
obj[F("success")] = (bool)mApp->getLastSaveSucceed(); obj[F("success")] = (bool)mApp->getLastSaveSucceed();
obj[F("reboot")] = (bool)mApp->getShouldReboot(); obj[F("reboot")] = (bool)mApp->getShouldReboot();
obj[F("refresh_url")] = "/";
#if defined(ETHERNET) && defined(CONFIG_IDF_TARGET_ESP32S3) #if defined(ETHERNET) && defined(CONFIG_IDF_TARGET_ESP32S3)
obj[F("reload")] = 5; obj[F("reload")] = 5;
#else #else

10
src/web/html/api.js

@ -84,10 +84,18 @@ function topnav() {
} }
function parseNav(obj) { function parseNav(obj) {
for(i = 0; i < 12; i++) { for(i = 0; i < 13; i++) {
if(i == 2) if(i == 2)
continue; continue;
var l = document.getElementById("nav"+i); 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(window.location.pathname == "/" + l.href.substring(0, l.href.indexOf("?")).split('/').pop()) {
if((i != 8 )&& (i != 9)) if((i != 8 )&& (i != 9))
l.classList.add("active"); l.classList.add("active");

1
src/web/html/includes/nav.html

@ -17,6 +17,7 @@
<a id="nav8" href="/api" target="_blank">REST API</a> <a id="nav8" href="/api" target="_blank">REST API</a>
<a id="nav9" href="https://ahoydtu.de" target="_blank">{#NAV_DOCUMENTATION}</a> <a id="nav9" href="https://ahoydtu.de" target="_blank">{#NAV_DOCUMENTATION}</a>
<a id="nav10" href="/about?v={#VERSION}">{#NAV_ABOUT}</a> <a id="nav10" href="/about?v={#VERSION}">{#NAV_ABOUT}</a>
<a id="nav12" href="#" class="hide" target="_blank">Custom Link</a>
<span class="seperator"></span> <span class="seperator"></span>
<a id="nav0" class="hide" href="/login">Login</a> <a id="nav0" class="hide" href="/login">Login</a>
<a id="nav1" class="hide" href="/logout">Logout</a> <a id="nav1" class="hide" href="/logout">Logout</a>

4
src/web/html/save.html

@ -32,10 +32,10 @@
meta.httpEquiv = "refresh" meta.httpEquiv = "refresh"
if(!obj.reboot) { if(!obj.reboot) {
html = "{#SUCCESS_SAVED_RELOAD}"; html = "{#SUCCESS_SAVED_RELOAD}";
meta.content = 3; meta.content = "2; URL=/setup"
} else { } else {
html = "{#SUCCESS_SAVED_REBOOT} " + obj.reload + " {#SECONDS}."; html = "{#SUCCESS_SAVED_REBOOT} " + obj.reload + " {#SECONDS}.";
meta.content = obj.reload + "; URL=/"; meta.content = obj.reload + "; URL=/"
} }
document.getElementsByTagName('head')[0].appendChild(meta); document.getElementsByTagName('head')[0].appendChild(meta);
} else { } else {

46
src/web/html/setup.html

@ -9,11 +9,10 @@
<div id="wrapper"> <div id="wrapper">
<div id="content"> <div id="content">
<form method="post" action="/save" id="settings"> <form method="post" action="/save" id="settings">
<fieldset>
<button type="button" class="s_collapsible mt-4">{#SYSTEM_CONFIG}</button> <button type="button" class="s_collapsible mt-4">{#SYSTEM_CONFIG}</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-2"> <fieldset class="mb-2">
<legend class="des">{#DEVICE_NAME}</legend> <legend class="des">{#SYSTEM_CONFIG}</legend>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 col-sm-3">{#DEVICE_NAME}</div> <div class="col-12 col-sm-3">{#DEVICE_NAME}</div>
<div class="col-12 col-sm-9"><input type="text" name="device"/></div> <div class="col-12 col-sm-9"><input type="text" name="device"/></div>
@ -22,24 +21,22 @@
<div class="col-8 col-sm-3">{#REBOOT_AT_MIDNIGHT}</div> <div class="col-8 col-sm-3">{#REBOOT_AT_MIDNIGHT}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="schedReboot"/></div> <div class="col-4 col-sm-9"><input type="checkbox" name="schedReboot"/></div>
</div> </div>
<div class="row mb-3"> <div class="row mb-5">
<div class="col-8 col-sm-3">{#DARK_MODE}</div> <div class="col-8 col-sm-3">{#DARK_MODE}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="darkMode"/></div> <div class="col-4 col-sm-9"><input type="checkbox" name="darkMode"/></div>
<div class="col-12">{#DARK_MODE_NOTE}</div> <div class="col-12">{#DARK_MODE_NOTE}</div>
</div> </div>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#CUSTOM_LINK}</div>
<div class="col-4 col-sm-9"><input type="text" name="cstLnk"/></div>
</div>
<div class="row mb-3">
<div class="col-8 col-sm-3">{#CUSTOM_LINK_TEXT}</div>
<div class="col-4 col-sm-9"><input type="text" name="cstLnkTxt"/></div>
</div>
</fieldset> </fieldset>
<fieldset class="mb-4"> <fieldset class="mb-4">
<legend class="des">{#PINOUT_CONFIGURATION}</legend> <legend class="des">{#SERIAL_CONSOLE}</legend>
<p class="des">Status LEDs</p>
<div id="pinout"></div>
<p class="des">{#RADIO} (NRF24L01+)</p>
<div id="rf24"></div>
<!--IF_ESP32-->
<p class="des">{#RADIO} (CMT2300A)</p>
<div id="cmt"></div>
<!--ENDIF_ESP32-->
<p class="des">{#SERIAL_CONSOLE}</p>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-8 col-sm-3">{#LOG_PRINT_INVERTER_DATA}</div> <div class="col-8 col-sm-3">{#LOG_PRINT_INVERTER_DATA}</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="serEn"/></div> <div class="col-4 col-sm-9"><input type="checkbox" name="serEn"/></div>
@ -276,6 +273,22 @@
</fieldset> </fieldset>
</div> </div>
<button type="button" class="s_collapsible">{#PINOUT_CONFIG}</button>
<div class="s_content">
<fieldset class="mb-4">
<legend class="des">{#PINOUT_CONFIG}</legend>
<p class="des">Status LEDs</p>
<div id="pinout"></div>
<p class="des">{#RADIO} (NRF24L01+)</p>
<div id="rf24"></div>
<!--IF_ESP32-->
<p class="des">{#RADIO} (CMT2300A)</p>
<div id="cmt"></div>
<!--ENDIF_ESP32-->
</fieldset>
</div>
<button type="button" class="s_collapsible">{#DISPLAY_CONFIG}</button> <button type="button" class="s_collapsible">{#DISPLAY_CONFIG}</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -644,6 +657,11 @@
parseESP(obj); parseESP(obj);
parseRssi(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"]; ts = obj["ts_now"];
window.setInterval("tick()", 1000); window.setInterval("tick()", 1000);
} }

3
src/web/html/visualization.html

@ -366,7 +366,6 @@
} else { } 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("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"}, ml("p", {}, "{#OPEN_ISSUE}."))))
content.push(ml("div", {class: "row"}, ml("div", {class: "col my-2"}, ml("pre", {}, obj.grid))))
} }
} else { } else {
content.push(ml("div", {class: "row"}, content.push(ml("div", {class: "row"},
@ -377,6 +376,8 @@
content.push(parseGridGroup(glob)) 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]))) modal("{#PROFILE_MODAL}: " + obj.name, ml("div", {}, ml("div", {class: "col mb-2"}, [...content])))
}) })

12
src/web/lang.json

@ -149,7 +149,17 @@
"de": "(der Browser-Cache muss geleert oder STRG + F5 gedr&uuml;ckt werden, um diese Einstellung zu aktivieren)" "de": "(der Browser-Cache muss geleert oder STRG + F5 gedr&uuml;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", "en": "Pinout Configuration",
"de": "Anschlusseinstellungen" "de": "Anschlusseinstellungen"
}, },

9
src/web/web.h

@ -482,6 +482,15 @@ class Web {
mConfig->sys.darkMode = (request->arg("darkMode") == "on"); mConfig->sys.darkMode = (request->arg("darkMode") == "on");
mConfig->sys.schedReboot = (request->arg("schedReboot") == "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 // protection
if (request->arg("adminpwd") != "{PWD}") { if (request->arg("adminpwd") != "{PWD}") {
request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN); request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);

Loading…
Cancel
Save