1
0
Fork 0
mirror of https://github.com/lumapu/ahoy.git synced 2025-07-12 05:57:15 +02:00

fix no reconnect at beginning of day

added immediate (each minute) report of inverter status MQTT 
added protection mask to select which pages should be protected
This commit is contained in:
lumapu 2022-12-26 23:32:22 +01:00
parent 6bb8a4e448
commit c3fc01b956
12 changed files with 222 additions and 96 deletions

View file

@ -1,5 +1,10 @@
# Changelog # Changelog
## 0.5.61
* fix #521 no reconnect at beginning of day
* added immediate (each minute) report of inverter status MQTT #522
* added protection mask to select which pages should be protected
## 0.5.60 ## 0.5.60
* added regex to inverter name and MQTT topic (setup.html) * added regex to inverter name and MQTT topic (setup.html)
* beautified serial.html * beautified serial.html

View file

@ -134,6 +134,10 @@ class app : public IApp, public ah::Scheduler {
return mMqtt.getRxCnt(); return mMqtt.getRxCnt();
} }
bool getProtection() {
return mWeb.getProtection();
}
uint8_t getIrqPin(void) { uint8_t getIrqPin(void) {
return mConfig->nrf.pinIrq; return mConfig->nrf.pinIrq;
} }

View file

@ -37,6 +37,8 @@ class IApp {
virtual bool getMqttIsConnected() = 0; virtual bool getMqttIsConnected() = 0;
virtual uint32_t getMqttRxCnt() = 0; virtual uint32_t getMqttRxCnt() = 0;
virtual uint32_t getMqttTxCnt() = 0; virtual uint32_t getMqttTxCnt() = 0;
virtual bool getProtection() = 0;
}; };
#endif /*__IAPP_H__*/ #endif /*__IAPP_H__*/

View file

@ -18,6 +18,26 @@
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */ * */
#define PROT_MASK_INDEX 0x0001
#define PROT_MASK_LIVE 0x0002
#define PROT_MASK_SERIAL 0x0004
#define PROT_MASK_SETUP 0x0008
#define PROT_MASK_UPDATE 0x0010
#define PROT_MASK_SYSTEM 0x0020
#define PROT_MASK_API 0x0040
#define PROT_MASK_MQTT 0x0080
#define DEF_PROT_INDEX 0x0001
#define DEF_PROT_LIVE 0x0000
#define DEF_PROT_SERIAL 0x0004
#define DEF_PROT_SETUP 0x0008
#define DEF_PROT_UPDATE 0x0010
#define DEF_PROT_SYSTEM 0x0020
#define DEF_PROT_API 0x0000
#define DEF_PROT_MQTT 0x0000
typedef struct { typedef struct {
uint8_t ip[4]; // ip address uint8_t ip[4]; // ip address
uint8_t mask[4]; // sub mask uint8_t mask[4]; // sub mask
@ -29,6 +49,7 @@ typedef struct {
typedef struct { typedef struct {
char deviceName[DEVNAME_LEN]; char deviceName[DEVNAME_LEN];
char adminPwd[PWD_LEN]; char adminPwd[PWD_LEN];
uint16_t protectionMask;
// wifi // wifi
char stationSsid[SSID_LEN]; char stationSsid[SSID_LEN];
@ -240,6 +261,8 @@ class settings {
} }
// erase all settings and reset to default // erase all settings and reset to default
memset(&mCfg, 0, sizeof(settings_t)); memset(&mCfg, 0, sizeof(settings_t));
mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT;
// restore temp settings // restore temp settings
if(keepWifi) if(keepWifi)
memcpy(&mCfg.sys, &tmp, sizeof(cfgSys_t)); memcpy(&mCfg.sys, &tmp, sizeof(cfgSys_t));
@ -288,6 +311,7 @@ class settings {
obj[F("pwd")] = mCfg.sys.stationPwd; obj[F("pwd")] = mCfg.sys.stationPwd;
obj[F("dev")] = mCfg.sys.deviceName; obj[F("dev")] = mCfg.sys.deviceName;
obj[F("adm")] = mCfg.sys.adminPwd; obj[F("adm")] = mCfg.sys.adminPwd;
obj[F("prot_mask")] = mCfg.sys.protectionMask;
ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf); ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf);
ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf); ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf);
ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf); ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf);
@ -298,11 +322,16 @@ class settings {
snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as<const char*>()); snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as<const char*>());
snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as<const char*>()); snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as<const char*>());
snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as<const char*>()); snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as<const char*>());
mCfg.sys.protectionMask = obj[F("prot_mask")];
ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as<const char*>()); ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as<const char*>());
ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as<const char*>()); ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as<const char*>());
ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as<const char*>()); ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as<const char*>());
ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as<const char*>()); ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as<const char*>());
ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as<const char*>()); ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as<const char*>());
if(mCfg.sys.protectionMask == 0)
mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT;
} }
} }

View file

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 5 #define VERSION_MINOR 5
#define VERSION_PATCH 60 #define VERSION_PATCH 61
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

View file

@ -36,6 +36,7 @@ class PubMqtt {
mSubscriptionCb = NULL; mSubscriptionCb = NULL;
mIsDay = false; mIsDay = false;
mIvAvail = true; mIvAvail = true;
memset(mLastIvState, 0xff, MAX_NUM_INVERTERS);
} }
~PubMqtt() { } ~PubMqtt() { }
@ -77,6 +78,7 @@ class PubMqtt {
} }
void tickerMinute() { void tickerMinute() {
processIvStatus();
char val[12]; char val[12];
snprintf(val, 12, "%ld", millis() / 1000); snprintf(val, 12, "%ld", millis() / 1000);
publish("uptime", val); publish("uptime", val);
@ -368,27 +370,22 @@ class PubMqtt {
return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId]; return (pos >= DEVICE_CLS_ASSIGN_LIST_LEN) ? NULL : stateClasses[deviceFieldAssignment[pos].stateClsId];
} }
void sendIvData(void) { bool processIvStatus() {
if(mSendList.empty()) // returns true if all inverters are available
return;
char topic[7 + MQTT_TOPIC_LEN], val[40];
float total[4];
bool sendTotal = false;
bool totalIncomplete = false;
bool allAvail = true; bool allAvail = true;
bool first = true; bool first = true;
bool changed = false;
char topic[7 + MQTT_TOPIC_LEN], val[40];
Inverter<> *iv;
record_t<> *rec;
bool totalComplete = true;
while(!mSendList.empty()) {
memset(total, 0, sizeof(float) * 4);
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id); iv = mSys->getInverterByPos(id);
if (NULL == iv) if (NULL == iv)
continue; // skip to next inverter continue; // skip to next inverter
record_t<> *rec = iv->getRecordStruct(mSendList.front()); rec = iv->getRecordStruct(RealTimeRunData_Debug);
if(mSendList.front() == RealTimeRunData_Debug) {
if(first) if(first)
mIvAvail = false; mIvAvail = false;
first = false; first = false;
@ -398,7 +395,7 @@ class PubMqtt {
if ((!iv->isAvailable(*mUtcTimestamp, rec)) || (!iv->config->enabled)) { if ((!iv->isAvailable(*mUtcTimestamp, rec)) || (!iv->config->enabled)) {
status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; status = MQTT_STATUS_NOT_AVAIL_NOT_PROD;
if(iv->config->enabled) { // only change all-avail if inverter is enabled! if(iv->config->enabled) { // only change all-avail if inverter is enabled!
totalIncomplete = true; totalComplete = false;
allAvail = false; allAvail = false;
} }
} }
@ -418,6 +415,9 @@ class PubMqtt {
); );
publish(topic, val, true); publish(topic, val, true);
if(mLastIvState[id] != status) {
mLastIvState[id] = status;
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
snprintf(val, 40, "%d", status); snprintf(val, 40, "%d", status);
publish(topic, val, true); publish(topic, val, true);
@ -426,6 +426,32 @@ class PubMqtt {
snprintf(val, 40, "%d", iv->getLastTs(rec)); snprintf(val, 40, "%d", iv->getLastTs(rec));
publish(topic, val, true); publish(topic, val, true);
} }
}
if(changed) {
snprintf(val, 32, "%s", ((allAvail) ? "online" : ((mIvAvail) ? "partial" : "offline")));
publish("status", val, true);
}
return totalComplete;
}
void sendIvData(void) {
if(mSendList.empty())
return;
char topic[7 + MQTT_TOPIC_LEN], val[40];
float total[4];
bool sendTotal = false;
while(!mSendList.empty()) {
memset(total, 0, sizeof(float) * 4);
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL == iv)
continue; // skip to next inverter
record_t<> *rec = iv->getRecordStruct(mSendList.front());
// data // data
if(iv->isAvailable(*mUtcTimestamp, rec)) { if(iv->isAvailable(*mUtcTimestamp, rec)) {
@ -471,10 +497,7 @@ class PubMqtt {
mSendList.pop(); // remove from list once all inverters were processed mSendList.pop(); // remove from list once all inverters were processed
snprintf(val, 32, "%s", ((allAvail) ? "online" : ((mIvAvail) ? "partial" : "offline"))); if ((true == sendTotal) && processIvStatus()) {
publish("status", val, true);
if ((true == sendTotal) && (false == totalIncomplete)) {
uint8_t fieldId; uint8_t fieldId;
for (uint8_t i = 0; i < 4; i++) { for (uint8_t i = 0; i < 4; i++) {
switch (i) { switch (i) {
@ -514,6 +537,7 @@ class PubMqtt {
subscriptionCb mSubscriptionCb; subscriptionCb mSubscriptionCb;
bool mIsDay; bool mIsDay;
bool mIvAvail; // shows if at least one inverter is available bool mIvAvail; // shows if at least one inverter is available
uint8_t mLastIvState[MAX_NUM_INVERTERS];
// last will topic and payload must be available trough lifetime of 'espMqttClient' // last will topic and payload must be available trough lifetime of 'espMqttClient'
char mLwtTopic[MQTT_TOPIC_LEN+5]; char mLwtTopic[MQTT_TOPIC_LEN+5];

View file

@ -13,6 +13,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <TimeLib.h> #include <TimeLib.h>
#define CHECK_MASK(a,b) ((a & b) == b)
namespace ah { namespace ah {
void ip2Arr(uint8_t ip[], const char *ipStr); void ip2Arr(uint8_t ip[], const char *ipStr);
void ip2Char(uint8_t ip[], char *str); void ip2Char(uint8_t ip[], char *str);

View file

@ -70,8 +70,10 @@ class llist {
elmType *t = p->nxt; elmType *t = p->nxt;
p->nxt->pre = p->pre; p->nxt->pre = p->pre;
p->pre->nxt = p->nxt; p->pre->nxt = p->nxt;
if(root == p) if((root == p) && (p->nxt == p))
root = NULL; root = NULL;
else
root = p->nxt;
p->nxt = NULL; p->nxt = NULL;
p->pre = NULL; p->pre = NULL;
p = NULL; p = NULL;

View file

@ -165,6 +165,7 @@ class RestApi {
obj[F("mac")] = WiFi.macAddress(); obj[F("mac")] = WiFi.macAddress();
obj[F("hostname")] = WiFi.getHostname(); obj[F("hostname")] = WiFi.getHostname();
obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0); obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0);
obj[F("prot_mask")] = mConfig->sys.protectionMask;
obj[F("sdk")] = ESP.getSdkVersion(); obj[F("sdk")] = ESP.getSdkVersion();
obj[F("cpu_freq")] = ESP.getCpuFreqMHz(); obj[F("cpu_freq")] = ESP.getCpuFreqMHz();
@ -324,29 +325,41 @@ class RestApi {
} }
void getMenu(JsonObject obj) { void getMenu(JsonObject obj) {
obj["name"][0] = "Live"; uint8_t i = 0;
obj["link"][0] = "/live"; uint16_t mask = (mApp->getProtection()) ? mConfig->sys.protectionMask : 0;
obj["name"][1] = "Serial / Control"; if(!CHECK_MASK(mask, PROT_MASK_LIVE)) {
obj["link"][1] = "/serial"; obj[F("name")][i] = "Live";
obj["name"][2] = "Settings"; obj[F("link")][i++] = "/live";
obj["link"][2] = "/setup"; }
obj["name"][3] = "-"; if(!CHECK_MASK(mask, PROT_MASK_SERIAL)) {
obj["name"][4] = "REST API"; obj[F("name")][i] = "Serial / Control";
obj["link"][4] = "/api"; obj[F("link")][i++] = "/serial";
obj["trgt"][4] = "_blank"; }
obj["name"][5] = "-"; if(!CHECK_MASK(mask, PROT_MASK_SETUP)) {
obj["name"][6] = "Update"; obj[F("name")][i] = "Settings";
obj["link"][6] = "/update"; obj[F("link")][i++] = "/setup";
obj["name"][7] = "System"; }
obj["link"][7] = "/system"; obj[F("name")][i++] = "-";
obj["name"][8] = "-"; obj[F("name")][i] = "REST API";
obj["name"][9] = "Documentation"; obj[F("link")][i] = "/api";
obj["link"][9] = "https://ahoydtu.de"; obj[F("trgt")][i++] = "_blank";
obj["trgt"][9] = "_blank"; obj[F("name")][i++] = "-";
if(strlen(mConfig->sys.adminPwd) > 0) { if(!CHECK_MASK(mask, PROT_MASK_UPDATE)) {
obj["name"][10] = "-"; obj[F("name")][i] = "Update";
obj["name"][11] = "Logout"; obj[F("link")][i++] = "/update";
obj["link"][11] = "/logout"; }
if(!CHECK_MASK(mask, PROT_MASK_SYSTEM)) {
obj[F("name")][i] = "System";
obj[F("link")][i++] = "/system";
}
obj[F("name")][i++] = "-";
obj[F("name")][i] = "Documentation";
obj[F("link")][i] = "https://ahoydtu.de";
obj[F("trgt")][i++] = "_blank";
if((strlen(mConfig->sys.adminPwd) > 0) && !mApp->getProtection()) {
obj[F("name")][i++] = "-";
obj[F("name")][i] = "Logout";
obj[F("link")][i++] = "/logout";
} }
} }

View file

@ -129,7 +129,7 @@ function lbl(htmlfor, val, cl=null, id=null) {
return e; return e;
} }
function inp(name, val, max=32, cl=["text"], id=null, type=null, pattern=null, title=null) { function inp(name, val, max=32, cl=["text"], id=null, type=null, pattern=null, title=null, checked=null) {
e = document.createElement('input'); e = document.createElement('input');
e.classList.add(...cl); e.classList.add(...cl);
e.name = name; e.name = name;
@ -139,6 +139,7 @@ function inp(name, val, max=32, cl=["text"], id=null, type=null, pattern=null, t
if(null != type) e.type = type; if(null != type) e.type = type;
if(null != pattern) e.pattern = pattern; if(null != pattern) e.pattern = pattern;
if(null != title) e.title = title; if(null != title) e.title = title;
if(null != checked) e.checked = checked;
return e; return e;
} }

View file

@ -37,9 +37,6 @@
<legend class="des">Device Host Name</legend> <legend class="des">Device Host Name</legend>
<label for="device">Device Name</label> <label for="device">Device Name</label>
<input type="text" name="device" class="text"/> <input type="text" name="device" class="text"/>
<label for="adminpwd">Admin Password</label>
<input type="password" name="adminpwd" class="text" value="{PWD}"/>
<input type="hidden" name="disclaimer" value="false" id="disclaimer">
</fieldset> </fieldset>
<button type="button" class="s_collapsible">Network</button> <button type="button" class="s_collapsible">Network</button>
@ -77,6 +74,18 @@
</fieldset> </fieldset>
</div> </div>
<button type="button" class="s_collapsible">Protection</button>
<div class="s_content">
<fieldset>
<legend class="des">Protection</legend>
<label for="adminpwd">Admin Password</label>
<input type="password" name="adminpwd" class="text" value="{PWD}"/>
<input type="hidden" name="disclaimer" value="false" id="disclaimer">
<p>Select pages which should be protected by password</p>
<div id="prot_mask"></div>
</fieldset>
</div>
<button type="button" class="s_collapsible">Inverter</button> <button type="button" class="s_collapsible">Inverter</button>
<div class="s_content"> <div class="s_content">
<fieldset> <fieldset>
@ -347,6 +356,17 @@
var e = document.getElementsByName("adminpwd")[0]; var e = document.getElementsByName("adminpwd")[0];
if(!obj["pwd_set"]) if(!obj["pwd_set"])
e.value = ""; e.value = "";
var d = document.getElementById("prot_mask");
var a = ["Index", "Live", "Serial / Console", "Settings", "Update", "System"]
for(var i = 0; i < 6; i++) {
var chkd = ((obj["prot_mask"] & (1 << i)) == (1 << i));
var sp = lbl("protMask" + i, a[i]);
var cb = inp("protMask" + i, null, null, ["cb"], "protMask" + i, "checkbox", null, null, chkd);
if(0 == i)
d.replaceChildren(sp, cb, br());
else
d.append(sp, cb, br());
}
} }
function parseGeneric(obj) { function parseGeneric(obj) {

View file

@ -121,6 +121,11 @@ class Web {
void setProtection(bool protect) { void setProtection(bool protect) {
mProtected = protect; mProtected = protect;
} }
bool getProtection() {
return mProtected;
}
void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) { void showUpdate2(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
if(!index) { if(!index) {
Serial.printf("Update Start: %s\n", filename.c_str()); Serial.printf("Update Start: %s\n", filename.c_str());
@ -180,10 +185,12 @@ class Web {
void onUpdate(AsyncWebServerRequest *request) { void onUpdate(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onUpdate")); DPRINTLN(DBG_VERBOSE, F("onUpdate"));
/*if(mProtected) { if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_UPDATE)) {
if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
}*/ }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), update_html, update_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), update_html, update_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -221,10 +228,12 @@ class Web {
void onIndex(AsyncWebServerRequest *request) { void onIndex(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onIndex")); DPRINTLN(DBG_VERBOSE, F("onIndex"));
if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_INDEX)) {
if(mProtected) { if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
} }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), index_html, index_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), index_html, index_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -346,10 +355,12 @@ class Web {
void onSetup(AsyncWebServerRequest *request) { void onSetup(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onSetup")); DPRINTLN(DBG_VERBOSE, F("onSetup"));
if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SETUP)) {
if(mProtected) { if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
} }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), setup_html, setup_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), setup_html, setup_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -376,11 +387,17 @@ class Web {
request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN); request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN);
if(request->arg("device") != "") if(request->arg("device") != "")
request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN); request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN);
// 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);
mProtected = (strlen(mConfig->sys.adminPwd) > 0); mProtected = (strlen(mConfig->sys.adminPwd) > 0);
} }
mConfig->sys.protectionMask = 0x0000;
for(uint8_t i = 0; i < 6; i++) {
if(request->arg("protMask" + String(i)) == "on")
mConfig->sys.protectionMask |= (1 << i);
}
// static ip // static ip
request->arg("ipAddr").toCharArray(buf, 20); request->arg("ipAddr").toCharArray(buf, 20);
@ -501,10 +518,12 @@ class Web {
void onLive(AsyncWebServerRequest *request) { void onLive(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onLive")); DPRINTLN(DBG_VERBOSE, F("onLive"));
if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) {
if(mProtected) { if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
} }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), visualization_html, visualization_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), visualization_html, visualization_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -579,10 +598,12 @@ class Web {
void onSerial(AsyncWebServerRequest *request) { void onSerial(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onSerial")); DPRINTLN(DBG_VERBOSE, F("onSerial"));
if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SERIAL)) {
if(mProtected) { if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
} }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), serial_html, serial_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), serial_html, serial_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");
@ -592,10 +613,12 @@ class Web {
void onSystem(AsyncWebServerRequest *request) { void onSystem(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onSystem")); DPRINTLN(DBG_VERBOSE, F("onSystem"));
if(CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_SYSTEM)) {
if(mProtected) { if(mProtected) {
request->redirect("/login"); request->redirect("/login");
return; return;
} }
}
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len); AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len);
response->addHeader(F("Content-Encoding"), "gzip"); response->addHeader(F("Content-Encoding"), "gzip");