Browse Source

Merge branch 'development03' into dev03

pull/361/head
Lukas Pusch 2 years ago
committed by GitHub
parent
commit
637459ab9e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      tools/esp8266/ahoywifi.cpp
  2. 1
      tools/esp8266/ahoywifi.h
  3. 40
      tools/esp8266/app.cpp
  4. 2
      tools/esp8266/app.h
  5. 2
      tools/esp8266/defines.h
  6. 61
      tools/esp8266/html/api.js
  7. 70
      tools/esp8266/html/index.html
  8. 37
      tools/esp8266/html/serial.html
  9. 102
      tools/esp8266/html/setup.html
  10. 197
      tools/esp8266/html/style.css
  11. 54
      tools/esp8266/html/system.html
  12. 39
      tools/esp8266/html/update.html
  13. 40
      tools/esp8266/html/visualization.html
  14. 15
      tools/esp8266/mqtt.h
  15. 2
      tools/esp8266/scripts/auto_firmware_version.py
  16. 14
      tools/esp8266/web.cpp
  17. 1
      tools/esp8266/web.h
  18. 30
      tools/esp8266/webApi.cpp
  19. 1
      tools/esp8266/webApi.h

28
tools/esp8266/ahoywifi.cpp

@ -209,24 +209,32 @@ time_t ahoywifi::getNtpTime(void) {
} }
//-----------------------------------------------------------------------------
void ahoywifi::scanAvailNetworks(void) {
int n = WiFi.scanComplete();
if(n == -2)
WiFi.scanNetworks(true);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ahoywifi::getAvailNetworks(JsonObject obj) { void ahoywifi::getAvailNetworks(JsonObject obj) {
JsonArray nets = obj.createNestedArray("networks"); JsonArray nets = obj.createNestedArray("networks");
int n = WiFi.scanComplete(); int n = WiFi.scanComplete();
if(n == -2) { if(n > 0) {
WiFi.scanNetworks(true); int sort[n];
} else if(n) { for (int i = 0; i < n; i++)
sort[i] = i;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (WiFi.RSSI(sort[j]) > WiFi.RSSI(sort[i]))
std::swap(sort[i], sort[j]);
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
nets[i]["ssid"] = WiFi.SSID(i); nets[i]["ssid"] = WiFi.SSID(sort[i]);
nets[i]["rssi"] = WiFi.RSSI(i); nets[i]["rssi"] = WiFi.RSSI(sort[i]);
// TODO: does github workflow use another version of this library?
// ahoywifi.cpp:223:38: error: 'class WiFiClass' has no member named 'isHidden'
//nets[i]["hidden"] = WiFi.isHidden(i) ? true : false;
} }
WiFi.scanDelete(); WiFi.scanDelete();
if(WiFi.scanComplete() == -2)
WiFi.scanNetworks(true);
} }
} }

1
tools/esp8266/ahoywifi.h

@ -30,6 +30,7 @@ class ahoywifi {
bool setupStation(uint32_t timeout); bool setupStation(uint32_t timeout);
bool getApActive(void); bool getApActive(void);
time_t getNtpTime(void); time_t getNtpTime(void);
void scanAvailNetworks(void);
void getAvailNetworks(JsonObject obj); void getAvailNetworks(JsonObject obj);
private: private:

40
tools/esp8266/app.cpp

@ -23,6 +23,7 @@ app::app() {
loadDefaultConfig(); loadDefaultConfig();
mSys = new HmSystemType(); mSys = new HmSystemType();
mSys->enableDebug();
mShouldReboot = false; mShouldReboot = false;
} }
@ -170,6 +171,23 @@ void app::loop(void) {
mMqtt.sendMsg("uptime", val); mMqtt.sendMsg("uptime", val);
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
char topic[32 + MAX_NAME_LENGTH], val[32];
if (!iv->isAvailable(mUtcTimestamp, rec) && !iv->isProducing(mUtcTimestamp, rec)){
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED);
mMqtt.sendMsg(topic, val);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
snprintf(val, 32, "0");
mMqtt.sendMsg(topic, val);
}
}
}
#ifdef __MQTT_TEST__ #ifdef __MQTT_TEST__
// für einfacheren Test mit MQTT, den MQTT abschnitt in 10 Sekunden wieder ausführen // für einfacheren Test mit MQTT, den MQTT abschnitt in 10 Sekunden wieder ausführen
mMqttTicker = mMqttInterval - 10; mMqttTicker = mMqttInterval - 10;
@ -487,19 +505,6 @@ void app::processPayload(bool retransmit) {
} }
} }
if (mMqttActive) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
char topic[32 + MAX_NAME_LENGTH], val[32];
if (!iv->isAvailable(mUtcTimestamp, rec) && !iv->isProducing(mUtcTimestamp, rec)) {
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED);
mMqtt.sendMsg(topic, val);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
snprintf(val, 32, "0");
mMqtt.sendMsg(topic, val);
}
}
yield(); yield();
} }
} }
@ -626,6 +631,12 @@ bool app::getWifiApActive(void) {
return mWifi->getApActive(); return mWifi->getApActive();
} }
//-----------------------------------------------------------------------------
void app::scanAvailNetworks(void) {
mWifi->scanAvailNetworks();
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void app::getAvailNetworks(JsonObject obj) { void app::getAvailNetworks(JsonObject obj) {
mWifi->getAvailNetworks(obj); mWifi->getAvailNetworks(obj);
@ -880,6 +891,7 @@ void app::setupMqtt(void) {
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void app::resetPayload(Inverter<> *iv) { void app::resetPayload(Inverter<> *iv) {
DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id)); DPRINTLN(DBG_INFO, "resetPayload: id: " + String(iv->id));
@ -892,6 +904,8 @@ void app::resetPayload(Inverter<> *iv) {
mPayload[iv->id].ts = mUtcTimestamp; mPayload[iv->id].ts = mUtcTimestamp;
} }
//-----------------------------------------------------------------------------
void app::calculateSunriseSunset() { void app::calculateSunriseSunset() {
// Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth // Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth

2
tools/esp8266/app.h

@ -68,6 +68,7 @@ class app {
void saveValues(void); void saveValues(void);
void resetPayload(Inverter<>* iv); void resetPayload(Inverter<>* iv);
bool getWifiApActive(void); bool getWifiApActive(void);
void scanAvailNetworks(void);
void getAvailNetworks(JsonObject obj); void getAvailNetworks(JsonObject obj);
uint8_t getIrqPin(void) { uint8_t getIrqPin(void) {
@ -171,6 +172,7 @@ class app {
inline bool mqttIsConnected(void) { return mMqtt.isConnected(); } inline bool mqttIsConnected(void) { return mMqtt.isConnected(); }
inline bool getSettingsValid(void) { return mSettingsValid; } inline bool getSettingsValid(void) { return mSettingsValid; }
inline bool getRebootRequestState(void) { return mShowRebootRequest; } inline bool getRebootRequestState(void) { return mShowRebootRequest; }
inline uint32_t getMqttTxCnt(void) { return mMqtt.getTxCnt(); }
HmSystemType *mSys; HmSystemType *mSys;
bool mShouldReboot; bool mShouldReboot;

2
tools/esp8266/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 5 #define VERSION_MINOR 5
#define VERSION_PATCH 22 #define VERSION_PATCH 25
//------------------------------------- //-------------------------------------

61
tools/esp8266/html/api.js

@ -1,4 +1,33 @@
function toggle(id, hide) { /**
* GENERIC FUNCTIONS
*/
function topnav() {
toggle("topnav");
}
function parseMenu(obj) {
var e = document.getElementById("topnav");
e.innerHTML = "";
for(var i = 0; i < obj["name"].length; i ++) {
if(obj["name"][i] == "-")
e.appendChild(span("", ["seperator"]));
else {
var l = link(obj["link"][i], obj["name"][i], obj["trgt"][i]);
if(obj["link"][i] == window.location.pathname)
l.classList.add("active");
e.appendChild(l);
}
}
}
function parseVersion(obj) {
document.getElementById("version").appendChild(
link("https://github.com/lumapu/ahoy/commits/" + obj["build"], "Git SHA: " + obj["build"] + " :: " + obj["version"], "_blank")
);
}
function setHide(id, hide) {
var elm = document.getElementById(id); var elm = document.getElementById(id);
if(hide) { if(hide) {
if(!elm.classList.contains("hide")) if(!elm.classList.contains("hide"))
@ -8,6 +37,15 @@ function toggle(id, hide) {
elm.classList.remove('hide'); elm.classList.remove('hide');
} }
function toggle(id) {
var e = document.getElementById(id);
if(!e.classList.contains("hide"))
e.classList.add("hide");
else
e.classList.remove('hide');
}
function getAjax(url, ptr, method="GET", json=null) { function getAjax(url, ptr, method="GET", json=null) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
if(xhr != null) { if(xhr != null) {
@ -27,6 +65,10 @@ function getAjax(url, ptr, method="GET", json=null) {
} }
} }
/**
* CREATE DOM FUNCTIONS
*/
function des(val) { function des(val) {
e = document.createElement('p'); e = document.createElement('p');
e.classList.add("subdes"); e.classList.add("subdes");
@ -68,6 +110,13 @@ function sel(name, opt, selId) {
return e; return e;
} }
function selDelAllOpt(sel) {
var i, l = sel.options.length - 1;
for(i = l; i >= 0; i--) {
sel.remove(i);
}
}
function opt(val, html) { function opt(val, html) {
o = document.createElement('option'); o = document.createElement('option');
o.value = val; o.value = val;
@ -93,3 +142,13 @@ function span(val, cl=null, id=null) {
function br() { function br() {
return document.createElement('br'); return document.createElement('br');
} }
function link(dst, text, target=null) {
var a = document.createElement('a');
var t = document.createTextNode(text);
a.href = dst;
if(null != target)
a.target = target;
a.appendChild(t);
return a;
}

70
tools/esp8266/html/index.html

@ -7,9 +7,18 @@
<script type="text/javascript" src="api.js"></script> <script type="text/javascript" src="api.js"></script>
</head> </head>
<body> <body>
<h1>AHOY</h1> <div class="topnav">
<div id="content" class="content"> <a href="/" class="title">AhoyDTU</a>
<SCRIPT> <a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content">
<script>
function promptFunction() { function promptFunction() {
var Text = prompt("This project was started from https://www.mikrocontroller.net/topic/525778 this discussion.\n\n" + var Text = prompt("This project was started from https://www.mikrocontroller.net/topic/525778 this discussion.\n\n" +
"The Hoymiles protocol was decrypted through the voluntary efforts of many participants. ahoy, among others, was developed based on this work.\n" + "The Hoymiles protocol was decrypted through the voluntary efforts of many participants. ahoy, among others, was developed based on this work.\n" +
@ -21,15 +30,7 @@
return true; return true;
} }
</SCRIPT> </script>
<p>
<a href="/live">Visualization</a><br/>
<br/>
<a href="/setup">Setup</a><br/>
<br/>
<a href="/serial">Webserial & Commands</a><br/>
</p>
<p><span class="des">Uptime: </span><span id="uptime"></span></p> <p><span class="des">Uptime: </span><span id="uptime"></span></p>
<p><span class="des">ESP-Time: </span><span id="date"></span></p> <p><span class="des">ESP-Time: </span><span id="date"></span></p>
<div id="sun"> <div id="sun">
@ -46,26 +47,35 @@
<p>Every <span id="refresh"></span> seconds the values are updated</p> <p>Every <span id="refresh"></span> seconds the values are updated</p>
<div id="note"> <div id="note">
New updates can be found on Github: <a href="https://github.com/lumapu/ahoy" target="_blank">https://github.com/lumapu/ahoy</a><br/>
<br/>
Please report issues in <a href="https://github.com/lumapu/ahoy/issues">Github</a><br/>
Discuss with us on <a href="https://discord.gg/WzhxEY62mB">Discord</a><br/> Discuss with us on <a href="https://discord.gg/WzhxEY62mB">Discord</a><br/>
Support this project: <a href="https://paypal.me/lupusch">Donate</a><br/> <h2>Support this project:</h2>
<p class="lic"><a href="https://creativecommons.org/licenses/by-nc-sa/3.0/de">Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/</a><br/> <ul>
Check the licenses which are published on <a href="https://github.com/lumapu/ahoy">https://github.com/lumapu/ahoy</a> as well</p><br/> <li>Report <a href="https://github.com/lumapu/ahoy/issues" target="_blank">issues</a></li>
<li>Contribute to <a href="https://github.com/lumapu/ahoy/blob/main/tools/esp8266/User_Manual.md" target="_blank">documentation</a></li>
<li>Test <a href="https://github.com/lumapu/ahoy/actions/workflows/compile_development.yml" target="_blank">development firmware</a></li>
<li>make a <a href="https://paypal.me/lupusch" target="_blank">donation</a></li>
</ul>
<p class="lic">
This project was started from <a href="https://www.mikrocontroller.net/topic/525778" target="_blank">this discussion. (Mikrocontroller.net)</a> This project was started from <a href="https://www.mikrocontroller.net/topic/525778" target="_blank">this discussion. (Mikrocontroller.net)</a>
</p>
</div>
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
<p class="left">&copy 2022</p> <div class="left">
<p class="left"><a href="/update">Update Firmware</a></p> AhoyDTU &copy 2022
<p class="right" id="version"></p> <ul>
<p class="right"><a href="/reboot">Reboot</a></p> <li><a href="https://discord.gg/WzhxEY62mB" target="_blank">Discord</a></li>
<p class="right"><a href="/api">REST API</a></p> <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> </div>
<script type="text/javascript"> <script type="text/javascript">
var mIntervalSet = false; var exeOnce = true;
function apiCb(obj) { function apiCb(obj) {
var e = document.getElementById("apiResult"); var e = document.getElementById("apiResult");
@ -88,8 +98,8 @@
function parseSys(obj) { function parseSys(obj) {
// Disclaimer // Disclaimer
//if(obj["disclaimer"] == false) sessionStorage.setItem("gDisclaimer", promptFunction()); //if(obj["disclaimer"] == false) sessionStorage.setItem("gDisclaimer", promptFunction());
if(true == exeOnce)
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; parseVersion(obj);
document.getElementById("wifi_rssi").innerHTML = obj["wifi_rssi"]; document.getElementById("wifi_rssi").innerHTML = obj["wifi_rssi"];
var date = new Date(obj["ts_now"] * 1000); var date = new Date(obj["ts_now"] * 1000);
@ -170,14 +180,16 @@
function parse(obj) { function parse(obj) {
if(null != obj) { if(null != obj) {
if(true == exeOnce)
parseMenu(obj["menu"]);
parseSys(obj["system"]); parseSys(obj["system"]);
parseStat(obj["statistics"]); parseStat(obj["statistics"]);
parseIv(obj["inverter"]); parseIv(obj["inverter"]);
parseWarnInfo(obj["warnings"], obj["infos"]); parseWarnInfo(obj["warnings"], obj["infos"]);
document.getElementById("refresh").innerHTML = obj["refresh_interval"]; document.getElementById("refresh").innerHTML = obj["refresh_interval"];
if(false == mIntervalSet) { if(true == exeOnce) {
window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000);
mIntervalSet = true; exeOnce = false;
} }
} }
else else

37
tools/esp8266/html/serial.html

@ -7,8 +7,17 @@
<script type="text/javascript" src="api.js"></script> <script type="text/javascript" src="api.js"></script>
</head> </head>
<body> <body>
<h1>Serial Console</h1> <div class="topnav">
<div id="content" class="content"> <a href="/" class="title">AhoyDTU</a>
<a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content">
<div class="serial"> <div class="serial">
<textarea id="serial" cols="80" rows="20" readonly></textarea><br/> <textarea id="serial" cols="80" rows="20" readonly></textarea><br/>
connected: <span class="dot" id="connected"></span> connected: <span class="dot" id="connected"></span>
@ -52,15 +61,24 @@
<p>Ctrl result: <span id="result">n/a</span></p> <p>Ctrl result: <span id="result">n/a</span></p>
</div> </div>
</div> </div>
</div>
<div id="footer"> <div id="footer">
<p class="left">&copy 2022</p> <div class="left">
<p class="left"><a href="/">Home</a></p> AhoyDTU &copy 2022
<p class="right" id="version"></p> <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> </div>
<script type="text/javascript"> <script type="text/javascript">
var mAutoScroll = true; var mAutoScroll = true;
var con = document.getElementById("serial"); var con = document.getElementById("serial");
var mIntervalSet = false; var exeOnce = true;
function parseSys(obj) { function parseSys(obj) {
var up = obj["ts_uptime"]; var up = obj["ts_uptime"];
@ -73,14 +91,15 @@
+ ("0"+min).substr(-2) + ":" + ("0"+min).substr(-2) + ":"
+ ("0"+sec).substr(-2); + ("0"+sec).substr(-2);
if(false == mIntervalSet) { if(true == exeOnce) {
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; parseVersion(obj);
window.setInterval("getAjax('/api/system', parseSys)", 10000); window.setInterval("getAjax('/api/system', parseSys)", 10000);
mIntervalSet = true; exeOnce = false;
} }
} }
function parse(root) { function parse(root) {
parseMenu(root["menu"]);
select = document.getElementById('InvID'); select = document.getElementById('InvID');
if(null == root) return; if(null == root) return;

102
tools/esp8266/html/setup.html

@ -18,10 +18,18 @@
</script> </script>
</head> </head>
<body onload="load()"> <body onload="load()">
<h1>Setup</h1> <div class="topnav">
<div id="setup" class="content"> <a href="/" class="title">AhoyDTU</a>
<a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content"> <div id="content">
<a class="erase" href="/erase">ERASE SETTINGS (not WiFi)</a> <a class="btn" href="/erase">ERASE SETTINGS (not WiFi)</a>
<form method="post" action="/save"> <form method="post" action="/save">
<fieldset> <fieldset>
@ -36,9 +44,11 @@
<fieldset> <fieldset>
<legend class="des">WiFi</legend> <legend class="des">WiFi</legend>
<p>Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.</p> <p>Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.</p>
<label for="scanbtn">Search Networks</label>
<input type="button" name="scanbtn" id="scanbtn" class="btn" value="scan" onclick="scan()"/><br/>
<label for="networks">Avail Networks</label> <label for="networks">Avail Networks</label>
<select name="networks" id="networks" onChange="selNet()"> <select name="networks" id="networks" onChange="selNet()">
<option value="-1">scanning ...</option> <option value="-1">not scanned</option>
</select> </select>
<label for="ssid">SSID</label> <label for="ssid">SSID</label>
<input type="text" name="ssid" class="text"/> <input type="text" name="ssid" class="text"/>
@ -52,7 +62,7 @@
<fieldset> <fieldset>
<legend class="des">Inverter</legend> <legend class="des">Inverter</legend>
<div id="inverter"></div><br/> <div id="inverter"></div><br/>
<input type="button" id="btnAdd" value="Add Inverter"/> <input type="button" id="btnAdd" class="btn" value="Add Inverter"/>
<p class="subdes">General</p> <p class="subdes">General</p>
<label for="invInterval">Interval [s]</label> <label for="invInterval">Interval [s]</label>
<input type="text" class="text" name="invInterval"/> <input type="text" class="text" name="invInterval"/>
@ -139,11 +149,17 @@
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
<p class="left"><a href="/">Home</a></p> <div class="left">
<p class="left"><a href="/update">Update Firmware</a></p> AhoyDTU &copy 2022
<p class="right" id="version"></p> <ul>
<p class="right"><a href="/factory">Factory Reset</a></p> <li><a href="https://discord.gg/WzhxEY62mB" target="_blank">Discord</a></li>
<p class="right"><a href="/reboot">Reboot</a></p> <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> </div>
<script type="text/javascript"> <script type="text/javascript">
var highestId = 0; var highestId = 0;
@ -156,6 +172,15 @@
ivHtml(JSON.parse('{"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""]}'), highestId + 1); ivHtml(JSON.parse('{"name":"","serial":"","channels":4,"ch_max_power":[0,0,0,0],"ch_name":["","","",""]}'), highestId + 1);
}); });
function apiCbWifi(obj) {
var e = document.getElementById("networks");
selDelAllOpt(e);
if(obj["success"])
e.appendChild(opt("-1", "scanning ..."))
else
e.appendChild(opt("-1", "Error: " + obj["error"]));
}
function apiCbNtp(obj) { function apiCbNtp(obj) {
var e = document.getElementById("apiResultNtp"); var e = document.getElementById("apiResultNtp");
if(obj["success"]) if(obj["success"])
@ -180,6 +205,13 @@
getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj)); getAjax("/api/setup", apiCbNtp, "POST", JSON.stringify(obj));
} }
function scan() {
var obj = new Object();
obj.cmd = "scan_wifi";
getAjax("/api/setup", apiCbWifi, "POST", JSON.stringify(obj));
setTimeout(function() {getAjax('/api/setup/networks', listNetworks)}, 7000);
}
function syncTime() { function syncTime() {
var obj = new Object(); var obj = new Object();
obj.cmd = "sync_ntp"; obj.cmd = "sync_ntp";
@ -197,13 +229,14 @@
var e = document.getElementsByName(id + "Addr")[0]; var e = document.getElementsByName(id + "Addr")[0];
e.value = ""; e.value = "";
e.dispatchEvent(new Event("keyup")); e.dispatchEvent(new Event("keyup"));
e.dispatchEvent(new Event("change"));
document.getElementsByName(id + "Name")[0].value = ""; document.getElementsByName(id + "Name")[0].value = "";
} }
function ivHtml(obj, id) { function ivHtml(obj, id) {
highestId = id; highestId = id;
if(highestId == (maxInv - 1)) if(highestId == (maxInv - 1))
toggle("btnAdd", true); setHide("btnAdd", true);
iv = document.getElementById("inverter"); iv = document.getElementById("inverter");
iv.appendChild(des("Inverter " + id)); iv.appendChild(des("Inverter " + id));
id = "inv" + id; id = "inv" + id;
@ -212,28 +245,32 @@
iv.appendChild(lbl(id + "Addr", "Address*")); iv.appendChild(lbl(id + "Addr", "Address*"));
var addr = inp(id + "Addr", obj["serial"], 12) var addr = inp(id + "Addr", obj["serial"], 12)
iv.appendChild(addr); iv.appendChild(addr);
addr.addEventListener("keyup", (e) => { ['keyup', 'change'].forEach(function(evt) {
addr.addEventListener(evt, (e) => {
var serial = addr.value.substring(0,4); var serial = addr.value.substring(0,4);
var max = 0; var max = 0;
for(var i=0;i<4;i++) { for(var i=0;i<4;i++) {
toggle(id+"ModPwr"+i, true); setHide(id+"ModPwr"+i, true);
toggle(id+"ModName"+i, true); setHide(id+"ModName"+i, true);
} }
toggle("lbl"+id+"ModPwr", true); setHide("lbl"+id+"ModPwr", true);
toggle("lbl"+id+"ModName", true); setHide("lbl"+id+"ModName", true);
if(serial == "1161") max = 4; if(serial === "1161") max = 4;
else if(serial == "1141") max = 2; else if(serial === "1141") max = 2;
else if(serial == "1121") max = 1; else if(serial === "1121") max = 1;
else max = 0;
if(max != 0) {
for(var i=0;i<max;i++) { for(var i=0;i<max;i++) {
toggle(id+"ModPwr"+i, false); setHide(id+"ModPwr"+i, false);
toggle(id+"ModName"+i, false); setHide(id+"ModName"+i, false);
} }
if(max != 0) { setHide("lbl"+id+"ModPwr", false);
toggle("lbl"+id+"ModPwr", false); setHide("lbl"+id+"ModName", false);
toggle("lbl"+id+"ModName", false);
} }
})
}); });
for(var i of [["Name", "name", "Name*", 32]]) { for(var i of [["Name", "name", "Name*", 32]]) {
@ -268,7 +305,7 @@
function parseSys(obj) { function parseSys(obj) {
for(var i of [["device", "device_name"], ["ssid", "ssid"]]) for(var i of [["device", "device_name"], ["ssid", "ssid"]])
document.getElementsByName(i[0])[0].value = obj[i[1]]; document.getElementsByName(i[0])[0].value = obj[i[1]];
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; parseVersion(obj);
} }
function parseIv(obj) { function parseIv(obj) {
@ -372,6 +409,7 @@
function parse(root) { function parse(root) {
if(null != root) { if(null != root) {
parseMenu(root["menu"]);
parseSys(root["system"]); parseSys(root["system"]);
parseIv(root["inverter"]); parseIv(root["inverter"]);
parseMqtt(root["mqtt"]); parseMqtt(root["mqtt"]);
@ -381,27 +419,25 @@
parseRadio(root["radio"]); parseRadio(root["radio"]);
parseSerial(root["serial"]); parseSerial(root["serial"]);
} }
getAjax('/api/setup/networks', listNetworks);
window.setInterval("getAjax('/api/setup/networks', listNetworks)", 7000);
} }
function listNetworks(root) { function listNetworks(root) {
if(root["networks"].length > 0) {
var s = document.getElementById("networks"); var s = document.getElementById("networks");
var i, l = s.options.length - 1; selDelAllOpt(s);
for(i = l; i >= 0; i--) { if(root["networks"].length > 0) {
s.remove(i); s.appendChild(opt("-1", "please select network"));
}
for(i = 0; i < root["networks"].length; i++) { for(i = 0; i < root["networks"].length; i++) {
s.appendChild(opt(root["networks"][i]["ssid"], root["networks"][i]["ssid"] + " (" + root["networks"][i]["rssi"] + " dBm)")); s.appendChild(opt(root["networks"][i]["ssid"], root["networks"][i]["ssid"] + " (" + root["networks"][i]["rssi"] + " dBm)"));
} }
} }
else
s.appendChild(opt("-1", "no network found"));
} }
function selNet() { function selNet() {
var s = document.getElementById("networks"); var s = document.getElementById("networks");
var e = document.getElementsByName("ssid")[0]; var e = document.getElementsByName("ssid")[0];
if(-1 != s.value)
e.value = s.value; e.value = s.value;
} }

197
tools/esp8266/html/style.css

@ -1,19 +1,158 @@
h1 { html, body {
font-family: Arial;
margin: 0; margin: 0;
padding: 20pt; padding: 0;
font-size: 22pt; height: 100%;
min-height: 100%;
}
h2 {
padding-left: 10px;
}
.topnav {
background-color: #333;
position: fixed;
top: 0;
width: 100%;
}
.topnav a {
color: #fff; color: #fff;
padding: 14px 14px;
text-decoration: none;
font-size: 17px;
display: block;
height: 20px;
}
#topnav a {
color: #fff;
}
.topnav a.icon {
background: #333;
display: block;
position: absolute;
left: 0;
top: 0;
}
.topnav a:hover {
background-color: #044e86 !important;
color: #000;
}
.title {
background-color: #006ec0; background-color: #006ec0;
color: #fff !important;
padding-left: 80px !important
}
.topnav .icon span {
display: block; display: block;
text-transform: uppercase; width: 30px;
height: 3px;
margin-bottom: 5px;
position: relative;
background: #fff;
border-radius: 2px;
} }
html, body { .topnav .active {
font-family: Arial; background-color: #555;
margin: 0; }
span.seperator {
width: 100%;
height: 1px;
margin: 5px 0px 5px;
background-color: #494949;
display: block;
}
#wrapper {
min-height: 100%;
}
#content {
padding: 50px 20px 120px 20px;
overflow: auto;
}
#footer {
height: 120px;
margin-top: -120px;
background-color: #555;
width: 100%;
font-size: 13px;
}
#footer .right {
color: #bbb;
margin: 23px 25px;
text-align: right;
}
#footer .left {
color: #bbb;
margin: 23px 0px 0px 25px;
}
#footer ul {
list-style-type: none;
margin: 20px auto;
padding: 0; padding: 0;
} }
#footer ul li, #footer a {
color: #bbb;
margin-bottom: 10px;
padding-left: 5px;
font-size: 13px;
}
#footer a:hover {
color: #fff;
}
.hide {
display: none;
}
@media only screen and (min-width: 992px) {
.topnav {
width: 230px !important;
height: 100%;
}
.topnav a.icon {
display: none !important;
}
.topnav a {
padding: 14px 24px;
}
.topnav .title {
padding-left: 24px !important;
}
.topnav .hide {
display: block;
}
#content {
padding: 15px 15px 120px 250px;
}
#footer .left {
margin-left: 250px !important;
}
}
/** old CSS below **/
p { p {
text-align: justify; text-align: justify;
font-size: 13pt; font-size: 13pt;
@ -31,17 +170,17 @@ p.lic, p.lic a {
} }
.s_active, .s_collapsible:hover { .s_active, .s_collapsible:hover {
background-color: #006ec0; background-color: #044e86;
color: #fff;
} }
.s_content { .s_content {
display: none; display: none;
overflow: hidden; overflow: hidden;
} }
.s_collapsible { .s_collapsible {
background-color: #044e86; background-color: #006ec0;
color: white; color: white;
cursor: pointer; cursor: pointer;
padding: 18px; padding: 18px;
@ -65,10 +204,6 @@ p.lic, p.lic a {
margin: 0 0 7px 12px; margin: 0 0 7px 12px;
} }
.hide {
display: none;
}
a:link, a:visited { a:link, a:visited {
text-decoration: none; text-decoration: none;
font-size: 13pt; font-size: 13pt;
@ -79,37 +214,15 @@ a:hover, a:focus {
color: #f00; color: #f00;
} }
a.erase { a.btn {
background-color: #006ec0; background-color: #006ec0;
color: #fff; color: #fff;
padding: 7px; padding: 7px 15px 7px 15px;
display: inline-block; display: inline-block;
margin-top: 30px;
}
#content {
padding: 15px 15px 60px 15px;
} }
#footer { a.btn:hover {
position: fixed; background-color: #044e86 !important;
bottom: 0px;
height: 45px;
background-color: #006ec0;
width: 100%;
border-top: 5px solid #fff;
}
#footer p, #footer a {
color: #fff;
padding: 0 7px 0 7px;
font-size: 10pt !important;
}
div.content {
background-color: #fff;
padding-bottom: 65px;
overflow: auto;
} }
input, select { input, select {
@ -160,6 +273,10 @@ label {
vertical-align: top; vertical-align: top;
} }
pre {
white-space: pre-wrap;
}
fieldset { fieldset {
margin-bottom: 15px; margin-bottom: 15px;
} }

54
tools/esp8266/html/system.html

@ -0,0 +1,54 @@
<!doctype html>
<html>
<head>
<title>System</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 class="topnav">
<a href="/" class="title">AhoyDTU</a>
<a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content">
<a href="/factory" class="btn">Factory Reset</a><br/>
<br/>
<a href="/reboot" class="btn">Reboot</a>
</div>
</div>
<div id="footer">
<div class="left">
AhoyDTU &copy 2022
<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 parseSys(obj) {
parseVersion(obj);
}
function parse(obj) {
if(null != obj) {
parseMenu(obj["menu"]);
parseSys(obj["system"]);
}
}
getAjax("/api/index", parse);
</script>
</body>
</html>

39
tools/esp8266/html/update.html

@ -7,8 +7,17 @@
<script type="text/javascript" src="api.js"></script> <script type="text/javascript" src="api.js"></script>
</head> </head>
<body> <body>
<h1>Update</h1> <div class="topnav">
<div id="content" class="content"> <a href="/" class="title">AhoyDTU</a>
<a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content">
<div> <div>
Make sure that you have noted all your settings before starting an update. New versions may have changed their memory layout which can break your existing settings.<br/> Make sure that you have noted all your settings before starting an update. New versions may have changed their memory layout which can break your existing settings.<br/>
<br/> <br/>
@ -19,17 +28,33 @@
<input type="file" name="update"><input type="submit" value="Update"> <input type="file" name="update"><input type="submit" value="Update">
</form> </form>
</div> </div>
</div>
<div id="footer"> <div id="footer">
<p class="left">&copy 2022</p> <div class="left">
<p class="left"><a href="/">Home</a></p> AhoyDTU &copy 2022
<p class="right" id="version"></p> <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> </div>
<script type="text/javascript"> <script type="text/javascript">
function parseSys(obj) { function parseSys(obj) {
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; parseVersion(obj);
}
function parse(obj) {
if(null != obj) {
parseMenu(obj["menu"]);
parseSys(obj["system"]);
}
} }
getAjax("/api/system", parseSys); getAjax("/api/index", parse);
</script> </script>
</body> </body>
</html> </html>

40
tools/esp8266/html/visualization.html

@ -8,20 +8,40 @@
<script type="text/javascript" src="api.js"></script> <script type="text/javascript" src="api.js"></script>
</head> </head>
<body> <body>
<h1>AHOY</h1> <div class="topnav">
<div id="content" class="content"> <a href="/" class="title">AhoyDTU</a>
<a href="javascript:void(0);" class="icon" onclick="topnav()">
<span></span>
<span></span>
<span></span>
</a>
<div id="topnav" class="hide"></div>
</div>
<div id="wrapper">
<div id="content">
<div id="live"></div> <div id="live"></div>
<p>Every <span id="refresh"></span> seconds the values are updated</p> <p>Every <span id="refresh"></span> seconds the values are updated</p>
</div> </div>
</div>
<div id="footer"> <div id="footer">
<p class="left">&copy 2022</p> <div class="left">
<p class="left"><a href="/">Home</a></p> AhoyDTU &copy 2022
<p class="right" id="version"></p> <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> </div>
<script type="text/javascript"> <script type="text/javascript">
var intervalSet = false; var exeOnce = true;
function parseSys(obj) { function parseSys(obj) {
document.getElementById("version").innerHTML = "Git SHA: " + obj["build"] + " :: " + obj["version"]; if(true == exeOnce)
parseVersion(obj);
} }
function parseIv(obj, root) { function parseIv(obj, root) {
@ -108,12 +128,14 @@
function parse(obj) { function parse(obj) {
if(null != obj) { if(null != obj) {
if(true == exeOnce)
parseMenu(obj["menu"]);
parseSys(obj["system"]); parseSys(obj["system"]);
parseIv(obj["inverter"], obj); parseIv(obj["inverter"], obj);
document.getElementById("refresh").innerHTML = obj["refresh_interval"]; document.getElementById("refresh").innerHTML = obj["refresh_interval"];
if(false == intervalSet) { if(true == exeOnce) {
window.setInterval("getAjax('/api/live', parse)", obj["refresh_interval"] * 1000); window.setInterval("getAjax('/api/live', parse)", obj["refresh_interval"] * 1000);
intervalSet = true; exeOnce = false;
} }
} }
else else

15
tools/esp8266/mqtt.h

@ -25,6 +25,9 @@ class mqtt {
mClient = new PubSubClient(mEspClient); mClient = new PubSubClient(mEspClient);
mAddressSet = false; mAddressSet = false;
mLastReconnect = 0;
mTxCnt = 0;
memset(mDevName, 0, DEVNAME_LEN); memset(mDevName, 0, DEVNAME_LEN);
} }
@ -50,6 +53,7 @@ class mqtt {
char top[64]; char top[64];
snprintf(top, 64, "%s/%s", mCfg->topic, topic); snprintf(top, 64, "%s/%s", mCfg->topic, topic);
sendMsg2(top, msg, false); sendMsg2(top, msg, false);
mTxCnt++;
} }
void sendMsg2(const char *topic, const char *msg, boolean retained) { void sendMsg2(const char *topic, const char *msg, boolean retained) {
@ -75,6 +79,10 @@ class mqtt {
mClient->loop(); mClient->loop();
} }
uint32_t getTxCnt(void) {
return mTxCnt;
}
private: private:
void reconnect(void) { void reconnect(void) {
DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect")); DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect"));
@ -85,8 +93,8 @@ class mqtt {
#endif #endif
boolean resub = false; boolean resub = false;
if(!mClient->connected() && (millis() - lastReconnect) > MQTT_RECONNECT_DELAY ) { if(!mClient->connected() && (millis() - mLastReconnect) > MQTT_RECONNECT_DELAY ) {
lastReconnect = millis(); mLastReconnect = millis();
if(strlen(mDevName) > 0) { if(strlen(mDevName) > 0) {
// der Server und der Port müssen neu gesetzt werden, // der Server und der Port müssen neu gesetzt werden,
// da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat. // da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat.
@ -118,7 +126,8 @@ class mqtt {
bool mAddressSet; bool mAddressSet;
mqttConfig_t *mCfg; mqttConfig_t *mCfg;
char mDevName[DEVNAME_LEN]; char mDevName[DEVNAME_LEN];
unsigned long lastReconnect = 0; uint32_t mLastReconnect;
uint32_t mTxCnt;
}; };
#endif /*__MQTT_H_*/ #endif /*__MQTT_H_*/

2
tools/esp8266/scripts/auto_firmware_version.py

@ -21,7 +21,7 @@ def get_firmware_specifier_build_flag():
except: except:
build_version = "g0000000" build_version = "g0000000"
build_flag = "-D AUTO_GIT_HASH=\\\"" + build_version + "\\\"" build_flag = "-D AUTO_GIT_HASH=\\\"" + build_version[1:] + "\\\""
print ("Firmware Revision: " + build_version) print ("Firmware Revision: " + build_version)
return (build_flag) return (build_flag)

14
tools/esp8266/web.cpp

@ -18,6 +18,7 @@
#include "html/h/visualization_html.h" #include "html/h/visualization_html.h"
#include "html/h/update_html.h" #include "html/h/update_html.h"
#include "html/h/serial_html.h" #include "html/h/serial_html.h"
#include "html/h/system_html.h"
const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"}; const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"};
@ -51,6 +52,7 @@ void web::setup(void) {
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));
mWeb->onNotFound ( std::bind(&web::showNotFound, this, std::placeholders::_1)); mWeb->onNotFound ( std::bind(&web::showNotFound, this, std::placeholders::_1));
mWeb->on("/reboot", HTTP_ANY, std::bind(&web::onReboot, this, std::placeholders::_1)); mWeb->on("/reboot", HTTP_ANY, std::bind(&web::onReboot, this, std::placeholders::_1));
mWeb->on("/system", HTTP_ANY, std::bind(&web::onSystem, this, std::placeholders::_1));
mWeb->on("/erase", HTTP_ANY, std::bind(&web::showErase, 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("/factory", HTTP_ANY, std::bind(&web::showFactoryRst, this, std::placeholders::_1));
@ -160,8 +162,18 @@ void web::showNotFound(AsyncWebServerRequest *request) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void web::onReboot(AsyncWebServerRequest *request) { void web::onReboot(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>"));
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>"));
}
//-----------------------------------------------------------------------------
void web::onSystem(AsyncWebServerRequest *request) {
DPRINTLN(DBG_VERBOSE, F("onSystem"));
AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html"), system_html, system_html_len);
response->addHeader(F("Content-Encoding"), "gzip");
request->send(response);
} }

1
tools/esp8266/web.h

@ -54,6 +54,7 @@ class web {
private: private:
void onSerial(AsyncWebServerRequest *request); void onSerial(AsyncWebServerRequest *request);
void onSystem(AsyncWebServerRequest *request);
AsyncWebServer *mWeb; AsyncWebServer *mWeb;
AsyncEventSource *mEvts; AsyncEventSource *mEvts;

30
tools/esp8266/webApi.cpp

@ -48,6 +48,7 @@ void webApi::onApi(AsyncWebServerRequest *request) {
if(path == "system") getSystem(root); if(path == "system") getSystem(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 == "index") getIndex(root); else if(path == "index") getIndex(root);
else if(path == "setup") getSetup(root); else if(path == "setup") getSetup(root);
else if(path == "setup/networks") getNetworks(root); else if(path == "setup/networks") getNetworks(root);
@ -241,8 +242,29 @@ void webApi::getSerial(JsonObject obj) {
} }
//-----------------------------------------------------------------------------
void webApi::getMenu(JsonObject obj) {
obj["name"][0] = "Live";
obj["link"][0] = "/live";
obj["name"][1] = "Serial Console";
obj["link"][1] = "/serial";
obj["name"][2] = "Settings";
obj["link"][2] = "/setup";
obj["name"][3] = "-";
obj["name"][4] = "REST API";
obj["link"][4] = "/api";
obj["trgt"][4] = "_blank";
obj["name"][5] = "-";
obj["name"][6] = "Update";
obj["link"][6] = "/update";
obj["name"][7] = "System";
obj["link"][7] = "/system";
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void webApi::getIndex(JsonObject obj) { void webApi::getIndex(JsonObject obj) {
getMenu(obj.createNestedObject(F("menu")));
getSystem(obj.createNestedObject(F("system"))); getSystem(obj.createNestedObject(F("system")));
getStatistics(obj.createNestedObject(F("statistics"))); getStatistics(obj.createNestedObject(F("statistics")));
obj["refresh_interval"] = SEND_INTERVAL; obj["refresh_interval"] = SEND_INTERVAL;
@ -275,12 +297,13 @@ void webApi::getIndex(JsonObject obj) {
if(!mApp->getSettingsValid()) if(!mApp->getSettingsValid())
info.add(F("your settings are invalid")); info.add(F("your settings are invalid"));
if(mApp->mqttIsConnected()) if(mApp->mqttIsConnected())
info.add(F("MQTT is connected")); info.add(F("MQTT is connected, ") + String(mApp->getMqttTxCnt()) + F(" packets sent"));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void webApi::getSetup(JsonObject obj) { void webApi::getSetup(JsonObject obj) {
getMenu(obj.createNestedObject(F("menu")));
getSystem(obj.createNestedObject(F("system"))); getSystem(obj.createNestedObject(F("system")));
getInverterList(obj.createNestedObject(F("inverter"))); getInverterList(obj.createNestedObject(F("inverter")));
getMqtt(obj.createNestedObject(F("mqtt"))); getMqtt(obj.createNestedObject(F("mqtt")));
@ -300,6 +323,7 @@ void webApi::getNetworks(JsonObject obj) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void webApi::getLive(JsonObject obj) { void webApi::getLive(JsonObject obj) {
getMenu(obj.createNestedObject(F("menu")));
getSystem(obj.createNestedObject(F("system"))); getSystem(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;
@ -435,7 +459,9 @@ bool webApi::setCtrl(DynamicJsonDocument jsonIn, JsonObject jsonOut) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool webApi::setSetup(DynamicJsonDocument jsonIn, JsonObject jsonOut) { bool webApi::setSetup(DynamicJsonDocument jsonIn, JsonObject jsonOut) {
if(F("set_time") == jsonIn[F("cmd")]) if(F("scan_wifi"))
mApp->scanAvailNetworks();
else if(F("set_time") == jsonIn[F("cmd")])
mApp->setTimestamp(jsonIn[F("ts")]); mApp->setTimestamp(jsonIn[F("ts")]);
else if(F("sync_ntp") == jsonIn[F("cmd")]) else if(F("sync_ntp") == jsonIn[F("cmd")])
mApp->setTimestamp(0); // 0: update ntp flag mApp->setTimestamp(0); // 0: update ntp flag

1
tools/esp8266/webApi.h

@ -42,6 +42,7 @@ class webApi {
void getRadio(JsonObject obj); void getRadio(JsonObject obj);
void getSerial(JsonObject obj); void getSerial(JsonObject obj);
void getMenu(JsonObject obj);
void getIndex(JsonObject obj); void getIndex(JsonObject obj);
void getSetup(JsonObject obj); void getSetup(JsonObject obj);
void getNetworks(JsonObject obj); void getNetworks(JsonObject obj);

Loading…
Cancel
Save