This commit is contained in:
Gunnar Skjold
2026-03-20 11:27:50 +01:00
parent 548012e90b
commit e91ef1a98c
19 changed files with 749 additions and 831 deletions

View File

@@ -1,9 +1,11 @@
#pragma once
#include "AmsDataStorage.h"
#include "AmsConfiguration.h"
class AmsJsonGenerator {
public:
static void generateDayPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize);
static void generateMonthPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize);
static void generateConfigurationJson(AmsConfiguration* config, char* buf, size_t bufSize);
};

View File

@@ -1,4 +1,8 @@
#include "AmsJsonGenerator.h"
#include "hexutils.h"
#include "AmsStorage.h"
#include "LittleFS.h"
#include "FirmwareVersion.h"
void AmsJsonGenerator::generateDayPlotJson(AmsDataStorage* ds, char* buf, size_t bufSize) {
uint16_t pos = snprintf_P(buf, bufSize, PSTR("{\"unit\":\"kwh\""));
@@ -15,3 +19,266 @@ void AmsJsonGenerator::generateMonthPlotJson(AmsDataStorage* ds, char* buf, size
}
snprintf_P(buf+pos, bufSize-pos, PSTR("}"));
}
void AmsJsonGenerator::generateConfigurationJson(AmsConfiguration* config, char* buf, size_t bufSize) {
uint16_t pos = snprintf_P(buf, bufSize, PSTR("{\"version\":\"%s\""), FirmwareVersion::VersionString);
SystemConfig sysConfig;
config->getSystemConfig(sysConfig);
WebConfig webConfig;
config->getWebConfig(webConfig);
MeterConfig meterConfig;
config->getMeterConfig(meterConfig);
NetworkConfig networkConfig;
config->getNetworkConfig(networkConfig);
NtpConfig ntpConfig;
config->getNtpConfig(ntpConfig);
EnergyAccountingConfig eac;
config->getEnergyAccountingConfig(eac);
MqttConfig mqttConfig;
config->getMqttConfig(mqttConfig);
PriceServiceConfig price;
config->getPriceServiceConfig(price);
DebugConfig debugConfig;
config->getDebugConfig(debugConfig);
GpioConfig gpioConfig;
config->getGpioConfig(gpioConfig);
UiConfig ui;
config->getUiConfig(ui);
DomoticzConfig domo;
config->getDomoticzConfig(domo);
HomeAssistantConfig haconf;
config->getHomeAssistantConfig(haconf);
CloudConfig cloud;
config->getCloudConfig(cloud);
ZmartChargeConfig zcc;
config->getZmartChargeConfig(zcc);
// General
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"g\":{\"t\":\"%s\",\"h\":\"%s\",\"s\":%d,\"u\":\"%s\",\"p\":\"%s\",\"c\":\"%s\"}"),
ntpConfig.timezone,
networkConfig.hostname,
webConfig.security,
webConfig.username,
strlen(webConfig.password) > 0 ? "***" : "",
webConfig.context
);
// Meter
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"m\":{\"o\":%d,\"a\":%d,\"b\":%d,\"p\":%d,\"i\":%s,\"s\":%d,\"d\":%d,\"f\":%d,\"r\":%d"),
meterConfig.source,
meterConfig.parser,
meterConfig.baud,
meterConfig.parity,
meterConfig.invert ? "true" : "false",
meterConfig.bufferSize * 64,
meterConfig.distributionSystem,
meterConfig.mainFuse,
meterConfig.productionCapacity
);
bool encen = false;
for(uint8_t i = 0; i < 16; i++) {
if(meterConfig.encryptionKey[i] > 0) {
encen = true;
}
}
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"e\":{\"e\":%s,\"k\":\"%s\",\"a\":\"%s\"}"),
encen ? "true" : "false",
toHex(meterConfig.encryptionKey, 16).c_str(),
toHex(meterConfig.authenticationKey, 16).c_str()
);
bool multEnable = false;
if(meterConfig.wattageMultiplier != 1.0 && meterConfig.wattageMultiplier != 0.0)
multEnable = true;
if(meterConfig.voltageMultiplier != 1.0 && meterConfig.voltageMultiplier != 0.0)
multEnable = true;
if(meterConfig.amperageMultiplier != 1.0 && meterConfig.amperageMultiplier != 0.0)
multEnable = true;
if(meterConfig.accumulatedMultiplier != 1.0 && meterConfig.accumulatedMultiplier != 0.0)
multEnable = true;
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"m\":{\"e\":%s,\"w\":%.3f,\"v\":%.3f,\"a\":%.3f,\"c\":%.3f}"),
multEnable ? "true" : "false",
meterConfig.wattageMultiplier == 0.0 ? 1.0 : meterConfig.wattageMultiplier / 1000.0,
meterConfig.voltageMultiplier == 0.0 ? 1.0 : meterConfig.voltageMultiplier / 1000.0,
meterConfig.amperageMultiplier == 0.0 ? 1.0 : meterConfig.amperageMultiplier / 1000.0,
meterConfig.accumulatedMultiplier == 0.0 ? 1.0 : meterConfig.accumulatedMultiplier / 1000.0
);
pos += snprintf_P(buf+pos, bufSize-pos, PSTR("}")); // End of meter
// Thresholds
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"t\":{\"t\":[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d],\"h\":%d}"),
eac.thresholds[0],
eac.thresholds[1],
eac.thresholds[2],
eac.thresholds[3],
eac.thresholds[4],
eac.thresholds[5],
eac.thresholds[6],
eac.thresholds[7],
eac.thresholds[8],
eac.thresholds[9],
eac.hours
);
// WiFi
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"w\":{\"s\":\"%s\",\"p\":\"%s\",\"w\":%.1f,\"z\":%d,\"b\":%s}"),
networkConfig.ssid,
strlen(networkConfig.psk) > 0 ? "***" : "",
networkConfig.power / 10.0,
networkConfig.sleep,
networkConfig.use11b ? "true" : "false"
);
// Network
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"n\":{\"c\":%d,\"m\":\"%s\",\"i\":\"%s\",\"s\":\"%s\",\"g\":\"%s\",\"d1\":\"%s\",\"d2\":\"%s\",\"d\":%s,\"n1\":\"%s\",\"h\":%s,\"x\":%s}"),
networkConfig.mode,
strlen(networkConfig.ip) > 0 ? "static" : "dhcp",
networkConfig.ip,
networkConfig.subnet,
networkConfig.gateway,
networkConfig.dns1,
networkConfig.dns2,
networkConfig.mdns ? "true" : "false",
ntpConfig.server,
ntpConfig.dhcp ? "true" : "false",
networkConfig.ipv6 ? "true" : "false"
);
// MQTT
bool qsc = false;
bool qsr = false;
bool qsk = false;
if(LittleFS.begin()) {
qsc = LittleFS.exists(FILE_MQTT_CA);
qsr = LittleFS.exists(FILE_MQTT_CERT);
qsk = LittleFS.exists(FILE_MQTT_KEY);
}
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"q\":{\"h\":\"%s\",\"p\":%d,\"u\":\"%s\",\"a\":\"%s\",\"c\":\"%s\",\"b\":\"%s\",\"r\":\"%s\",\"m\":%d,\"s\":{\"e\":%s,\"c\":%s,\"r\":%s,\"k\":%s},\"t\":%d,\"d\":%d,\"i\":%d,\"k\":%d,\"e\":%d}"),
mqttConfig.host,
mqttConfig.port,
mqttConfig.username,
strlen(mqttConfig.password) > 0 ? "***" : "",
mqttConfig.clientId,
mqttConfig.publishTopic,
mqttConfig.subscribeTopic,
mqttConfig.payloadFormat,
mqttConfig.ssl ? "true" : "false",
qsc ? "true" : "false",
qsr ? "true" : "false",
qsk ? "true" : "false",
mqttConfig.stateUpdate,
mqttConfig.stateUpdateInterval,
mqttConfig.timeout,
mqttConfig.keepalive,
mqttConfig.rebootMinutes == 0 ? "null" : String(mqttConfig.rebootMinutes, 10).c_str()
);
// Price
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"p\":{\"e\":%s,\"t\":\"%s\",\"r\":\"%s\",\"c\":\"%s\",\"m\":%d}"),
price.enabled ? "true" : "false",
price.entsoeToken,
price.area,
price.currency,
price.resolutionInMinutes
);
// Debug
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"d\":{\"s\":%s,\"t\":%s,\"l\":%d}"),
debugConfig.serial ? "true" : "false",
debugConfig.telnet ? "true" : "false",
debugConfig.level
);
// GPIO
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"i\":{\"h\":{\"p\":%s,\"u\":%s,\"t\":%s},\"a\":%s,\"l\":{\"p\":%s,\"i\":%s},\"r\":{\"r\":%s,\"g\":%s,\"b\":%s,\"i\":%s},\"d\":{\"d\":%s,\"b\":%d},\"t\":{\"d\":%s,\"a\":%s},\"v\":{\"p\":%s,\"o\":%.2f,\"m\":%.3f,\"d\":{\"v\":%d,\"g\":%d},\"b\":%.1f},\"p\":%d}"),
meterConfig.rxPin == 0xff ? "null" : String(meterConfig.rxPin, 10).c_str(),
meterConfig.rxPinPullup ? "true" : "false",
meterConfig.txPin == 0xff ? "null" : String(meterConfig.txPin, 10).c_str(),
gpioConfig.apPin == 0xff ? "null" : String(gpioConfig.apPin, 10).c_str(),
gpioConfig.ledPin == 0xff ? "null" : String(gpioConfig.ledPin, 10).c_str(),
gpioConfig.ledInverted ? "true" : "false",
gpioConfig.ledPinRed == 0xff ? "null" : String(gpioConfig.ledPinRed, 10).c_str(),
gpioConfig.ledPinGreen == 0xff ? "null" : String(gpioConfig.ledPinGreen, 10).c_str(),
gpioConfig.ledPinBlue == 0xff ? "null" : String(gpioConfig.ledPinBlue, 10).c_str(),
gpioConfig.ledRgbInverted ? "true" : "false",
gpioConfig.ledDisablePin == 0xff ? "null" : String(gpioConfig.ledDisablePin, 10).c_str(),
gpioConfig.ledBehaviour,
gpioConfig.tempSensorPin == 0xff ? "null" : String(gpioConfig.tempSensorPin, 10).c_str(),
gpioConfig.tempAnalogSensorPin == 0xff ? "null" : String(gpioConfig.tempAnalogSensorPin, 10).c_str(),
gpioConfig.vccPin == 0xff ? "null" : String(gpioConfig.vccPin, 10).c_str(),
gpioConfig.vccOffset / 100.0,
gpioConfig.vccMultiplier / 1000.0,
gpioConfig.vccResistorVcc,
gpioConfig.vccResistorGnd,
gpioConfig.vccBootLimit / 10.0,
gpioConfig.powersaving
);
// UI
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"u\":{\"i\":%d,\"e\":%d,\"v\":%d,\"a\":%d,\"r\":%d,\"c\":%d,\"t\":%d,\"p\":%d,\"d\":%d,\"m\":%d,\"s\":%d,\"l\":%d,\"h\":%d,\"f\":%d,\"k\":%d,\"lang\":\"%s\"}"),
ui.showImport,
ui.showExport,
ui.showVoltage,
ui.showAmperage,
ui.showReactive,
ui.showRealtime,
ui.showPeaks,
ui.showPricePlot,
ui.showDayPlot,
ui.showMonthPlot,
ui.showTemperaturePlot,
ui.showRealtimePlot,
ui.showPerPhasePower,
ui.showPowerFactor,
ui.darkMode,
ui.language
);
// Domoticz
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"o\":{\"e\":%d,\"c\":%d,\"u1\":%d,\"u2\":%d,\"u3\":%d}"),
domo.elidx,
domo.cl1idx,
domo.vl1idx,
domo.vl2idx,
domo.vl3idx
);
// Home-Assistant
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"h\":{\"t\":\"%s\",\"h\":\"%s\",\"n\":\"%s\"}"),
haconf.discoveryPrefix,
haconf.discoveryHostname,
haconf.discoveryNameTag
);
// Cloud
pos += snprintf_P(buf+pos, bufSize-pos, PSTR(",\"c\":{\"e\":%s,\"p\":%d,\"es\":%s,\"ze\":%s,\"zt\":\"%s\"}"),
cloud.enabled ? "true" : "false",
cloud.proto,
#if defined(ESP32) && defined(ENERGY_SPEEDOMETER_PASS)
sysConfig.energyspeedometer == 7 ? "true" : "false",
#else
"null",
#endif
zcc.enabled ? "true" : "false",
zcc.token
);
pos += snprintf_P(buf+pos, bufSize-pos, PSTR("}")); // End of config
}

View File

@@ -8,6 +8,7 @@
#define _JSONMQTTHANDLER_H
#include "AmsMqttHandler.h"
#include "ArduinoJson.h"
class JsonMqttHandler : public AmsMqttHandler {
public:
@@ -51,5 +52,6 @@ private:
bool publishList4(AmsData* data, EnergyAccounting* ea);
String getMeterModel(AmsData* data);
void toJsonIsoTimestamp(time_t t, char* buf, size_t buflen);
void handleConfigMessage(JsonObject& configObj);
};
#endif

View File

@@ -9,7 +9,6 @@
#include "hexutils.h"
#include "Uptime.h"
#include "AmsJsonGenerator.h"
#include "ArduinoJson.h"
bool JsonMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAccounting* ea, PriceService* ps) {
if(strlen(mqttConfig.publishTopic) == 0) {
@@ -528,7 +527,7 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) {
debugger->printf_P(PSTR(" - this is our subscribed topic\n"));
if(payload.startsWith("{")) {
DynamicJsonDocument doc(BufferSize);
DynamicJsonDocument doc(512);
DeserializationError error = deserializeJson(doc, payload);
if(error) {
#if defined(AMS_REMOTE_DEBUG)
@@ -538,429 +537,41 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) {
return;
} else {
JsonObject obj = doc.as<JsonObject>();
if(obj.containsKey("action")) {
const char* action = obj["action"];
if(strcmp(action, "fwupgrade") == 0) {
if(obj.containsKey(F("action"))) {
const char* action = obj[F("action")];
if(strcmp_P(action, PSTR("fwupgrade")) == 0) {
if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) {
updater->setTargetVersion(updater->getNextVersion());
}
} else if(strcmp(action, "dayplot") == 0) {
} else if(strcmp_P(action, PSTR("dayplot")) == 0) {
char pubTopic[192];
snprintf_P(pubTopic, 192, PSTR("%s/dayplot"), mqttConfig.publishTopic);
AmsJsonGenerator::generateDayPlotJson(ds, json, BufferSize);
bool ret = mqtt.publish(pubTopic, json);
loop();
} else if(strcmp(action, "monthplot") == 0) {
} else if(strcmp_P(action, PSTR("monthplot")) == 0) {
char pubTopic[192];
snprintf_P(pubTopic, 192, PSTR("%s/monthplot"), mqttConfig.publishTopic);
AmsJsonGenerator::generateMonthPlotJson(ds, json, BufferSize);
bool ret = mqtt.publish(pubTopic, json);
loop();
} else if(strcmp(action, "config") == 0 && obj.containsKey("config")) {
JsonObject configObj = obj["config"];
if(configObj.containsKey("system")) {
SystemConfig newConfig;
config->getSystemConfig(newConfig);
JsonObject systemObj = configObj["system"];
if(systemObj.containsKey("country")) {
strlcpy(newConfig.country, systemObj["country"], sizeof(newConfig.country));
}
if(systemObj.containsKey("firmwareChannel")) {
newConfig.firmwareChannel = systemObj["firmwareChannel"];
}
config->setSystemConfig(newConfig);
}
if(configObj.containsKey("network")) {
NetworkConfig newConfig;
config->getNetworkConfig(newConfig);
JsonObject networkObj = configObj["network"];
if(networkObj.containsKey("mode")) {
newConfig.mode = networkObj["mode"];
}
if(newConfig.mode == 1 || newConfig.mode == 2) {
if(networkObj.containsKey("ssid")) {
strlcpy(newConfig.ssid, networkObj["ssid"], sizeof(newConfig.ssid));
}
if(networkObj.containsKey("psk")) {
strlcpy(newConfig.psk, networkObj["psk"], sizeof(newConfig.psk));
}
if(networkObj.containsKey("power")) {
newConfig.power = networkObj["power"];
}
if(networkObj.containsKey("sleep")) {
newConfig.sleep = networkObj["sleep"];
}
if(networkObj.containsKey("use11b")) {
newConfig.use11b = networkObj["use11b"];
}
}
if(networkObj.containsKey("ip")) {
strlcpy(newConfig.ip, networkObj["ip"], sizeof(newConfig.ip));
}
if(networkObj.containsKey("gateway")) {
strlcpy(newConfig.gateway, networkObj["gateway"], sizeof(newConfig.gateway));
}
if(networkObj.containsKey("subnet")) {
strlcpy(newConfig.subnet, networkObj["subnet"], sizeof(newConfig.subnet));
}
if(networkObj.containsKey("dns1")) {
strlcpy(newConfig.dns1, networkObj["dns1"], sizeof(newConfig.dns1));
}
if(networkObj.containsKey("dns2")) {
strlcpy(newConfig.dns2, networkObj["dns2"], sizeof(newConfig.dns2));
}
if(networkObj.containsKey("hostname")) {
strlcpy(newConfig.hostname, networkObj["hostname"], sizeof(newConfig.hostname));
}
if(networkObj.containsKey("mdns")) {
newConfig.mdns = networkObj["mdns"];
}
if(networkObj.containsKey("ipv6")) {
newConfig.ipv6 = networkObj["ipv6"];
}
config->setNetworkConfig(newConfig);
}
if(configObj.containsKey("web")) {
WebConfig newConfig;
config->getWebConfig(newConfig);
JsonObject webObj = configObj["web"];
if(webObj.containsKey("security")) {
newConfig.security = webObj["security"];
}
if(newConfig.security > 0) {
if(webObj.containsKey("username")) {
strlcpy(newConfig.username, webObj["username"], sizeof(newConfig.username));
}
if(webObj.containsKey("password")) {
strlcpy(newConfig.password, webObj["password"], sizeof(newConfig.password));
}
}
if(webObj.containsKey("context")) {
strlcpy(newConfig.context, webObj["context"], sizeof(newConfig.context));
}
config->setWebConfig(newConfig);
}
if(configObj.containsKey("meter")) {
MeterConfig newConfig;
config->getMeterConfig(newConfig);
JsonObject meterObj = configObj["meter"];
if(meterObj.containsKey("baud")) {
newConfig.baud = meterObj["baud"];
}
if(meterObj.containsKey("parity")) {
newConfig.parity = meterObj["parity"];
}
if(meterObj.containsKey("invert")) {
newConfig.invert = meterObj["invert"];
}
if(meterObj.containsKey("distributionSystem")) {
newConfig.distributionSystem = meterObj["distributionSystem"];
}
if(meterObj.containsKey("mainFuse")) {
newConfig.mainFuse = meterObj["mainFuse"];
}
if(meterObj.containsKey("productionCapacity")) {
newConfig.productionCapacity = meterObj["productionCapacity"];
}
if(meterObj.containsKey("wattageMultiplier")) {
newConfig.wattageMultiplier = meterObj["wattageMultiplier"];
}
if(meterObj.containsKey("voltageMultiplier")) {
newConfig.voltageMultiplier = meterObj["voltageMultiplier"];
}
if(meterObj.containsKey("amperageMultiplier")) {
newConfig.amperageMultiplier = meterObj["amperageMultiplier"];
}
if(meterObj.containsKey("accumulatedMultiplier")) {
newConfig.accumulatedMultiplier = meterObj["accumulatedMultiplier"];
}
if(meterObj.containsKey("parser")) {
newConfig.parser = meterObj["parser"];
}
if(meterObj.containsKey("bufferSize")) {
newConfig.bufferSize = meterObj["bufferSize"];
}
if(meterObj.containsKey("rxPin")) {
newConfig.rxPin = meterObj["rxPin"];
}
if(meterObj.containsKey("rxPinPullup")) {
newConfig.rxPinPullup = meterObj["rxPinPullup"];
}
if(meterObj.containsKey("txPin")) {
newConfig.txPin = meterObj["txPin"];
}
}
if(configObj.containsKey("mqtt")) {
MqttConfig newConfig;
config->getMqttConfig(newConfig);
JsonObject mqttObj = configObj["mqtt"];
if(mqttObj.containsKey("host")) {
strlcpy(newConfig.host, mqttObj["host"], sizeof(newConfig.host));
}
if(mqttObj.containsKey("port")) {
newConfig.port = mqttObj["port"];
}
if(mqttObj.containsKey("clientId")) {
strlcpy(newConfig.clientId, mqttObj["clientId"], sizeof(newConfig.clientId));
}
if(mqttObj.containsKey("publishTopic")) {
strlcpy(newConfig.publishTopic, mqttObj["publishTopic"], sizeof(newConfig.publishTopic));
}
if(mqttObj.containsKey("subscribeTopic")) {
strlcpy(newConfig.subscribeTopic, mqttObj["subscribeTopic"], sizeof(newConfig.subscribeTopic));
}
if(mqttObj.containsKey("username")) {
strlcpy(newConfig.username, mqttObj["username"], sizeof(newConfig.username));
}
if(mqttObj.containsKey("password")) {
strlcpy(newConfig.password, mqttObj["password"], sizeof(newConfig.password));
}
if(mqttObj.containsKey("payloadFormat")) {
newConfig.payloadFormat = mqttObj["payloadFormat"];
}
if(mqttObj.containsKey("ssl")) {
newConfig.ssl = mqttObj["ssl"];
}
if(mqttObj.containsKey("stateUpdate")) {
newConfig.stateUpdate = mqttObj["stateUpdate"];
}
if(mqttObj.containsKey("stateUpdateInterval")) {
newConfig.stateUpdateInterval = mqttObj["stateUpdateInterval"];
}
if(mqttObj.containsKey("timeout")) {
newConfig.timeout = mqttObj["timeout"];
}
if(mqttObj.containsKey("keepalive")) {
newConfig.keepalive = mqttObj["keepalive"];
}
if(mqttObj.containsKey("rebootMinutes")) {
newConfig.rebootMinutes = mqttObj["rebootMinutes"];
}
config->setMqttConfig(newConfig);
if(mqttObj.containsKey("domoticz")) {
DomoticzConfig newConfig;
config->getDomoticzConfig(newConfig);
JsonObject domoticzObj = mqttObj["domoticz"];
if(domoticzObj.containsKey("elidx")) {
newConfig.elidx = domoticzObj["elidx"];
}
if(domoticzObj.containsKey("vl1idx")) {
newConfig.vl1idx = domoticzObj["vl1idx"];
}
if(domoticzObj.containsKey("vl2idx")) {
newConfig.vl2idx = domoticzObj["vl2idx"];
}
if(domoticzObj.containsKey("vl3idx")) {
newConfig.vl3idx = domoticzObj["vl3idx"];
}
if(domoticzObj.containsKey("cl1idx")) {
newConfig.cl1idx = domoticzObj["cl1idx"];
}
config->setDomoticzConfig(newConfig);
}
if(mqttObj.containsKey("homeAssistant")) {
HomeAssistantConfig newConfig;
config->getHomeAssistantConfig(newConfig);
JsonObject haObj = mqttObj["homeAssistant"];
if(haObj.containsKey("discoveryPrefix")) {
strlcpy(newConfig.discoveryPrefix, haObj["discoveryPrefix"], sizeof(newConfig.discoveryPrefix));
}
if(haObj.containsKey("discoveryHostname")) {
strlcpy(newConfig.discoveryHostname, haObj["discoveryHostname"], sizeof(newConfig.discoveryHostname));
}
if(haObj.containsKey("discoveryNameTag")) {
strlcpy(newConfig.discoveryNameTag, haObj["discoveryNameTag"], sizeof(newConfig.discoveryNameTag));
}
config->setHomeAssistantConfig(newConfig);
}
}
if(configObj.containsKey("debug")) {
DebugConfig newConfig;
config->getDebugConfig(newConfig);
JsonObject debugObj = configObj["debug"];
if(debugObj.containsKey("telnet")) {
newConfig.telnet = debugObj["telnet"];
}
if(debugObj.containsKey("serial")) {
newConfig.serial = debugObj["serial"];
}
if(debugObj.containsKey("level")) {
newConfig.level = debugObj["level"];
}
config->setDebugConfig(newConfig);
}
if(configObj.containsKey("gpio")) {
GpioConfig newConfig;
config->getGpioConfig(newConfig);
JsonObject gpioObj = configObj["gpio"];
if(gpioObj.containsKey("apPin")) {
newConfig.apPin = gpioObj["apPin"];
}
if(gpioObj.containsKey("ledPin")) {
newConfig.ledPin = gpioObj["ledPin"];
}
if(gpioObj.containsKey("ledInverted")) {
newConfig.ledInverted = gpioObj["ledInverted"];
}
if(gpioObj.containsKey("ledPinRed")) {
newConfig.ledPinRed = gpioObj["ledPinRed"];
}
if(gpioObj.containsKey("ledPinGreen")) {
newConfig.ledPinGreen = gpioObj["ledPinGreen"];
}
if(gpioObj.containsKey("ledPinBlue")) {
newConfig.ledPinBlue = gpioObj["ledPinBlue"];
}
if(gpioObj.containsKey("ledRgbInverted")) {
newConfig.ledRgbInverted = gpioObj["ledRgbInverted"];
}
if(gpioObj.containsKey("tempSensorPin")) {
newConfig.tempSensorPin = gpioObj["tempSensorPin"];
}
if(gpioObj.containsKey("tempAnalogSensorPin")) {
newConfig.tempAnalogSensorPin = gpioObj["tempAnalogSensorPin"];
}
if(gpioObj.containsKey("vccPin")) {
newConfig.vccPin = gpioObj["vccPin"];
}
if(gpioObj.containsKey("vccOffset")) {
newConfig.vccOffset = gpioObj["vccOffset"];
}
if(gpioObj.containsKey("vccMultiplier")) {
newConfig.vccMultiplier = gpioObj["vccMultiplier"];
}
if(gpioObj.containsKey("vccBootLimit")) {
newConfig.vccBootLimit = gpioObj["vccBootLimit"];
}
if(gpioObj.containsKey("vccResistorGnd")) {
newConfig.vccResistorGnd = gpioObj["vccResistorGnd"];
}
if(gpioObj.containsKey("vccResistorVcc")) {
newConfig.vccResistorVcc = gpioObj["vccResistorVcc"];
}
if(gpioObj.containsKey("ledDisablePin")) {
newConfig.ledDisablePin = gpioObj["ledDisablePin"];
}
if(gpioObj.containsKey("ledBehaviour")) {
newConfig.ledBehaviour = gpioObj["ledBehaviour"];
}
config->setGpioConfig(newConfig);
}
if(configObj.containsKey("ntp")) {
NtpConfig newConfig;
config->getNtpConfig(newConfig);
JsonObject ntpObj = configObj["ntp"];
if(ntpObj.containsKey("enable")) {
newConfig.enable = ntpObj["enable"];
}
if(ntpObj.containsKey("dhcp")) {
newConfig.dhcp = ntpObj["dhcp"];
}
if(ntpObj.containsKey("server")) {
strlcpy(newConfig.server, ntpObj["server"], sizeof(newConfig.server));
}
if(ntpObj.containsKey("timezone")) {
strlcpy(newConfig.timezone, ntpObj["timezone"], sizeof(newConfig.timezone));
}
config->setNtpConfig(newConfig);
}
if(configObj.containsKey("priceService")) {
PriceServiceConfig newConfig;
config->getPriceServiceConfig(newConfig);
JsonObject priceServiceObj = configObj["priceService"];
if(priceServiceObj.containsKey("area")) {
strlcpy(newConfig.area, priceServiceObj["area"], sizeof(newConfig.area));
}
if(priceServiceObj.containsKey("currency")) {
strlcpy(newConfig.currency, priceServiceObj["currency"], sizeof(newConfig.currency));
}
if(priceServiceObj.containsKey("resolutionInMinutes")) {
newConfig.resolutionInMinutes = priceServiceObj["resolutionInMinutes"];
}
if(priceServiceObj.containsKey("enabled")) {
newConfig.enabled = priceServiceObj["enabled"];
}
config->setPriceServiceConfig(newConfig);
}
if(configObj.containsKey("cloud")) {
JsonObject cloudObj = configObj["cloud"];
if(cloudObj.containsKey("amsleser")) {
CloudConfig newConfig;
config->getCloudConfig(newConfig);
JsonObject amsCloudObj = cloudObj["amsleser"];
if(amsCloudObj.containsKey("enabled")) {
newConfig.enabled = amsCloudObj["enabled"];
}
if(amsCloudObj.containsKey("interval")) {
newConfig.interval = amsCloudObj["interval"];
}
if(amsCloudObj.containsKey("hostname")) {
strlcpy(newConfig.hostname, amsCloudObj["hostname"], sizeof(newConfig.hostname));
}
if(amsCloudObj.containsKey("port")) {
newConfig.port = amsCloudObj["port"];
}
if(amsCloudObj.containsKey("clientId")) {
strlcpy((char*)newConfig.clientId, amsCloudObj["clientId"], sizeof(newConfig.clientId));
}
if(amsCloudObj.containsKey("proto")) {
newConfig.proto = amsCloudObj["proto"];
}
config->setCloudConfig(newConfig);
}
if(cloudObj.containsKey("zmartCharge")) {
ZmartChargeConfig newConfig;
config->getZmartChargeConfig(newConfig);
JsonObject zmartChargeObj = cloudObj["zmartCharge"];
if(zmartChargeObj.containsKey("enabled")) {
newConfig.enabled = zmartChargeObj["enabled"];
}
if(zmartChargeObj.containsKey("token")) {
strlcpy(newConfig.token, zmartChargeObj["token"], sizeof(newConfig.token));
}
if(zmartChargeObj.containsKey("baseUrl")) {
strlcpy(newConfig.baseUrl, zmartChargeObj["baseUrl"], sizeof(newConfig.baseUrl));
}
config->setZmartChargeConfig(newConfig);
}
}
} else if(strcmp_P(action, PSTR("config")) == 0 && obj.containsKey(F("config"))) {
JsonObject configObj = obj[F("config")];
handleConfigMessage(configObj);
}
}
}
} else if(payload.equals("fwupgrade")) {
} else if(payload.equals(F("fwupgrade"))) {
if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) {
updater->setTargetVersion(updater->getNextVersion());
}
} else if(payload.equals("dayplot")) {
} else if(payload.equals(F("dayplot"))) {
char pubTopic[192];
snprintf_P(pubTopic, 192, PSTR("%s/dayplot"), mqttConfig.publishTopic);
AmsJsonGenerator::generateDayPlotJson(ds, json, BufferSize);
bool ret = mqtt.publish(pubTopic, json);
loop();
} else if(payload.equals("monthplot")) {
} else if(payload.equals(F("monthplot"))) {
char pubTopic[192];
snprintf_P(pubTopic, 192, PSTR("%s/monthplot"), mqttConfig.publishTopic);
AmsJsonGenerator::generateMonthPlotJson(ds, json, BufferSize);
@@ -970,6 +581,469 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) {
}
}
void JsonMqttHandler::handleConfigMessage(JsonObject& configObj) {
// General
if(configObj.containsKey(F("g"))) {
JsonObject generalObj = configObj[F("g")];
if(generalObj.containsKey(F("t"))) {
NtpConfig ntpConfig;
config->getNtpConfig(ntpConfig);
strlcpy(ntpConfig.timezone, generalObj[F("t")], sizeof(ntpConfig.timezone));
config->setNtpConfig(ntpConfig);
}
if(generalObj.containsKey(F("h"))) {
NetworkConfig networkConfig;
config->getNetworkConfig(networkConfig);
strlcpy(networkConfig.hostname, generalObj[F("h")], sizeof(networkConfig.hostname));
config->setNetworkConfig(networkConfig);
}
WebConfig webConfig;
config->getWebConfig(webConfig);
if(generalObj.containsKey(F("s"))) {
webConfig.security = generalObj[F("s")];
}
if(webConfig.security > 0) {
if(generalObj.containsKey(F("u"))) {
strlcpy(webConfig.username, generalObj[F("u")], sizeof(webConfig.username));
}
if(generalObj.containsKey(F("p"))) {
strlcpy(webConfig.password, generalObj[F("p")], sizeof(webConfig.password));
}
}
if(generalObj.containsKey(F("c"))) {
strlcpy(webConfig.context, generalObj[F("c")], sizeof(webConfig.context));
}
config->setWebConfig(webConfig);
}
// Meter
if(configObj.containsKey(F("m"))) {
JsonObject meterObj = configObj[F("m")];
MeterConfig newConfig;
config->getMeterConfig(newConfig);
if(meterObj.containsKey(F("o"))) {
newConfig.source = meterObj[F("o")];
}
if(meterObj.containsKey(F("a"))) {
newConfig.parser = meterObj[F("a")];
}
if(meterObj.containsKey(F("b"))) {
newConfig.baud = meterObj[F("b")];
}
if(meterObj.containsKey(F("p"))) {
// TODO, string to enum
newConfig.parity = meterObj[F("p")];
}
if(meterObj.containsKey(F("i"))) {
newConfig.invert = meterObj[F("i")];
}
if(meterObj.containsKey(F("s"))) {
newConfig.bufferSize = meterObj[F("s")] / 64; // convert from bytes to 64 byte blocks
}
if(meterObj.containsKey(F("d"))) {
newConfig.distributionSystem = meterObj[F("d")];
}
if(meterObj.containsKey(F("f"))) {
newConfig.mainFuse = meterObj[F("f")];
}
if(meterObj.containsKey(F("r"))) {
newConfig.productionCapacity = meterObj[F("r")];
}
if(meterObj.containsKey(F("e"))) {
JsonObject encryptionObj = meterObj[F("e")];
if(encryptionObj.containsKey(F("e"))) {
bool enabled = encryptionObj[F("e")];
if(enabled) {
if(encryptionObj.containsKey(F("k"))) {
// TODO
}
if(encryptionObj.containsKey(F("a"))) {
// TODO
}
} else {
memset(newConfig.encryptionKey, 0, sizeof(newConfig.encryptionKey));
memset(newConfig.authenticationKey, 0, sizeof(newConfig.authenticationKey));
}
}
}
config->setMeterConfig(newConfig);
}
if(configObj.containsKey(F("system"))) {
SystemConfig newConfig;
config->getSystemConfig(newConfig);
JsonObject systemObj = configObj[F("system")];
if(systemObj.containsKey(F("country"))) {
strlcpy(newConfig.country, systemObj[F("country")], sizeof(newConfig.country));
}
if(systemObj.containsKey(F("firmwareChannel"))) {
newConfig.firmwareChannel = systemObj[F("firmwareChannel")];
}
config->setSystemConfig(newConfig);
}
if(configObj.containsKey(F("network"))) {
NetworkConfig newConfig;
config->getNetworkConfig(newConfig);
JsonObject networkObj = configObj[F("network")];
if(networkObj.containsKey(F("mode"))) {
newConfig.mode = networkObj[F("mode")];
}
if(newConfig.mode == 1 || newConfig.mode == 2) {
if(networkObj.containsKey(F("ssid"))) {
strlcpy(newConfig.ssid, networkObj[F("ssid")], sizeof(newConfig.ssid));
}
if(networkObj.containsKey(F("psk"))) {
strlcpy(newConfig.psk, networkObj[F("psk")], sizeof(newConfig.psk));
}
if(networkObj.containsKey(F("power"))) {
newConfig.power = networkObj[F("power")];
}
if(networkObj.containsKey(F("sleep"))) {
newConfig.sleep = networkObj[F("sleep")];
}
if(networkObj.containsKey(F("use11b"))) {
newConfig.use11b = networkObj[F("use11b")];
}
}
if(networkObj.containsKey(F("ip"))) {
strlcpy(newConfig.ip, networkObj[F("ip")], sizeof(newConfig.ip));
}
if(networkObj.containsKey(F("gateway"))) {
strlcpy(newConfig.gateway, networkObj[F("gateway")], sizeof(newConfig.gateway));
}
if(networkObj.containsKey(F("subnet"))) {
strlcpy(newConfig.subnet, networkObj[F("subnet")], sizeof(newConfig.subnet));
}
if(networkObj.containsKey(F("dns1"))) {
strlcpy(newConfig.dns1, networkObj[F("dns1")], sizeof(newConfig.dns1));
}
if(networkObj.containsKey(F("dns2"))) {
strlcpy(newConfig.dns2, networkObj[F("dns2")], sizeof(newConfig.dns2));
}
if(networkObj.containsKey(F("mdns"))) {
newConfig.mdns = networkObj[F("mdns")];
}
if(networkObj.containsKey(F("ipv6"))) {
newConfig.ipv6 = networkObj[F("ipv6")];
}
config->setNetworkConfig(newConfig);
}
if(configObj.containsKey(F("meter"))) {
MeterConfig newConfig;
config->getMeterConfig(newConfig);
JsonObject meterObj = configObj[F("meter")];
if(meterObj.containsKey(F("baud"))) {
newConfig.baud = meterObj[F("baud")];
}
if(meterObj.containsKey(F("parity"))) {
newConfig.parity = meterObj[F("parity")];
}
if(meterObj.containsKey(F("invert"))) {
newConfig.invert = meterObj[F("invert")];
}
if(meterObj.containsKey(F("distributionSystem"))) {
newConfig.distributionSystem = meterObj[F("distributionSystem")];
}
if(meterObj.containsKey(F("mainFuse"))) {
newConfig.mainFuse = meterObj[F("mainFuse")];
}
if(meterObj.containsKey(F("productionCapacity"))) {
newConfig.productionCapacity = meterObj[F("productionCapacity")];
}
if(meterObj.containsKey(F("wattageMultiplier"))) {
newConfig.wattageMultiplier = meterObj[F("wattageMultiplier")];
}
if(meterObj.containsKey(F("voltageMultiplier"))) {
newConfig.voltageMultiplier = meterObj[F("voltageMultiplier")];
}
if(meterObj.containsKey(F("amperageMultiplier"))) {
newConfig.amperageMultiplier = meterObj[F("amperageMultiplier")];
}
if(meterObj.containsKey(F("accumulatedMultiplier"))) {
newConfig.accumulatedMultiplier = meterObj[F("accumulatedMultiplier")];
}
if(meterObj.containsKey(F("parser"))) {
newConfig.parser = meterObj[F("parser")];
}
if(meterObj.containsKey(F("bufferSize"))) {
newConfig.bufferSize = meterObj[F("bufferSize")];
}
if(meterObj.containsKey(F("rxPin"))) {
newConfig.rxPin = meterObj[F("rxPin")];
}
if(meterObj.containsKey(F("rxPinPullup"))) {
newConfig.rxPinPullup = meterObj[F("rxPinPullup")];
}
if(meterObj.containsKey(F("txPin"))) {
newConfig.txPin = meterObj[F("txPin")];
}
}
if(configObj.containsKey(F("mqtt"))) {
MqttConfig newConfig;
config->getMqttConfig(newConfig);
JsonObject mqttObj = configObj[F("mqtt")];
if(mqttObj.containsKey(F("host"))) {
strlcpy(newConfig.host, mqttObj[F("host")], sizeof(newConfig.host));
}
if(mqttObj.containsKey(F("port"))) {
newConfig.port = mqttObj[F("port")];
}
if(mqttObj.containsKey(F("clientId"))) {
strlcpy(newConfig.clientId, mqttObj[F("clientId")], sizeof(newConfig.clientId));
}
if(mqttObj.containsKey(F("publishTopic"))) {
strlcpy(newConfig.publishTopic, mqttObj[F("publishTopic")], sizeof(newConfig.publishTopic));
}
if(mqttObj.containsKey(F("subscribeTopic"))) {
strlcpy(newConfig.subscribeTopic, mqttObj[F("subscribeTopic")], sizeof(newConfig.subscribeTopic));
}
if(mqttObj.containsKey(F("username"))) {
strlcpy(newConfig.username, mqttObj[F("username")], sizeof(newConfig.username));
}
if(mqttObj.containsKey(F("password"))) {
strlcpy(newConfig.password, mqttObj[F("password")], sizeof(newConfig.password));
}
if(mqttObj.containsKey(F("payloadFormat"))) {
newConfig.payloadFormat = mqttObj[F("payloadFormat")];
}
if(mqttObj.containsKey(F("ssl"))) {
newConfig.ssl = mqttObj[F("ssl")];
}
if(mqttObj.containsKey(F("stateUpdate"))) {
newConfig.stateUpdate = mqttObj[F("stateUpdate")];
}
if(mqttObj.containsKey(F("stateUpdateInterval"))) {
newConfig.stateUpdateInterval = mqttObj[F("stateUpdateInterval")];
}
if(mqttObj.containsKey(F("timeout"))) {
newConfig.timeout = mqttObj[F("timeout")];
}
if(mqttObj.containsKey(F("keepalive"))) {
newConfig.keepalive = mqttObj[F("keepalive")];
}
if(mqttObj.containsKey(F("rebootMinutes"))) {
newConfig.rebootMinutes = mqttObj[F("rebootMinutes")];
}
config->setMqttConfig(newConfig);
if(mqttObj.containsKey(F("domoticz"))) {
DomoticzConfig newConfig;
config->getDomoticzConfig(newConfig);
JsonObject domoticzObj = mqttObj[F("domoticz")];
if(domoticzObj.containsKey(F("elidx"))) {
newConfig.elidx = domoticzObj[F("elidx")];
}
if(domoticzObj.containsKey(F("vl1idx"))) {
newConfig.vl1idx = domoticzObj[F("vl1idx")];
}
if(domoticzObj.containsKey(F("vl2idx"))) {
newConfig.vl2idx = domoticzObj[F("vl2idx")];
}
if(domoticzObj.containsKey(F("vl3idx"))) {
newConfig.vl3idx = domoticzObj[F("vl3idx")];
}
if(domoticzObj.containsKey(F("cl1idx"))) {
newConfig.cl1idx = domoticzObj[F("cl1idx")];
}
config->setDomoticzConfig(newConfig);
}
if(mqttObj.containsKey(F("homeAssistant"))) {
HomeAssistantConfig newConfig;
config->getHomeAssistantConfig(newConfig);
JsonObject haObj = mqttObj[F("homeAssistant")];
if(haObj.containsKey(F("discoveryPrefix"))) {
strlcpy(newConfig.discoveryPrefix, haObj[F("discoveryPrefix")], sizeof(newConfig.discoveryPrefix));
}
if(haObj.containsKey(F("discoveryHostname"))) {
strlcpy(newConfig.discoveryHostname, haObj[F("discoveryHostname")], sizeof(newConfig.discoveryHostname));
}
if(haObj.containsKey(F("discoveryNameTag"))) {
strlcpy(newConfig.discoveryNameTag, haObj[F("discoveryNameTag")], sizeof(newConfig.discoveryNameTag));
}
config->setHomeAssistantConfig(newConfig);
}
}
if(configObj.containsKey(F("debug"))) {
DebugConfig newConfig;
config->getDebugConfig(newConfig);
JsonObject debugObj = configObj[F("debug")];
if(debugObj.containsKey(F("telnet"))) {
newConfig.telnet = debugObj[F("telnet")];
}
if(debugObj.containsKey(F("serial"))) {
newConfig.serial = debugObj[F("serial")];
}
if(debugObj.containsKey(F("level"))) {
newConfig.level = debugObj[F("level")];
}
config->setDebugConfig(newConfig);
}
if(configObj.containsKey(F("gpio"))) {
GpioConfig newConfig;
config->getGpioConfig(newConfig);
JsonObject gpioObj = configObj[F("gpio")];
if(gpioObj.containsKey(F("apPin"))) {
newConfig.apPin = gpioObj[F("apPin")];
}
if(gpioObj.containsKey(F("ledPin"))) {
newConfig.ledPin = gpioObj[F("ledPin")];
}
if(gpioObj.containsKey(F("ledInverted"))) {
newConfig.ledInverted = gpioObj[F("ledInverted")];
}
if(gpioObj.containsKey(F("ledPinRed"))) {
newConfig.ledPinRed = gpioObj[F("ledPinRed")];
}
if(gpioObj.containsKey(F("ledPinGreen"))) {
newConfig.ledPinGreen = gpioObj[F("ledPinGreen")];
}
if(gpioObj.containsKey(F("ledPinBlue"))) {
newConfig.ledPinBlue = gpioObj[F("ledPinBlue")];
}
if(gpioObj.containsKey(F("ledRgbInverted"))) {
newConfig.ledRgbInverted = gpioObj[F("ledRgbInverted")];
}
if(gpioObj.containsKey(F("tempSensorPin"))) {
newConfig.tempSensorPin = gpioObj[F("tempSensorPin")];
}
if(gpioObj.containsKey(F("tempAnalogSensorPin"))) {
newConfig.tempAnalogSensorPin = gpioObj[F("tempAnalogSensorPin")];
}
if(gpioObj.containsKey(F("vccPin"))) {
newConfig.vccPin = gpioObj[F("vccPin")];
}
if(gpioObj.containsKey(F("vccOffset"))) {
newConfig.vccOffset = gpioObj[F("vccOffset")];
}
if(gpioObj.containsKey(F("vccMultiplier"))) {
newConfig.vccMultiplier = gpioObj[F("vccMultiplier")];
}
if(gpioObj.containsKey(F("vccBootLimit"))) {
newConfig.vccBootLimit = gpioObj[F("vccBootLimit")];
}
if(gpioObj.containsKey(F("vccResistorGnd"))) {
newConfig.vccResistorGnd = gpioObj[F("vccResistorGnd")];
}
if(gpioObj.containsKey(F("vccResistorVcc"))) {
newConfig.vccResistorVcc = gpioObj[F("vccResistorVcc")];
}
if(gpioObj.containsKey(F("ledDisablePin"))) {
newConfig.ledDisablePin = gpioObj[F("ledDisablePin")];
}
if(gpioObj.containsKey(F("ledBehaviour"))) {
newConfig.ledBehaviour = gpioObj[F("ledBehaviour")];
}
config->setGpioConfig(newConfig);
}
if(configObj.containsKey(F("ntp"))) {
NtpConfig newConfig;
config->getNtpConfig(newConfig);
JsonObject ntpObj = configObj[F("ntp")];
if(ntpObj.containsKey(F("enable"))) {
newConfig.enable = ntpObj[F("enable")];
}
if(ntpObj.containsKey(F("dhcp"))) {
newConfig.dhcp = ntpObj[F("dhcp")];
}
if(ntpObj.containsKey(F("server"))) {
strlcpy(newConfig.server, ntpObj[F("server")], sizeof(newConfig.server));
}
config->setNtpConfig(newConfig);
}
if(configObj.containsKey(F("priceService"))) {
PriceServiceConfig newConfig;
config->getPriceServiceConfig(newConfig);
JsonObject priceServiceObj = configObj[F("priceService")];
if(priceServiceObj.containsKey(F("area"))) {
strlcpy(newConfig.area, priceServiceObj[F("area")], sizeof(newConfig.area));
}
if(priceServiceObj.containsKey(F("currency"))) {
strlcpy(newConfig.currency, priceServiceObj[F("currency")], sizeof(newConfig.currency));
}
if(priceServiceObj.containsKey(F("resolutionInMinutes"))) {
newConfig.resolutionInMinutes = priceServiceObj[F("resolutionInMinutes")];
}
if(priceServiceObj.containsKey(F("enabled"))) {
newConfig.enabled = priceServiceObj[F("enabled")];
}
config->setPriceServiceConfig(newConfig);
}
if(configObj.containsKey(F("cloud"))) {
JsonObject cloudObj = configObj[F("cloud")];
if(cloudObj.containsKey(F("amsleser"))) {
CloudConfig newConfig;
config->getCloudConfig(newConfig);
JsonObject amsCloudObj = cloudObj[F("amsleser")];
if(amsCloudObj.containsKey(F("enabled"))) {
newConfig.enabled = amsCloudObj[F("enabled")];
}
if(amsCloudObj.containsKey(F("interval"))) {
newConfig.interval = amsCloudObj[F("interval")];
}
if(amsCloudObj.containsKey(F("hostname"))) {
strlcpy(newConfig.hostname, amsCloudObj[F("hostname")], sizeof(newConfig.hostname));
}
if(amsCloudObj.containsKey(F("port"))) {
newConfig.port = amsCloudObj[F("port")];
}
if(amsCloudObj.containsKey(F("clientId"))) {
strlcpy((char*)newConfig.clientId, amsCloudObj[F("clientId")], sizeof(newConfig.clientId));
}
if(amsCloudObj.containsKey(F("proto"))) {
newConfig.proto = amsCloudObj[F("proto")];
}
config->setCloudConfig(newConfig);
}
if(cloudObj.containsKey(F("zmartcharge"))) {
ZmartChargeConfig newConfig;
config->getZmartChargeConfig(newConfig);
JsonObject zmartChargeObj = cloudObj[F("zmartcharge")];
if(zmartChargeObj.containsKey(F("enabled"))) {
newConfig.enabled = zmartChargeObj[F("enabled")];
}
if(zmartChargeObj.containsKey(F("token"))) {
strlcpy(newConfig.token, zmartChargeObj[F("token")], sizeof(newConfig.token));
}
if(zmartChargeObj.containsKey(F("baseUrl"))) {
strlcpy(newConfig.baseUrl, zmartChargeObj[F("baseUrl")], sizeof(newConfig.baseUrl));
}
config->setZmartChargeConfig(newConfig);
}
if(cloudObj.containsKey(F("energyspeedometer"))) {
SystemConfig newConfig;
config->getSystemConfig(newConfig);
JsonObject speedometerObj = cloudObj[F("energyspeedometer")];
if(speedometerObj.containsKey(F("enabled"))) {
newConfig.energyspeedometer = speedometerObj[F("enabled")];
}
config->setSystemConfig(newConfig);
}
}
}
void JsonMqttHandler::toJsonIsoTimestamp(time_t t, char* buf, size_t buflen) {
memset(buf, 0, buflen);
if(t > 0) {

View File

@@ -1,7 +0,0 @@
"c": {
"e" : %s,
"p" : %d,
"es": %s,
"ze": %s,
"zt" : "%s"
}

View File

@@ -1,5 +0,0 @@
"d": {
"s": %s,
"t": %s,
"l": %d
},

View File

@@ -1,7 +0,0 @@
"o": {
"e" : %d,
"c" : %d,
"u1" : %d,
"u2" : %d,
"u3" : %d
},

View File

@@ -1,8 +0,0 @@
"g": {
"t": "%s",
"h": "%s",
"s": %d,
"u": "%s",
"p": "%s",
"c": "%s"
},

View File

@@ -1,37 +0,0 @@
"i": {
"h": {
"p": %s,
"u": %s,
"t": %s
},
"a": %s,
"l": {
"p": %s,
"i": %s
},
"r": {
"r": %s,
"g": %s,
"b": %s,
"i": %s
},
"d": {
"d": %s,
"b": %d
},
"t": {
"d": %s,
"a": %s
},
"v": {
"p": %s,
"o": %.2f,
"m": %.3f,
"d": {
"v": %d,
"g": %d
},
"b": %.1f
},
"p": %d
},

View File

@@ -1,5 +0,0 @@
"h": {
"t" : "%s",
"h" : "%s",
"n" : "%s"
},

View File

@@ -1,23 +0,0 @@
"m": {
"o": %d,
"a": %d,
"b": %d,
"p": %d,
"i": %s,
"s": %d,
"d": %d,
"f": %d,
"r": %d,
"e": {
"e": %s,
"k": "%s",
"a": "%s"
},
"m": {
"e": %s,
"w": %.3f,
"v": %.3f,
"a": %.3f,
"c": %.3f
}
},

View File

@@ -1,21 +0,0 @@
"q": {
"h": "%s",
"p": %d,
"u": "%s",
"a": "%s",
"c": "%s",
"b": "%s",
"r": "%s",
"m": %d,
"s": {
"e": %s,
"c": %s,
"r": %s,
"k": %s
},
"t": %d,
"d": %d,
"i": %d,
"k": %d,
"e": %s
},

View File

@@ -1,13 +0,0 @@
"n": {
"c": %d,
"m": "%s",
"i": "%s",
"s": "%s",
"g": "%s",
"d1": "%s",
"d2": "%s",
"d": %s,
"n1": "%s",
"h": %s,
"x": %s
},

View File

@@ -1,7 +0,0 @@
"p": {
"e": %s,
"t": "%s",
"r": "%s",
"c": "%s",
"m": %d
},

View File

@@ -1,10 +0,0 @@
{
"t" : %d,
"n" : "%s",
"d" : %d,
"a" : [%s],
"h" : [%s],
"v" : %.4f,
"s" : { "m":%d,"d":%d},
"e" : { "m":%d,"d":%d}
}%s

View File

@@ -1,15 +0,0 @@
"t": {
"t": [
%d,
%d,
%d,
%d,
%d,
%d,
%d,
%d,
%d,
%d
],
"h": %d
},

View File

@@ -1,18 +0,0 @@
"u": {
"i": %d,
"e": %d,
"v": %d,
"a": %d,
"r": %d,
"c": %d,
"t": %d,
"p": %d,
"d": %d,
"m": %d,
"s": %d,
"l": %d,
"h": %d,
"f": %d,
"k": %d,
"lang" : "%s"
},

View File

@@ -1,7 +0,0 @@
"w": {
"s": "%s",
"p": "%s",
"w": %.1f,
"z": %d,
"b": %s
},

View File

@@ -19,20 +19,6 @@
#include "html/response_json.h"
#include "html/sysinfo_json.h"
#include "html/tariff_json.h"
#include "html/conf_general_json.h"
#include "html/conf_meter_json.h"
#include "html/conf_wifi_json.h"
#include "html/conf_net_json.h"
#include "html/conf_mqtt_json.h"
#include "html/conf_price_json.h"
#include "html/conf_price_row_json.h"
#include "html/conf_thresholds_json.h"
#include "html/conf_debug_json.h"
#include "html/conf_gpio_json.h"
#include "html/conf_domoticz_json.h"
#include "html/conf_ha_json.h"
#include "html/conf_ui_json.h"
#include "html/conf_cloud_json.h"
#include "html/firmware_html.h"
#if defined(ESP32)
@@ -892,244 +878,14 @@ void AmsWebServer::configurationJson() {
if(!checkSecurity(1))
return;
MeterConfig meterConfig;
config->getMeterConfig(meterConfig);
bool multEnable = false;
if(meterConfig.wattageMultiplier != 1.0 && meterConfig.wattageMultiplier != 0.0)
multEnable = true;
if(meterConfig.voltageMultiplier != 1.0 && meterConfig.voltageMultiplier != 0.0)
multEnable = true;
if(meterConfig.amperageMultiplier != 1.0 && meterConfig.amperageMultiplier != 0.0)
multEnable = true;
if(meterConfig.accumulatedMultiplier != 1.0 && meterConfig.accumulatedMultiplier != 0.0)
multEnable = true;
SystemConfig sysConfig;
config->getSystemConfig(sysConfig);
NtpConfig ntpConfig;
config->getNtpConfig(ntpConfig);
NetworkConfig networkConfig;
config->getNetworkConfig(networkConfig);
bool encen = false;
for(uint8_t i = 0; i < 16; i++) {
if(meterConfig.encryptionKey[i] > 0) {
encen = true;
}
}
EnergyAccountingConfig* eac = ea->getConfig();
MqttConfig mqttConfig;
config->getMqttConfig(mqttConfig);
PriceServiceConfig price;
config->getPriceServiceConfig(price);
DebugConfig debugConfig;
config->getDebugConfig(debugConfig);
DomoticzConfig domo;
config->getDomoticzConfig(domo);
UiConfig ui;
config->getUiConfig(ui);
HomeAssistantConfig haconf;
config->getHomeAssistantConfig(haconf);
CloudConfig cloud;
config->getCloudConfig(cloud);
ZmartChargeConfig zcc;
config->getZmartChargeConfig(zcc);
stripNonAscii((uint8_t*) zcc.token, 21);
bool qsc = false;
bool qsr = false;
bool qsk = false;
if(LittleFS.begin()) {
qsc = LittleFS.exists(FILE_MQTT_CA);
qsr = LittleFS.exists(FILE_MQTT_CERT);
qsk = LittleFS.exists(FILE_MQTT_KEY);
}
addConditionalCloudHeaders();
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send_P(200, MIME_JSON, PSTR("{\"version\":\""));
server.sendContent_P(FirmwareVersion::VersionString);
server.sendContent_P(PSTR("\","));
snprintf_P(buf, BufferSize, CONF_GENERAL_JSON,
ntpConfig.timezone,
networkConfig.hostname,
webConfig.security,
webConfig.username,
strlen(webConfig.password) > 0 ? "***" : "",
webConfig.context
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_METER_JSON,
meterConfig.source,
meterConfig.parser,
meterConfig.baud,
meterConfig.parity,
meterConfig.invert ? "true" : "false",
meterConfig.bufferSize * 64,
meterConfig.distributionSystem,
meterConfig.mainFuse,
meterConfig.productionCapacity,
encen ? "true" : "false",
toHex(meterConfig.encryptionKey, 16).c_str(),
toHex(meterConfig.authenticationKey, 16).c_str(),
multEnable ? "true" : "false",
meterConfig.wattageMultiplier == 0.0 ? 1.0 : meterConfig.wattageMultiplier / 1000.0,
meterConfig.voltageMultiplier == 0.0 ? 1.0 : meterConfig.voltageMultiplier / 1000.0,
meterConfig.amperageMultiplier == 0.0 ? 1.0 : meterConfig.amperageMultiplier / 1000.0,
meterConfig.accumulatedMultiplier == 0.0 ? 1.0 : meterConfig.accumulatedMultiplier / 1000.0
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_THRESHOLDS_JSON,
eac->thresholds[0],
eac->thresholds[1],
eac->thresholds[2],
eac->thresholds[3],
eac->thresholds[4],
eac->thresholds[5],
eac->thresholds[6],
eac->thresholds[7],
eac->thresholds[8],
eac->thresholds[9],
eac->hours
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_WIFI_JSON,
networkConfig.ssid,
strlen(networkConfig.psk) > 0 ? "***" : "",
networkConfig.power / 10.0,
networkConfig.sleep,
networkConfig.use11b ? "true" : "false"
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_NET_JSON,
networkConfig.mode,
strlen(networkConfig.ip) > 0 ? "static" : "dhcp",
networkConfig.ip,
networkConfig.subnet,
networkConfig.gateway,
networkConfig.dns1,
networkConfig.dns2,
networkConfig.mdns ? "true" : "false",
ntpConfig.server,
ntpConfig.dhcp ? "true" : "false",
networkConfig.ipv6 ? "true" : "false"
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_MQTT_JSON,
mqttConfig.host,
mqttConfig.port,
mqttConfig.username,
strlen(mqttConfig.password) > 0 ? "***" : "",
mqttConfig.clientId,
mqttConfig.publishTopic,
mqttConfig.subscribeTopic,
mqttConfig.payloadFormat,
mqttConfig.ssl ? "true" : "false",
qsc ? "true" : "false",
qsr ? "true" : "false",
qsk ? "true" : "false",
mqttConfig.stateUpdate,
mqttConfig.stateUpdateInterval,
mqttConfig.timeout,
mqttConfig.keepalive,
mqttConfig.rebootMinutes == 0 ? "null" : String(mqttConfig.rebootMinutes, 10).c_str()
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_PRICE_JSON,
price.enabled ? "true" : "false",
price.entsoeToken,
price.area,
price.currency,
price.resolutionInMinutes
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_DEBUG_JSON,
debugConfig.serial ? "true" : "false",
debugConfig.telnet ? "true" : "false",
debugConfig.level
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_GPIO_JSON,
meterConfig.rxPin == 0xff ? "null" : String(meterConfig.rxPin, 10).c_str(),
meterConfig.rxPinPullup ? "true" : "false",
meterConfig.txPin == 0xff ? "null" : String(meterConfig.txPin, 10).c_str(),
gpioConfig->apPin == 0xff ? "null" : String(gpioConfig->apPin, 10).c_str(),
gpioConfig->ledPin == 0xff ? "null" : String(gpioConfig->ledPin, 10).c_str(),
gpioConfig->ledInverted ? "true" : "false",
gpioConfig->ledPinRed == 0xff ? "null" : String(gpioConfig->ledPinRed, 10).c_str(),
gpioConfig->ledPinGreen == 0xff ? "null" : String(gpioConfig->ledPinGreen, 10).c_str(),
gpioConfig->ledPinBlue == 0xff ? "null" : String(gpioConfig->ledPinBlue, 10).c_str(),
gpioConfig->ledRgbInverted ? "true" : "false",
gpioConfig->ledDisablePin == 0xff ? "null" : String(gpioConfig->ledDisablePin, 10).c_str(),
gpioConfig->ledBehaviour,
gpioConfig->tempSensorPin == 0xff ? "null" : String(gpioConfig->tempSensorPin, 10).c_str(),
gpioConfig->tempAnalogSensorPin == 0xff ? "null" : String(gpioConfig->tempAnalogSensorPin, 10).c_str(),
gpioConfig->vccPin == 0xff ? "null" : String(gpioConfig->vccPin, 10).c_str(),
gpioConfig->vccOffset / 100.0,
gpioConfig->vccMultiplier / 1000.0,
gpioConfig->vccResistorVcc,
gpioConfig->vccResistorGnd,
gpioConfig->vccBootLimit / 10.0,
gpioConfig->powersaving
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_UI_JSON,
ui.showImport,
ui.showExport,
ui.showVoltage,
ui.showAmperage,
ui.showReactive,
ui.showRealtime,
ui.showPeaks,
ui.showPricePlot,
ui.showDayPlot,
ui.showMonthPlot,
ui.showTemperaturePlot,
ui.showRealtimePlot,
ui.showPerPhasePower,
ui.showPowerFactor,
ui.darkMode,
ui.language
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_DOMOTICZ_JSON,
domo.elidx,
domo.cl1idx,
domo.vl1idx,
domo.vl2idx,
domo.vl3idx
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_HA_JSON,
haconf.discoveryPrefix,
haconf.discoveryHostname,
haconf.discoveryNameTag
);
server.sendContent(buf);
snprintf_P(buf, BufferSize, CONF_CLOUD_JSON,
cloud.enabled ? "true" : "false",
cloud.proto,
#if defined(ESP32) && defined(ENERGY_SPEEDOMETER_PASS)
sysConfig.energyspeedometer == 7 ? "true" : "false",
#else
"null",
#endif
zcc.enabled ? "true" : "false",
zcc.token
);
server.sendContent(buf);
server.sendContent_P(PSTR("}"));
AmsJsonGenerator::generateConfigurationJson(config, buf, BufferSize);
server.send(200, MIME_JSON, buf);
}
void AmsWebServer::priceConfigJson() {
@@ -1165,7 +921,7 @@ void AmsWebServer::priceConfigJson() {
}
hours = hours.substring(0, hours.length()-1);
snprintf_P(buf, BufferSize, CONF_PRICE_ROW_JSON,
snprintf_P(buf, BufferSize, PSTR("{\"t\":%d,\"n\":\"%s\",\"d\":%d,\"a\":[%s],\"h\":[%s],\"v\":%.4f,\"s\":{\"m\":%d,\"d\":%d},\"e\":{\"m\":%d,\"d\":%d}}%s"),
p.type,
p.name,
p.direction,