mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-11 07:01:38 +02:00
Merge branch 'VArt67-Merge-to-upstream' into development03
This commit is contained in:
commit
fa32906707
12 changed files with 353 additions and 12 deletions
|
@ -92,6 +92,8 @@ void app::setup() {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
mHistory.setup(this, &mSys, mConfig, &mTimestamp);
|
||||
|
||||
mPubSerial.setup(mConfig, &mSys, &mTimestamp);
|
||||
|
||||
#if !defined(ETHERNET)
|
||||
|
@ -149,6 +151,8 @@ void app::regularTickers(void) {
|
|||
#if !defined(ETHERNET)
|
||||
//everySec([this]() { mImprov.tickSerial(); }, "impro");
|
||||
#endif
|
||||
|
||||
everySec(std::bind(&HistoryType::tickerSecond, mHistory), "hist");
|
||||
}
|
||||
|
||||
#if defined(ETHERNET)
|
||||
|
|
14
src/app.h
14
src/app.h
|
@ -24,6 +24,7 @@
|
|||
#include "utils/scheduler.h"
|
||||
#include "utils/syslog.h"
|
||||
#include "web/RestApi.h"
|
||||
#include "plugins/history.h"
|
||||
#include "web/web.h"
|
||||
#include "hm/Communication.h"
|
||||
#if defined(ETHERNET)
|
||||
|
@ -35,6 +36,7 @@
|
|||
|
||||
#include <RF24.h> // position is relevant since version 1.4.7 of this library
|
||||
|
||||
|
||||
// convert degrees and radians for sun calculation
|
||||
#define SIN(x) (sin(radians(x)))
|
||||
#define COS(x) (cos(radians(x)))
|
||||
|
@ -42,12 +44,11 @@
|
|||
#define ACOS(x) (degrees(acos(x)))
|
||||
|
||||
typedef HmSystem<MAX_NUM_INVERTERS> HmSystemType;
|
||||
#ifdef ESP32
|
||||
#endif
|
||||
typedef Web<HmSystemType> WebType;
|
||||
typedef RestApi<HmSystemType> RestApiType;
|
||||
typedef PubMqtt<HmSystemType> PubMqttType;
|
||||
typedef PubSerial<HmSystemType> PubSerialType;
|
||||
typedef HistoryData<HmSystemType> HistoryType;
|
||||
|
||||
// PLUGINS
|
||||
#if defined(PLUGIN_DISPLAY)
|
||||
|
@ -251,6 +252,14 @@ class app : public IApp, public ah::Scheduler {
|
|||
Scheduler::setTimestamp(newTime);
|
||||
}
|
||||
|
||||
uint16_t getHistoryValue(uint8_t type, uint16_t i) {
|
||||
return mHistory.valueAt((HistoryStorageType)type, i);
|
||||
}
|
||||
|
||||
uint16_t getHistoryMaxDay() {
|
||||
return mHistory.getMaximumDay();
|
||||
}
|
||||
|
||||
private:
|
||||
#define CHECK_AVAIL true
|
||||
#define SKIP_YIELD_DAY true
|
||||
|
@ -358,6 +367,7 @@ class app : public IApp, public ah::Scheduler {
|
|||
DisplayType mDisplay;
|
||||
DisplayData mDispData;
|
||||
#endif
|
||||
HistoryType mHistory;
|
||||
};
|
||||
|
||||
#endif /*__APP_H__*/
|
||||
|
|
|
@ -14,11 +14,6 @@
|
|||
#include "ESPAsyncWebServer.h"
|
||||
#endif
|
||||
|
||||
//#include "hms/hmsRadio.h"
|
||||
#if defined(ESP32)
|
||||
//typedef CmtRadio<esp32_3wSpi<>> CmtRadioType;
|
||||
#endif
|
||||
|
||||
// abstract interface to App. Make members of App accessible from child class
|
||||
// like web or API without forward declaration
|
||||
class IApp {
|
||||
|
@ -65,8 +60,10 @@ class IApp {
|
|||
|
||||
virtual bool getProtection(AsyncWebServerRequest *request) = 0;
|
||||
|
||||
virtual void* getRadioObj(bool nrf) = 0;
|
||||
virtual uint16_t getHistoryValue(uint8_t type, uint16_t i) = 0;
|
||||
virtual uint16_t getHistoryMaxDay() = 0;
|
||||
|
||||
virtual void* getRadioObj(bool nrf) = 0;
|
||||
};
|
||||
|
||||
#endif /*__IAPP_H__*/
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#define PROT_MASK_SYSTEM 0x0020
|
||||
#define PROT_MASK_API 0x0040
|
||||
#define PROT_MASK_MQTT 0x0080
|
||||
#define PROT_MASK_HISTORY 0x0100
|
||||
|
||||
#define DEF_PROT_INDEX 0x0001
|
||||
#define DEF_PROT_LIVE 0x0000
|
||||
|
@ -50,6 +51,7 @@
|
|||
#define DEF_PROT_SYSTEM 0x0020
|
||||
#define DEF_PROT_API 0x0000
|
||||
#define DEF_PROT_MQTT 0x0000
|
||||
#define DEF_PROT_HISTORY 0x0000
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -375,7 +377,7 @@ class settings {
|
|||
// erase all settings and reset to default
|
||||
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;
|
||||
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY;
|
||||
mCfg.sys.darkMode = false;
|
||||
mCfg.sys.schedReboot = false;
|
||||
// restore temp settings
|
||||
|
@ -555,7 +557,7 @@ class settings {
|
|||
|
||||
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;
|
||||
| DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT | DEF_PROT_HISTORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
123
src/plugins/history.h
Normal file
123
src/plugins/history.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 2024 Ahoy, https://ahoydtu.de
|
||||
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __HISTORY_DATA_H__
|
||||
#define __HISTORY_DATA_H__
|
||||
|
||||
#include <array>
|
||||
#include "../appInterface.h"
|
||||
#include "../hm/hmSystem.h"
|
||||
#include "../utils/helper.h"
|
||||
|
||||
#define HISTORY_DATA_ARR_LENGTH 256
|
||||
|
||||
enum class HistoryStorageType : uint8_t {
|
||||
POWER,
|
||||
YIELD
|
||||
};
|
||||
|
||||
template<class HMSYSTEM>
|
||||
class HistoryData {
|
||||
private:
|
||||
struct storage_t {
|
||||
uint16_t refreshCycle;
|
||||
uint16_t loopCnt;
|
||||
uint16_t listIdx; // index for next Element to write into WattArr
|
||||
uint16_t dispIdx; // index for 1st Element to display from WattArr
|
||||
bool wrapped;
|
||||
// ring buffer for watt history
|
||||
std::array<uint16_t, HISTORY_DATA_ARR_LENGTH + 1> data;
|
||||
|
||||
void reset() {
|
||||
loopCnt = 0;
|
||||
listIdx = 0;
|
||||
dispIdx = 0;
|
||||
wrapped = false;
|
||||
for(uint16_t i = 0; i < (HISTORY_DATA_ARR_LENGTH + 1); i++) {
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void setup(IApp *app, HMSYSTEM *sys, settings_t *config, uint32_t *ts) {
|
||||
mApp = app;
|
||||
mSys = sys;
|
||||
mConfig = config;
|
||||
mTs = ts;
|
||||
|
||||
mCurPwr.reset();
|
||||
mCurPwr.refreshCycle = mConfig->inst.sendInterval;
|
||||
mYieldDay.reset();
|
||||
mYieldDay.refreshCycle = 60;
|
||||
}
|
||||
|
||||
void tickerSecond() {
|
||||
Inverter<> *iv;
|
||||
record_t<> *rec;
|
||||
float curPwr = 0;
|
||||
float maxPwr = 0;
|
||||
float yldDay = -0.1;
|
||||
for (uint8_t i = 0; i < mSys->getNumInverters(); i++) {
|
||||
iv = mSys->getInverterByPos(i);
|
||||
rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||
if (iv == NULL)
|
||||
continue;
|
||||
curPwr += iv->getChannelFieldValue(CH0, FLD_PAC, rec);
|
||||
maxPwr += iv->getChannelFieldValue(CH0, FLD_MP, rec);
|
||||
yldDay += iv->getChannelFieldValue(CH0, FLD_YD, rec);
|
||||
}
|
||||
|
||||
if ((++mCurPwr.loopCnt % mCurPwr.refreshCycle) == 0) {
|
||||
mCurPwr.loopCnt = 0;
|
||||
if (curPwr > 0)
|
||||
addValue(&mCurPwr, roundf(curPwr));
|
||||
if (maxPwr > 0)
|
||||
mMaximumDay = roundf(maxPwr);
|
||||
}
|
||||
|
||||
if (*mTs > mApp->getSunset()) {
|
||||
if ((!mDayStored) && (yldDay > 0)) {
|
||||
addValue(&mYieldDay, roundf(yldDay));
|
||||
mDayStored = true;
|
||||
}
|
||||
} else if (*mTs > mApp->getSunrise())
|
||||
mDayStored = false;
|
||||
}
|
||||
|
||||
uint16_t valueAt(HistoryStorageType type, uint16_t i) {
|
||||
storage_t *s = (HistoryStorageType::POWER == type) ? &mCurPwr : &mYieldDay;
|
||||
uint16_t idx = (s->dispIdx + i) % HISTORY_DATA_ARR_LENGTH;
|
||||
return s->data[idx];
|
||||
}
|
||||
|
||||
uint16_t getMaximumDay() {
|
||||
return mMaximumDay;
|
||||
}
|
||||
|
||||
private:
|
||||
void addValue(storage_t *s, uint16_t value) {
|
||||
if (s->wrapped) // after 1st time array wrap we have to increase the display index
|
||||
s->dispIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH);
|
||||
s->data[s->listIdx] = value;
|
||||
s->listIdx = (s->listIdx + 1) % (HISTORY_DATA_ARR_LENGTH);
|
||||
if (s->listIdx == 0)
|
||||
s->wrapped = true;
|
||||
}
|
||||
|
||||
private:
|
||||
IApp *mApp;
|
||||
HMSYSTEM *mSys;
|
||||
settings *mSettings;
|
||||
settings_t *mConfig;
|
||||
uint32_t *mTs;
|
||||
|
||||
storage_t mCurPwr;
|
||||
storage_t mYieldDay;
|
||||
bool mDayStored = false;
|
||||
uint16_t mMaximumDay = 0;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,6 +22,8 @@
|
|||
#include "ESPAsyncWebServer.h"
|
||||
#endif
|
||||
|
||||
#include "plugins/history.h"
|
||||
|
||||
#if defined(F) && defined(ESP32)
|
||||
#undef F
|
||||
#define F(sl) (sl)
|
||||
|
@ -103,6 +105,8 @@ class RestApi {
|
|||
else if(path == "setup/getip") getWifiIp(root);
|
||||
#endif /* !defined(ETHERNET) */
|
||||
else if(path == "live") getLive(request,root);
|
||||
else if (path == "powerHistory") getPowerHistory(request, root);
|
||||
else if (path == "yieldDayHistory") getYieldDayHistory(request, root);
|
||||
else {
|
||||
if(path.substring(0, 12) == "inverter/id/")
|
||||
getInverter(root, request->url().substring(17).toInt());
|
||||
|
@ -197,6 +201,8 @@ class RestApi {
|
|||
ep[F("setup")] = url + F("setup");
|
||||
ep[F("system")] = url + F("system");
|
||||
ep[F("live")] = url + F("live");
|
||||
ep[F("powerHistory")] = url + F("powerHistory");
|
||||
ep[F("yieldDayHistory")] = url + F("yieldDayHistory");
|
||||
}
|
||||
|
||||
|
||||
|
@ -785,6 +791,36 @@ class RestApi {
|
|||
}
|
||||
}
|
||||
|
||||
void getPowerHistory(AsyncWebServerRequest *request, JsonObject obj) {
|
||||
getGeneric(request, obj.createNestedObject(F("generic")));
|
||||
obj[F("refresh")] = mConfig->inst.sendInterval;
|
||||
obj[F("datapoints")] = HISTORY_DATA_ARR_LENGTH;
|
||||
uint16_t max = 0;
|
||||
for (uint16_t fld = 0; fld < HISTORY_DATA_ARR_LENGTH; fld++) {
|
||||
uint16_t value = mApp->getHistoryValue((uint8_t)HistoryStorageType::POWER, fld);
|
||||
obj[F("value")][fld] = value;
|
||||
if (value > max)
|
||||
max = value;
|
||||
}
|
||||
obj[F("max")] = max;
|
||||
obj[F("maxDay")] = mApp->getHistoryMaxDay();
|
||||
}
|
||||
|
||||
void getYieldDayHistory(AsyncWebServerRequest *request, JsonObject obj) {
|
||||
getGeneric(request, obj.createNestedObject(F("generic")));
|
||||
obj[F("refresh")] = 86400; // 1 day
|
||||
obj[F("datapoints")] = HISTORY_DATA_ARR_LENGTH;
|
||||
uint16_t max = 0;
|
||||
for (uint16_t fld = 0; fld < HISTORY_DATA_ARR_LENGTH; fld++) {
|
||||
uint16_t value = mApp->getHistoryValue((uint8_t)HistoryStorageType::YIELD, fld);
|
||||
obj[F("value")][fld] = value;
|
||||
if (value > max)
|
||||
max = value;
|
||||
}
|
||||
obj[F("max")] = max;
|
||||
}
|
||||
|
||||
|
||||
bool setCtrl(JsonObject jsonIn, JsonObject jsonOut) {
|
||||
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")]);
|
||||
bool accepted = true;
|
||||
|
|
|
@ -84,7 +84,7 @@ function topnav() {
|
|||
}
|
||||
|
||||
function parseNav(obj) {
|
||||
for(i = 0; i < 11; i++) {
|
||||
for(i = 0; i < 12; i++) {
|
||||
if(i == 2)
|
||||
continue;
|
||||
var l = document.getElementById("nav"+i);
|
||||
|
|
135
src/web/html/history.html
Normal file
135
src/web/html/history.html
Normal file
|
@ -0,0 +1,135 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>History</title>
|
||||
{#HTML_HEADER}
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{#HTML_NAV}
|
||||
<div id="wrapper">
|
||||
<div id="content">
|
||||
<h3>Total Power history</h3>
|
||||
<div class="chartDivContainer">
|
||||
<div class="chartDiv" id="phHistoryChart"> </div>
|
||||
<p class="center" style="margin:0px;border:0px;">
|
||||
Maximum day: <span id="phMaximumDay"></span> W. Last value: <span id="phActual"></span> W.<br />
|
||||
Maximum graphics: <span id="phMaximum"></span> W. Updated every <span id="phRefresh"></span> seconds </p>
|
||||
</div>
|
||||
<h3>Yield per day history</h3>
|
||||
<div class="chartDivContainer">
|
||||
<div class="chartDiv" id="ydHistoryChart"> </div>
|
||||
<p class="center" style="margin:0px;border:0px;">
|
||||
Maximum value: <span id="ydMaximum"></span> Wh<br />
|
||||
Updated every <span id="ydRefresh"></span> seconds </p>
|
||||
</div>
|
||||
|
||||
<h4 style="margin-bottom:0px;">Insert data into Yield per day history</h4>
|
||||
<fieldset style="padding: 1px;">
|
||||
<legend class="des" style="margin-top: 0px;">Insert data (*.json) i.e. from a saved "/api/yieldDayHistory" call </legend>
|
||||
<form id="form" method="POST" action="/api/insertYieldDayHistory" enctype="multipart/form-data" accept-charset="utf-8">
|
||||
<input type="button" class="btn my-4" style="padding: 3px;margin: 3px;" value="Insert" onclick="submit()">
|
||||
<input type="file" name="insert" style="width: 80%;">
|
||||
</form>
|
||||
</fieldset>
|
||||
<p></p>
|
||||
</div>
|
||||
</div>
|
||||
{#HTML_FOOTER}
|
||||
|
||||
<script type="text/javascript">
|
||||
const svgns = "http://www.w3.org/2000/svg";
|
||||
var phExeOnce = true;
|
||||
var ydExeOnce = true;
|
||||
// make a simple rectangle
|
||||
var mRefresh = 60;
|
||||
var phDatapoints = 512;
|
||||
var mMaximum = 0;
|
||||
var mLastValue = 0;
|
||||
var mDataValues = [];
|
||||
const mChartHight = 250;
|
||||
|
||||
function parseHistory(obj, namePrefix, execOnce) {
|
||||
mRefresh = obj["refresh"];
|
||||
phDatapoints = obj["datapoints"];
|
||||
mDataValues = Object.assign({}, obj["value"]);
|
||||
mMaximum = obj["maximum"];
|
||||
// generate svg
|
||||
if (true == execOnce) {
|
||||
let svg = document.createElementNS(svgns, "svg");
|
||||
svg.setAttribute("class", "chart");
|
||||
svg.setAttribute("width", String((phDatapoints+2) * 2));
|
||||
svg.setAttribute("height", String(mChartHight) + "");
|
||||
svg.setAttribute("aria-labelledby", "title desc");
|
||||
svg.setAttribute("role", "img");
|
||||
t = ml("title");
|
||||
t.innerHTML = "History of day";
|
||||
svg.appendChild(t);
|
||||
let g = document.createElementNS(svgns, "g");
|
||||
svg.appendChild(g);
|
||||
for (var i = 0; i < phDatapoints; i++) {
|
||||
val = mDataValues[i];
|
||||
let rect = document.createElementNS(svgns, "rect");
|
||||
rect.setAttribute("id", namePrefix+"Rect" + i);
|
||||
rect.setAttribute("x", String(i * 2) + "");
|
||||
rect.setAttribute("width", String(2) + "");
|
||||
g.appendChild(rect);
|
||||
}
|
||||
document.getElementById(namePrefix+"HistoryChart").appendChild(svg);
|
||||
}
|
||||
// normalize data to chart
|
||||
let divider = mMaximum / mChartHight;
|
||||
if (divider == 0)
|
||||
divider = 1;
|
||||
for (var i = 0; i < phDatapoints; i++) {
|
||||
val = mDataValues[i];
|
||||
if (val>0)
|
||||
mLastValue = val
|
||||
val = val / divider
|
||||
rect = document.getElementById(namePrefix+"Rect" + i);
|
||||
rect.setAttribute("height", val);
|
||||
rect.setAttribute("y", mChartHight - val);
|
||||
}
|
||||
document.getElementById(namePrefix + "Maximum").innerHTML = mMaximum;
|
||||
if (mRefresh < 5)
|
||||
mRefresh = 5;
|
||||
document.getElementById(namePrefix + "Refresh").innerHTML = mRefresh;
|
||||
}
|
||||
function parsePowerHistory(obj){
|
||||
if (null != obj) {
|
||||
parseNav(obj["generic"]);
|
||||
parseHistory(obj,"ph", phExeOnce)
|
||||
let maximumDay = obj["maximumDay"];
|
||||
document.getElementById("phActual").innerHTML = mLastValue;
|
||||
document.getElementById("phMaximumDay").innerHTML = maximumDay;
|
||||
}
|
||||
if (true == phExeOnce) {
|
||||
phExeOnce = false;
|
||||
window.setInterval("getAjax('/api/powerHistory', parsePowerHistory)", mRefresh * 1000);
|
||||
// one after the other
|
||||
setTimeout(() => {
|
||||
getAjax("/api/yieldDayHistory", parseYieldDayHistory);
|
||||
} , 20);
|
||||
}
|
||||
}
|
||||
function parseYieldDayHistory(obj) {
|
||||
if (null != obj) {
|
||||
parseNav(obj["generic"]);
|
||||
parseHistory(obj, "yd", ydExeOnce)
|
||||
}
|
||||
if (true == ydExeOnce) {
|
||||
ydExeOnce = false;
|
||||
window.setInterval("getAjax('/api/yieldDayHistory', parseYieldDayHistory)", mRefresh * 500);
|
||||
}
|
||||
}
|
||||
|
||||
getAjax("/api/powerHistory", parsePowerHistory);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -7,6 +7,7 @@
|
|||
</a>
|
||||
<div id="topnav" class="mobile">
|
||||
<a id="nav3" class="hide" href="/live?v={#VERSION}">{#NAV_LIVE}</a>
|
||||
<a id="nav11" class="acitve" href="/history?v={#VERSION}">{#NAV_HISTORY}</a>
|
||||
<a id="nav4" class="hide" href="/serial?v={#VERSION}">{#NAV_WEBSERIAL}</a>
|
||||
<a id="nav5" class="hide" href="/setup?v={#VERSION}">{#NAV_SETTINGS}</a>
|
||||
<span class="seperator"></span>
|
||||
|
|
|
@ -33,6 +33,26 @@ textarea {
|
|||
color: var(--fg2);
|
||||
}
|
||||
|
||||
svg rect {fill: #0000AA;}
|
||||
svg.chart {
|
||||
background: #f2f2f2;
|
||||
border: 2px solid gray;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
div.chartDivContainer {
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
}
|
||||
div.chartdivContainer span {
|
||||
color: var(--fg2);
|
||||
}
|
||||
div.chartDiv {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
.topnav {
|
||||
background-color: var(--nav-bg);
|
||||
position: fixed;
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
"en": "Live",
|
||||
"de": "Daten"
|
||||
},
|
||||
{
|
||||
"token": "{#NAV_HISTORY}",
|
||||
"en": "History",
|
||||
"de": "Verlauf"
|
||||
},
|
||||
{
|
||||
"token": "NAV_WEBSERIAL",
|
||||
"en": "Webserial",
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "html/h/visualization_html.h"
|
||||
#include "html/h/about_html.h"
|
||||
#include "html/h/wizard_html.h"
|
||||
#include "html/h/history_html.h"
|
||||
|
||||
#define WEB_SERIAL_BUF_SIZE 2048
|
||||
|
||||
|
@ -82,6 +83,7 @@ class Web {
|
|||
mWeb.on("/save", HTTP_POST, std::bind(&Web::showSave, this, std::placeholders::_1));
|
||||
|
||||
mWeb.on("/live", HTTP_ANY, std::bind(&Web::onLive, this, std::placeholders::_1));
|
||||
mWeb.on("/history", HTTP_ANY, std::bind(&Web::onHistory, this, std::placeholders::_1));
|
||||
|
||||
#ifdef ENABLE_PROMETHEUS_EP
|
||||
mWeb.on("/metrics", HTTP_ANY, std::bind(&Web::showMetrics, this, std::placeholders::_1));
|
||||
|
@ -251,6 +253,8 @@ class Web {
|
|||
request->redirect(F("/index"));
|
||||
else if ((mConfig->sys.protectionMask & PROT_MASK_LIVE) != PROT_MASK_LIVE)
|
||||
request->redirect(F("/live"));
|
||||
else if ((mConfig->sys.protectionMask & PROT_MASK_HISTORY) != PROT_MASK_HISTORY)
|
||||
request->redirect(F("/history"));
|
||||
else if ((mConfig->sys.protectionMask & PROT_MASK_SERIAL) != PROT_MASK_SERIAL)
|
||||
request->redirect(F("/serial"));
|
||||
else if ((mConfig->sys.protectionMask & PROT_MASK_SYSTEM) != PROT_MASK_SYSTEM)
|
||||
|
@ -266,7 +270,7 @@ class Web {
|
|||
}
|
||||
}
|
||||
|
||||
void getPage(AsyncWebServerRequest *request, uint8_t mask, const uint8_t *zippedHtml, uint32_t len) {
|
||||
void getPage(AsyncWebServerRequest *request, uint16_t mask, const uint8_t *zippedHtml, uint32_t len) {
|
||||
if (CHECK_MASK(mConfig->sys.protectionMask, mask))
|
||||
checkProtection(request);
|
||||
|
||||
|
@ -608,6 +612,10 @@ class Web {
|
|||
getPage(request, PROT_MASK_LIVE, visualization_html, visualization_html_len);
|
||||
}
|
||||
|
||||
void onHistory(AsyncWebServerRequest *request) {
|
||||
getPage(request, PROT_MASK_HISTORY, history_html, history_html_len);
|
||||
}
|
||||
|
||||
void onAbout(AsyncWebServerRequest *request) {
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), about_html, about_html_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue