Browse Source

switch to ESP32

pull/1155/head
DanielR92 2 years ago
parent
commit
15ddc01746
  1. 8
      src/app.cpp
  2. 3
      src/app.h
  3. 18
      src/config/settings.h
  4. 88
      src/plugins/zeroExport/zeroExport.h
  5. 7
      src/web/RestApi.h
  6. 55
      src/web/html/setup.html
  7. 4
      src/web/html/style.css
  8. 2
      src/web/web.h

8
src/app.cpp

@ -495,7 +495,10 @@ void app::tickSend(void) {
yield(); yield();
updateLed(); updateLed();
#if defined(ESP32)
zeroexport(); zeroexport();
#endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -622,12 +625,14 @@ void app::updateLed(void) {
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if defined(ESP32)
void app::zeroexport() { void app::zeroexport() {
if (!mConfig->plugin.zexport.enabled) return; if (!mConfig->plugin.zexport.enabled) return;
DynamicJsonDocument doc(512); DynamicJsonDocument doc(512);
JsonObject object = doc.to<JsonObject>(); JsonObject object = doc.to<JsonObject>();
object["path"] = "ctrl"; object["path"] = "ctrl";
object["id"] = 0; object["id"] = 0;
object["val"] = round(mzExport.sum()); object["val"] = round(mzExport.sum());
@ -638,4 +643,5 @@ void app::zeroexport() {
DPRINTLN(DBG_INFO, data);*/ DPRINTLN(DBG_INFO, data);*/
mApi.ctrlRequest(object); mApi.ctrlRequest(object);
} }
#endif

3
src/app.h

@ -283,7 +283,10 @@ class app : public IApp, public ah::Scheduler {
void setupLed(); void setupLed();
void updateLed(); void updateLed();
#if defined(ESP32)
void zeroexport(); void zeroexport();
#endif
void tickReboot(void) { void tickReboot(void) {
DPRINTLN(DBG_INFO, F("Rebooting...")); DPRINTLN(DBG_INFO, F("Rebooting..."));

18
src/config/settings.h

@ -134,6 +134,8 @@ typedef struct {
uint16_t interval; uint16_t interval;
} cfgMqtt_t; } cfgMqtt_t;
/* Zero Export section */
#if defined(ESP32)
typedef struct { typedef struct {
float power; float power;
float pf; float pf;
@ -143,13 +145,12 @@ typedef struct {
uint16_t total; uint16_t total;
uint16_t total_returned; uint16_t total_returned;
} cfgShellyEM3_t; } cfgShellyEM3_t;
typedef struct { typedef struct {
char monitor_ip[ZEXPORT_ADDR_LEN]; char monitor_ip[ZEXPORT_ADDR_LEN];
bool enabled; bool enabled;
cfgShellyEM3_t PHASE[3]; cfgShellyEM3_t PHASE[3];
} cfgzeroExport_t; } cfgzeroExport_t;
#endif
typedef struct { typedef struct {
bool enabled; bool enabled;
@ -190,7 +191,9 @@ typedef struct {
typedef struct { typedef struct {
display_t display; display_t display;
#if defined(ESP32)
cfgzeroExport_t zexport; cfgzeroExport_t zexport;
#endif
} plugins_t; } plugins_t;
typedef struct { typedef struct {
@ -293,12 +296,12 @@ class settings {
if(root.containsKey(F("nrf"))) jsonNrf(root[F("nrf")]); if(root.containsKey(F("nrf"))) jsonNrf(root[F("nrf")]);
#if defined(ESP32) #if defined(ESP32)
if(root.containsKey(F("cmt"))) jsonCmt(root[F("cmt")]); if(root.containsKey(F("cmt"))) jsonCmt(root[F("cmt")]);
if(root.containsKey(F("zeroExport"))) jsonzeroExport(root[F("zeroExport")]);
#endif #endif
if(root.containsKey(F("ntp"))) jsonNtp(root[F("ntp")]); if(root.containsKey(F("ntp"))) jsonNtp(root[F("ntp")]);
if(root.containsKey(F("sun"))) jsonSun(root[F("sun")]); if(root.containsKey(F("sun"))) jsonSun(root[F("sun")]);
if(root.containsKey(F("serial"))) jsonSerial(root[F("serial")]); if(root.containsKey(F("serial"))) jsonSerial(root[F("serial")]);
if(root.containsKey(F("mqtt"))) jsonMqtt(root[F("mqtt")]); if(root.containsKey(F("mqtt"))) jsonMqtt(root[F("mqtt")]);
if(root.containsKey(F("zeroExport"))) jsonzeroExport(root[F("zeroExport")]);
if(root.containsKey(F("led"))) jsonLed(root[F("led")]); if(root.containsKey(F("led"))) jsonLed(root[F("led")]);
if(root.containsKey(F("plugin"))) jsonPlugin(root[F("plugin")]); if(root.containsKey(F("plugin"))) jsonPlugin(root[F("plugin")]);
if(root.containsKey(F("inst"))) jsonInst(root[F("inst")]); if(root.containsKey(F("inst"))) jsonInst(root[F("inst")]);
@ -321,6 +324,7 @@ class settings {
jsonNrf(root.createNestedObject(F("nrf")), true); jsonNrf(root.createNestedObject(F("nrf")), true);
#if defined(ESP32) #if defined(ESP32)
jsonCmt(root.createNestedObject(F("cmt")), true); jsonCmt(root.createNestedObject(F("cmt")), true);
jsonzeroExport(root.createNestedObject(F("zeroExport")), true);
#endif #endif
jsonNtp(root.createNestedObject(F("ntp")), true); jsonNtp(root.createNestedObject(F("ntp")), true);
jsonSun(root.createNestedObject(F("sun")), true); jsonSun(root.createNestedObject(F("sun")), true);
@ -329,7 +333,7 @@ class settings {
jsonLed(root.createNestedObject(F("led")), true); jsonLed(root.createNestedObject(F("led")), true);
jsonPlugin(root.createNestedObject(F("plugin")), true); jsonPlugin(root.createNestedObject(F("plugin")), true);
jsonInst(root.createNestedObject(F("inst")), true); jsonInst(root.createNestedObject(F("inst")), true);
jsonzeroExport(root.createNestedObject(F("zeroExport")), true);
DPRINT(DBG_INFO, F("memory usage: ")); DPRINT(DBG_INFO, F("memory usage: "));
DBGPRINTLN(String(json.memoryUsage())); DBGPRINTLN(String(json.memoryUsage()));
@ -446,8 +450,10 @@ class settings {
mCfg.mqtt.interval = 0; // off mCfg.mqtt.interval = 0; // off
// Zero-Export // Zero-Export
#if defined(ESP32)
snprintf(mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN, "%s", DEF_ZEXPORT); snprintf(mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN, "%s", DEF_ZEXPORT);
mCfg.plugin.zexport.enabled = false; mCfg.plugin.zexport.enabled = false;
#endif
mCfg.inst.rstYieldMidNight = false; mCfg.inst.rstYieldMidNight = false;
mCfg.inst.rstValsNotAvail = false; mCfg.inst.rstValsNotAvail = false;
@ -630,6 +636,7 @@ class settings {
} }
} }
#if defined(ESP32)
void jsonzeroExport(JsonObject obj, bool set = false) { void jsonzeroExport(JsonObject obj, bool set = false) {
if(set) { if(set) {
obj[F("en_zeroexport")] = (bool) mCfg.plugin.zexport.enabled; obj[F("en_zeroexport")] = (bool) mCfg.plugin.zexport.enabled;
@ -639,7 +646,7 @@ class settings {
for (size_t i = 0; i < sizeof(mCfg.plugin.zexport.PHASE); i++) for (size_t i = 0; i < sizeof(mCfg.plugin.zexport.PHASE); i++)
{ {
char str[10]; char str[10];
sprintf(str, "phase_%d", i); sprintf(str, "phase_%d", i + 1);
obj[str][F("power")] = mCfg.plugin.zexport.PHASE[i].power; obj[str][F("power")] = mCfg.plugin.zexport.PHASE[i].power;
obj[str][F("pf")] = mCfg.plugin.zexport.PHASE[i].pf; obj[str][F("pf")] = mCfg.plugin.zexport.PHASE[i].pf;
obj[str][F("current")] = mCfg.plugin.zexport.PHASE[i].current; obj[str][F("current")] = mCfg.plugin.zexport.PHASE[i].current;
@ -655,6 +662,7 @@ class settings {
getChar(obj, F("monitor_ipAddr"), mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN); getChar(obj, F("monitor_ipAddr"), mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN);
} }
} }
#endif
void jsonLed(JsonObject obj, bool set = false) { void jsonLed(JsonObject obj, bool set = false) {
if(set) { if(set) {

88
src/plugins/zeroExport/zeroExport.h

@ -1,7 +1,9 @@
#if defined(ESP32)
#ifndef __ZEROEXPORT__ #ifndef __ZEROEXPORT__
#define __ZEROEXPORT__ #define __ZEROEXPORT__
#include <ESP8266HTTPClient.h> #include <HTTPClient.h>
#include <string.h> #include <string.h>
#include "AsyncJson.h" #include "AsyncJson.h"
@ -52,68 +54,48 @@ class ZeroExport {
} }
private: private:
WiFiClient client; HTTPClient http;
int status = WL_IDLE_STATUS; //char msgBuffer[256] = {'\0'};
const uint16_t httpPort = 80;
const String url = "/emeter/";
char msgBuffer[256] = {'\0'};
const String serverIp = "192.168.5.30";
static char msg[50];
void loop() { } void loop() { }
void zero() { void zero() {
sendReq(0); sendReq(0);
sendReq(1); sendReq(1);
sendReq(2); sendReq(2);
} }
// TODO: change int to u_short void sendReq(int index)
void sendReq(int index) { {
if (!client.connect(serverIp, httpPort)) { http.begin(String(mCfg->monitor_ip), 80, "/emeter/" + String(index));
delay(1000);
DPRINTLN(DBG_INFO, F("connection failed")); int httpResponseCode = http.GET();
if (httpResponseCode > 0)
{
DynamicJsonDocument json(128);
deserializeJson(json, getData());
mCfg->PHASE[index].power = json[F("power")];
mCfg->PHASE[index].pf = json[F("pf")];
mCfg->PHASE[index].current = json[F("current")];
mCfg->PHASE[index].voltage = json[F("voltage")];
mCfg->PHASE[index].is_valid = json[F("is_valid")];
mCfg->PHASE[index].total = json[F("total")];
mCfg->PHASE[index].total_returned = json[F("total_returned")];
}
else
{
DPRINT(DBG_INFO, "Error code: ");
DPRINTLN(DBG_INFO, String(httpResponseCode));
} }
strcpy ( msgBuffer, "GET ");
strcat ( msgBuffer, url.c_str());
char str[10];
sprintf(str, "%d", index);
strcat ( msgBuffer, str);
strcat ( msgBuffer, "\r\nHTTP/1.1\r\n\r\n" );
client.print(msgBuffer);
DynamicJsonDocument json(128);
String raw = getData();
deserializeJson(json, raw);
//DPRINTLN(DBG_INFO, raw);
mCfg->PHASE[index].power = json[F("power")];
mCfg->PHASE[index].pf = json[F("pf")];
mCfg->PHASE[index].current = json[F("current")];
mCfg->PHASE[index].voltage = json[F("voltage")];
mCfg->PHASE[index].is_valid = json[F("is_valid")];
mCfg->PHASE[index].total = json[F("total")];
mCfg->PHASE[index].total_returned = json[F("total_returned")];
} }
String getData() { String getData()
while (client.connected()) { {
//TODO: what if available is not true? It will stuck here then... String payload = http.getString();
while (client.available()) DPRINTLN(DBG_INFO, payload);
{
String raw = client.readString(); int x = payload.indexOf("{", 0);
int x = raw.indexOf("{", 0); return payload.substring(x, payload.length());
client.stop();
return raw.substring(x, raw.length());
}
}
return F("error");
} }
// private member variables // private member variables
@ -127,4 +109,6 @@ class ZeroExport {
uint16_t mRefreshCycle; uint16_t mRefreshCycle;
}; };
#endif /*__ZEROEXPORT__*/ #endif /*__ZEROEXPORT__*/
#endif /* #if defined(ESP32) */

7
src/web/RestApi.h

@ -465,6 +465,7 @@ class RestApi {
obj[F("interval")] = String(mConfig->mqtt.interval); obj[F("interval")] = String(mConfig->mqtt.interval);
} }
#if defined(ESP32)
void getzeroExport(JsonObject obj) { void getzeroExport(JsonObject obj) {
obj[F("en_zeroexport")] = (bool) mConfig->plugin.zexport.enabled; obj[F("en_zeroexport")] = (bool) mConfig->plugin.zexport.enabled;
obj[F("monitor_ipAddr")] = String(mConfig->plugin.zexport.monitor_ip); obj[F("monitor_ipAddr")] = String(mConfig->plugin.zexport.monitor_ip);
@ -483,6 +484,7 @@ class RestApi {
phases[F("total_returned")] = mConfig->plugin.zexport.PHASE[i].total_returned; phases[F("total_returned")] = mConfig->plugin.zexport.PHASE[i].total_returned;
} }
} }
#endif
void getNtp(JsonObject obj) { void getNtp(JsonObject obj) {
obj[F("addr")] = String(mConfig->ntp.addr); obj[F("addr")] = String(mConfig->ntp.addr);
@ -609,7 +611,6 @@ class RestApi {
getSysInfo(request, obj.createNestedObject(F("system"))); getSysInfo(request, obj.createNestedObject(F("system")));
//getInverterList(obj.createNestedObject(F("inverter"))); //getInverterList(obj.createNestedObject(F("inverter")));
getMqtt(obj.createNestedObject(F("mqtt"))); getMqtt(obj.createNestedObject(F("mqtt")));
getzeroExport(obj.createNestedObject(F("zeroExport")));
getNtp(obj.createNestedObject(F("ntp"))); getNtp(obj.createNestedObject(F("ntp")));
getSun(obj.createNestedObject(F("sun"))); getSun(obj.createNestedObject(F("sun")));
getPinout(obj.createNestedObject(F("pinout"))); getPinout(obj.createNestedObject(F("pinout")));
@ -618,6 +619,10 @@ class RestApi {
getSerial(obj.createNestedObject(F("serial"))); getSerial(obj.createNestedObject(F("serial")));
getStaticIp(obj.createNestedObject(F("static_ip"))); getStaticIp(obj.createNestedObject(F("static_ip")));
getDisplay(obj.createNestedObject(F("display"))); getDisplay(obj.createNestedObject(F("display")));
#if defined(ESP32)
getzeroExport(obj.createNestedObject(F("zeroExport")));
#endif
} }
#if !defined(ETHERNET) #if !defined(ETHERNET)

55
src/web/html/setup.html

@ -316,8 +316,8 @@
</div> </div>
<!-- Zero Export --> <!-- Zero Export -->
<button type="button" class="s_collapsible">Zero Export</button> <button type="button" class="s_collapsible" id="zeroExport_button">Zero Export</button>
<div class="s_content"> <div class="s_content" id="zeroExport">
<fieldset class="mb-4"> <fieldset class="mb-4">
<legend class="des">Zero Export</legend> <legend class="des">Zero Export</legend>
<div id="zeroType"></div> <div id="zeroType"></div>
@ -330,10 +330,12 @@
<div class="row mb-3"> <div class="row mb-3">
<div class="col-12 col-sm-3 my-2">Shelly EM3 IP: </div> <div class="col-12 col-sm-3 my-2">Shelly EM3 IP: </div>
<div class="col-12 col-sm-9"><input type="text" name="monitor_ipAddr" maxlength="15"></div> <div class="col-12 col-sm-9"><input type="text" name="monitor_ipAddr" maxlength="15"></div>
<div class="col-12 col-sm-3 my-2">Prio Inverter</div>
<div class="col-12 col-sm-9"><select name="iv" id="Inv_ID"></select></div>
</div> </div>
<p name="phase_0">L1: n/a</p> <p name="phase_1">L1: n/a</p>
<p name="phase_1">L2: n/a</p> <p name="phase_2">L2: n/a</p>
<p name="phase_2">L3: n/a</p> <p name="phase_3">L3: n/a</p>
</fieldset> </fieldset>
</div> </div>
@ -936,15 +938,47 @@
document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000))); document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000)));
} }
function parsezeroExport(obj) { function parsezeroExport(obj, type, ) {
if ("ESP8266" == type) {
var e = document.getElementById("zeroExport");
e.remove();
var e = document.getElementById("zeroExport_button");
e.textContent += " (only for ESP32 available)";
e.disabled = true;
element.classList.add("disabled");
return;
}
getAjax("/api/inverter/list", parseZeroIv);
for(var i of [["monitor_ipAddr", "monitor_ipAddr"]]) for(var i of [["monitor_ipAddr", "monitor_ipAddr"]])
if(null != obj[i[1]]) if(null != obj[i[1]])
document.getElementsByName(i[0])[0].value = obj[i[1]]; document.getElementsByName(i[0])[0].value = obj[i[1]];
document.getElementsByName("en_zeroexport")[0].checked = obj["en_zeroexport"]; document.getElementsByName("en_zeroexport")[0].checked = obj["en_zeroexport"];
document.getElementsByName("phase_0")[0].innerHTML = "L1: " + obj["phase_0"]["power"].toFixed(2) + "W";
document.getElementsByName("phase_1")[0].innerHTML = "L2: " + obj["phase_1"]["power"].toFixed(2) + "W"; for (let i = 0; i < 3; i++) document.getElementsByName("phase_" + (i + 1))[0].innerHTML = "L" + (i + 1) + ": " + obj["phase_" + i]["power"].toFixed(2) + "W";
document.getElementsByName("phase_2")[0].innerHTML = "L3: " + obj["phase_2"]["power"].toFixed(2) + "W"; }
function parseZeroIv(root)
{
for(var i = 0; i < root.inverter.length; i++)
root.inverter[i];
select = document.getElementById('Inv_ID');
parseInt(select.value)
if(null == root) return;
root = root.inverter;
for(var i = 0; i < root.length; i++) {
inv = root[i];
var opt = document.createElement('option');
opt.value = inv.id;
opt.innerHTML = inv.name;
select.appendChild(opt);
}
} }
function parse(root) { function parse(root) {
@ -959,9 +993,10 @@
parseNrfRadio(root["radioNrf"], root["pinout"], root["system"]["esp_type"], root["system"]); parseNrfRadio(root["radioNrf"], root["pinout"], root["system"]["esp_type"], root["system"]);
if(root["generic"]["esp_type"] == "ESP32") if(root["generic"]["esp_type"] == "ESP32")
parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]);
parsezeroExport(root["zeroExport"], root["system"]["esp_type"]);
parseSerial(root["serial"]); parseSerial(root["serial"]);
parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); parseDisplay(root["display"], root["system"]["esp_type"], root["system"]);
parsezeroExport(root["zeroExport"]);
getAjax("/api/inverter/list", parseIv); getAjax("/api/inverter/list", parseIv);
} }
} }

4
src/web/html/style.css

@ -434,6 +434,10 @@ p.lic, p.lic a {
color: #fff; color: #fff;
} }
.disabled {
background-color: dimgray;
}
.s_content { .s_content {
display: none; display: none;
overflow: hidden; overflow: hidden;

2
src/web/web.h

@ -604,6 +604,7 @@ class Web {
mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt();
// zero-export // zero-export
#if defined(ESP32)
mConfig->plugin.zexport.enabled = (request->arg("en_zeroexport") == "on"); mConfig->plugin.zexport.enabled = (request->arg("en_zeroexport") == "on");
if (request->arg("monitor_ipAddr") != "") { if (request->arg("monitor_ipAddr") != "") {
String addr = request->arg("monitor_ipAddr"); String addr = request->arg("monitor_ipAddr");
@ -611,6 +612,7 @@ class Web {
addr.toCharArray(mConfig->plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN); addr.toCharArray(mConfig->plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN);
} else } else
mConfig->plugin.zexport.monitor_ip[0] = '\0'; mConfig->plugin.zexport.monitor_ip[0] = '\0';
#endif
// serial console // serial console
if (request->arg("serIntvl") != "") { if (request->arg("serIntvl") != "") {

Loading…
Cancel
Save