mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-24 06:16:11 +02:00
added login / logout
prepared static IP storage and disable inverter IMPORTANT: new memory layout, your inverter settings will be lost
This commit is contained in:
parent
56b8096bed
commit
6a6d522d3b
11 changed files with 290 additions and 31 deletions
|
@ -44,6 +44,9 @@ void app::setup(uint32_t timeout) {
|
||||||
|
|
||||||
mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion);
|
mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion);
|
||||||
mWebInst->setup();
|
mWebInst->setup();
|
||||||
|
mWebInst->setProtection(strlen(mConfig.password) != 0);
|
||||||
|
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettingsValid) ? F("true") : F("false")));
|
||||||
|
DPRINTLN(DBG_INFO, F("EEprom storage size: 0x") + String(ADDR_SETTINGS_CRC, HEX));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -58,6 +61,13 @@ void app::loop(void) {
|
||||||
mUptimeSecs++;
|
mUptimeSecs++;
|
||||||
if (0 != mUtcTimestamp)
|
if (0 != mUtcTimestamp)
|
||||||
mUtcTimestamp++;
|
mUtcTimestamp++;
|
||||||
|
|
||||||
|
mWebInst->tickSecond();
|
||||||
|
|
||||||
|
if (mShouldReboot) {
|
||||||
|
DPRINTLN(DBG_INFO, F("Rebooting..."));
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) {
|
if (checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) {
|
||||||
|
@ -76,11 +86,6 @@ void app::loop(void) {
|
||||||
sendMqttDiscoveryConfig();
|
sendMqttDiscoveryConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mShouldReboot) {
|
|
||||||
DPRINTLN(DBG_INFO, F("Rebooting..."));
|
|
||||||
ESP.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
mSys->Radio.loop();
|
mSys->Radio.loop();
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
|
@ -743,6 +748,9 @@ void app::loadDefaultConfig(void) {
|
||||||
snprintf(mSysConfig.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID);
|
snprintf(mSysConfig.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID);
|
||||||
snprintf(mSysConfig.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD);
|
snprintf(mSysConfig.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD);
|
||||||
|
|
||||||
|
// password
|
||||||
|
snprintf(mConfig.password, PWD_LEN, "%s", GUI_DEF_PASSWORD);
|
||||||
|
|
||||||
// nrf24
|
// nrf24
|
||||||
mConfig.sendInterval = SEND_INTERVAL;
|
mConfig.sendInterval = SEND_INTERVAL;
|
||||||
mConfig.maxRetransPerPyld = DEF_MAX_RETRANS_PER_PYLD;
|
mConfig.maxRetransPerPyld = DEF_MAX_RETRANS_PER_PYLD;
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
// If the next line is uncommented, Ahoy will stay in access point mode all the time
|
// If the next line is uncommented, Ahoy will stay in access point mode all the time
|
||||||
//#define AP_ONLY
|
//#define AP_ONLY
|
||||||
|
|
||||||
|
// protection of the GUI by password
|
||||||
|
#define GUI_DEF_PASSWORD ""
|
||||||
|
|
||||||
|
// timeout for automatic logoff (20 minutes)
|
||||||
|
#define LOGOUT_TIMEOUT (20 * 60 * 60)
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
// CONFIGURATION - COMPILE TIME
|
// CONFIGURATION - COMPILE TIME
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 29
|
#define VERSION_PATCH 30
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -87,6 +87,7 @@ typedef enum {
|
||||||
#define INV_CH_CH_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH * 4 // (4 channels)
|
#define INV_CH_CH_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH * 4 // (4 channels)
|
||||||
#define INV_INTERVAL_LEN 2 // uint16_t
|
#define INV_INTERVAL_LEN 2 // uint16_t
|
||||||
#define INV_MAX_RTRY_LEN 1 // uint8_t
|
#define INV_MAX_RTRY_LEN 1 // uint8_t
|
||||||
|
#define INV_ENABLED_LEN 1 // uint8_t
|
||||||
|
|
||||||
#define CFG_SUN_LEN 9 // 2x float(4+4) + bool(1)
|
#define CFG_SUN_LEN 9 // 2x float(4+4) + bool(1)
|
||||||
|
|
||||||
|
@ -112,6 +113,8 @@ typedef struct {
|
||||||
#pragma pack(pop) // restore original alignment from stack
|
#pragma pack(pop) // restore original alignment from stack
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push) // push current alignment to stack
|
||||||
|
#pragma pack(1) // set alignment to 1 byte boundary
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char deviceName[DEVNAME_LEN];
|
char deviceName[DEVNAME_LEN];
|
||||||
|
|
||||||
|
@ -119,10 +122,15 @@ typedef struct {
|
||||||
char stationSsid[SSID_LEN];
|
char stationSsid[SSID_LEN];
|
||||||
char stationPwd[PWD_LEN];
|
char stationPwd[PWD_LEN];
|
||||||
} sysConfig_t;
|
} sysConfig_t;
|
||||||
|
#pragma pack(pop) // restore original alignment from stack
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push) // push current alignment to stack
|
#pragma pack(push) // push current alignment to stack
|
||||||
#pragma pack(1) // set alignment to 1 byte boundary
|
#pragma pack(1) // set alignment to 1 byte boundary
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
// protection
|
||||||
|
char password[PWD_LEN];
|
||||||
|
|
||||||
// nrf24
|
// nrf24
|
||||||
uint16_t sendInterval;
|
uint16_t sendInterval;
|
||||||
uint8_t maxRetransPerPyld;
|
uint8_t maxRetransPerPyld;
|
||||||
|
@ -150,6 +158,9 @@ typedef struct {
|
||||||
uint16_t serialInterval;
|
uint16_t serialInterval;
|
||||||
bool serialShowIv;
|
bool serialShowIv;
|
||||||
bool serialDebug;
|
bool serialDebug;
|
||||||
|
|
||||||
|
// static ip placeholder
|
||||||
|
uint32_t staticIp[4];
|
||||||
} config_t;
|
} config_t;
|
||||||
#pragma pack(pop) // restore original alignment from stack
|
#pragma pack(pop) // restore original alignment from stack
|
||||||
|
|
||||||
|
@ -162,7 +173,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
#define CFG_MQTT_LEN MQTT_ADDR_LEN + 2 + MQTT_USER_LEN + MQTT_PWD_LEN +MQTT_TOPIC_LEN
|
#define CFG_MQTT_LEN MQTT_ADDR_LEN + 2 + MQTT_USER_LEN + MQTT_PWD_LEN +MQTT_TOPIC_LEN
|
||||||
#define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN + 1
|
#define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN
|
||||||
#define CFG_LEN 7 + NTP_ADDR_LEN + 2 + CFG_MQTT_LEN + CFG_SUN_LEN + 4 + DISCLAIMER
|
#define CFG_LEN 7 + NTP_ADDR_LEN + 2 + CFG_MQTT_LEN + CFG_SUN_LEN + 4 + DISCLAIMER
|
||||||
|
|
||||||
#define ADDR_START 0
|
#define ADDR_START 0
|
||||||
|
@ -179,8 +190,9 @@ typedef struct {
|
||||||
#define ADDR_INV_CH_NAME ADDR_INV_CH_PWR + INV_CH_CH_PWR_LEN
|
#define ADDR_INV_CH_NAME ADDR_INV_CH_PWR + INV_CH_CH_PWR_LEN
|
||||||
#define ADDR_INV_INTERVAL ADDR_INV_CH_NAME + INV_CH_CH_NAME_LEN
|
#define ADDR_INV_INTERVAL ADDR_INV_CH_NAME + INV_CH_CH_NAME_LEN
|
||||||
#define ADDR_INV_MAX_RTRY ADDR_INV_INTERVAL + INV_INTERVAL_LEN
|
#define ADDR_INV_MAX_RTRY ADDR_INV_INTERVAL + INV_INTERVAL_LEN
|
||||||
|
#define ADDR_INV_ENABLED ADDR_INV_MAX_RTRY + INV_MAX_RTRY_LEN
|
||||||
|
|
||||||
#define ADDR_NEXT ADDR_INV_MAX_RTRY + INV_INTERVAL_LEN
|
#define ADDR_NEXT ADDR_INV_MAX_RTRY + INV_ENABLED_LEN
|
||||||
|
|
||||||
|
|
||||||
#define ADDR_SETTINGS_CRC ADDR_NEXT + 2
|
#define ADDR_SETTINGS_CRC ADDR_NEXT + 2
|
||||||
|
|
42
tools/esp8266/html/login.html
Normal file
42
tools/esp8266/html/login.html
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Login</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<script type="text/javascript" src="api.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
<div id="login">
|
||||||
|
<div class="pad">
|
||||||
|
<form action="/login" method="post">
|
||||||
|
<h2>AhoyDTU</h2>
|
||||||
|
<input type="password" name="pwd" value="">
|
||||||
|
<input type="submit" name="login" value="login" class="btn">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<div class="left">
|
||||||
|
<a href="https://ahoydtu.de" target="_blank">AhoyDTU © 2022</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://discord.gg/WzhxEY62mB" target="_blank">Discord</a></li>
|
||||||
|
<li><a href="https://github.com/lumapu/ahoy" target="_blank">Github</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<span id="version"></span><br/><br/>
|
||||||
|
<a href="https://creativecommons.org/licenses/by-nc-sa/3.0/de" target="_blank" >CC BY-NC-SA 3.0</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function parse(obj) {
|
||||||
|
parseVersion(obj["system"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAjax("/api/index", parse);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -36,6 +36,8 @@
|
||||||
<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">
|
<input type="hidden" name="disclaimer" value="false" id="disclaimer">
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
|
@ -414,3 +414,26 @@ div.ModPwr, div.ModName {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#login {
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #eee;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
margin-top: -160px;
|
||||||
|
margin-left: -150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login .pad {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login .pad input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 7px 0 7px 0;
|
||||||
|
border: 0px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -17,11 +17,7 @@
|
||||||
<div id="topnav" class="hide"></div>
|
<div id="topnav" class="hide"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div id="content">
|
<div id="content"></div>
|
||||||
<a href="/factory" class="btn">Factory Reset</a><br/>
|
|
||||||
<br/>
|
|
||||||
<a href="/reboot" class="btn">Reboot</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
|
@ -45,10 +41,19 @@
|
||||||
if(null != obj) {
|
if(null != obj) {
|
||||||
parseMenu(obj["menu"]);
|
parseMenu(obj["menu"]);
|
||||||
parseSys(obj["system"]);
|
parseSys(obj["system"]);
|
||||||
|
var e = document.getElementById("content");
|
||||||
|
e.innerHTML = obj["html"];
|
||||||
|
|
||||||
|
if(null != obj["refresh"]) {
|
||||||
|
var meta = document.createElement('meta');
|
||||||
|
meta.httpEquiv = "refresh"
|
||||||
|
meta.content = obj["refresh"] + "; URL=" + obj["refresh_url"];
|
||||||
|
document.getElementsByTagName('head')[0].appendChild(meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAjax("/api/index", parse);
|
getAjax("/api" + window.location.pathname, parse);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "web.h"
|
#include "web.h"
|
||||||
|
|
||||||
#include "html/h/index_html.h"
|
#include "html/h/index_html.h"
|
||||||
|
#include "html/h/login_html.h"
|
||||||
#include "html/h/style_css.h"
|
#include "html/h/style_css.h"
|
||||||
#include "html/h/api_js.h"
|
#include "html/h/api_js.h"
|
||||||
#include "html/h/favicon_ico_gz.h"
|
#include "html/h/favicon_ico_gz.h"
|
||||||
|
@ -33,6 +34,9 @@ web::web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, c
|
||||||
mEvts = new AsyncEventSource("/events");
|
mEvts = new AsyncEventSource("/events");
|
||||||
mApi = new webApi(mWeb, main, sysCfg, config, stat, version);
|
mApi = new webApi(mWeb, main, sysCfg, config, stat, version);
|
||||||
|
|
||||||
|
mProtected = true;
|
||||||
|
mLogoutTimeout = 0;
|
||||||
|
|
||||||
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
|
memset(mSerialBuf, 0, WEB_SERIAL_BUF_SIZE);
|
||||||
mSerialBufFill = 0;
|
mSerialBufFill = 0;
|
||||||
mWebSerialTicker = 0;
|
mWebSerialTicker = 0;
|
||||||
|
@ -47,6 +51,8 @@ void web::setup(void) {
|
||||||
mWeb->begin();
|
mWeb->begin();
|
||||||
DPRINTLN(DBG_VERBOSE, F("app::setup-on"));
|
DPRINTLN(DBG_VERBOSE, F("app::setup-on"));
|
||||||
mWeb->on("/", HTTP_GET, std::bind(&web::onIndex, this, std::placeholders::_1));
|
mWeb->on("/", HTTP_GET, std::bind(&web::onIndex, this, std::placeholders::_1));
|
||||||
|
mWeb->on("/login", HTTP_ANY, std::bind(&web::onLogin, this, std::placeholders::_1));
|
||||||
|
mWeb->on("/logout", HTTP_GET, std::bind(&web::onLogout, this, std::placeholders::_1));
|
||||||
mWeb->on("/style.css", HTTP_GET, std::bind(&web::onCss, this, std::placeholders::_1));
|
mWeb->on("/style.css", HTTP_GET, std::bind(&web::onCss, this, std::placeholders::_1));
|
||||||
mWeb->on("/api.js", HTTP_GET, std::bind(&web::onApiJs, this, std::placeholders::_1));
|
mWeb->on("/api.js", HTTP_GET, std::bind(&web::onApiJs, this, std::placeholders::_1));
|
||||||
mWeb->on("/favicon.ico", HTTP_GET, std::bind(&web::onFavicon, this, std::placeholders::_1));
|
mWeb->on("/favicon.ico", HTTP_GET, std::bind(&web::onFavicon, this, std::placeholders::_1));
|
||||||
|
@ -77,7 +83,6 @@ void web::setup(void) {
|
||||||
registerDebugCb(std::bind(&web::serialCb, this, std::placeholders::_1));
|
registerDebugCb(std::bind(&web::serialCb, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::loop(void) {
|
void web::loop(void) {
|
||||||
mApi->loop();
|
mApi->loop();
|
||||||
|
@ -91,6 +96,21 @@ void web::loop(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void web::tickSecond(void) {
|
||||||
|
if(0 != mLogoutTimeout) {
|
||||||
|
mLogoutTimeout -= 1;
|
||||||
|
if(0 == mLogoutTimeout)
|
||||||
|
mProtected = true;
|
||||||
|
|
||||||
|
DPRINTLN(DBG_DEBUG, "auto logout in " + String(mLogoutTimeout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void web::setProtection(bool protect) {
|
||||||
|
mProtected = protect;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::onConnect(AsyncEventSourceClient *client) {
|
void web::onConnect(AsyncEventSourceClient *client) {
|
||||||
|
@ -107,14 +127,37 @@ void web::onConnect(AsyncEventSourceClient *client) {
|
||||||
void web::onIndex(AsyncWebServerRequest *request) {
|
void web::onIndex(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onIndex"));
|
DPRINTLN(DBG_VERBOSE, F("onIndex"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
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");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void web::onLogin(AsyncWebServerRequest *request) {
|
||||||
|
DPRINTLN(DBG_VERBOSE, F("onLogin"));
|
||||||
|
|
||||||
|
if(request->args() > 0) {
|
||||||
|
if(String(request->arg("pwd")) == String(mConfig->password)) {
|
||||||
|
mProtected = false;
|
||||||
|
request->redirect("/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), login_html, login_html_len);
|
||||||
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::onCss(AsyncWebServerRequest *request) {
|
void web::onCss(AsyncWebServerRequest *request) {
|
||||||
|
mLogoutTimeout = LOGOUT_TIMEOUT;
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len);
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len);
|
||||||
response->addHeader(F("Content-Encoding"), "gzip");
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
@ -163,7 +206,9 @@ void web::showNotFound(AsyncWebServerRequest *request) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::onReboot(AsyncWebServerRequest *request) {
|
void web::onReboot(AsyncWebServerRequest *request) {
|
||||||
mMain->mShouldReboot = true;
|
mMain->mShouldReboot = true;
|
||||||
request->send(200, F("text/html"), F("<!doctype html><html><head><title>Reboot</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta http-equiv=\"refresh\" content=\"10; URL=/\"></head><body>reboot. Autoreload after 10 seconds</body></html>"));
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len);
|
||||||
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,6 +216,28 @@ void web::onReboot(AsyncWebServerRequest *request) {
|
||||||
void web::onSystem(AsyncWebServerRequest *request) {
|
void web::onSystem(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onSystem"));
|
DPRINTLN(DBG_VERBOSE, F("onSystem"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len);
|
||||||
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void web::onLogout(AsyncWebServerRequest *request) {
|
||||||
|
DPRINTLN(DBG_VERBOSE, F("onLogout"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mProtected = true;
|
||||||
|
|
||||||
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");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
@ -179,6 +246,11 @@ void web::onSystem(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::showErase(AsyncWebServerRequest *request) {
|
void web::showErase(AsyncWebServerRequest *request) {
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("showErase"));
|
DPRINTLN(DBG_VERBOSE, F("showErase"));
|
||||||
mMain->eraseSettings();
|
mMain->eraseSettings();
|
||||||
onReboot(request);
|
onReboot(request);
|
||||||
|
@ -187,6 +259,11 @@ void web::showErase(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void web::showFactoryRst(AsyncWebServerRequest *request) {
|
void web::showFactoryRst(AsyncWebServerRequest *request) {
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("showFactoryRst"));
|
DPRINTLN(DBG_VERBOSE, F("showFactoryRst"));
|
||||||
String content = "";
|
String content = "";
|
||||||
int refresh = 3;
|
int refresh = 3;
|
||||||
|
@ -218,6 +295,11 @@ void web::showFactoryRst(AsyncWebServerRequest *request) {
|
||||||
void web::onSetup(AsyncWebServerRequest *request) {
|
void web::onSetup(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onSetup"));
|
DPRINTLN(DBG_VERBOSE, F("onSetup"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
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");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
@ -228,6 +310,11 @@ void web::onSetup(AsyncWebServerRequest *request) {
|
||||||
void web::showSave(AsyncWebServerRequest *request) {
|
void web::showSave(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("showSave"));
|
DPRINTLN(DBG_VERBOSE, F("showSave"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(request->args() > 0) {
|
if(request->args() > 0) {
|
||||||
char buf[20] = {0};
|
char buf[20] = {0};
|
||||||
|
|
||||||
|
@ -238,6 +325,10 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
request->arg("pwd").toCharArray(mSysCfg->stationPwd, PWD_LEN);
|
request->arg("pwd").toCharArray(mSysCfg->stationPwd, PWD_LEN);
|
||||||
if(request->arg("device") != "")
|
if(request->arg("device") != "")
|
||||||
request->arg("device").toCharArray(mSysCfg->deviceName, DEVNAME_LEN);
|
request->arg("device").toCharArray(mSysCfg->deviceName, DEVNAME_LEN);
|
||||||
|
if(request->arg("adminpwd") != "{PWD}") {
|
||||||
|
request->arg("adminpwd").toCharArray(mConfig->password, PWD_LEN);
|
||||||
|
mProtected = true;
|
||||||
|
}
|
||||||
|
|
||||||
// inverter
|
// inverter
|
||||||
Inverter<> *iv;
|
Inverter<> *iv;
|
||||||
|
@ -333,9 +424,11 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
if(request->arg("reboot") == "on")
|
if(request->arg("reboot") == "on")
|
||||||
onReboot(request);
|
onReboot(request);
|
||||||
else
|
else {
|
||||||
request->send(200, F("text/html"), F("<!doctype html><html><head><title>Setup saved</title><meta http-equiv=\"refresh\" content=\"0; URL=/setup\"></head><body>"
|
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len);
|
||||||
"<p>saved</p></body></html>"));
|
response->addHeader(F("Content-Encoding"), "gzip");
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,6 +437,11 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
void web::onLive(AsyncWebServerRequest *request) {
|
void web::onLive(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onLive"));
|
DPRINTLN(DBG_VERBOSE, F("onLive"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
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");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
@ -420,6 +518,10 @@ void web::showWebApi(AsyncWebServerRequest *request) {
|
||||||
void web::onUpdate(AsyncWebServerRequest *request) {
|
void web::onUpdate(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onUpdate"));
|
DPRINTLN(DBG_VERBOSE, F("onUpdate"));
|
||||||
|
|
||||||
|
/*if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
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");
|
||||||
|
@ -475,6 +577,11 @@ void web::showUpdate2(AsyncWebServerRequest *request, String filename, size_t in
|
||||||
void web::onSerial(AsyncWebServerRequest *request) {
|
void web::onSerial(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onSerial"));
|
DPRINTLN(DBG_VERBOSE, F("onSerial"));
|
||||||
|
|
||||||
|
if(mProtected) {
|
||||||
|
request->redirect("/login");
|
||||||
|
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");
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|
|
@ -29,10 +29,15 @@ class web {
|
||||||
|
|
||||||
void setup(void);
|
void setup(void);
|
||||||
void loop(void);
|
void loop(void);
|
||||||
|
void tickSecond(void);
|
||||||
|
|
||||||
|
void setProtection(bool protect);
|
||||||
|
|
||||||
void onConnect(AsyncEventSourceClient *client);
|
void onConnect(AsyncEventSourceClient *client);
|
||||||
|
|
||||||
void onIndex(AsyncWebServerRequest *request);
|
void onIndex(AsyncWebServerRequest *request);
|
||||||
|
void onLogin(AsyncWebServerRequest *request);
|
||||||
|
void onLogout(AsyncWebServerRequest *request);
|
||||||
void onCss(AsyncWebServerRequest *request);
|
void onCss(AsyncWebServerRequest *request);
|
||||||
void onApiJs(AsyncWebServerRequest *request);
|
void onApiJs(AsyncWebServerRequest *request);
|
||||||
void onFavicon(AsyncWebServerRequest *request);
|
void onFavicon(AsyncWebServerRequest *request);
|
||||||
|
@ -58,6 +63,8 @@ class web {
|
||||||
|
|
||||||
AsyncWebServer *mWeb;
|
AsyncWebServer *mWeb;
|
||||||
AsyncEventSource *mEvts;
|
AsyncEventSource *mEvts;
|
||||||
|
bool mProtected;
|
||||||
|
uint32_t mLogoutTimeout;
|
||||||
|
|
||||||
config_t *mConfig;
|
config_t *mConfig;
|
||||||
sysConfig_t *mSysCfg;
|
sysConfig_t *mSysCfg;
|
||||||
|
|
|
@ -22,7 +22,6 @@ webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *con
|
||||||
mTimezoneOffset = 0;
|
mTimezoneOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::setup(void) {
|
void webApi::setup(void) {
|
||||||
mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1));
|
mSrv->on("/api", HTTP_GET, std::bind(&webApi::onApi, this, std::placeholders::_1));
|
||||||
|
@ -32,7 +31,6 @@ void webApi::setup(void) {
|
||||||
mSrv->on("/get_setup", HTTP_GET, std::bind(&webApi::onDwnldSetup, this, std::placeholders::_1));
|
mSrv->on("/get_setup", HTTP_GET, std::bind(&webApi::onDwnldSetup, this, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::loop(void) {
|
void webApi::loop(void) {
|
||||||
}
|
}
|
||||||
|
@ -46,6 +44,9 @@ void webApi::onApi(AsyncWebServerRequest *request) {
|
||||||
Inverter<> *iv = mApp->mSys->getInverterByPos(0, false);
|
Inverter<> *iv = mApp->mSys->getInverterByPos(0, false);
|
||||||
String path = request->url().substring(5);
|
String path = request->url().substring(5);
|
||||||
if(path == "system") getSystem(root);
|
if(path == "system") getSystem(root);
|
||||||
|
else if(path == "logout") getLogout(root);
|
||||||
|
else if(path == "save") getSave(root);
|
||||||
|
else if(path == "reboot") getReboot(root);
|
||||||
else if(path == "statistics") getStatistics(root);
|
else if(path == "statistics") getStatistics(root);
|
||||||
else if(path == "inverter/list") getInverterList(root);
|
else if(path == "inverter/list") getInverterList(root);
|
||||||
else if(path == "menu") getMenu(root);
|
else if(path == "menu") getMenu(root);
|
||||||
|
@ -140,7 +141,7 @@ void webApi::onDwnldSetup(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getSystem(JsonObject obj) {
|
void webApi::getSysInfo(JsonObject obj) {
|
||||||
obj[F("ssid")] = mSysCfg->stationSsid;
|
obj[F("ssid")] = mSysCfg->stationSsid;
|
||||||
obj[F("device_name")] = mSysCfg->deviceName;
|
obj[F("device_name")] = mSysCfg->deviceName;
|
||||||
obj[F("version")] = String(mVersion);
|
obj[F("version")] = String(mVersion);
|
||||||
|
@ -160,6 +161,44 @@ void webApi::getSystem(JsonObject obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void webApi::getSystem(JsonObject obj) {
|
||||||
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
|
obj[F("html")] = F("<a href=\"/factory\" class=\"btn\">Factory Reset</a><br/><br/><a href=\"/reboot\" class=\"btn\">Reboot</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void webApi::getLogout(JsonObject obj) {
|
||||||
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
|
obj[F("refresh")] = 3;
|
||||||
|
obj[F("refresh_url")] = "/";
|
||||||
|
obj[F("html")] = F("succesfully logged out");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void webApi::getSave(JsonObject obj) {
|
||||||
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
|
obj[F("refresh")] = 2;
|
||||||
|
obj[F("refresh_url")] = "/setup";
|
||||||
|
obj[F("html")] = F("settings succesfully save");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void webApi::getReboot(JsonObject obj) {
|
||||||
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
|
obj[F("refresh")] = 10;
|
||||||
|
obj[F("refresh_url")] = "/";
|
||||||
|
obj[F("html")] = F("reboot. Autoreload after 10 seconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getStatistics(JsonObject obj) {
|
void webApi::getStatistics(JsonObject obj) {
|
||||||
obj[F("rx_success")] = mStat->rxSuccess;
|
obj[F("rx_success")] = mStat->rxSuccess;
|
||||||
|
@ -260,13 +299,18 @@ void webApi::getMenu(JsonObject obj) {
|
||||||
obj["link"][6] = "/update";
|
obj["link"][6] = "/update";
|
||||||
obj["name"][7] = "System";
|
obj["name"][7] = "System";
|
||||||
obj["link"][7] = "/system";
|
obj["link"][7] = "/system";
|
||||||
|
if(strlen(mConfig->password) > 0) {
|
||||||
|
obj["name"][8] = "-";
|
||||||
|
obj["name"][9] = "Logout";
|
||||||
|
obj["link"][9] = "/logout";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getIndex(JsonObject obj) {
|
void webApi::getIndex(JsonObject obj) {
|
||||||
getMenu(obj.createNestedObject(F("menu")));
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
getSystem(obj.createNestedObject(F("system")));
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
getStatistics(obj.createNestedObject(F("statistics")));
|
getStatistics(obj.createNestedObject(F("statistics")));
|
||||||
obj["refresh_interval"] = SEND_INTERVAL;
|
obj["refresh_interval"] = SEND_INTERVAL;
|
||||||
|
|
||||||
|
@ -305,7 +349,7 @@ void webApi::getIndex(JsonObject obj) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getSetup(JsonObject obj) {
|
void webApi::getSetup(JsonObject obj) {
|
||||||
getMenu(obj.createNestedObject(F("menu")));
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
getSystem(obj.createNestedObject(F("system")));
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
getInverterList(obj.createNestedObject(F("inverter")));
|
getInverterList(obj.createNestedObject(F("inverter")));
|
||||||
getMqtt(obj.createNestedObject(F("mqtt")));
|
getMqtt(obj.createNestedObject(F("mqtt")));
|
||||||
getNtp(obj.createNestedObject(F("ntp")));
|
getNtp(obj.createNestedObject(F("ntp")));
|
||||||
|
@ -325,7 +369,7 @@ void webApi::getNetworks(JsonObject obj) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getLive(JsonObject obj) {
|
void webApi::getLive(JsonObject obj) {
|
||||||
getMenu(obj.createNestedObject(F("menu")));
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
getSystem(obj.createNestedObject(F("system")));
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
JsonArray invArr = obj.createNestedArray(F("inverter"));
|
JsonArray invArr = obj.createNestedArray(F("inverter"));
|
||||||
obj["refresh_interval"] = SEND_INTERVAL;
|
obj["refresh_interval"] = SEND_INTERVAL;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,11 @@ class webApi {
|
||||||
void getNotFound(JsonObject obj, String url);
|
void getNotFound(JsonObject obj, String url);
|
||||||
void onDwnldSetup(AsyncWebServerRequest *request);
|
void onDwnldSetup(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
void getSysInfo(JsonObject obj);
|
||||||
void getSystem(JsonObject obj);
|
void getSystem(JsonObject obj);
|
||||||
|
void getLogout(JsonObject obj);
|
||||||
|
void getSave(JsonObject obj);
|
||||||
|
void getReboot(JsonObject obj);
|
||||||
void getStatistics(JsonObject obj);
|
void getStatistics(JsonObject obj);
|
||||||
void getInverterList(JsonObject obj);
|
void getInverterList(JsonObject obj);
|
||||||
void getMqtt(JsonObject obj);
|
void getMqtt(JsonObject obj);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue