Browse Source

first test

pull/1155/head
DanielR92 2 years ago
parent
commit
269f94997a
  1. 3
      ahoy.code-workspace
  2. 9
      src/app.cpp
  3. 4
      src/app.h
  4. 3
      src/config/config.h
  5. 24
      src/config/settings.h
  6. 2
      src/defines.h
  7. 0
      src/plugins/zeroExport/zeroExport.cpp
  8. 81
      src/plugins/zeroExport/zeroExport.h
  9. 6
      src/web/RestApi.h
  10. 38
      src/web/html/setup.html
  11. 9
      src/web/web.h

3
ahoy.code-workspace

@ -2,9 +2,6 @@
"folders": [ "folders": [
{ {
"path": "." "path": "."
},
{
"path": "src"
} }
], ],
"settings": { "settings": {

9
src/app.cpp

@ -119,6 +119,11 @@ void app::setup() {
mPubSerial.setup(mConfig, &mSys, &mTimestamp); mPubSerial.setup(mConfig, &mSys, &mTimestamp);
// ZeroExport
if (mConfig->plugin.zexport.enabled) {
mzExport.setup(&mConfig->plugin.zexport, &mSys, mConfig);
}
#if !defined(ETHERNET) #if !defined(ETHERNET)
//mImprov.setup(this, mConfig->sys.deviceName, mVersion); //mImprov.setup(this, mConfig->sys.deviceName, mVersion);
#endif #endif
@ -248,6 +253,10 @@ void app::regularTickers(void) {
// Plugins // Plugins
if (mConfig->plugin.display.type != 0) if (mConfig->plugin.display.type != 0)
everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp"); everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp");
// Plugins
if (mConfig->plugin.zexport.enabled)
everyMin(std::bind(&ZeroExportType::tickerSecond, &mzExport), "zExport");
every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart");
#if !defined(ETHERNET) #if !defined(ETHERNET)
//everySec([this]() { mImprov.tickSerial(); }, "impro"); //everySec([this]() { mImprov.tickSerial(); }, "impro");

4
src/app.h

@ -55,7 +55,10 @@ typedef PubSerial<HmSystemType> PubSerialType;
// PLUGINS // PLUGINS
#include "plugins/Display/Display.h" #include "plugins/Display/Display.h"
#include "plugins/zeroExport/zeroExport.h"
typedef Display<HmSystemType> DisplayType; typedef Display<HmSystemType> DisplayType;
typedef ZeroExport<HmSystemType> ZeroExportType;
class app : public IApp, public ah::Scheduler { class app : public IApp, public ah::Scheduler {
public: public:
@ -361,6 +364,7 @@ class app : public IApp, public ah::Scheduler {
// plugins // plugins
DisplayType mDisplay; DisplayType mDisplay;
ZeroExportType mzExport;
}; };
#endif /*__APP_H__*/ #endif /*__APP_H__*/

3
src/config/config.h

@ -184,6 +184,9 @@
// default MQTT broker uri // default MQTT broker uri
#define DEF_MQTT_BROKER "\0" #define DEF_MQTT_BROKER "\0"
// default zero-export uri
#define DEF_ZEXPORT "\0"
// default MQTT port // default MQTT port
#define DEF_MQTT_PORT 1883 #define DEF_MQTT_PORT 1883

24
src/config/settings.h

@ -134,6 +134,11 @@ typedef struct {
uint16_t interval; uint16_t interval;
} cfgMqtt_t; } cfgMqtt_t;
typedef struct {
char monitor_ip[ZEXPORT_ADDR_LEN];
bool enabled;
} cfgzeroExport_t;
typedef struct { typedef struct {
bool enabled; bool enabled;
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH];
@ -173,6 +178,7 @@ typedef struct {
typedef struct { typedef struct {
display_t display; display_t display;
cfgzeroExport_t zexport;
} plugins_t; } plugins_t;
typedef struct { typedef struct {
@ -280,6 +286,7 @@ class settings {
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")]);
@ -310,6 +317,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()));
@ -425,6 +433,9 @@ class settings {
snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC); snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC);
mCfg.mqtt.interval = 0; // off mCfg.mqtt.interval = 0; // off
snprintf(mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN, "%s", DEF_ZEXPORT);
mCfg.plugin.zexport.enabled = false;
mCfg.inst.rstYieldMidNight = false; mCfg.inst.rstYieldMidNight = false;
mCfg.inst.rstValsNotAvail = false; mCfg.inst.rstValsNotAvail = false;
mCfg.inst.rstValsCommStop = false; mCfg.inst.rstValsCommStop = false;
@ -469,6 +480,7 @@ class settings {
ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf); ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf);
ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf); ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf);
ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf); ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf);
} else { } else {
#if !defined(ETHERNET) #if !defined(ETHERNET)
getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN);
@ -605,6 +617,18 @@ class settings {
} }
} }
void jsonzeroExport(JsonObject obj, bool set = false) {
if(set) {
obj[F("en_zeroexport")] = (bool) mCfg.plugin.zexport.enabled;
obj[F("monitor_ipAddr")] = mCfg.plugin.zexport.monitor_ip;
}
else
{
getVal<bool>(obj, F("en_zeroexport"), &mCfg.plugin.zexport.enabled);
getChar(obj, F("monitor_ipAddr"), mCfg.plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN);
}
}
void jsonLed(JsonObject obj, bool set = false) { void jsonLed(JsonObject obj, bool set = false) {
if(set) { if(set) {
obj[F("0")] = mCfg.led.led0; obj[F("0")] = mCfg.led.led0;

2
src/defines.h

@ -85,6 +85,8 @@ enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE};
#define DEVNAME_LEN 16 #define DEVNAME_LEN 16
#define NTP_ADDR_LEN 32 // DNS Name #define NTP_ADDR_LEN 32 // DNS Name
#define ZEXPORT_ADDR_LEN 64 // Zero-Export Address
#define MQTT_ADDR_LEN 64 // DNS Name #define MQTT_ADDR_LEN 64 // DNS Name
#define MQTT_CLIENTID_LEN 22 // number of chars is limited to 23 up to v3.1 of MQTT #define MQTT_CLIENTID_LEN 22 // number of chars is limited to 23 up to v3.1 of MQTT
#define MQTT_USER_LEN 65 // there is another byte necessary for \0 #define MQTT_USER_LEN 65 // there is another byte necessary for \0

0
src/plugins/zeroExport/zeroExport.cpp

81
src/plugins/zeroExport/zeroExport.h

@ -0,0 +1,81 @@
#ifndef __ZEROEXPORT__
#define __ZEROEXPORT__
#include <ESP8266HTTPClient.h>
template <class HMSYSTEM>
class ZeroExport {
public:
ZeroExport() { }
WiFiClientSecure client;
const uint8_t fingerprint[20] = {0x5A, 0xCF, 0xFE, 0xF0, 0xF1, 0xA6, 0xF4, 0x5F, 0xD2, 0x11, 0x11, 0xC6, 0x1D, 0x2F, 0x0E, 0xBC, 0x39, 0x8D, 0x50, 0xE0};
void setup(cfgzeroExport_t *cfg, HMSYSTEM *sys, settings_t *config) {
mCfg = cfg;
mSys = sys;
mConfig = config;
}
void payloadEventListener(uint8_t cmd) {
mNewPayload = true;
}
void tickerSecond() {
if (mNewPayload || ((++mLoopCnt % 10) == 0)) {
mNewPayload = false;
mLoopCnt = 0;
zero();
}
}
private:
void zero() {
char host[20];
const char* meter = "/emeter/0";
sprintf(host, mCfg->monitor_ip, meter);
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
client->setFingerprint(fingerprint);
HTTPClient https;
DPRINTLN(DBG_INFO, host);
if (https.begin(*client, host)) // HTTPS
{
DPRINTLN(DBG_INFO, F("[HTTPS] GET...\n"));
// start connection and send HTTP header
int httpCode = https.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = https.getString();
DPRINTLN(DBG_INFO, payload);
}
} else {
DPRINTLN(DBG_INFO, https.errorToString(httpCode).c_str());
}
https.end();
}
else
{
DPRINTLN(DBG_INFO, F("[HTTPS] Unable to connect\n"));
}
}
// private member variables
bool mNewPayload;
uint8_t mLoopCnt;
uint32_t *mUtcTs;
const char *mVersion;
cfgzeroExport_t *mCfg;
settings_t *mConfig;
HMSYSTEM *mSys;
uint16_t mRefreshCycle;
};
#endif /*__ZEROEXPORT__*/

6
src/web/RestApi.h

@ -465,6 +465,11 @@ class RestApi {
obj[F("interval")] = String(mConfig->mqtt.interval); obj[F("interval")] = String(mConfig->mqtt.interval);
} }
void getzeroExport(JsonObject obj) {
obj[F("en_zeroexport")] = (bool) mConfig->plugin.zexport.enabled;
obj[F("monitor_ipAddr")] = String(mConfig->plugin.zexport.monitor_ip);
}
void getNtp(JsonObject obj) { void getNtp(JsonObject obj) {
obj[F("addr")] = String(mConfig->ntp.addr); obj[F("addr")] = String(mConfig->ntp.addr);
obj[F("port")] = String(mConfig->ntp.port); obj[F("port")] = String(mConfig->ntp.port);
@ -590,6 +595,7 @@ 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")));

38
src/web/html/setup.html

@ -10,6 +10,7 @@
<div id="content"> <div id="content">
<form method="post" action="/save" id="settings"> <form method="post" action="/save" id="settings">
<fieldset> <fieldset>
<!-- System Config -->
<button type="button" class="s_collapsible mt-4">System Config</button> <button type="button" class="s_collapsible mt-4">System Config</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-2"> <fieldset class="mb-2">
@ -55,6 +56,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- Network -->
<button type="button" class="s_collapsible">Network</button> <button type="button" class="s_collapsible">Network</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-2"> <fieldset class="mb-2">
@ -122,6 +124,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- Protection -->
<button type="button" class="s_collapsible">Protection</button> <button type="button" class="s_collapsible">Protection</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -135,6 +138,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- Inverter -->
<button type="button" class="s_collapsible">Inverter</button> <button type="button" class="s_collapsible">Inverter</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -187,6 +191,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- NTP Server -->
<button type="button" class="s_collapsible">NTP Server</button> <button type="button" class="s_collapsible">NTP Server</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -218,6 +223,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- Sunrise & Sunset -->
<button type="button" class="s_collapsible">Sunrise & Sunset</button> <button type="button" class="s_collapsible">Sunrise & Sunset</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -241,6 +247,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- MQTT -->
<button type="button" class="s_collapsible">MQTT</button> <button type="button" class="s_collapsible">MQTT</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -284,6 +291,7 @@
</fieldset> </fieldset>
</div> </div>
<!-- Display Config -->
<button type="button" class="s_collapsible">Display Config</button> <button type="button" class="s_collapsible">Display Config</button>
<div class="s_content"> <div class="s_content">
<fieldset class="mb-4"> <fieldset class="mb-4">
@ -307,6 +315,25 @@
</fieldset> </fieldset>
</div> </div>
<!-- Zero Export -->
<button type="button" class="s_collapsible">Zero Export</button>
<div class="s_content">
<fieldset class="mb-4">
<legend class="des">Zero Export</legend>
<div id="zeroType"></div>
<div class="row mb-3">
<div class="col-8 col-sm-3">Enable zero export</div>
<div class="col-4 col-sm-9"><input type="checkbox" name="en_zeroexport"/></div>
</div>
<div class="row mb-3">
<div class="col-12 col-sm-3 my-2">Monitor IP: </div>
<div class="col-12 col-sm-9"><input type="text" name="monitor_ipAddr" maxlength="15"></div>
</div>
</fieldset>
</div>
<div class="row mb-4 mt-4"> <div class="row mb-4 mt-4">
<div class="col-8 col-sm-3">Reboot device after successful save</div> <div class="col-8 col-sm-3">Reboot device after successful save</div>
<div class="col-4 col-sm-9"> <div class="col-4 col-sm-9">
@ -691,7 +718,7 @@
} }
function parseStaticIp(obj) { function parseStaticIp(obj) {
for(var i of [["ipAddr", "ip"], ["ipMask", "mask"], ["ipDns1", "dns1"], ["ipDns2", "dns2"], ["ipGateway", "gateway"]]) for(var i of [["ipAddr", "ip"], ["ipMask", "mask"], ["ipDns1", "dns1"], ["ipDns2", "dns2"], ["ipGateway", "gateway"], ["monitor_ipAddr", "mon_ip"]])
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]];
} }
@ -897,6 +924,14 @@
document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000))); document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000)));
} }
function parsezeroExport(obj) {
// keep display types grouped
var opts = [[0, "None"], [1, "Shelly EM3"]];
document.getElementsByName("monitor_ipAddr")[0].value = obj["monitor_ipAddr"];
}
function parse(root) { function parse(root) {
if(null != root) { if(null != root) {
parseGeneric(root["generic"]); parseGeneric(root["generic"]);
@ -911,6 +946,7 @@
parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]);
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);
} }
} }

9
src/web/web.h

@ -603,6 +603,15 @@ class Web {
mConfig->mqtt.port = request->arg("mqttPort").toInt(); mConfig->mqtt.port = request->arg("mqttPort").toInt();
mConfig->mqtt.interval = request->arg("mqttInterval").toInt(); mConfig->mqtt.interval = request->arg("mqttInterval").toInt();
// zero-export
mConfig->plugin.zexport.enabled = (request->arg("en_zeroexport") == "on");
if (request->arg("monitor_ipAddr") != "") {
String addr = request->arg("monitor_ipAddr");
addr.trim();
addr.toCharArray(mConfig->plugin.zexport.monitor_ip, ZEXPORT_ADDR_LEN);
} else
mConfig->plugin.zexport.monitor_ip[0] = '\0';
// serial console // serial console
if (request->arg("serIntvl") != "") { if (request->arg("serIntvl") != "") {
mConfig->serial.interval = request->arg("serIntvl").toInt() & 0xffff; mConfig->serial.interval = request->arg("serIntvl").toInt() & 0xffff;

Loading…
Cancel
Save