mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-10 07:26:38 +02:00
* improved api (now webApi)
* converted index to static page
This commit is contained in:
parent
08d8658737
commit
440d386ec0
11 changed files with 266 additions and 240 deletions
|
@ -42,7 +42,7 @@ void app::setup(uint32_t timeout) {
|
|||
#endif
|
||||
mSys->setup(&mConfig);
|
||||
|
||||
mWebInst = new web(this, &mSysConfig, &mConfig, mVersion);
|
||||
mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion);
|
||||
mWebInst->setup();
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ void app::loop(void) {
|
|||
DPRINT(DBG_INFO, "RX " + String(len) + "B Ch" + String(p->rxCh) + " | ");
|
||||
mSys->Radio.dumpBuf(NULL, p->packet, len);
|
||||
}
|
||||
mFrameCnt++;
|
||||
mStat.frmCnt++;
|
||||
|
||||
if(0 != len) {
|
||||
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
|
||||
|
@ -231,7 +231,7 @@ void app::loop(void) {
|
|||
processPayload(false);
|
||||
|
||||
if(!mPayload[iv->id].complete) {
|
||||
mRxFailed++;
|
||||
mStat.rxFail++;
|
||||
iv->setQueuedCmdFinished(); // command failed
|
||||
if(mConfig.serialDebug) {
|
||||
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
|
||||
|
@ -358,7 +358,7 @@ void app::processPayload(bool retransmit) {
|
|||
DPRINT(DBG_INFO, F("Payload (") + String(offs) + "): ");
|
||||
mSys->Radio.dumpBuf(NULL, payload, offs);
|
||||
}
|
||||
mRxSuccess++;
|
||||
mStat.rxSuccess++;
|
||||
|
||||
iv->getAssignment(); // choose the parser
|
||||
for(uint8_t i = 0; i < iv->listLen; i++) {
|
||||
|
@ -498,9 +498,9 @@ void app::cbMqtt(char* topic, byte* payload, unsigned int length) {
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
String app::getStatistics(void) {
|
||||
String content = F("Receive success: ") + String(mRxSuccess) + "\n";
|
||||
content += F("Receive fail: ") + String(mRxFailed) + "\n";
|
||||
content += F("Frames received: ") + String(mFrameCnt) + "\n";
|
||||
String content = F("Receive success: ") + String(mStat.rxSuccess) + "\n";
|
||||
content += F("Receive fail: ") + String(mStat.rxFail) + "\n";
|
||||
content += F("Frames received: ") + String(mStat.frmCnt) + "\n";
|
||||
content += F("Send Cnt: ") + String(mSys->Radio.mSendCnt) + String("\n\n");
|
||||
|
||||
Inverter<> *iv;
|
||||
|
@ -686,9 +686,7 @@ void app::resetSystem(void) {
|
|||
|
||||
|
||||
memset(mPayload, 0, (MAX_NUM_INVERTERS * sizeof(invPayload_t)));
|
||||
mRxFailed = 0;
|
||||
mRxSuccess = 0;
|
||||
mFrameCnt = 0;
|
||||
memset(&mStat, 0, sizeof(statistics_t));
|
||||
mLastPacketId = 0x00;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ typedef struct {
|
|||
bool requested;
|
||||
} invPayload_t;
|
||||
|
||||
|
||||
class ahoywifi;
|
||||
class web;
|
||||
|
||||
|
@ -239,9 +238,7 @@ class app {
|
|||
uint8_t mSendLastIvId;
|
||||
|
||||
invPayload_t mPayload[MAX_NUM_INVERTERS];
|
||||
uint32_t mRxFailed;
|
||||
uint32_t mRxSuccess;
|
||||
uint32_t mFrameCnt;
|
||||
statistics_t mStat;
|
||||
uint8_t mLastPacketId;
|
||||
|
||||
// timer
|
||||
|
|
|
@ -154,6 +154,12 @@ typedef struct {
|
|||
} /*__attribute__((__packed__))*/ config_t;
|
||||
#pragma pack(pop) // restore original alignment from stack
|
||||
|
||||
typedef struct {
|
||||
uint32_t rxFail;
|
||||
uint32_t rxSuccess;
|
||||
uint32_t frmCnt;
|
||||
} statistics_t;
|
||||
|
||||
|
||||
#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
|
||||
|
|
65
tools/esp8266/html/api.js
Normal file
65
tools/esp8266/html/api.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
function toggle(name, hide) {
|
||||
var elm = document.getElementsByName(name)[0];
|
||||
if(hide) {
|
||||
if(!elm.classList.contains("hide"))
|
||||
elm.classList.add("hide");
|
||||
}
|
||||
else
|
||||
elm.classList.remove('hide');
|
||||
}
|
||||
|
||||
function getAjax(url, ptr) {
|
||||
var http = new XMLHttpRequest();
|
||||
if(http != null) {
|
||||
http.open("GET", url, true);
|
||||
http.onreadystatechange = p;
|
||||
http.send(null);
|
||||
}
|
||||
function p() {
|
||||
if(http.readyState == 4)
|
||||
ptr(JSON.parse(http.responseText));
|
||||
}
|
||||
}
|
||||
|
||||
function des(val) {
|
||||
e = document.createElement('p');
|
||||
e.classList.add("subdes");
|
||||
e.innerHTML = val;
|
||||
return e;
|
||||
}
|
||||
|
||||
function lbl(id, val) {
|
||||
e = document.createElement('label');
|
||||
e.htmlFor = id;
|
||||
e.innerHTML = val;
|
||||
return e;
|
||||
}
|
||||
|
||||
function inp(name, val, max=32, cl=["text"]) {
|
||||
e = document.createElement('input');
|
||||
e.classList.add(...cl);
|
||||
e.name = name;
|
||||
e.value = val;
|
||||
e.maxLength = max;
|
||||
return e;
|
||||
}
|
||||
|
||||
function sel(name, opt, selId) {
|
||||
e = document.createElement('select');
|
||||
e.name = name;
|
||||
for(it of opt) {
|
||||
o = document.createElement('option');
|
||||
o.value = it[0];
|
||||
o.innerHTML = it[1];
|
||||
if(it[0] == selId)
|
||||
o.selected = true;
|
||||
e.appendChild(o);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
function div(cl) {
|
||||
e = document.createElement('div');
|
||||
e.classList.add(cl);
|
||||
return e;
|
||||
}
|
|
@ -7,30 +7,36 @@ def convert2Header(inFile, compress):
|
|||
define = inFile.split(".")[0].upper()
|
||||
define2 = inFile.split(".")[1].upper()
|
||||
inFileVarName = inFile.replace(".", "_")
|
||||
print(inFile + ", compress: " + str(compress))
|
||||
|
||||
if os.getcwd()[-4:] != "html":
|
||||
print("ok")
|
||||
outName = "html/" + "h/" + inFileVarName + ".h"
|
||||
inFile = "html/" + inFile
|
||||
else:
|
||||
outName = "h/" + inFileVarName + ".h"
|
||||
|
||||
f = open(inFile, "r")
|
||||
data = f.read().replace('\n', '')
|
||||
data = f.read()
|
||||
f.close()
|
||||
if False == compress:
|
||||
if fileType == "html":
|
||||
|
||||
if fileType == "html":
|
||||
if False == compress:
|
||||
data = data.replace('\n', '')
|
||||
data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags
|
||||
data = re.sub(r"(\s?\;|\}|\>|\{|\=)\s+", r'\1', data) # whitespaces inner javascript
|
||||
length = len(data) # get unescaped length
|
||||
data = re.sub(r"\"", '\\\"', data) # escape quotation marks
|
||||
else:
|
||||
data = re.sub(r"(\;|\}|\:|\{)\s+", r'\1', data) # whitespaces inner css
|
||||
length = len(data) # get unescaped length
|
||||
else:
|
||||
data = re.sub(r"\>\s+\<", '><', data) # whitespaces between xml tags
|
||||
data = re.sub(r"(\;|\}|\>|\{)\s+", r'\1', data) # whitespaces inner javascript
|
||||
data = re.sub(r"(\r\n|\r|\n)(\s+|\s?)", '', data) # whitespaces inner javascript
|
||||
length = len(data) # get unescaped length
|
||||
if False == compress:
|
||||
data = re.sub(r"\"", '\\\"', data) # escape quotation marks
|
||||
elif fileType == "js":
|
||||
#data = re.sub(r"(\r\n|\r|\n)(\s+|\s?)", '', data) # whitespaces inner javascript
|
||||
#data = re.sub(r"\s?(\=|\!\=|\{|,)+\s?", r'\1', data) # whitespaces inner javascript
|
||||
length = len(data) # get unescaped length
|
||||
if False == compress:
|
||||
data = re.sub(r"\"", '\\\"', data) # escape quotation marks
|
||||
else:
|
||||
data = data.replace('\n', '')
|
||||
data = re.sub(r"(\;|\}|\:|\{)\s+", r'\1', data) # whitespaces inner css
|
||||
length = len(data) # get unescaped length # get unescaped length
|
||||
|
||||
f = open(outName, "w")
|
||||
f.write("#ifndef __{}_{}_H__\n".format(define, define2))
|
||||
|
@ -52,8 +58,9 @@ def convert2Header(inFile, compress):
|
|||
f.write("#endif /*__{}_{}_H__*/\n".format(define, define2))
|
||||
f.close()
|
||||
|
||||
convert2Header("index.html", False)
|
||||
convert2Header("index.html", True)
|
||||
convert2Header("setup.html", True)
|
||||
convert2Header("visualization.html", False)
|
||||
convert2Header("update.html", False)
|
||||
convert2Header("style.css", False)
|
||||
convert2Header("style.css", True)
|
||||
convert2Header("api.js", True)
|
||||
|
|
|
@ -1,44 +1,13 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Index - {DEVICE}</title>
|
||||
<title>Index</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="text/javascript">
|
||||
getAjax('/uptime', 'uptime');
|
||||
getAjax('/cmdstat', 'cmds');
|
||||
window.setInterval("getAjax('/uptime', 'uptime')", {JS_TS});
|
||||
window.setInterval("getAjax('/cmdstat', 'cmds')", {JS_TS});
|
||||
|
||||
function getAjax(url, resid) {
|
||||
var http = null;
|
||||
http = new XMLHttpRequest();
|
||||
if(http != null) {
|
||||
http.open("GET", url, true);
|
||||
http.onreadystatechange = print;
|
||||
http.send(null);
|
||||
}
|
||||
|
||||
function print() {
|
||||
if(http.readyState == 4) {
|
||||
document.getElementById(resid).innerHTML = http.responseText;
|
||||
}
|
||||
}
|
||||
}
|
||||
function getInverterInfo(data){
|
||||
var http = null;
|
||||
http = new XMLHttpRequest();
|
||||
if(http != null) {
|
||||
http.open("POST", "/api");
|
||||
http.setRequestHeader("Accept", "application/json");
|
||||
http.setRequestHeader("Content-Type", "application/json");
|
||||
http.send(data);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="api.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>AHOY - {DEVICE}</h1>
|
||||
<h1>AHOY</h1>
|
||||
<div id="content" class="content">
|
||||
<p>
|
||||
<a href="/visualization">Visualization</a><br/>
|
||||
|
@ -46,7 +15,7 @@
|
|||
<a href="/setup">Setup</a><br/>
|
||||
</p>
|
||||
<p><span class="des">Uptime: </span><span id="uptime"></span></p>
|
||||
<p><span class="des">Statistics: </span><pre id="cmds"></pre></p>
|
||||
<p><span class="des">Statistics: </span><pre id="stat"></pre></p>
|
||||
<p>Every {TS}seconds the values are updated</p>
|
||||
|
||||
<div id="note">
|
||||
|
@ -64,9 +33,40 @@
|
|||
<div id="footer">
|
||||
<p class="left">© 2022</p>
|
||||
<p class="left"><a href="/update">Update Firmware</a></p>
|
||||
<p class="right">AHOY :: {VERSION}</p>
|
||||
<p class="right" id="version"></p>
|
||||
<p class="right"><a href="/reboot">Reboot</a></p>
|
||||
<p class="right">Git SHA: {BUILD}</p>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
function parseSys(obj) {
|
||||
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"];
|
||||
|
||||
var date = new Date(obj["ts_now"] * 1000);
|
||||
var up = obj["ts_uptime"];
|
||||
var days = parseInt(up / 86400) % 365;
|
||||
var hrs = parseInt(up / 3600) % 24;
|
||||
var min = parseInt(up / 60) % 60;
|
||||
var sec = up % 60;
|
||||
document.getElementById("uptime").innerHTML = days + " Days, "
|
||||
+ ("0"+hrs).substr(-2) + ":"
|
||||
+ ("0"+min).substr(-2) + ":"
|
||||
+ ("0"+sec).substr(-2) + "; now: "
|
||||
+ ("0"+date.getHours()).substr(-2) + ":"
|
||||
+ ("0"+date.getMinutes()).substr(-2) + ":"
|
||||
+ ("0"+date.getSeconds()).substr(-2);
|
||||
}
|
||||
|
||||
function parseStat(obj) {
|
||||
document.getElementById("stat").innerHTML = "RX success: " + obj["rx_success"]
|
||||
+ "\nRX fail: " + obj["rx_fail"]
|
||||
+ "\nFrames received: " + obj["frame_cnt"]
|
||||
+ "\nTX Cnt: " + obj["tx_cnt"];
|
||||
}
|
||||
|
||||
window.setInterval("getAjax('/api/system', parseSys)", 30000);
|
||||
window.setInterval("getAjax('/api/system', parseStat)", 30000);
|
||||
|
||||
getAjax("/api/system", parseSys);
|
||||
getAjax("/api/statistics", parseStat);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -4,49 +4,7 @@
|
|||
<title>Setup</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="text/javascript">
|
||||
function toggle(name, hide) {
|
||||
var elm = document.getElementsByName(name)[0];
|
||||
if(hide) {
|
||||
if(!elm.classList.contains("hide"))
|
||||
elm.classList.add("hide");
|
||||
}
|
||||
else
|
||||
elm.classList.remove('hide');
|
||||
}
|
||||
|
||||
function load() {
|
||||
document.querySelectorAll('input[name^="inv"][name$="Addr"]').forEach(elm => {
|
||||
elm.addEventListener("keyup", (e) => {
|
||||
serial = elm.value.substring(0,4);
|
||||
iv = elm.name.substring(3,4);
|
||||
max = 0;
|
||||
for(i=0;i<4;i++) {
|
||||
toggle("inv"+iv+"ModPwr"+i, true);
|
||||
toggle("inv"+iv+"ModName"+i, true);
|
||||
}
|
||||
toggle("lbl"+iv+"ModPwr", true);
|
||||
toggle("lbl"+iv+"ModName", true);
|
||||
|
||||
if(serial == "1161") max = 4;
|
||||
else if(serial == "1141") max = 2;
|
||||
else if(serial == "1121") max = 1;
|
||||
|
||||
for(i=0;i<max;i++) {
|
||||
toggle("inv"+iv+"ModPwr"+i, false);
|
||||
toggle("inv"+iv+"ModName"+i, false);
|
||||
}
|
||||
if(max != 0) {
|
||||
toggle("lbl"+iv+"ModPwr", false);
|
||||
toggle("lbl"+iv+"ModName", false);
|
||||
}
|
||||
});
|
||||
evt = document.createEvent("HTMLEvents");
|
||||
evt.initEvent("keyup", false, true);
|
||||
elm.dispatchEvent(evt);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="api.js"></script>
|
||||
</head>
|
||||
<body onload="load()">
|
||||
<h1>Setup</h1>
|
||||
|
@ -141,7 +99,6 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<p class="left"><a href="/">Home</a></p>
|
||||
<p class="left"><a href="/update">Update Firmware</a></p>
|
||||
|
@ -149,14 +106,45 @@
|
|||
<p class="right"><a href="/factory">Factory Reset</a></p>
|
||||
<p class="right"><a href="/reboot">Reboot</a></p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
for(it of document.getElementsByClassName("s_collapsible")) {
|
||||
it.addEventListener("click", function() {
|
||||
this.classList.toggle("active");
|
||||
var content = this.nextElementSibling;
|
||||
content.style.display = (content.style.display === "block") ? "none" : "block";
|
||||
function load() {
|
||||
document.querySelectorAll('input[name^="inv"][name$="Addr"]').forEach(elm => {
|
||||
elm.addEventListener("keyup", (e) => {
|
||||
serial = elm.value.substring(0,4);
|
||||
iv = elm.name.substring(3,4);
|
||||
max = 0;
|
||||
for(i=0;i<4;i++) {
|
||||
toggle("inv"+iv+"ModPwr"+i, true);
|
||||
toggle("inv"+iv+"ModName"+i, true);
|
||||
}
|
||||
toggle("lbl"+iv+"ModPwr", true);
|
||||
toggle("lbl"+iv+"ModName", true);
|
||||
|
||||
if(serial == "1161") max = 4;
|
||||
else if(serial == "1141") max = 2;
|
||||
else if(serial == "1121") max = 1;
|
||||
|
||||
for(i=0;i<max;i++) {
|
||||
toggle("inv"+iv+"ModPwr"+i, false);
|
||||
toggle("inv"+iv+"ModName"+i, false);
|
||||
}
|
||||
if(max != 0) {
|
||||
toggle("lbl"+iv+"ModPwr", false);
|
||||
toggle("lbl"+iv+"ModName", false);
|
||||
}
|
||||
});
|
||||
evt = document.createEvent("HTMLEvents");
|
||||
evt.initEvent("keyup", false, true);
|
||||
elm.dispatchEvent(evt);
|
||||
});
|
||||
|
||||
for(it of document.getElementsByClassName("s_collapsible")) {
|
||||
it.addEventListener("click", function() {
|
||||
this.classList.toggle("active");
|
||||
var content = this.nextElementSibling;
|
||||
content.style.display = (content.style.display === "block") ? "none" : "block";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var highestId = 0;
|
||||
|
@ -167,62 +155,6 @@
|
|||
ivHtml(JSON.parse('{"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""],"power_limit":1500,"power_limit_option":65535}'), highestId + 1);
|
||||
});
|
||||
|
||||
function getAjax(url, ptr) {
|
||||
var http = new XMLHttpRequest();
|
||||
if(http != null) {
|
||||
http.open("GET", url, true);
|
||||
http.onreadystatechange = p;
|
||||
http.send(null);
|
||||
}
|
||||
function p() {
|
||||
if(http.readyState == 4)
|
||||
ptr(JSON.parse(http.responseText));
|
||||
}
|
||||
}
|
||||
|
||||
function des(val) {
|
||||
e = document.createElement('p');
|
||||
e.classList.add("subdes");
|
||||
e.innerHTML = val;
|
||||
return e;
|
||||
}
|
||||
|
||||
function lbl(id, val) {
|
||||
e = document.createElement('label');
|
||||
e.htmlFor = id;
|
||||
e.innerHTML = val;
|
||||
return e;
|
||||
}
|
||||
|
||||
function inp(name, val, max=32, cl=["text"]) {
|
||||
e = document.createElement('input');
|
||||
e.classList.add(...cl);
|
||||
e.name = name;
|
||||
e.value = val;
|
||||
e.maxLength = max;
|
||||
return e;
|
||||
}
|
||||
|
||||
function sel(name, opt, selId) {
|
||||
e = document.createElement('select');
|
||||
e.name = name;
|
||||
for(it of opt) {
|
||||
o = document.createElement('option');
|
||||
o.value = it[0];
|
||||
o.innerHTML = it[1];
|
||||
if(it[0] == selId)
|
||||
o.selected = true;
|
||||
e.appendChild(o);
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
function div(cl) {
|
||||
e = document.createElement('div');
|
||||
e.classList.add(cl);
|
||||
return e;
|
||||
}
|
||||
|
||||
function ivHtml(obj, id) {
|
||||
highestId = id;
|
||||
if(highestId == (maxInv - 1))
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "html/h/index_html.h"
|
||||
#include "html/h/style_css.h"
|
||||
#include "html/h/api_js.h"
|
||||
#include "html/h/favicon_ico_gz.h"
|
||||
#include "html/h/setup_html.h"
|
||||
#include "html/h/visualization_html.h"
|
||||
|
@ -20,15 +21,16 @@
|
|||
const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
web::web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]) {
|
||||
web::web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) {
|
||||
mMain = main;
|
||||
mSysCfg = sysCfg;
|
||||
mConfig = config;
|
||||
mStat = stat;
|
||||
mVersion = version;
|
||||
mWeb = new AsyncWebServer(80);
|
||||
//mEvts = new AsyncEventSource("/events");
|
||||
|
||||
mApi = new api(mWeb, main, sysCfg, config, version);
|
||||
mApi = new webApi(mWeb, main, sysCfg, config, stat, version);
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,16 +39,16 @@ void web::setup(void) {
|
|||
DPRINTLN(DBG_VERBOSE, F("app::setup-begin"));
|
||||
mWeb->begin();
|
||||
DPRINTLN(DBG_VERBOSE, F("app::setup-on"));
|
||||
mWeb->on("/", HTTP_ANY, std::bind(&web::showIndex, this, std::placeholders::_1));
|
||||
mWeb->on("/style.css", HTTP_ANY, std::bind(&web::showCss, this, std::placeholders::_1));
|
||||
mWeb->on("/favicon.ico", HTTP_ANY, std::bind(&web::showFavicon, this, std::placeholders::_1));
|
||||
mWeb->on("/", HTTP_GET, std::bind(&web::onIndex, 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("/favicon.ico", HTTP_GET, std::bind(&web::onFavicon, this, std::placeholders::_1));
|
||||
mWeb->onNotFound ( std::bind(&web::showNotFound, this, std::placeholders::_1));
|
||||
mWeb->on("/uptime", HTTP_ANY, std::bind(&web::showUptime, this, std::placeholders::_1));
|
||||
mWeb->on("/reboot", HTTP_ANY, std::bind(&web::showReboot, this, std::placeholders::_1));
|
||||
mWeb->on("/erase", HTTP_ANY, std::bind(&web::showErase, this, std::placeholders::_1));
|
||||
mWeb->on("/factory", HTTP_ANY, std::bind(&web::showFactoryRst, this, std::placeholders::_1));
|
||||
|
||||
mWeb->on("/setup", HTTP_ANY, std::bind(&web::showSetup, this, std::placeholders::_1));
|
||||
mWeb->on("/setup", HTTP_GET, std::bind(&web::onSetup, this, std::placeholders::_1));
|
||||
mWeb->on("/save", HTTP_ANY, std::bind(&web::showSave, this, std::placeholders::_1));
|
||||
|
||||
mWeb->on("/cmdstat", HTTP_ANY, std::bind(&web::showStatistics, this, std::placeholders::_1));
|
||||
|
@ -85,26 +87,41 @@ void web::loop(void) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showIndex(AsyncWebServerRequest *request) {
|
||||
DPRINTLN(DBG_VERBOSE, F("showIndex"));
|
||||
String html = FPSTR(index_html);
|
||||
html.replace(F("{DEVICE}"), mSysCfg->deviceName);
|
||||
html.replace(F("{VERSION}"), mVersion);
|
||||
void web::onIndex(AsyncWebServerRequest *request) {
|
||||
DPRINTLN(DBG_VERBOSE, F("onIndex"));
|
||||
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), index_html, index_html_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
request->send(response);
|
||||
|
||||
/*
|
||||
html.replace(F("{TS}"), String(mConfig->sendInterval) + " ");
|
||||
html.replace(F("{JS_TS}"), String(mConfig->sendInterval * 1000));
|
||||
html.replace(F("{BUILD}"), String(AUTO_GIT_HASH));
|
||||
request->send(200, "text/html", html);
|
||||
request->send(200, "text/html", html);*/
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showCss(AsyncWebServerRequest *request) {
|
||||
request->send(200, "text/css", FPSTR(style_css));
|
||||
void web::onCss(AsyncWebServerRequest *request) {
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/css"), style_css, style_css_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::onApiJs(AsyncWebServerRequest *request) {
|
||||
DPRINTLN(DBG_VERBOSE, F("onApiJs"));
|
||||
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/javascript"), api_js, api_js_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showFavicon(AsyncWebServerRequest *request) {
|
||||
void web::onFavicon(AsyncWebServerRequest *request) {
|
||||
static const char favicon_type[] PROGMEM = "image/x-icon";
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, favicon_type, favicon_ico_gz, favicon_ico_gz_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
|
@ -131,22 +148,6 @@ void web::showNotFound(AsyncWebServerRequest *request) {
|
|||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showUptime(AsyncWebServerRequest *request) {
|
||||
char time[21] = {0};
|
||||
uint32_t uptime = mMain->getUptime();
|
||||
|
||||
uint32_t upTimeSc = uint32_t((uptime) % 60);
|
||||
uint32_t upTimeMn = uint32_t((uptime / (60)) % 60);
|
||||
uint32_t upTimeHr = uint32_t((uptime / (60 * 60)) % 24);
|
||||
uint32_t upTimeDy = uint32_t((uptime / (60 * 60 * 24)) % 365);
|
||||
|
||||
snprintf(time, 20, "%d Days, %02d:%02d:%02d", upTimeDy, upTimeHr, upTimeMn, upTimeSc);
|
||||
|
||||
request->send(200, "text/plain", String(time) + "; now: " + mMain->getDateTimeStr(mMain->getTimestamp()));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showReboot(AsyncWebServerRequest *request) {
|
||||
request->send(200, F("text/html"), F("<!doctype html><html><head><title>Rebooting ...</title><meta http-equiv=\"refresh\" content=\"10; URL=/\"></head><body>rebooting ... auto reload after 10s</body></html>"));
|
||||
|
@ -193,8 +194,8 @@ void web::showFactoryRst(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void web::showSetup(AsyncWebServerRequest *request) {
|
||||
DPRINTLN(DBG_VERBOSE, F("app::showSetup"));
|
||||
void web::onSetup(AsyncWebServerRequest *request) {
|
||||
DPRINTLN(DBG_VERBOSE, F("onSetup"));
|
||||
|
||||
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), setup_html, setup_html_len);
|
||||
response->addHeader(F("Content-Encoding"), "gzip");
|
||||
|
|
|
@ -10,15 +10,15 @@
|
|||
#include "ESPAsyncTCP.h"
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "app.h"
|
||||
#include "api.h"
|
||||
#include "webApi.h"
|
||||
#include "tmplProc.h"
|
||||
|
||||
class app;
|
||||
class api;
|
||||
class webApi;
|
||||
|
||||
class web {
|
||||
public:
|
||||
web(app *main, sysConfig_t *sysCfg, config_t *config, char version[]);
|
||||
web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]);
|
||||
~web() {}
|
||||
|
||||
void setup(void);
|
||||
|
@ -26,15 +26,15 @@ class web {
|
|||
|
||||
void onConnect(AsyncEventSourceClient *client);
|
||||
|
||||
void showIndex(AsyncWebServerRequest *request);
|
||||
void showCss(AsyncWebServerRequest *request);
|
||||
void showFavicon(AsyncWebServerRequest *request);
|
||||
void onIndex(AsyncWebServerRequest *request);
|
||||
void onCss(AsyncWebServerRequest *request);
|
||||
void onApiJs(AsyncWebServerRequest *request);
|
||||
void onFavicon(AsyncWebServerRequest *request);
|
||||
void showNotFound(AsyncWebServerRequest *request);
|
||||
void showUptime(AsyncWebServerRequest *request);
|
||||
void showReboot(AsyncWebServerRequest *request);
|
||||
void showErase(AsyncWebServerRequest *request);
|
||||
void showFactoryRst(AsyncWebServerRequest *request);
|
||||
void showSetup(AsyncWebServerRequest *request);
|
||||
void onSetup(AsyncWebServerRequest *request);
|
||||
void showSave(AsyncWebServerRequest *request);
|
||||
|
||||
void showStatistics(AsyncWebServerRequest *request);
|
||||
|
@ -56,9 +56,10 @@ class web {
|
|||
|
||||
config_t *mConfig;
|
||||
sysConfig_t *mSysCfg;
|
||||
statistics_t *mStat;
|
||||
char *mVersion;
|
||||
app *mMain;
|
||||
api *mApi;
|
||||
webApi *mApi;
|
||||
};
|
||||
|
||||
#endif /*__WEB_H__*/
|
||||
|
|
|
@ -8,39 +8,41 @@
|
|||
#define F(sl) (sl)
|
||||
#endif
|
||||
|
||||
#include "api.h"
|
||||
#include "webApi.h"
|
||||
#include "AsyncJson.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
api::api(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, char version[]) {
|
||||
webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) {
|
||||
mSrv = srv;
|
||||
mApp = app;
|
||||
mSysCfg = sysCfg;
|
||||
mConfig = config;
|
||||
mStat = stat;
|
||||
mVersion = version;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::setup(void) {
|
||||
mSrv->on("/api/system", HTTP_GET, std::bind(&api::onSystem, this, std::placeholders::_1));
|
||||
mSrv->on("/api/inverter/list", HTTP_GET, std::bind(&api::onInverterList, this, std::placeholders::_1));
|
||||
mSrv->on("/api/mqtt", HTTP_GET, std::bind(&api::onMqtt, this, std::placeholders::_1));
|
||||
mSrv->on("/api/ntp", HTTP_GET, std::bind(&api::onNtp, this, std::placeholders::_1));
|
||||
mSrv->on("/api/pinout", HTTP_GET, std::bind(&api::onPinout, this, std::placeholders::_1));
|
||||
mSrv->on("/api/radio", HTTP_GET, std::bind(&api::onRadio, this, std::placeholders::_1));
|
||||
mSrv->on("/api/serial", HTTP_GET, std::bind(&api::onSerial, this, std::placeholders::_1));
|
||||
void webApi::setup(void) {
|
||||
mSrv->on("/api/system", HTTP_GET, std::bind(&webApi::onSystem, this, std::placeholders::_1));
|
||||
mSrv->on("/api/statistics", HTTP_GET, std::bind(&webApi::onStatistics, this, std::placeholders::_1));
|
||||
mSrv->on("/api/inverter/list", HTTP_GET, std::bind(&webApi::onInverterList, this, std::placeholders::_1));
|
||||
mSrv->on("/api/mqtt", HTTP_GET, std::bind(&webApi::onMqtt, this, std::placeholders::_1));
|
||||
mSrv->on("/api/ntp", HTTP_GET, std::bind(&webApi::onNtp, this, std::placeholders::_1));
|
||||
mSrv->on("/api/pinout", HTTP_GET, std::bind(&webApi::onPinout, this, std::placeholders::_1));
|
||||
mSrv->on("/api/radio", HTTP_GET, std::bind(&webApi::onRadio, this, std::placeholders::_1));
|
||||
mSrv->on("/api/serial", HTTP_GET, std::bind(&webApi::onSerial, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::loop(void) {
|
||||
void webApi::loop(void) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onSystem(AsyncWebServerRequest *request) {
|
||||
void webApi::onSystem(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
|
@ -59,7 +61,22 @@ void api::onSystem(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onInverterList(AsyncWebServerRequest *request) {
|
||||
void webApi::onStatistics(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root[F("rx_success")] = mStat->rxSuccess;
|
||||
root[F("rx_fail")] = mStat->rxFail;
|
||||
root[F("frame_cnt")] = mStat->frmCnt;
|
||||
root[F("tx_cnt")] = mApp->mSys->Radio.mSendCnt;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void webApi::onInverterList(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
JsonArray invArr = root.createNestedArray("inverter");
|
||||
|
@ -94,7 +111,7 @@ void api::onInverterList(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onMqtt(AsyncWebServerRequest *request) {
|
||||
void webApi::onMqtt(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
|
@ -110,7 +127,7 @@ void api::onMqtt(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onNtp(AsyncWebServerRequest *request) {
|
||||
void webApi::onNtp(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
|
@ -123,7 +140,7 @@ void api::onNtp(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onPinout(AsyncWebServerRequest *request) {
|
||||
void webApi::onPinout(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
|
@ -137,7 +154,7 @@ void api::onPinout(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onRadio(AsyncWebServerRequest *request) {
|
||||
void webApi::onRadio(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
|
@ -150,7 +167,7 @@ void api::onRadio(AsyncWebServerRequest *request) {
|
|||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void api::onSerial(AsyncWebServerRequest *request) {
|
||||
void webApi::onSerial(AsyncWebServerRequest *request) {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef __API_H__
|
||||
#define __API_H__
|
||||
#ifndef __WEB_API_H__
|
||||
#define __WEB_API_H__
|
||||
|
||||
#include "dbg.h"
|
||||
#include "ESPAsyncTCP.h"
|
||||
|
@ -9,15 +9,16 @@
|
|||
|
||||
class app;
|
||||
|
||||
class api {
|
||||
class webApi {
|
||||
public:
|
||||
api(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, char version[]);
|
||||
webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]);
|
||||
|
||||
void setup(void);
|
||||
void loop(void);
|
||||
|
||||
private:
|
||||
void onSystem(AsyncWebServerRequest *request);
|
||||
void onStatistics(AsyncWebServerRequest *request);
|
||||
void onInverterList(AsyncWebServerRequest *request);
|
||||
void onMqtt(AsyncWebServerRequest *request);
|
||||
void onNtp(AsyncWebServerRequest *request);
|
||||
|
@ -30,7 +31,8 @@ class api {
|
|||
|
||||
config_t *mConfig;
|
||||
sysConfig_t *mSysCfg;
|
||||
statistics_t *mStat;
|
||||
char *mVersion;
|
||||
};
|
||||
|
||||
#endif /*__API_H__*/
|
||||
#endif /*__WEB_API_H__*/
|
Loading…
Add table
Add a link
Reference in a new issue