mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-01 19:26:20 +02:00
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
This commit is contained in:
parent
6bb8a4e448
commit
c3fc01b956
12 changed files with 222 additions and 96 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__*/
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Add table
Reference in a new issue