mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-03-27 18:49:49 +00:00
Compare commits
5 Commits
main
...
feat/confi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
048bd474e4 | ||
|
|
9609e9fb85 | ||
|
|
ecd7017ac5 | ||
|
|
e91ef1a98c | ||
|
|
548012e90b |
@@ -9,8 +9,14 @@
|
||||
#include <EEPROM.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define BUF_SIZE_COMMON 2048
|
||||
#else
|
||||
#define BUF_SIZE_COMMON 4096
|
||||
#endif
|
||||
|
||||
#define EEPROM_SIZE 1024*3
|
||||
#define EEPROM_CHECK_SUM 104 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_EXPECTED_VERSION 104 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_CLEARED_INDICATOR 0xFC
|
||||
#define EEPROM_CONFIG_ADDRESS 0
|
||||
|
||||
@@ -283,11 +289,12 @@ struct ZmartChargeConfig {
|
||||
|
||||
class AmsConfiguration {
|
||||
public:
|
||||
bool load();
|
||||
bool save();
|
||||
|
||||
bool hasConfig();
|
||||
int getConfigVersion();
|
||||
|
||||
bool save();
|
||||
|
||||
bool getSystemConfig(SystemConfig&);
|
||||
bool setSystemConfig(SystemConfig&);
|
||||
bool isSystemConfigChanged();
|
||||
|
||||
@@ -11,16 +11,14 @@
|
||||
#endif
|
||||
|
||||
bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
EEPROM.get(CONFIG_SYSTEM_START, config);
|
||||
EEPROM.end();
|
||||
|
||||
if(config.firmwareChannel > 3) {
|
||||
config.firmwareChannel = 0;
|
||||
}
|
||||
|
||||
if(configVersion == EEPROM_CHECK_SUM) {
|
||||
if(configVersion == EEPROM_EXPECTED_VERSION) {
|
||||
return true;
|
||||
} else {
|
||||
if(configVersion == EEPROM_CLEARED_INDICATOR && config.boardType > 0 && config.boardType < 250) {
|
||||
@@ -52,12 +50,9 @@ bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
} else {
|
||||
sysChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
stripNonAscii((uint8_t*) config.country, 2);
|
||||
EEPROM.put(CONFIG_SYSTEM_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return sysChanged;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::isSystemConfigChanged() {
|
||||
@@ -70,10 +65,8 @@ void AmsConfiguration::ackSystemConfigChanged() {
|
||||
|
||||
bool AmsConfiguration::getNetworkConfig(NetworkConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_NETWORK_START, config);
|
||||
EEPROM.end();
|
||||
if(config.sleep > 2) config.sleep = 1;
|
||||
EEPROM.get(CONFIG_NETWORK_START, config);
|
||||
if(config.sleep > 2) config.sleep = 1;
|
||||
return true;
|
||||
} else {
|
||||
clearNetworkConfig(config);
|
||||
@@ -113,11 +106,8 @@ bool AmsConfiguration::setNetworkConfig(NetworkConfig& config) {
|
||||
stripNonAscii((uint8_t*) config.dns2, 16);
|
||||
stripNonAscii((uint8_t*) config.hostname, 32);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_NETWORK_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return networkChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearNetworkConfig(NetworkConfig& config) {
|
||||
@@ -158,10 +148,8 @@ void AmsConfiguration::ackNetworkConfigChange() {
|
||||
|
||||
bool AmsConfiguration::getMqttConfig(MqttConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_MQTT_START, config);
|
||||
EEPROM.end();
|
||||
if(config.magic != 0xA5) { // New magic for 2.4.11
|
||||
EEPROM.get(CONFIG_MQTT_START, config);
|
||||
if(config.magic != 0xA5) { // New magic for 2.4.11
|
||||
if(config.magic != 0x9C) {
|
||||
if(config.magic != 0x7B) {
|
||||
config.stateUpdate = false;
|
||||
@@ -213,11 +201,8 @@ bool AmsConfiguration::setMqttConfig(MqttConfig& config) {
|
||||
if(config.keepalive > 240) config.keepalive = 60;
|
||||
if(config.rebootMinutes > 240) config.rebootMinutes = 0;
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_MQTT_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return mqttChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearMqtt(MqttConfig& config) {
|
||||
@@ -253,10 +238,8 @@ void AmsConfiguration::ackMqttChange() {
|
||||
|
||||
bool AmsConfiguration::getWebConfig(WebConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_WEB_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
EEPROM.get(CONFIG_WEB_START, config);
|
||||
return true;
|
||||
} else {
|
||||
clearWebConfig(config);
|
||||
return false;
|
||||
@@ -277,11 +260,8 @@ bool AmsConfiguration::setWebConfig(WebConfig& config) {
|
||||
stripNonAscii((uint8_t*) config.password, 37, false, false);
|
||||
stripNonAscii((uint8_t*) config.context, 37);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_WEB_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return webChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearWebConfig(WebConfig& config) {
|
||||
@@ -300,12 +280,10 @@ void AmsConfiguration::ackWebChange() {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::getMeterConfig(MeterConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
if(configVersion == EEPROM_CHECK_SUM || configVersion == EEPROM_CLEARED_INDICATOR) {
|
||||
if(configVersion == EEPROM_EXPECTED_VERSION || configVersion == EEPROM_CLEARED_INDICATOR) {
|
||||
EEPROM.get(CONFIG_METER_START, config);
|
||||
EEPROM.end();
|
||||
if(config.bufferSize < 1 || config.bufferSize > 64) {
|
||||
if(config.bufferSize < 1 || config.bufferSize > 64) {
|
||||
#if defined(ESP32)
|
||||
config.bufferSize = 2;
|
||||
#else
|
||||
@@ -346,11 +324,8 @@ bool AmsConfiguration::setMeterConfig(MeterConfig& config) {
|
||||
} else {
|
||||
meterChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_METER_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return meterChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearMeter(MeterConfig& config) {
|
||||
@@ -388,10 +363,8 @@ void AmsConfiguration::setMeterChanged() {
|
||||
|
||||
bool AmsConfiguration::getDebugConfig(DebugConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_DEBUG_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
EEPROM.get(CONFIG_DEBUG_START, config);
|
||||
return true;
|
||||
} else {
|
||||
clearDebug(config);
|
||||
return false;
|
||||
@@ -401,11 +374,8 @@ bool AmsConfiguration::getDebugConfig(DebugConfig& config) {
|
||||
bool AmsConfiguration::setDebugConfig(DebugConfig& config) {
|
||||
if(!config.serial && !config.telnet)
|
||||
config.level = 4; // Force warning level when debug is disabled
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_DEBUG_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearDebug(DebugConfig& config) {
|
||||
@@ -416,10 +386,8 @@ void AmsConfiguration::clearDebug(DebugConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getDomoticzConfig(DomoticzConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_DOMOTICZ_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
EEPROM.get(CONFIG_DOMOTICZ_START, config);
|
||||
return true;
|
||||
} else {
|
||||
clearDomo(config);
|
||||
return false;
|
||||
@@ -437,11 +405,8 @@ bool AmsConfiguration::setDomoticzConfig(DomoticzConfig& config) {
|
||||
} else {
|
||||
mqttChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_DOMOTICZ_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return mqttChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearDomo(DomoticzConfig& config) {
|
||||
@@ -454,10 +419,8 @@ void AmsConfiguration::clearDomo(DomoticzConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getHomeAssistantConfig(HomeAssistantConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_HA_START, config);
|
||||
EEPROM.end();
|
||||
if(stripNonAscii((uint8_t*) config.discoveryPrefix, 64) || stripNonAscii((uint8_t*) config.discoveryHostname, 64) || stripNonAscii((uint8_t*) config.discoveryNameTag, 16)) {
|
||||
EEPROM.get(CONFIG_HA_START, config);
|
||||
if(stripNonAscii((uint8_t*) config.discoveryPrefix, 64) || stripNonAscii((uint8_t*) config.discoveryHostname, 64) || stripNonAscii((uint8_t*) config.discoveryNameTag, 16)) {
|
||||
clearHomeAssistantConfig(config);
|
||||
return false;
|
||||
}
|
||||
@@ -482,11 +445,8 @@ bool AmsConfiguration::setHomeAssistantConfig(HomeAssistantConfig& config) {
|
||||
stripNonAscii((uint8_t*) config.discoveryHostname, 64);
|
||||
stripNonAscii((uint8_t*) config.discoveryNameTag, 16);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_HA_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return mqttChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearHomeAssistantConfig(HomeAssistantConfig& config) {
|
||||
@@ -512,12 +472,10 @@ bool AmsConfiguration::pinUsed(uint8_t pin, GpioConfig& config) {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::getGpioConfig(GpioConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
if(configVersion == EEPROM_CHECK_SUM || configVersion == EEPROM_CLEARED_INDICATOR) {
|
||||
if(configVersion == EEPROM_EXPECTED_VERSION || configVersion == EEPROM_CLEARED_INDICATOR) {
|
||||
EEPROM.get(CONFIG_GPIO_START, config);
|
||||
EEPROM.end();
|
||||
if(config.powersaving > 4) config.powersaving = 0;
|
||||
if(config.powersaving > 4) config.powersaving = 0;
|
||||
return true;
|
||||
} else {
|
||||
clearGpio(config);
|
||||
@@ -572,11 +530,8 @@ bool AmsConfiguration::setGpioConfig(GpioConfig& config) {
|
||||
if(config.apPin >= 0)
|
||||
pinMode(config.apPin, INPUT_PULLUP);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_GPIO_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearGpio(GpioConfig& config, bool all) {
|
||||
@@ -605,10 +560,8 @@ void AmsConfiguration::clearGpio(GpioConfig& config, bool all) {
|
||||
|
||||
bool AmsConfiguration::getNtpConfig(NtpConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_NTP_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
EEPROM.get(CONFIG_NTP_START, config);
|
||||
return true;
|
||||
} else {
|
||||
clearNtp(config);
|
||||
return false;
|
||||
@@ -635,11 +588,8 @@ bool AmsConfiguration::setNtpConfig(NtpConfig& config) {
|
||||
stripNonAscii((uint8_t*) config.server, 64);
|
||||
stripNonAscii((uint8_t*) config.timezone, 32);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_NTP_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return ntpChanged;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::isNtpChanged() {
|
||||
@@ -659,10 +609,8 @@ void AmsConfiguration::clearNtp(NtpConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getPriceServiceConfig(PriceServiceConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_PRICE_START, config);
|
||||
EEPROM.end();
|
||||
if(strlen(config.entsoeToken) != 0 && strlen(config.entsoeToken) != 36) {
|
||||
EEPROM.get(CONFIG_PRICE_START, config);
|
||||
if(strlen(config.entsoeToken) != 0 && strlen(config.entsoeToken) != 36) {
|
||||
clearPriceServiceConfig(config);
|
||||
return false;
|
||||
}
|
||||
@@ -692,11 +640,8 @@ bool AmsConfiguration::setPriceServiceConfig(PriceServiceConfig& config) {
|
||||
stripNonAscii((uint8_t*) config.area, 17);
|
||||
stripNonAscii((uint8_t*) config.currency, 4);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_PRICE_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return priceChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearPriceServiceConfig(PriceServiceConfig& config) {
|
||||
@@ -718,10 +663,8 @@ void AmsConfiguration::ackPriceServiceChange() {
|
||||
|
||||
bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_ENERGYACCOUNTING_START, config);
|
||||
EEPROM.end();
|
||||
if(config.thresholds[9] != 0xFFFF) {
|
||||
EEPROM.get(CONFIG_ENERGYACCOUNTING_START, config);
|
||||
if(config.thresholds[9] != 0xFFFF) {
|
||||
clearEnergyAccountingConfig(config);
|
||||
return false;
|
||||
}
|
||||
@@ -747,11 +690,8 @@ bool AmsConfiguration::setEnergyAccountingConfig(EnergyAccountingConfig& config)
|
||||
} else {
|
||||
energyAccountingChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return energyAccountingChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||
@@ -778,11 +718,9 @@ void AmsConfiguration::ackEnergyAccountingChange() {
|
||||
|
||||
bool AmsConfiguration::getUiConfig(UiConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_UI_START, config);
|
||||
EEPROM.get(CONFIG_UI_START, config);
|
||||
if(config.showImport > 2) clearUiConfig(config); // Must be wrong
|
||||
EEPROM.end();
|
||||
return true;
|
||||
return true;
|
||||
} else {
|
||||
clearUiConfig(config);
|
||||
return false;
|
||||
@@ -796,11 +734,8 @@ bool AmsConfiguration::setUiConfig(UiConfig& config) {
|
||||
} else {
|
||||
uiLanguageChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_UI_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return uiLanguageChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearUiConfig(UiConfig& config) {
|
||||
@@ -835,19 +770,14 @@ bool AmsConfiguration::setUpgradeInformation(UpgradeInformation& upinfo) {
|
||||
stripNonAscii((uint8_t*) upinfo.fromVersion, 16);
|
||||
stripNonAscii((uint8_t*) upinfo.toVersion, 16);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_UPGRADE_INFO_START, upinfo);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::getUpgradeInformation(UpgradeInformation& upinfo) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_UPGRADE_INFO_START, upinfo);
|
||||
EEPROM.end();
|
||||
if(stripNonAscii((uint8_t*) upinfo.fromVersion, 16) || stripNonAscii((uint8_t*) upinfo.toVersion, 16)) {
|
||||
EEPROM.get(CONFIG_UPGRADE_INFO_START, upinfo);
|
||||
if(stripNonAscii((uint8_t*) upinfo.fromVersion, 16) || stripNonAscii((uint8_t*) upinfo.toVersion, 16)) {
|
||||
clearUpgradeInformation(upinfo);
|
||||
return false;
|
||||
}
|
||||
@@ -870,10 +800,8 @@ void AmsConfiguration::clearUpgradeInformation(UpgradeInformation& upinfo) {
|
||||
|
||||
bool AmsConfiguration::getCloudConfig(CloudConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_CLOUD_START, config);
|
||||
EEPROM.end();
|
||||
if(config.proto > 2) config.proto = 0;
|
||||
EEPROM.get(CONFIG_CLOUD_START, config);
|
||||
if(config.proto > 2) config.proto = 0;
|
||||
return true;
|
||||
} else {
|
||||
clearCloudConfig(config);
|
||||
@@ -896,11 +824,8 @@ bool AmsConfiguration::setCloudConfig(CloudConfig& config) {
|
||||
|
||||
stripNonAscii((uint8_t*) config.hostname, 64);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_CLOUD_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return cloudChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearCloudConfig(CloudConfig& config) {
|
||||
@@ -922,11 +847,9 @@ void AmsConfiguration::ackCloudConfig() {
|
||||
|
||||
bool AmsConfiguration::getZmartChargeConfig(ZmartChargeConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_ZC_START, config);
|
||||
EEPROM.end();
|
||||
stripNonAscii((uint8_t*) config.token, 21);
|
||||
stripNonAscii((uint8_t*) config.baseUrl, 64);
|
||||
EEPROM.get(CONFIG_ZC_START, config);
|
||||
stripNonAscii((uint8_t*) config.token, 21);
|
||||
stripNonAscii((uint8_t*) config.baseUrl, 64);
|
||||
if(strlen(config.token) != 20 || !config.enabled) {
|
||||
config.enabled = false;
|
||||
memset(config.token, 0, 64);
|
||||
@@ -959,11 +882,8 @@ bool AmsConfiguration::setZmartChargeConfig(ZmartChargeConfig& config) {
|
||||
memset(config.baseUrl, 0, 64);
|
||||
}
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(CONFIG_ZC_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return zcChanged;
|
||||
}
|
||||
|
||||
void AmsConfiguration::clearZmartChargeConfig(ZmartChargeConfig& config) {
|
||||
@@ -984,8 +904,6 @@ void AmsConfiguration::setUiLanguageChanged() {
|
||||
}
|
||||
|
||||
void AmsConfiguration::clear() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
|
||||
SystemConfig sys;
|
||||
EEPROM.get(CONFIG_SYSTEM_START, sys);
|
||||
sys.userConfigured = false;
|
||||
@@ -1053,18 +971,16 @@ void AmsConfiguration::clear() {
|
||||
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CLEARED_INDICATOR);
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
}
|
||||
|
||||
bool AmsConfiguration::hasConfig() {
|
||||
bool AmsConfiguration::load() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
if(configVersion == 0) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
EEPROM.end();
|
||||
}
|
||||
if(configVersion > EEPROM_CHECK_SUM) {
|
||||
if(loadFromFs(EEPROM_CHECK_SUM)) {
|
||||
configVersion = EEPROM_CHECK_SUM;
|
||||
if(configVersion > EEPROM_EXPECTED_VERSION) {
|
||||
if(loadFromFs(EEPROM_EXPECTED_VERSION)) {
|
||||
configVersion = EEPROM_EXPECTED_VERSION;
|
||||
} else {
|
||||
configVersion = 0;
|
||||
}
|
||||
@@ -1078,14 +994,18 @@ bool AmsConfiguration::hasConfig() {
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
case EEPROM_CHECK_SUM:
|
||||
case EEPROM_EXPECTED_VERSION:
|
||||
return true;
|
||||
default:
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return configVersion == EEPROM_CHECK_SUM;
|
||||
return configVersion == EEPROM_EXPECTED_VERSION;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::hasConfig() {
|
||||
return configVersion == EEPROM_EXPECTED_VERSION;
|
||||
}
|
||||
|
||||
int AmsConfiguration::getConfigVersion() {
|
||||
@@ -1093,8 +1013,6 @@ int AmsConfiguration::getConfigVersion() {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::relocateConfig103() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
|
||||
MeterConfig meter;
|
||||
UpgradeInformation upinfo;
|
||||
UiConfig ui;
|
||||
@@ -1191,19 +1109,14 @@ bool AmsConfiguration::relocateConfig103() {
|
||||
EEPROM.put(CONFIG_ZC_START, zcc);
|
||||
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, 104);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
return EEPROM.commit();
|
||||
}
|
||||
|
||||
bool AmsConfiguration::save() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_EXPECTED_VERSION);
|
||||
bool success = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
|
||||
configVersion = EEPROM_CHECK_SUM;
|
||||
configVersion = EEPROM_EXPECTED_VERSION;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,9 @@ protected:
|
||||
uint64_t lastList2 = 0;
|
||||
uint8_t listType = 0, meterType = AmsTypeUnknown;
|
||||
time_t packageTimestamp = 0;
|
||||
String listId = "", meterId = "", meterModel = "";
|
||||
char listId[32] = {};
|
||||
char meterId[32] = {};
|
||||
char meterModel[65] = {};
|
||||
time_t meterTimestamp = 0;
|
||||
uint32_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
|
||||
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
|
||||
|
||||
@@ -88,10 +88,10 @@ void AmsData::apply(AmsData& other) {
|
||||
}
|
||||
this->counterEstimated = false;
|
||||
case 2:
|
||||
this->listId = other.getListId();
|
||||
this->meterId = other.getMeterId();
|
||||
strncpy(this->listId, other.listId, sizeof(this->listId) - 1);
|
||||
strncpy(this->meterId, other.meterId, sizeof(this->meterId) - 1);
|
||||
this->meterType = other.getMeterType();
|
||||
this->meterModel = other.getMeterModel();
|
||||
strncpy(this->meterModel, other.meterModel, sizeof(this->meterModel) - 1);
|
||||
this->reactiveImportPower = other.getReactiveImportPower();
|
||||
this->reactiveExportPower = other.getReactiveExportPower();
|
||||
this->l1current = other.getL1Current();
|
||||
@@ -119,7 +119,7 @@ void AmsData::apply(OBIS_code_t obis, double value) {
|
||||
if(obis.gr == 1) {
|
||||
if(obis.sensor == 96) {
|
||||
if(obis.tariff == 0) {
|
||||
meterId = String((long) value, 10);
|
||||
snprintf(meterId, sizeof(meterId), "%ld", (long) value);
|
||||
return;
|
||||
} else if(obis.tariff == 1) {
|
||||
return;
|
||||
@@ -278,11 +278,11 @@ uint8_t AmsData::getListType() {
|
||||
}
|
||||
|
||||
String AmsData::getListId() {
|
||||
return this->listId;
|
||||
return String(this->listId);
|
||||
}
|
||||
|
||||
String AmsData::getMeterId() {
|
||||
return this->meterId;
|
||||
return String(this->meterId);
|
||||
}
|
||||
|
||||
uint8_t AmsData::getMeterType() {
|
||||
@@ -290,7 +290,7 @@ uint8_t AmsData::getMeterType() {
|
||||
}
|
||||
|
||||
String AmsData::getMeterModel() {
|
||||
return this->meterModel;
|
||||
return String(this->meterModel);
|
||||
}
|
||||
|
||||
time_t AmsData::getMeterTimestamp() {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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\":%s}"),
|
||||
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
|
||||
}
|
||||
@@ -23,21 +23,23 @@
|
||||
class AmsMqttHandler {
|
||||
public:
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
AmsMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
AmsMqttHandler(AmsConfiguration* config, RemoteDebug* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#else
|
||||
AmsMqttHandler(MqttConfig& mqttConfig, Stream* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
AmsMqttHandler(AmsConfiguration* config, Stream* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#endif
|
||||
this->mqttConfig = mqttConfig;
|
||||
this->mqttConfigChanged = true;
|
||||
this->debugger = debugger;
|
||||
this->json = buf;
|
||||
this->updater = updater;
|
||||
mqtt.dropOverflow(true);
|
||||
|
||||
pubTopic = String(mqttConfig.publishTopic);
|
||||
subTopic = String(mqttConfig.subscribeTopic);
|
||||
if(subTopic.isEmpty()) subTopic = pubTopic+"/command";
|
||||
this->config = config;
|
||||
config->getMqttConfig(mqttConfig);
|
||||
mqttConfigChanged = true;
|
||||
init(debugger, buf, updater);
|
||||
};
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
AmsMqttHandler(MqttConfig& MqttConfig, RemoteDebug* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#else
|
||||
AmsMqttHandler(MqttConfig& MqttConfig, Stream* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#endif
|
||||
this->mqttConfig = MqttConfig;
|
||||
init(debugger, buf, updater);
|
||||
}
|
||||
|
||||
void setCaVerification(bool);
|
||||
void setConfig(MqttConfig& mqttConfig);
|
||||
@@ -79,24 +81,49 @@ protected:
|
||||
#else
|
||||
Stream* debugger;
|
||||
#endif
|
||||
AmsConfiguration* config;
|
||||
MqttConfig mqttConfig;
|
||||
bool mqttConfigChanged = true;
|
||||
#if defined(ESP32)
|
||||
MQTTClient mqtt = MQTTClient(2048);
|
||||
#else
|
||||
MQTTClient mqtt = MQTTClient(256);
|
||||
#endif
|
||||
unsigned long lastMqttRetry = -10000;
|
||||
bool caVerification = true;
|
||||
WiFiClient *mqttClient = NULL;
|
||||
WiFiClientSecure *mqttSecureClient = NULL;
|
||||
boolean _connected = false;
|
||||
char* json;
|
||||
uint16_t BufferSize = 2048;
|
||||
uint64_t lastStateUpdate = 0;
|
||||
uint64_t lastSuccessfulLoop = 0;
|
||||
|
||||
String pubTopic;
|
||||
String subTopic;
|
||||
char pubTopic[64];
|
||||
char subTopic[64];
|
||||
|
||||
AmsFirmwareUpdater* updater = NULL;
|
||||
bool rebootSuggested = false;
|
||||
|
||||
private:
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
void init(RemoteDebug* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#else
|
||||
void init(Stream* debugger, char* buf, AmsFirmwareUpdater* updater) {
|
||||
#endif
|
||||
this->debugger = debugger;
|
||||
this->json = buf;
|
||||
this->updater = updater;
|
||||
mqtt.dropOverflow(true);
|
||||
|
||||
strncpy(pubTopic, mqttConfig.publishTopic, sizeof(pubTopic) - 1);
|
||||
pubTopic[sizeof(pubTopic) - 1] = '\0';
|
||||
if(strlen(mqttConfig.subscribeTopic) > 0) {
|
||||
strncpy(subTopic, mqttConfig.subscribeTopic, sizeof(subTopic) - 1);
|
||||
subTopic[sizeof(subTopic) - 1] = '\0';
|
||||
} else {
|
||||
snprintf(subTopic, sizeof(subTopic), "%s/command", mqttConfig.publishTopic);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -118,8 +118,9 @@ bool AmsMqttHandler::connect() {
|
||||
mqtt.setTimeout(mqttConfig.timeout);
|
||||
mqtt.setKeepAlive(mqttConfig.keepalive);
|
||||
mqtt.begin(mqttConfig.host, mqttConfig.port, *actualClient);
|
||||
String statusTopic = String(mqttConfig.publishTopic) + "/status";
|
||||
mqtt.setWill(statusTopic.c_str(), "offline", true, 0);
|
||||
char statusTopic[72];
|
||||
snprintf(statusTopic, sizeof(statusTopic), "%s/status", mqttConfig.publishTopic);
|
||||
mqtt.setWill(statusTopic, "offline", true, 0);
|
||||
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
@@ -149,7 +150,7 @@ bool AmsMqttHandler::connect() {
|
||||
debugger->printf_P(PSTR("Failed to connect to MQTT: %d\n"), mqtt.lastError());
|
||||
#if defined(ESP8266)
|
||||
if(mqttSecureClient) {
|
||||
mqttSecureClient->getLastSSLError((char*) json, BufferSize);
|
||||
mqttSecureClient->getLastSSLError((char*) json, BUF_SIZE_COMMON);
|
||||
debugger->println((char*) json);
|
||||
}
|
||||
#endif
|
||||
@@ -160,17 +161,17 @@ bool AmsMqttHandler::connect() {
|
||||
|
||||
bool AmsMqttHandler::defaultSubscribe() {
|
||||
bool ret = true;
|
||||
if(!subTopic.isEmpty()) {
|
||||
if(subTopic[0] != '\0') {
|
||||
if(mqtt.subscribe(subTopic)) {
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR(" Subscribed to [%s]\n"), subTopic.c_str());
|
||||
debugger->printf_P(PSTR(" Subscribed to [%s]\n"), subTopic);
|
||||
} else {
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR(" Unable to subscribe to [%s]\n"), subTopic.c_str());
|
||||
debugger->printf_P(PSTR(" Unable to subscribe to [%s]\n"), subTopic);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ bool DomoticzMqttHandler::publish(AmsData* update, AmsData* previousState, Energ
|
||||
if(energy > 0.0) {
|
||||
char val[16];
|
||||
snprintf_P(val, 16, PSTR("%.1f;%.1f"), (data.getActiveImportPower()/1.0), energy*1000.0);
|
||||
snprintf_P(json, BufferSize, DOMOTICZ_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, DOMOTICZ_JSON,
|
||||
config.elidx,
|
||||
val
|
||||
);
|
||||
@@ -44,7 +44,7 @@ bool DomoticzMqttHandler::publish(AmsData* update, AmsData* previousState, Energ
|
||||
if (config.vl1idx > 0){
|
||||
char val[16];
|
||||
snprintf_P(val, 16, PSTR("%.2f"), data.getL1Voltage());
|
||||
snprintf_P(json, BufferSize, DOMOTICZ_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, DOMOTICZ_JSON,
|
||||
config.vl1idx,
|
||||
val
|
||||
);
|
||||
@@ -55,7 +55,7 @@ bool DomoticzMqttHandler::publish(AmsData* update, AmsData* previousState, Energ
|
||||
if (config.vl2idx > 0){
|
||||
char val[16];
|
||||
snprintf_P(val, 16, PSTR("%.2f"), data.getL2Voltage());
|
||||
snprintf_P(json, BufferSize, DOMOTICZ_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, DOMOTICZ_JSON,
|
||||
config.vl2idx,
|
||||
val
|
||||
);
|
||||
@@ -66,7 +66,7 @@ bool DomoticzMqttHandler::publish(AmsData* update, AmsData* previousState, Energ
|
||||
if (config.vl3idx > 0){
|
||||
char val[16];
|
||||
snprintf(val, 16, "%.2f", data.getL3Voltage());
|
||||
snprintf_P(json, BufferSize, DOMOTICZ_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, DOMOTICZ_JSON,
|
||||
config.vl3idx,
|
||||
val
|
||||
);
|
||||
@@ -77,7 +77,7 @@ bool DomoticzMqttHandler::publish(AmsData* update, AmsData* previousState, Energ
|
||||
if (config.cl1idx > 0){
|
||||
char val[16];
|
||||
snprintf(val, 16, "%.1f;%.1f;%.1f", data.getL1Current(), data.getL2Current(), data.getL3Current());
|
||||
snprintf_P(json, BufferSize, DOMOTICZ_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, DOMOTICZ_JSON,
|
||||
config.cl1idx,
|
||||
val
|
||||
);
|
||||
|
||||
@@ -88,7 +88,7 @@ bool HomeAssistantMqttHandler::postConnect() {
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAccounting* ea, PriceService* ps) {
|
||||
if(pubTopic.isEmpty() || !connected())
|
||||
if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected())
|
||||
return false;
|
||||
|
||||
if(time(nullptr) < FirmwareVersion::BuildEpoch)
|
||||
@@ -135,8 +135,9 @@ bool HomeAssistantMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea)
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||
|
||||
snprintf_P(json, BufferSize, HA1_JSON, data->getActiveImportPower(), pt);
|
||||
return mqtt.publish(pubTopic + "/power", json);
|
||||
snprintf_P(json, BUF_SIZE_COMMON, HA1_JSON, data->getActiveImportPower(), pt);
|
||||
{ char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic);
|
||||
return mqtt.publish(_t, json); }
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
@@ -146,7 +147,7 @@ bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea)
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||
|
||||
snprintf_P(json, BufferSize, HA3_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, HA3_JSON,
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
getMeterModel(data).c_str(),
|
||||
@@ -162,7 +163,8 @@ bool HomeAssistantMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea)
|
||||
data->getL3Voltage(),
|
||||
pt
|
||||
);
|
||||
return mqtt.publish(pubTopic + "/power", json);
|
||||
{ char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic);
|
||||
return mqtt.publish(_t, json); }
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
@@ -176,7 +178,7 @@ bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea)
|
||||
memset(pt, 0, 24);
|
||||
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||
|
||||
snprintf_P(json, BufferSize, HA2_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, HA2_JSON,
|
||||
data->getActiveImportCounter(),
|
||||
data->getActiveExportCounter(),
|
||||
data->getReactiveImportCounter(),
|
||||
@@ -184,7 +186,8 @@ bool HomeAssistantMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea)
|
||||
mt,
|
||||
pt
|
||||
);
|
||||
return mqtt.publish(pubTopic + "/energy", json);
|
||||
{ char _t[72]; snprintf(_t, sizeof(_t), "%s/energy", pubTopic);
|
||||
return mqtt.publish(_t, json); }
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) {
|
||||
@@ -194,7 +197,7 @@ bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea)
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(data->getPackageTimestamp(), pt, sizeof(pt));
|
||||
|
||||
snprintf_P(json, BufferSize, HA4_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, HA4_JSON,
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
getMeterModel(data).c_str(),
|
||||
@@ -226,7 +229,8 @@ bool HomeAssistantMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea)
|
||||
data->getL3ActiveExportCounter(),
|
||||
pt
|
||||
);
|
||||
return mqtt.publish(pubTopic + "/power", json);
|
||||
{ char _t[72]; snprintf(_t, sizeof(_t), "%s/power", pubTopic);
|
||||
return mqtt.publish(_t, json); }
|
||||
}
|
||||
|
||||
String HomeAssistantMqttHandler::getMeterModel(AmsData* data) {
|
||||
@@ -246,7 +250,7 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting*
|
||||
if(!peaks.isEmpty()) peaks += ",";
|
||||
peaks += String(ea->getPeak(i).value / 100.0, 2);
|
||||
}
|
||||
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"max\":%.1f,\"peaks\":[%s],\"threshold\":%d,\"hour\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f},\"day\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f},\"month\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f}"),
|
||||
uint16_t pos = snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"max\":%.1f,\"peaks\":[%s],\"threshold\":%d,\"hour\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f},\"day\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f},\"month\":{\"use\":%.2f,\"cost\":%.2f,\"produced\":%.2f,\"income\":%.2f}"),
|
||||
ea->getMonthMax(),
|
||||
peaks.c_str(),
|
||||
ea->getCurrentThreshold(),
|
||||
@@ -266,7 +270,7 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting*
|
||||
uint32_t ms = millis();
|
||||
if(lastThresholdPublish == 0 || ms-lastThresholdPublish > 3600000) {
|
||||
EnergyAccountingConfig* conf = ea->getConfig();
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"thresholds\": [%d,%d,%d,%d,%d,%d,%d,%d,%d]"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR(",\"thresholds\": [%d,%d,%d,%d,%d,%d,%d,%d,%d]"),
|
||||
conf->thresholds[0],
|
||||
conf->thresholds[1],
|
||||
conf->thresholds[2],
|
||||
@@ -283,12 +287,13 @@ bool HomeAssistantMqttHandler::publishRealtime(AmsData* data, EnergyAccounting*
|
||||
time_t now = time(nullptr);
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR(",\"t\":%s"), pt);
|
||||
|
||||
json[pos++] = '}';
|
||||
json[pos] = '\0';
|
||||
|
||||
return mqtt.publish(pubTopic + "/realtime", json);
|
||||
{ char _t[72]; snprintf(_t, sizeof(_t), "%s/realtime", pubTopic);
|
||||
return mqtt.publish(_t, json); }
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwTools* hw) {
|
||||
@@ -301,7 +306,7 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT
|
||||
TempSensorData* data = hw->getTempSensorData(i);
|
||||
if(data != NULL) {
|
||||
String id = toHex(data->address, 8);
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"%s\":%.2f,"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"%s\":%.2f,"),
|
||||
id.c_str(),
|
||||
data->lastRead
|
||||
);
|
||||
@@ -309,21 +314,22 @@ bool HomeAssistantMqttHandler::publishTemperatures(AmsConfiguration* config, HwT
|
||||
publishTemperatureSensor(i+1, id);
|
||||
}
|
||||
}
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("}"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("}"));
|
||||
|
||||
time_t now = time(nullptr);
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("}"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR(",\"t\":%s"), pt);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("}"));
|
||||
|
||||
bool ret = mqtt.publish(pubTopic + "/temperatures", json);
|
||||
char _t[72]; snprintf(_t, sizeof(_t), "%s/temperatures", pubTopic);
|
||||
bool ret = mqtt.publish(_t, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
||||
if(pubTopic.isEmpty() || !connected())
|
||||
if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected())
|
||||
return false;
|
||||
if(!ps->hasPrice())
|
||||
return false;
|
||||
@@ -416,33 +422,33 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
||||
toJsonIsoTimestamp(ts, ts6hr, sizeof(ts6hr));
|
||||
}
|
||||
|
||||
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
||||
uint16_t pos = snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
||||
|
||||
uint8_t currentPricePointIndex = ps->getCurrentPricePointIndex();
|
||||
uint8_t numberOfPoints = ps->getNumberOfPointsAvailable();
|
||||
for(int i = currentPricePointIndex; i < numberOfPoints; i++) {
|
||||
float val = ps->getPricePoint(PRICE_DIRECTION_IMPORT, i);
|
||||
if(val == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("null,"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("null,"));
|
||||
} else {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("%.4f,"), val);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("%.4f,"), val);
|
||||
}
|
||||
}
|
||||
if(rteInit && ps->isExportPricesDifferentFromImport()) {
|
||||
pos--;
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"export\":["));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("],\"export\":["));
|
||||
for(int i = currentPricePointIndex; i < numberOfPoints; i++) {
|
||||
float val = ps->getPricePoint(PRICE_DIRECTION_EXPORT, i);
|
||||
if(val == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("null,"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("null,"));
|
||||
} else {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("%.4f,"), val);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("%.4f,"), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos--;
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":%s,\"cheapest3hr\":%s,\"cheapest6hr\":%s}"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":%s,\"cheapest3hr\":%s,\"cheapest6hr\":%s}"),
|
||||
min == INT16_MAX ? 0.0 : min,
|
||||
max == INT16_MIN ? 0.0 : max,
|
||||
ts1hr,
|
||||
@@ -452,18 +458,19 @@ bool HomeAssistantMqttHandler::publishPrices(PriceService* ps) {
|
||||
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR(",\"t\":%s"), pt);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR(",\"t\":%s"), pt);
|
||||
|
||||
json[pos++] = '}';
|
||||
json[pos] = '\0';
|
||||
|
||||
bool ret = mqtt.publish(pubTopic + "/prices", json, true, 0);
|
||||
char _t[72]; snprintf(_t, sizeof(_t), "%s/prices", pubTopic);
|
||||
bool ret = mqtt.publish(_t, json, true, 0);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, EnergyAccounting* ea) {
|
||||
if(pubTopic.isEmpty() || !connected())
|
||||
if(pubTopic[0] == 'pubTopic.isEmpty()' || !connected())
|
||||
return false;
|
||||
|
||||
publishSystemSensors();
|
||||
@@ -473,7 +480,7 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, Ener
|
||||
char pt[24];
|
||||
toJsonIsoTimestamp(now, pt, sizeof(pt));
|
||||
|
||||
snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\",\"t\":%s}"),
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\",\"t\":%s}"),
|
||||
WiFi.macAddress().c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
@@ -483,7 +490,8 @@ bool HomeAssistantMqttHandler::publishSystem(HwTools* hw, PriceService* ps, Ener
|
||||
FirmwareVersion::VersionString,
|
||||
pt
|
||||
);
|
||||
bool ret = mqtt.publish(pubTopic + "/state", json);
|
||||
char _t[72]; snprintf(_t, sizeof(_t), "%s/state", pubTopic);
|
||||
bool ret = mqtt.publish(_t, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
@@ -499,7 +507,7 @@ void HomeAssistantMqttHandler::publishSensor(const HomeAssistantSensor sensor) {
|
||||
uid.replace("]", "");
|
||||
uid.replace("'", "");
|
||||
}
|
||||
snprintf_P(json, BufferSize, HADISCOVER_JSON,
|
||||
snprintf_P(json, BUF_SIZE_COMMON, HADISCOVER_JSON,
|
||||
sensorNamePrefix.c_str(),
|
||||
sensor.name,
|
||||
mqttConfig.publishTopic, sensor.topic,
|
||||
@@ -805,7 +813,7 @@ bool HomeAssistantMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
if(strlen(mqttConfig.publishTopic) == 0 || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
if(length <= 0 || length > BufferSize) return false;
|
||||
if(length <= 0 || length > BUF_SIZE_COMMON) return false;
|
||||
|
||||
if(!dInit) {
|
||||
// Not sure how this sensor should be defined in HA, so skipping for now
|
||||
@@ -815,7 +823,7 @@ bool HomeAssistantMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
|
||||
String str = toHex(raw, length);
|
||||
|
||||
snprintf_P(json, BufferSize, PSTR("{\"data\":\"%s\"}"), str.c_str());
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"data\":\"%s\"}"), str.c_str());
|
||||
char topic[192];
|
||||
snprintf_P(topic, 192, PSTR("%s/data"), mqttConfig.publishTopic);
|
||||
bool ret = mqtt.publish(topic, json);
|
||||
@@ -825,23 +833,24 @@ bool HomeAssistantMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
|
||||
bool HomeAssistantMqttHandler::publishFirmware() {
|
||||
if(!fInit) {
|
||||
snprintf_P(json, BufferSize, PSTR("{\"name\":\"%sFirmware\",\"stat_t\":\"%s/firmware\",\"uniq_id\":\"%s_fwupgrade\",\"dev_cla\":\"firmware\",\"cmd_t\":\"%s\",\"pl_inst\":\"fwupgrade\"}"),
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"name\":\"%sFirmware\",\"stat_t\":\"%s/firmware\",\"uniq_id\":\"%s_fwupgrade\",\"dev_cla\":\"firmware\",\"cmd_t\":\"%s\",\"pl_inst\":\"fwupgrade\"}"),
|
||||
sensorNamePrefix.c_str(),
|
||||
pubTopic.c_str(),
|
||||
pubTopic,
|
||||
deviceUid.c_str(),
|
||||
subTopic.c_str()
|
||||
subTopic
|
||||
);
|
||||
fInit = mqtt.publish(updateTopic + "/" + deviceUid + "/config", json, true, 0);
|
||||
loop();
|
||||
return fInit;
|
||||
}
|
||||
snprintf_P(json, BufferSize, PSTR("{\"installed_version\":\"%s\",\"latest_version\":\"%s\",\"title\":\"amsreader firmware\",\"release_url\":\"https://github.com/UtilitechAS/amsreader-firmware/releases\",\"release_summary\":\"New version %s is available\",\"update_percentage\":%s}"),
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"installed_version\":\"%s\",\"latest_version\":\"%s\",\"title\":\"amsreader firmware\",\"release_url\":\"https://github.com/UtilitechAS/amsreader-firmware/releases\",\"release_summary\":\"New version %s is available\",\"update_percentage\":%s}"),
|
||||
FirmwareVersion::VersionString,
|
||||
strlen(updater->getNextVersion()) == 0 ? FirmwareVersion::VersionString : updater->getNextVersion(),
|
||||
strlen(updater->getNextVersion()) == 0 ? FirmwareVersion::VersionString : updater->getNextVersion(),
|
||||
updater->getProgress() < 0 ? "null" : String(updater->getProgress(), 0)
|
||||
);
|
||||
bool ret = mqtt.publish(pubTopic + "/firmware", json);
|
||||
char _t[72]; snprintf(_t, sizeof(_t), "%s/firmware", pubTopic);
|
||||
bool ret = mqtt.publish(_t, json);
|
||||
loop();
|
||||
return ret;
|
||||
}
|
||||
@@ -858,7 +867,7 @@ void HomeAssistantMqttHandler::onMessage(String &topic, String &payload) {
|
||||
priceImportInit = 0;
|
||||
priceExportInit = 0;
|
||||
}
|
||||
} else if(topic.equals(subTopic)) {
|
||||
} else if(topic == subTopic) {
|
||||
if(payload.equals("fwupgrade")) {
|
||||
if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) {
|
||||
updater->setTargetVersion(updater->getNextVersion());
|
||||
|
||||
@@ -8,9 +8,18 @@
|
||||
#define _JSONMQTTHANDLER_H
|
||||
|
||||
#include "AmsMqttHandler.h"
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
class JsonMqttHandler : public AmsMqttHandler {
|
||||
public:
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
JsonMqttHandler(AmsConfiguration* config, RemoteDebug* debugger, char* buf, HwTools* hw, AmsDataStorage* ds, AmsFirmwareUpdater* updater) : AmsMqttHandler(config, debugger, buf, updater) {
|
||||
#else
|
||||
JsonMqttHandler(AmsConfiguration* config, Stream* debugger, char* buf, HwTools* hw, AmsDataStorage* ds, AmsFirmwareUpdater* updater) : AmsMqttHandler(config, debugger, buf, updater) {
|
||||
#endif
|
||||
this->hw = hw;
|
||||
this->ds = ds;
|
||||
};
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
JsonMqttHandler(MqttConfig& mqttConfig, RemoteDebug* debugger, char* buf, HwTools* hw, AmsDataStorage* ds, AmsFirmwareUpdater* updater) : AmsMqttHandler(mqttConfig, debugger, buf, updater) {
|
||||
#else
|
||||
@@ -43,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
|
||||
|
||||
@@ -19,7 +19,7 @@ bool JsonMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAcc
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
memset(json, 0, BufferSize);
|
||||
memset(json, 0, BUF_SIZE_COMMON);
|
||||
|
||||
AmsData data;
|
||||
if(mqttConfig.stateUpdate) {
|
||||
@@ -59,7 +59,7 @@ bool JsonMqttHandler::publish(AmsData* update, AmsData* previousState, EnergyAcc
|
||||
}
|
||||
|
||||
uint16_t JsonMqttHandler::appendJsonHeader(AmsData* data) {
|
||||
return snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%u,\"t\":%lu,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,"),
|
||||
return snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%u,\"t\":%lu,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,"),
|
||||
WiFi.macAddress().c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
@@ -86,7 +86,7 @@ uint16_t JsonMqttHandler::appendJsonFooter(EnergyAccounting* ea, uint16_t pos) {
|
||||
peaks += String(ea->getPeak(i).value / 100.0, 2);
|
||||
}
|
||||
|
||||
return snprintf_P(json+pos, BufferSize-pos, PSTR("%s\"%sh\":%.3f,\"%sd\":%.2f,\"%sm\":%.1f,\"%st\":%d,\"%sx\":%.2f,\"%she\":%.3f,\"%sde\":%.2f,\"%sme\":%.1f,\"peaks\":[%s]%s"),
|
||||
return snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("%s\"%sh\":%.3f,\"%sd\":%.2f,\"%sm\":%.1f,\"%st\":%d,\"%sx\":%.2f,\"%she\":%.3f,\"%sde\":%.2f,\"%sme\":%.1f,\"peaks\":[%s]%s"),
|
||||
strlen(pf) == 0 ? "},\"realtime\":{" : ",",
|
||||
pf,
|
||||
ea->getUseThisHour(),
|
||||
@@ -112,9 +112,9 @@ uint16_t JsonMqttHandler::appendJsonFooter(EnergyAccounting* ea, uint16_t pos) {
|
||||
bool JsonMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea) {
|
||||
uint16_t pos = appendJsonHeader(data);
|
||||
if(mqttConfig.payloadFormat != 6) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"data\":{"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"data\":{"));
|
||||
}
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"P\":%d"), data->getActiveImportPower());
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"P\":%d"), data->getActiveImportPower());
|
||||
pos += appendJsonFooter(ea, pos);
|
||||
json[pos++] = '}';
|
||||
json[pos] = '\0';
|
||||
@@ -130,9 +130,9 @@ bool JsonMqttHandler::publishList1(AmsData* data, EnergyAccounting* ea) {
|
||||
bool JsonMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
uint16_t pos = appendJsonHeader(data);
|
||||
if(mqttConfig.payloadFormat != 6) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"data\":{"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"data\":{"));
|
||||
}
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"Q\":%d,\"PO\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"Q\":%d,\"PO\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f"),
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
getMeterModel(data).c_str(),
|
||||
@@ -162,9 +162,9 @@ bool JsonMqttHandler::publishList2(AmsData* data, EnergyAccounting* ea) {
|
||||
bool JsonMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
uint16_t pos = appendJsonHeader(data);
|
||||
if(mqttConfig.payloadFormat != 6) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"data\":{"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"data\":{"));
|
||||
}
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"Q\":%d,\"PO\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f,\"tPI\":%.3f,\"tPO\":%.3f,\"tQI\":%.3f,\"tQO\":%.3f,\"rtc\":%lu"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"Q\":%d,\"PO\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f,\"tPI\":%.3f,\"tPO\":%.3f,\"tQI\":%.3f,\"tQO\":%.3f,\"rtc\":%lu"),
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
getMeterModel(data).c_str(),
|
||||
@@ -199,9 +199,9 @@ bool JsonMqttHandler::publishList3(AmsData* data, EnergyAccounting* ea) {
|
||||
bool JsonMqttHandler::publishList4(AmsData* data, EnergyAccounting* ea) {
|
||||
uint16_t pos = appendJsonHeader(data);
|
||||
if(mqttConfig.payloadFormat != 6) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"data\":{"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"data\":{"));
|
||||
}
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"P1\":%d,\"P2\":%d,\"P3\":%d,\"Q\":%d,\"PO\":%d,\"PO1\":%d,\"PO2\":%d,\"PO3\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f,\"PF\":%.2f,\"PF1\":%.2f,\"PF2\":%.2f,\"PF3\":%.2f,\"tPI\":%.3f,\"tPO\":%.3f,\"tQI\":%.3f,\"tQO\":%.3f,\"tPI1\":%.3f,\"tPI2\":%.3f,\"tPI3\":%.3f,\"tPO1\":%.3f,\"tPO2\":%.3f,\"tPO3\":%.3f,\"rtc\":%lu"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"lv\":\"%s\",\"meterId\":\"%s\",\"type\":\"%s\",\"P\":%d,\"P1\":%d,\"P2\":%d,\"P3\":%d,\"Q\":%d,\"PO\":%d,\"PO1\":%d,\"PO2\":%d,\"PO3\":%d,\"QO\":%d,\"I1\":%.2f,\"I2\":%.2f,\"I3\":%.2f,\"U1\":%.2f,\"U2\":%.2f,\"U3\":%.2f,\"PF\":%.2f,\"PF1\":%.2f,\"PF2\":%.2f,\"PF3\":%.2f,\"tPI\":%.3f,\"tPO\":%.3f,\"tQI\":%.3f,\"tQO\":%.3f,\"tPI1\":%.3f,\"tPI2\":%.3f,\"tPI3\":%.3f,\"tPO1\":%.3f,\"tPO2\":%.3f,\"tPO3\":%.3f,\"rtc\":%lu"),
|
||||
data->getListId().c_str(),
|
||||
data->getMeterId().c_str(),
|
||||
getMeterModel(data).c_str(),
|
||||
@@ -387,17 +387,17 @@ bool JsonMqttHandler::publishPrices(PriceService* ps) {
|
||||
}
|
||||
|
||||
if(mqttConfig.payloadFormat == 6) {
|
||||
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\","), WiFi.macAddress().c_str());
|
||||
uint16_t pos = snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\","), WiFi.macAddress().c_str());
|
||||
|
||||
for(uint8_t i = 0;i < 38; i++) {
|
||||
if(values[i] == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"pr_%d\":null,"), i);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"pr_%d\":null,"), i);
|
||||
} else {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"pr_%d\":%.4f,"), i, values[i]);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"pr_%d\":%.4f,"), i, values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("\"pr_min\":%.4f,\"pr_max\":%.4f,\"pr_cheapest1hr\":%s,\"pr_cheapest3hr\":%s,\"pr_cheapest6hr\":%s}"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("\"pr_min\":%.4f,\"pr_max\":%.4f,\"pr_cheapest1hr\":%s,\"pr_cheapest3hr\":%s,\"pr_cheapest6hr\":%s}"),
|
||||
min == INT16_MAX ? 0.0 : min,
|
||||
max == INT16_MIN ? 0.0 : max,
|
||||
ts1hr,
|
||||
@@ -405,33 +405,33 @@ bool JsonMqttHandler::publishPrices(PriceService* ps) {
|
||||
ts6hr
|
||||
);
|
||||
} else {
|
||||
uint16_t pos = snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
||||
uint16_t pos = snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\",\"prices\":{\"import\":["), WiFi.macAddress().c_str());
|
||||
|
||||
uint8_t currentPricePointIndex = ps->getCurrentPricePointIndex();
|
||||
uint8_t numberOfPoints = ps->getNumberOfPointsAvailable();
|
||||
for(int i = currentPricePointIndex; i < numberOfPoints; i++) {
|
||||
float val = ps->getPricePoint(PRICE_DIRECTION_IMPORT, i);
|
||||
if(val == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("null,"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("null,"));
|
||||
} else {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("%.4f,"), val);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("%.4f,"), val);
|
||||
}
|
||||
}
|
||||
if(hasExport && ps->isExportPricesDifferentFromImport()) {
|
||||
pos--;
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"export\":["));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("],\"export\":["));
|
||||
for(int i = currentPricePointIndex; i < numberOfPoints; i++) {
|
||||
float val = ps->getPricePoint(PRICE_DIRECTION_EXPORT, i);
|
||||
if(val == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("null,"));
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("null,"));
|
||||
} else {
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("%.4f,"), val);
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("%.4f,"), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos--;
|
||||
pos += snprintf_P(json+pos, BufferSize-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":%s,\"cheapest3hr\":%s,\"cheapest6hr\":%s}}"),
|
||||
pos += snprintf_P(json+pos, BUF_SIZE_COMMON-pos, PSTR("],\"min\":%.4f,\"max\":%.4f,\"cheapest1hr\":%s,\"cheapest3hr\":%s,\"cheapest6hr\":%s}}"),
|
||||
min == INT16_MAX ? 0.0 : min,
|
||||
max == INT16_MIN ? 0.0 : max,
|
||||
ts1hr,
|
||||
@@ -456,7 +456,7 @@ bool JsonMqttHandler::publishSystem(HwTools* hw, PriceService* ps, EnergyAccount
|
||||
if(strlen(mqttConfig.publishTopic) == 0 || !connected())
|
||||
return false;
|
||||
|
||||
snprintf_P(json, BufferSize, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\"}"),
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"id\":\"%s\",\"name\":\"%s\",\"up\":%d,\"vcc\":%.3f,\"rssi\":%d,\"temp\":%.2f,\"version\":\"%s\"}"),
|
||||
WiFi.macAddress().c_str(),
|
||||
mqttConfig.clientId,
|
||||
(uint32_t) (millis64()/1000),
|
||||
@@ -485,11 +485,11 @@ bool JsonMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
if(strlen(mqttConfig.publishTopic) == 0 || !mqtt.connected())
|
||||
return false;
|
||||
|
||||
if(length <= 0 || length > BufferSize) return false;
|
||||
if(length <= 0 || length > BUF_SIZE_COMMON) return false;
|
||||
|
||||
String str = toHex(raw, length);
|
||||
|
||||
snprintf_P(json, BufferSize, PSTR("{\"data\":\"%s\"}"), str.c_str());
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"data\":\"%s\"}"), str.c_str());
|
||||
char topic[192];
|
||||
snprintf_P(topic, 192, PSTR("%s/data"), mqttConfig.publishTopic);
|
||||
bool ret = mqtt.publish(topic, json);
|
||||
@@ -498,7 +498,7 @@ bool JsonMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
}
|
||||
|
||||
bool JsonMqttHandler::publishFirmware() {
|
||||
snprintf_P(json, BufferSize, PSTR("{\"installed_version\":\"%s\",\"latest_version\":\"%s\",\"title\":\"amsreader firmware\",\"release_url\":\"https://github.com/UtilitechAS/amsreader-firmware/releases\",\"release_summary\":\"New version %s is available\",\"update_percentage\":%s}"),
|
||||
snprintf_P(json, BUF_SIZE_COMMON, PSTR("{\"installed_version\":\"%s\",\"latest_version\":\"%s\",\"title\":\"amsreader firmware\",\"release_url\":\"https://github.com/UtilitechAS/amsreader-firmware/releases\",\"release_summary\":\"New version %s is available\",\"update_percentage\":%s}"),
|
||||
FirmwareVersion::VersionString,
|
||||
strlen(updater->getNextVersion()) == 0 ? FirmwareVersion::VersionString : updater->getNextVersion(),
|
||||
strlen(updater->getNextVersion()) == 0 ? FirmwareVersion::VersionString : updater->getNextVersion(),
|
||||
@@ -520,31 +520,624 @@ void JsonMqttHandler::onMessage(String &topic, String &payload) {
|
||||
#endif
|
||||
debugger->printf_P(PSTR("Received command [%s] to [%s]\n"), payload.c_str(), topic.c_str());
|
||||
|
||||
if(topic.equals(subTopic)) {
|
||||
if(topic == subTopic) {
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
if (debugger->isActive(RemoteDebug::DEBUG))
|
||||
#endif
|
||||
debugger->printf_P(PSTR(" - this is our subscribed topic\n"));
|
||||
if(payload.equals("fwupgrade")) {
|
||||
|
||||
if(payload.startsWith("{")) {
|
||||
DynamicJsonDocument doc(512);
|
||||
DeserializationError error = deserializeJson(doc, payload);
|
||||
if(error) {
|
||||
#if defined(AMS_REMOTE_DEBUG)
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR(" - failed to parse JSON: %s\n"), error.c_str());
|
||||
return;
|
||||
} else {
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
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_P(action, PSTR("dayplot")) == 0) {
|
||||
char pubTopic[192];
|
||||
snprintf_P(pubTopic, 192, PSTR("%s/dayplot"), mqttConfig.publishTopic);
|
||||
AmsJsonGenerator::generateDayPlotJson(ds, json, BUF_SIZE_COMMON);
|
||||
bool ret = mqtt.publish(pubTopic, json);
|
||||
loop();
|
||||
} else if(strcmp_P(action, PSTR("monthplot")) == 0) {
|
||||
char pubTopic[192];
|
||||
snprintf_P(pubTopic, 192, PSTR("%s/monthplot"), mqttConfig.publishTopic);
|
||||
AmsJsonGenerator::generateMonthPlotJson(ds, json, BUF_SIZE_COMMON);
|
||||
bool ret = mqtt.publish(pubTopic, json);
|
||||
loop();
|
||||
#if defined(ESP32)
|
||||
} else if(strcmp_P(action, PSTR("getconfig")) == 0) {
|
||||
char pubTopic[192];
|
||||
snprintf_P(pubTopic, 192, PSTR("%s/config"), mqttConfig.publishTopic);
|
||||
AmsJsonGenerator::generateConfigurationJson(config, json, BUF_SIZE_COMMON);
|
||||
bool ret = mqtt.publish(pubTopic, json);
|
||||
loop();
|
||||
} else if(strcmp_P(action, PSTR("setconfig")) == 0 && obj.containsKey(F("config"))) {
|
||||
JsonObject configObj = obj[F("config")];
|
||||
handleConfigMessage(configObj);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
AmsJsonGenerator::generateDayPlotJson(ds, json, BUF_SIZE_COMMON);
|
||||
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);
|
||||
AmsJsonGenerator::generateMonthPlotJson(ds, json, BUF_SIZE_COMMON);
|
||||
bool ret = mqtt.publish(pubTopic, json);
|
||||
loop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
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));
|
||||
}
|
||||
// Check if password is provided and that it is not empty and is not equal *** (which is used in the UI to indicate that the password is set but not shown)
|
||||
if(generalObj.containsKey(F("p")) && strlen(generalObj[F("p")]) > 0 && strcmp(generalObj[F("p")], "***") != 0) {
|
||||
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"))) {
|
||||
newConfig.parity = meterObj[F("p")];
|
||||
}
|
||||
if(meterObj.containsKey(F("i"))) {
|
||||
newConfig.invert = meterObj[F("i")];
|
||||
}
|
||||
if(meterObj.containsKey(F("s"))) {
|
||||
newConfig.bufferSize = (int) 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"))) {
|
||||
String encryptionKeyHex = encryptionObj[F("k")];
|
||||
if(encryptionKeyHex.length() == 16) {
|
||||
fromHex(newConfig.encryptionKey, encryptionKeyHex, 16);
|
||||
}
|
||||
}
|
||||
if(encryptionObj.containsKey(F("a"))) {
|
||||
String authenticationKeyHex = encryptionObj[F("a")];
|
||||
if(authenticationKeyHex.length() == 16) {
|
||||
fromHex(newConfig.authenticationKey, authenticationKeyHex, 16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(newConfig.encryptionKey, 0, sizeof(newConfig.encryptionKey));
|
||||
memset(newConfig.authenticationKey, 0, sizeof(newConfig.authenticationKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(meterObj.containsKey(F("m"))) {
|
||||
JsonObject multipliersObj = meterObj[F("m")];
|
||||
bool enabled = multipliersObj[F("e")];
|
||||
if(enabled) {
|
||||
if(multipliersObj.containsKey(F("w"))) {
|
||||
newConfig.wattageMultiplier = multipliersObj[F("w")];
|
||||
}
|
||||
if(multipliersObj.containsKey(F("v"))) {
|
||||
newConfig.voltageMultiplier = multipliersObj[F("v")];
|
||||
}
|
||||
if(multipliersObj.containsKey(F("a"))) {
|
||||
newConfig.amperageMultiplier = multipliersObj[F("a")];
|
||||
}
|
||||
if(multipliersObj.containsKey(F("c"))) {
|
||||
newConfig.accumulatedMultiplier = multipliersObj[F("c")];
|
||||
}
|
||||
} else {
|
||||
newConfig.wattageMultiplier = 1.0;
|
||||
newConfig.voltageMultiplier = 1.0;
|
||||
newConfig.amperageMultiplier = 1.0;
|
||||
newConfig.accumulatedMultiplier = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
config->setMeterConfig(newConfig);
|
||||
}
|
||||
|
||||
// Network
|
||||
if(configObj.containsKey(F("n"))) {
|
||||
NetworkConfig newConfig;
|
||||
config->getNetworkConfig(newConfig);
|
||||
|
||||
JsonObject networkObj = configObj[F("n")];
|
||||
if(networkObj.containsKey(F("c"))) {
|
||||
newConfig.mode = networkObj[F("c")];
|
||||
}
|
||||
if(networkObj.containsKey(F("m"))) {
|
||||
if(strcmp_P(networkObj[F("m")], PSTR("dhcp")) == 0) {
|
||||
newConfig.mode = 1;
|
||||
} else if(strcmp_P(networkObj[F("m")], PSTR("static")) == 0) {
|
||||
newConfig.mode = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if(networkObj.containsKey(F("i"))) {
|
||||
strlcpy(newConfig.ip, networkObj[F("i")], sizeof(newConfig.ip));
|
||||
}
|
||||
if(networkObj.containsKey(F("s"))) {
|
||||
strlcpy(newConfig.subnet, networkObj[F("s")], sizeof(newConfig.subnet));
|
||||
}
|
||||
if(networkObj.containsKey(F("g"))) {
|
||||
strlcpy(newConfig.gateway, networkObj[F("g")], sizeof(newConfig.gateway));
|
||||
}
|
||||
if(networkObj.containsKey(F("d1"))) {
|
||||
strlcpy(newConfig.dns1, networkObj[F("d1")], sizeof(newConfig.dns1));
|
||||
}
|
||||
if(networkObj.containsKey(F("d2"))) {
|
||||
strlcpy(newConfig.dns2, networkObj[F("d2")], sizeof(newConfig.dns2));
|
||||
}
|
||||
if(networkObj.containsKey(F("d"))) {
|
||||
newConfig.mdns = networkObj[F("d")];
|
||||
}
|
||||
if(networkObj.containsKey(F("x"))) {
|
||||
newConfig.ipv6 = networkObj[F("x")];
|
||||
}
|
||||
config->setNetworkConfig(newConfig);
|
||||
|
||||
NtpConfig ntpConfig;
|
||||
config->getNtpConfig(ntpConfig);
|
||||
if(networkObj.containsKey(F("n1"))) {
|
||||
strlcpy(ntpConfig.server, networkObj[F("n1")], sizeof(ntpConfig.server));
|
||||
config->setNtpConfig(ntpConfig);
|
||||
}
|
||||
if(networkObj.containsKey(F("h"))) {
|
||||
ntpConfig.dhcp = networkObj[F("h")];
|
||||
config->setNtpConfig(ntpConfig);
|
||||
}
|
||||
config->getNtpConfig(ntpConfig);
|
||||
}
|
||||
|
||||
// WiFi
|
||||
if(configObj.containsKey(F("w"))) {
|
||||
NetworkConfig newConfig;
|
||||
config->getNetworkConfig(newConfig);
|
||||
|
||||
if(newConfig.mode == 1 || newConfig.mode == 2) {
|
||||
JsonObject wifiObj = configObj[F("w")];
|
||||
if(wifiObj.containsKey(F("s"))) {
|
||||
strlcpy(newConfig.ssid, wifiObj[F("s")], sizeof(newConfig.ssid));
|
||||
}
|
||||
// Check if PSK is provided and that it is not empty and is not equal *** (which is used in the UI to indicate that the password is set but not shown)
|
||||
if(wifiObj.containsKey(F("p")) && strlen(wifiObj[F("p")]) > 0 && strcmp(wifiObj[F("p")], "***") != 0) {
|
||||
strlcpy(newConfig.psk, wifiObj[F("p")], sizeof(newConfig.psk));
|
||||
}
|
||||
if(wifiObj.containsKey(F("w"))) {
|
||||
newConfig.power = wifiObj[F("w")];
|
||||
}
|
||||
if(wifiObj.containsKey(F("z"))) {
|
||||
newConfig.sleep = wifiObj[F("z")];
|
||||
}
|
||||
if(wifiObj.containsKey(F("b"))) {
|
||||
newConfig.use11b = wifiObj[F("b")];
|
||||
}
|
||||
config->setNetworkConfig(newConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// MQTT
|
||||
if(configObj.containsKey(F("q"))) {
|
||||
JsonObject mqttObj = configObj[F("q")];
|
||||
MqttConfig newConfig;
|
||||
config->getMqttConfig(newConfig);
|
||||
if(mqttObj.containsKey(F("p"))) {
|
||||
newConfig.port = mqttObj[F("p")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("u"))) {
|
||||
strlcpy(newConfig.username, mqttObj[F("u")], sizeof(newConfig.username));
|
||||
}
|
||||
// Check if password is provided and that it is not empty and is not equal *** (which is used in the UI to indicate that the password is set but not shown)
|
||||
if(mqttObj.containsKey(F("a")) && strlen(mqttObj[F("a")]) > 0 && strcmp(mqttObj[F("a")], "***") != 0) {
|
||||
strlcpy(newConfig.password, mqttObj[F("a")], sizeof(newConfig.password));
|
||||
}
|
||||
if(mqttObj.containsKey(F("c"))) {
|
||||
strlcpy(newConfig.clientId, mqttObj[F("c")], sizeof(newConfig.clientId));
|
||||
}
|
||||
if(mqttObj.containsKey(F("b"))) {
|
||||
strlcpy(newConfig.publishTopic, mqttObj[F("b")], sizeof(newConfig.publishTopic));
|
||||
}
|
||||
if(mqttObj.containsKey(F("r"))) {
|
||||
strlcpy(newConfig.subscribeTopic, mqttObj[F("r")], sizeof(newConfig.subscribeTopic));
|
||||
}
|
||||
if(mqttObj.containsKey(F("m"))) {
|
||||
newConfig.payloadFormat = mqttObj[F("m")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("t"))) {
|
||||
newConfig.stateUpdate = mqttObj[F("s")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("d"))) {
|
||||
newConfig.stateUpdateInterval = mqttObj[F("d")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("i"))) {
|
||||
newConfig.timeout = mqttObj[F("i")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("k"))) {
|
||||
newConfig.keepalive = mqttObj[F("k")];
|
||||
}
|
||||
if(mqttObj.containsKey(F("e"))) {
|
||||
newConfig.rebootMinutes = mqttObj[F("e")];
|
||||
}
|
||||
config->setMqttConfig(newConfig);
|
||||
|
||||
if(newConfig.payloadFormat == 3) { // Domiticz
|
||||
if(configObj.containsKey(F("o"))) {
|
||||
JsonObject domoticzObj = configObj[F("o")];
|
||||
DomoticzConfig domoticzConfig;
|
||||
config->getDomoticzConfig(domoticzConfig);
|
||||
if(domoticzObj.containsKey(F("e"))) {
|
||||
domoticzConfig.elidx = domoticzObj[F("e")];
|
||||
}
|
||||
if(domoticzObj.containsKey(F("c"))) {
|
||||
domoticzConfig.cl1idx = domoticzObj[F("c")];
|
||||
}
|
||||
if(domoticzObj.containsKey(F("u1"))) {
|
||||
domoticzConfig.vl1idx = domoticzObj[F("u1")];
|
||||
}
|
||||
if(domoticzObj.containsKey(F("u2"))) {
|
||||
domoticzConfig.vl2idx = domoticzObj[F("u2")];
|
||||
}
|
||||
if(domoticzObj.containsKey(F("u3"))) {
|
||||
domoticzConfig.vl3idx = domoticzObj[F("u3")];
|
||||
}
|
||||
config->setDomoticzConfig(domoticzConfig);
|
||||
}
|
||||
} else if(newConfig.payloadFormat == 4) { // Home Assistant
|
||||
if(configObj.containsKey(F("h"))) {
|
||||
JsonObject haObj = configObj[F("h")];
|
||||
HomeAssistantConfig haConfig;
|
||||
config->getHomeAssistantConfig(haConfig);
|
||||
if(haObj.containsKey(F("t"))) {
|
||||
strlcpy(haConfig.discoveryPrefix, haObj[F("t")], sizeof(haConfig.discoveryPrefix));
|
||||
}
|
||||
if(haObj.containsKey(F("h"))) {
|
||||
strlcpy(haConfig.discoveryHostname, haObj[F("h")], sizeof(haConfig.discoveryHostname));
|
||||
}
|
||||
if(haObj.containsKey(F("n"))) {
|
||||
strlcpy(haConfig.discoveryNameTag, haObj[F("n")], sizeof(haConfig.discoveryNameTag));
|
||||
}
|
||||
config->setHomeAssistantConfig(haConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Price service
|
||||
if(configObj.containsKey(F("p"))) {
|
||||
PriceServiceConfig newConfig;
|
||||
config->getPriceServiceConfig(newConfig);
|
||||
JsonObject priceServiceObj = configObj[F("p")];
|
||||
if(priceServiceObj.containsKey(F("e"))) {
|
||||
newConfig.enabled = priceServiceObj[F("e")];
|
||||
}
|
||||
if(priceServiceObj.containsKey(F("r"))) {
|
||||
strlcpy(newConfig.area, priceServiceObj[F("r")], sizeof(newConfig.area));
|
||||
}
|
||||
if(priceServiceObj.containsKey(F("c"))) {
|
||||
strlcpy(newConfig.currency, priceServiceObj[F("c")], sizeof(newConfig.currency));
|
||||
}
|
||||
if(priceServiceObj.containsKey(F("m"))) {
|
||||
newConfig.resolutionInMinutes = priceServiceObj[F("m")];
|
||||
}
|
||||
config->setPriceServiceConfig(newConfig);
|
||||
}
|
||||
|
||||
// Thresholds
|
||||
if(configObj.containsKey(F("t"))) {
|
||||
EnergyAccountingConfig newConfig;
|
||||
config->getEnergyAccountingConfig(newConfig);
|
||||
JsonObject thresholdObj = configObj[F("t")];
|
||||
if(thresholdObj.containsKey(F("h"))) {
|
||||
newConfig.hours = thresholdObj[F("h")];
|
||||
}
|
||||
if(thresholdObj.containsKey(F("t"))) {
|
||||
JsonArray thresholdsArray = thresholdObj[F("t")].as<JsonArray>();
|
||||
for(size_t i = 0; i < thresholdsArray.size(); i++) {
|
||||
newConfig.thresholds[i] = thresholdsArray[i];
|
||||
}
|
||||
}
|
||||
config->setEnergyAccountingConfig(newConfig);
|
||||
}
|
||||
|
||||
// Debug
|
||||
if(configObj.containsKey(F("d"))) {
|
||||
DebugConfig newConfig;
|
||||
config->getDebugConfig(newConfig);
|
||||
|
||||
JsonObject debugObj = configObj[F("d")];
|
||||
if(debugObj.containsKey(F("s"))) {
|
||||
newConfig.serial = debugObj[F("s")];
|
||||
}
|
||||
if(debugObj.containsKey(F("t"))) {
|
||||
newConfig.telnet = debugObj[F("t")];
|
||||
}
|
||||
if(debugObj.containsKey(F("l"))) {
|
||||
newConfig.level = debugObj[F("l")];
|
||||
}
|
||||
config->setDebugConfig(newConfig);
|
||||
}
|
||||
|
||||
// Cloud
|
||||
if(configObj.containsKey(F("c"))) {
|
||||
CloudConfig newConfig;
|
||||
config->getCloudConfig(newConfig);
|
||||
|
||||
JsonObject cloudObj = configObj[F("c")];
|
||||
if(cloudObj.containsKey(F("e"))) {
|
||||
newConfig.enabled = cloudObj[F("e")];
|
||||
}
|
||||
if(cloudObj.containsKey(F("p"))) {
|
||||
newConfig.proto = cloudObj[F("p")];
|
||||
}
|
||||
config->setCloudConfig(newConfig);
|
||||
|
||||
if(cloudObj.containsKey(F("es"))) {
|
||||
SystemConfig sysConfig;
|
||||
config->getSystemConfig(sysConfig);
|
||||
sysConfig.energyspeedometer = cloudObj[F("es")];
|
||||
config->setSystemConfig(sysConfig);
|
||||
}
|
||||
if(cloudObj.containsKey(F("ze"))) {
|
||||
ZmartChargeConfig zmartConfig;
|
||||
config->getZmartChargeConfig(zmartConfig);
|
||||
zmartConfig.enabled = cloudObj[F("ze")];
|
||||
if(cloudObj.containsKey(F("zt"))) {
|
||||
strlcpy(zmartConfig.token, cloudObj[F("zt")], sizeof(zmartConfig.token));
|
||||
}
|
||||
if(cloudObj.containsKey(F("zu"))) {
|
||||
strlcpy(zmartConfig.baseUrl, cloudObj[F("zu")], sizeof(zmartConfig.baseUrl));
|
||||
}
|
||||
config->setZmartChargeConfig(zmartConfig);
|
||||
}
|
||||
}
|
||||
|
||||
// UI
|
||||
if(configObj.containsKey(F("u"))) {
|
||||
UiConfig newConfig;
|
||||
config->getUiConfig(newConfig);
|
||||
JsonObject uiObj = configObj[F("u")];
|
||||
if(uiObj.containsKey(F("i"))) {
|
||||
newConfig.showImport = uiObj[F("i")];
|
||||
}
|
||||
if(uiObj.containsKey(F("e"))) {
|
||||
newConfig.showExport = uiObj[F("e")];
|
||||
}
|
||||
if(uiObj.containsKey(F("v"))) {
|
||||
newConfig.showVoltage = uiObj[F("v")];
|
||||
}
|
||||
if(uiObj.containsKey(F("a"))) {
|
||||
newConfig.showAmperage = uiObj[F("a")];
|
||||
}
|
||||
if(uiObj.containsKey(F("r"))) {
|
||||
newConfig.showReactive = uiObj[F("r")];
|
||||
}
|
||||
if(uiObj.containsKey(F("c"))) {
|
||||
newConfig.showRealtime = uiObj[F("c")];
|
||||
}
|
||||
if(uiObj.containsKey(F("t"))) {
|
||||
newConfig.showPeaks = uiObj[F("t")];
|
||||
}
|
||||
if(uiObj.containsKey(F("p"))) {
|
||||
newConfig.showPricePlot = uiObj[F("p")];
|
||||
}
|
||||
if(uiObj.containsKey(F("d"))) {
|
||||
newConfig.showDayPlot = uiObj[F("d")];
|
||||
}
|
||||
if(uiObj.containsKey(F("m"))) {
|
||||
newConfig.showMonthPlot = uiObj[F("m")];
|
||||
}
|
||||
if(uiObj.containsKey(F("s"))) {
|
||||
newConfig.showTemperaturePlot = uiObj[F("s")];
|
||||
}
|
||||
if(uiObj.containsKey(F("l"))) {
|
||||
newConfig.showRealtimePlot = uiObj[F("l")];
|
||||
}
|
||||
if(uiObj.containsKey(F("h"))) {
|
||||
newConfig.showPerPhasePower = uiObj[F("h")];
|
||||
}
|
||||
if(uiObj.containsKey(F("f"))) {
|
||||
newConfig.showPowerFactor = uiObj[F("f")];
|
||||
}
|
||||
if(uiObj.containsKey(F("k"))) {
|
||||
newConfig.darkMode = uiObj[F("k")];
|
||||
}
|
||||
if(uiObj.containsKey(F("lang"))) {
|
||||
strlcpy(newConfig.language, uiObj[F("lang")], sizeof(newConfig.language));
|
||||
}
|
||||
config->setUiConfig(newConfig);
|
||||
}
|
||||
|
||||
// System
|
||||
if(configObj.containsKey(F("s"))) {
|
||||
SystemConfig sysConfig;
|
||||
config->getSystemConfig(sysConfig);
|
||||
JsonObject sysObj = configObj[F("s")];
|
||||
if(sysObj.containsKey(F("b"))) {
|
||||
sysConfig.boardType = sysObj[F("b")];
|
||||
}
|
||||
if(sysObj.containsKey(F("v"))) {
|
||||
sysConfig.vendorConfigured = sysObj[F("v")];
|
||||
}
|
||||
if(sysObj.containsKey(F("u"))) {
|
||||
sysConfig.userConfigured = sysObj[F("u")];
|
||||
}
|
||||
if(sysObj.containsKey(F("d"))) {
|
||||
sysConfig.dataCollectionConsent = sysObj[F("d")];
|
||||
}
|
||||
if(sysObj.containsKey(F("o"))) {
|
||||
strlcpy(sysConfig.country, sysObj[F("o")], sizeof(sysConfig.country));
|
||||
}
|
||||
if(sysObj.containsKey(F("c"))) {
|
||||
sysConfig.firmwareChannel = sysObj[F("c")];
|
||||
}
|
||||
config->setSystemConfig(sysConfig);
|
||||
}
|
||||
|
||||
// GPIO
|
||||
if(configObj.containsKey(F("i"))) {
|
||||
JsonObject gpioObj = configObj[F("i")];
|
||||
GpioConfig newConfig;
|
||||
config->getGpioConfig(newConfig);
|
||||
if(gpioObj.containsKey(F("a"))) {
|
||||
newConfig.apPin = gpioObj[F("a")];
|
||||
}
|
||||
if(gpioObj.containsKey(F("l"))) {
|
||||
JsonObject ledObj = gpioObj[F("l")];
|
||||
if(ledObj.containsKey(F("p"))) {
|
||||
newConfig.ledPin = ledObj[F("p")];
|
||||
}
|
||||
if(ledObj.containsKey(F("i"))) {
|
||||
newConfig.ledInverted = ledObj[F("i")];
|
||||
}
|
||||
}
|
||||
if(gpioObj.containsKey(F("r"))) {
|
||||
JsonObject rgbLedObj = gpioObj[F("r")];
|
||||
if(rgbLedObj.containsKey(F("r"))) {
|
||||
newConfig.ledPinRed = rgbLedObj[F("r")];
|
||||
}
|
||||
if(rgbLedObj.containsKey(F("g"))) {
|
||||
newConfig.ledPinGreen = rgbLedObj[F("g")];
|
||||
}
|
||||
if(rgbLedObj.containsKey(F("b"))) {
|
||||
newConfig.ledPinBlue = rgbLedObj[F("b")];
|
||||
}
|
||||
if(rgbLedObj.containsKey(F("i"))) {
|
||||
newConfig.ledRgbInverted = rgbLedObj[F("i")];
|
||||
}
|
||||
}
|
||||
if(gpioObj.containsKey(F("d"))) {
|
||||
JsonObject ledDisableObj = gpioObj[F("d")];
|
||||
if(ledDisableObj.containsKey(F("d"))) {
|
||||
newConfig.ledDisablePin = ledDisableObj[F("d")];
|
||||
}
|
||||
if(ledDisableObj.containsKey(F("b"))) {
|
||||
newConfig.ledBehaviour = ledDisableObj[F("b")];
|
||||
}
|
||||
}
|
||||
if(gpioObj.containsKey(F("t"))) {
|
||||
JsonObject tempSensorObj = gpioObj[F("t")];
|
||||
if(tempSensorObj.containsKey(F("d"))) {
|
||||
newConfig.tempSensorPin = tempSensorObj[F("d")];
|
||||
}
|
||||
if(tempSensorObj.containsKey(F("a"))) {
|
||||
newConfig.tempAnalogSensorPin = tempSensorObj[F("a")];
|
||||
}
|
||||
}
|
||||
if(gpioObj.containsKey(F("v"))) {
|
||||
JsonObject vccObj = gpioObj[F("v")];
|
||||
if(vccObj.containsKey(F("p"))) {
|
||||
newConfig.vccPin = vccObj[F("p")];
|
||||
}
|
||||
if(vccObj.containsKey(F("o"))) {
|
||||
newConfig.vccOffset = vccObj[F("o")];
|
||||
}
|
||||
if(vccObj.containsKey(F("m"))) {
|
||||
newConfig.vccMultiplier = vccObj[F("m")];
|
||||
}
|
||||
if(vccObj.containsKey(F("d"))) {
|
||||
JsonObject vccDividerObj = vccObj[F("d")];
|
||||
if(vccDividerObj.containsKey(F("v"))) {
|
||||
newConfig.vccResistorVcc = vccDividerObj[F("v")];
|
||||
}
|
||||
if(vccDividerObj.containsKey(F("g"))) {
|
||||
newConfig.vccResistorGnd = vccDividerObj[F("g")];
|
||||
}
|
||||
}
|
||||
}
|
||||
config->setGpioConfig(newConfig);
|
||||
|
||||
if(gpioObj.containsKey(F("h"))) {
|
||||
JsonObject hwObj = gpioObj[F("h")];
|
||||
MeterConfig meterConfig;
|
||||
config->getMeterConfig(meterConfig);
|
||||
if(hwObj.containsKey(F("p"))) {
|
||||
meterConfig.rxPin = hwObj[F("p")];
|
||||
}
|
||||
if(hwObj.containsKey(F("u"))) {
|
||||
meterConfig.rxPinPullup = hwObj[F("u")];
|
||||
}
|
||||
if(hwObj.containsKey(F("t"))) {
|
||||
meterConfig.txPin = hwObj[F("t")];
|
||||
}
|
||||
config->setMeterConfig(meterConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void JsonMqttHandler::toJsonIsoTimestamp(time_t t, char* buf, size_t buflen) {
|
||||
memset(buf, 0, buflen);
|
||||
if(t > 0) {
|
||||
|
||||
@@ -16,50 +16,53 @@ IEC6205621::IEC6205621(const char* p, Timezone* tz, MeterConfig* meterConfig) {
|
||||
String payload(p+1);
|
||||
|
||||
lastUpdateMillis = millis64();
|
||||
listId = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n"));
|
||||
String listIdStr = payload.substring(payload.startsWith("/") ? 1 : 0, payload.indexOf("\n"));
|
||||
|
||||
if(listId.startsWith(F("ADN"))) {
|
||||
if(listIdStr.startsWith(F("ADN"))) {
|
||||
meterType = AmsTypeAidon;
|
||||
listId = listId.substring(0,4);
|
||||
} else if(listId.startsWith(F("KFM"))) {
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else if(listIdStr.startsWith(F("KFM"))) {
|
||||
meterType = AmsTypeKaifa;
|
||||
listId = listId.substring(0,4);
|
||||
} else if(listId.startsWith(F("KMP"))) {
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else if(listIdStr.startsWith(F("KMP"))) {
|
||||
meterType = AmsTypeKamstrup;
|
||||
listId = listId.substring(0,4);
|
||||
} else if(listId.startsWith(F("KAM"))) {
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else if(listIdStr.startsWith(F("KAM"))) {
|
||||
meterType = AmsTypeKamstrup;
|
||||
listId = listId.substring(0,4);
|
||||
} else if(listId.startsWith(F("ISk"))) {
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else if(listIdStr.startsWith(F("ISk"))) {
|
||||
meterType = AmsTypeIskra;
|
||||
listId = listId.substring(0,5);
|
||||
} else if(listId.startsWith(F("XMX"))) {
|
||||
listIdStr = listIdStr.substring(0,5);
|
||||
} else if(listIdStr.startsWith(F("XMX"))) {
|
||||
meterType = AmsTypeLandisGyr;
|
||||
listId = listId.substring(0,6);
|
||||
} else if(listId.startsWith(F("Ene")) || listId.startsWith(F("EST"))) {
|
||||
listIdStr = listIdStr.substring(0,6);
|
||||
} else if(listIdStr.startsWith(F("Ene")) || listIdStr.startsWith(F("EST"))) {
|
||||
meterType = AmsTypeSagemcom;
|
||||
listId = listId.substring(0,4);
|
||||
} else if(listId.startsWith(F("LGF"))) {
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else if(listIdStr.startsWith(F("LGF"))) {
|
||||
meterType = AmsTypeLandisGyr;
|
||||
listId = listId.substring(0,4);
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
} else {
|
||||
meterType = AmsTypeUnknown;
|
||||
listId = listId.substring(0,4);
|
||||
}
|
||||
|
||||
meterId = extract(payload, F("96.1.0"));
|
||||
if(meterId.isEmpty()) {
|
||||
meterId = extract(payload, F("0.0.5"));
|
||||
listIdStr = listIdStr.substring(0,4);
|
||||
}
|
||||
strncpy(listId, listIdStr.c_str(), sizeof(listId) - 1);
|
||||
|
||||
meterModel = extract(payload, F("96.1.1"));
|
||||
if(meterModel.isEmpty()) {
|
||||
meterModel = extract(payload, F("96.1.7"));
|
||||
if(meterModel.isEmpty()) {
|
||||
meterModel = payload.substring(payload.indexOf(listId) + listId.length(), payload.indexOf(F("\n")));
|
||||
meterModel.trim();
|
||||
String meterIdStr = extract(payload, F("96.1.0"));
|
||||
if(meterIdStr.isEmpty()) {
|
||||
meterIdStr = extract(payload, F("0.0.5"));
|
||||
}
|
||||
strncpy(meterId, meterIdStr.c_str(), sizeof(meterId) - 1);
|
||||
|
||||
String meterModelStr = extract(payload, F("96.1.1"));
|
||||
if(meterModelStr.isEmpty()) {
|
||||
meterModelStr = extract(payload, F("96.1.7"));
|
||||
if(meterModelStr.isEmpty()) {
|
||||
meterModelStr = payload.substring(payload.indexOf(listIdStr) + listIdStr.length(), payload.indexOf(F("\n")));
|
||||
meterModelStr.trim();
|
||||
}
|
||||
}
|
||||
strncpy(meterModel, meterModelStr.c_str(), sizeof(meterModel) - 1);
|
||||
|
||||
tmElements_t tm { 0, 0, 0, 0, 0, 0, 0 };
|
||||
String timestamp = extract(payload, F("1.0.0"));
|
||||
|
||||
@@ -213,7 +213,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
uint8_t str_len = 0;
|
||||
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
}
|
||||
|
||||
listType = 4;
|
||||
@@ -227,9 +227,8 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
} else if(data->base.type == CosemTypeOctetString) { // Assuming first string is a list identifier
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
String listId = String(str);
|
||||
if(listId.startsWith(F("KFM_001"))) {
|
||||
this->listId = listId;
|
||||
if(strncmp(str, "KFM_001", 7) == 0) {
|
||||
strncpy(this->listId, str, sizeof(this->listId) - 1);
|
||||
meterType = AmsTypeKaifa;
|
||||
|
||||
uint8_t idx = 0;
|
||||
@@ -241,12 +240,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterModel = String(str);
|
||||
strncpy(meterModel, str, sizeof(meterModel) - 1);
|
||||
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
activeImportPower = ntohl(data->dlu.data);
|
||||
@@ -277,12 +276,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterModel = String(str);
|
||||
strncpy(meterModel, str, sizeof(meterModel) - 1);
|
||||
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
activeImportPower = ntohl(data->dlu.data);
|
||||
@@ -301,7 +300,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
l1voltage = ntohl(data->dlu.data) / 10.0;
|
||||
}
|
||||
|
||||
if(listType >= 2 && memcmp(meterModel.c_str(), "MA304T3", 7) == 0) {
|
||||
if(listType >= 2 && memcmp(meterModel, "MA304T3", 7) == 0) {
|
||||
l2voltage = sqrt(pow(l1voltage - l3voltage * cos(60 * (PI/180)), 2) + pow(l3voltage * sin(60 * (PI/180)),2));
|
||||
l2currentMissing = true;
|
||||
}
|
||||
@@ -330,8 +329,8 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
}
|
||||
|
||||
lastUpdateMillis = millis64();
|
||||
} else if(listId.startsWith("ISK")) { // Iskra special case
|
||||
this->listId = listId;
|
||||
} else if(strncmp(listId, "ISK", 3) == 0) { // Iskra special case
|
||||
strncpy(this->listId, str, sizeof(this->listId) - 1);
|
||||
meterType = AmsTypeIskra;
|
||||
|
||||
uint8_t idx = 0;
|
||||
@@ -347,7 +346,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 1.7.0
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -427,7 +426,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 96.3.10 Disconnect control
|
||||
// 96.14.0 Currently acrive energy tariff
|
||||
@@ -469,7 +468,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 32.7.0
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -526,7 +525,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 1.7.0
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -572,7 +571,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 1.8.1
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -633,7 +632,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 1.7.0
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -707,7 +706,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
memcpy(str, data->oct.data, data->oct.length);
|
||||
str[data->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
|
||||
// 32.7.0
|
||||
data = getCosemDataAt(idx++, ((char *) (d)));
|
||||
@@ -778,7 +777,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
str_len = getString(AMS_OBIS_UNKNOWN_1, sizeof(AMS_OBIS_UNKNOWN_1), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterType = AmsTypeIskra;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
lastUpdateMillis = millis64();
|
||||
listType = 3;
|
||||
}
|
||||
@@ -810,7 +809,7 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
uint8_t str_len = 0;
|
||||
str_len = getString(AMS_OBIS_VERSION, sizeof(AMS_OBIS_VERSION), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
listId = String(str);
|
||||
strncpy(listId, str, sizeof(listId) - 1);
|
||||
}
|
||||
|
||||
val = getNumber(AMS_OBIS_ACTIVE_EXPORT, sizeof(AMS_OBIS_ACTIVE_EXPORT), ((char *) (d)));
|
||||
@@ -885,21 +884,21 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
|
||||
str_len = getString(AMS_OBIS_METER_MODEL, sizeof(AMS_OBIS_METER_MODEL), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterModel = String(str);
|
||||
strncpy(meterModel, str, sizeof(meterModel) - 1);
|
||||
} else {
|
||||
str_len = getString(AMS_OBIS_METER_MODEL_2, sizeof(AMS_OBIS_METER_MODEL_2), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterModel = String(str);
|
||||
strncpy(meterModel, str, sizeof(meterModel) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
str_len = getString(AMS_OBIS_METER_ID, sizeof(AMS_OBIS_METER_ID), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
} else {
|
||||
str_len = getString(AMS_OBIS_METER_ID_2, sizeof(AMS_OBIS_METER_ID_2), ((char *) (d)), str);
|
||||
if(str_len > 0) {
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1035,12 +1034,12 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
case CosemTypeString:
|
||||
memcpy(str, mid->oct.data, mid->oct.length);
|
||||
str[mid->oct.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
break;
|
||||
case CosemTypeOctetString:
|
||||
memcpy(str, mid->str.data, mid->str.length);
|
||||
str[mid->str.length] = 0x00;
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1059,9 +1058,9 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
meterType = AmsTypeIskra;
|
||||
}
|
||||
|
||||
if(meterId.isEmpty() && meterType != AmsTypeUnknown) {
|
||||
if(meterId[0] == '\0' && meterType != AmsTypeUnknown) {
|
||||
stripNonAscii((uint8_t*) ctx.system_title, 8);
|
||||
meterId = String((const char*)ctx.system_title);
|
||||
strncpy(meterId, (const char*)ctx.system_title, sizeof(meterId) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,7 +1104,13 @@ IEC6205675::IEC6205675(const char* d, Timezone* tz, uint8_t useMeterType, MeterC
|
||||
threePhase = true;
|
||||
}
|
||||
}
|
||||
meterId.trim();
|
||||
// Trim trailing whitespace from meterId
|
||||
{
|
||||
int len = strlen(meterId);
|
||||
while(len > 0 && (meterId[len-1] == ' ' || meterId[len-1] == '\t' || meterId[len-1] == '\r' || meterId[len-1] == '\n')) {
|
||||
meterId[--len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CosemData* IEC6205675::getCosemDataAt(uint8_t index, const char* ptr) {
|
||||
|
||||
@@ -210,13 +210,13 @@ LNG::LNG(AmsData& meterState, const char* payload, uint8_t useMeterType, MeterCo
|
||||
char str[item->oct.length+1];
|
||||
memcpy(str, item->oct.data, item->oct.length);
|
||||
str[item->oct.length] = '\0';
|
||||
meterId = String(str);
|
||||
strncpy(meterId, str, sizeof(meterId) - 1);
|
||||
listType = listType >= 2 ? listType : 2;
|
||||
} else if(descriptor->obis[4] == 1) {
|
||||
char str[item->oct.length+1];
|
||||
memcpy(str, item->oct.data, item->oct.length);
|
||||
str[item->oct.length] = '\0';
|
||||
meterModel = String(str);
|
||||
strncpy(meterModel, str, sizeof(meterModel) - 1);
|
||||
listType = listType >= 2 ? listType : 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ LNG2::LNG2(AmsData& meterState, const char* payload, uint8_t useMeterType, Meter
|
||||
char str[64];
|
||||
uint8_t str_len = getString((CosemData*) &d->meterId, str);
|
||||
if(str_len > 0) {
|
||||
this->meterId = String(str);
|
||||
strncpy(this->meterId, str, sizeof(this->meterId) - 1);
|
||||
}
|
||||
listType = 3;
|
||||
lastUpdateMillis = millis64();
|
||||
@@ -57,7 +57,7 @@ LNG2::LNG2(AmsData& meterState, const char* payload, uint8_t useMeterType, Meter
|
||||
char str[64];
|
||||
uint8_t str_len = getString((CosemData*) &d->meterId, str);
|
||||
if(str_len > 0) {
|
||||
this->meterId = String(str);
|
||||
strncpy(this->meterId, str, sizeof(this->meterId) - 1);
|
||||
}
|
||||
listType = 3;
|
||||
lastUpdateMillis = millis64();
|
||||
|
||||
@@ -400,7 +400,7 @@ bool RawMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
if(topic.isEmpty() || !connected())
|
||||
return false;
|
||||
|
||||
if(length <= 0 || length > BufferSize) return false;
|
||||
if(length <= 0 || length > BUF_SIZE_COMMON) return false;
|
||||
|
||||
String str = toHex(raw, length);
|
||||
bool ret = mqtt.publish(topic + "/data", str);
|
||||
@@ -409,7 +409,7 @@ bool RawMqttHandler::publishRaw(uint8_t* raw, size_t length) {
|
||||
}
|
||||
|
||||
void RawMqttHandler::onMessage(String &topic, String &payload) {
|
||||
if(topic.equals(subTopic)) {
|
||||
if(topic == subTopic) {
|
||||
if(payload.equals("fwupgrade")) {
|
||||
if(strcmp(updater->getNextVersion(), FirmwareVersion::VersionString) != 0) {
|
||||
updater->setTargetVersion(updater->getNextVersion());
|
||||
|
||||
@@ -21,8 +21,8 @@ public:
|
||||
int16_t getSize();
|
||||
|
||||
private:
|
||||
int8_t* values;
|
||||
uint8_t* scaling;
|
||||
int8_t values[REALTIME_SIZE];
|
||||
uint8_t scaling[REALTIME_SIZE];
|
||||
|
||||
unsigned long lastMillis = 0;
|
||||
double lastReading = 0;
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
*/
|
||||
|
||||
#include "RealtimePlot.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
RealtimePlot::RealtimePlot() {
|
||||
values = (int8_t*) malloc(REALTIME_SIZE);
|
||||
scaling = (uint8_t*) malloc(REALTIME_SIZE);
|
||||
memset(values, 0, REALTIME_SIZE);
|
||||
memset(scaling, 0, REALTIME_SIZE);
|
||||
}
|
||||
|
||||
@@ -96,16 +96,15 @@ private:
|
||||
bool uploading = false;
|
||||
File file;
|
||||
bool performRestart = false;
|
||||
String priceRegion = "";
|
||||
String priceCurrency = "";
|
||||
char priceRegion[8] = {};
|
||||
char priceCurrency[4] = {};
|
||||
#if defined(AMS2MQTT_FIRMWARE_URL)
|
||||
String customFirmwareUrl = AMS2MQTT_FIRMWARE_URL;
|
||||
char customFirmwareUrl[128] = AMS2MQTT_FIRMWARE_URL;
|
||||
#else
|
||||
String customFirmwareUrl;
|
||||
char customFirmwareUrl[128] = {};
|
||||
#endif
|
||||
|
||||
static const uint16_t BufferSize = 2048;
|
||||
char* buf;
|
||||
char* buf;
|
||||
|
||||
#if defined(ESP8266)
|
||||
ESP8266WebServer server;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
"c": {
|
||||
"e" : %s,
|
||||
"p" : %d,
|
||||
"es": %s,
|
||||
"ze": %s,
|
||||
"zt" : "%s"
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
"d": {
|
||||
"s": %s,
|
||||
"t": %s,
|
||||
"l": %d
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
"o": {
|
||||
"e" : %d,
|
||||
"c" : %d,
|
||||
"u1" : %d,
|
||||
"u2" : %d,
|
||||
"u3" : %d
|
||||
},
|
||||
@@ -1,8 +0,0 @@
|
||||
"g": {
|
||||
"t": "%s",
|
||||
"h": "%s",
|
||||
"s": %d,
|
||||
"u": "%s",
|
||||
"p": "%s",
|
||||
"c": "%s"
|
||||
},
|
||||
@@ -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
|
||||
},
|
||||
@@ -1,5 +0,0 @@
|
||||
"h": {
|
||||
"t" : "%s",
|
||||
"h" : "%s",
|
||||
"n" : "%s"
|
||||
},
|
||||
@@ -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
|
||||
}
|
||||
},
|
||||
@@ -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
|
||||
},
|
||||
@@ -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
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
"p": {
|
||||
"e": %s,
|
||||
"t": "%s",
|
||||
"r": "%s",
|
||||
"c": "%s",
|
||||
"m": %d
|
||||
},
|
||||
@@ -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
|
||||
@@ -1,15 +0,0 @@
|
||||
"t": {
|
||||
"t": [
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d,
|
||||
%d
|
||||
],
|
||||
"h": %d
|
||||
},
|
||||
@@ -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"
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
"w": {
|
||||
"s": "%s",
|
||||
"p": "%s",
|
||||
"w": %.1f,
|
||||
"z": %d,
|
||||
"b": %s
|
||||
},
|
||||
@@ -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)
|
||||
@@ -406,7 +392,7 @@ void AmsWebServer::sysinfoJson() {
|
||||
features += "\"zc\"";
|
||||
#endif
|
||||
|
||||
int size = snprintf_P(buf, BufferSize, SYSINFO_JSON,
|
||||
int size = snprintf_P(buf, BUF_SIZE_COMMON, SYSINFO_JSON,
|
||||
FirmwareVersion::VersionString,
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
"esp32s2",
|
||||
@@ -598,7 +584,7 @@ void AmsWebServer::dataJson() {
|
||||
|
||||
time_t now = time(nullptr);
|
||||
|
||||
snprintf_P(buf, BufferSize, DATA_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, DATA_JSON,
|
||||
maxPwr == 0 ? meterState->isThreePhase() ? 20000 : 10000 : maxPwr,
|
||||
productionCapacity,
|
||||
mainFuse == 0 ? 40 : mainFuse,
|
||||
@@ -662,8 +648,8 @@ void AmsWebServer::dataJson() {
|
||||
ea->getProducedThisMonth(),
|
||||
ea->getIncomeThisMonth(),
|
||||
price == PRICE_NO_VALUE ? "false" : "true",
|
||||
priceRegion.c_str(),
|
||||
priceCurrency.c_str(),
|
||||
priceRegion,
|
||||
priceCurrency,
|
||||
meterState->getLastError(),
|
||||
ps == NULL ? 0 : ps->getLastError(),
|
||||
(uint32_t) now,
|
||||
@@ -686,7 +672,7 @@ void AmsWebServer::dayplotJson() {
|
||||
if(ds == NULL) {
|
||||
notFound();
|
||||
} else {
|
||||
AmsJsonGenerator::generateDayPlotJson(ds, buf, BufferSize);
|
||||
AmsJsonGenerator::generateDayPlotJson(ds, buf, BUF_SIZE_COMMON);
|
||||
addConditionalCloudHeaders();
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
|
||||
@@ -704,7 +690,7 @@ void AmsWebServer::monthplotJson() {
|
||||
if(ds == NULL) {
|
||||
notFound();
|
||||
} else {
|
||||
AmsJsonGenerator::generateMonthPlotJson(ds, buf, BufferSize);
|
||||
AmsJsonGenerator::generateMonthPlotJson(ds, buf, BUF_SIZE_COMMON);
|
||||
addConditionalCloudHeaders();
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
|
||||
@@ -730,19 +716,19 @@ void AmsWebServer::energyPriceJson() {
|
||||
prices[i] = ps->getPriceForRelativeHour(PRICE_DIRECTION_IMPORT, i);
|
||||
}
|
||||
|
||||
uint16_t pos = snprintf_P(buf, BufferSize, PSTR("{\"currency\":\"%s\",\"source\":\"%s\""),
|
||||
uint16_t pos = snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"currency\":\"%s\",\"source\":\"%s\""),
|
||||
ps->getCurrency(),
|
||||
ps->getSource()
|
||||
);
|
||||
|
||||
for(uint8_t i = 0;i < 36; i++) {
|
||||
if(prices[i] == PRICE_NO_VALUE) {
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR(",\"%02d\":null"), i);
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR(",\"%02d\":null"), i);
|
||||
} else {
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR(",\"%02d\":%.4f"), i, prices[i]);
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR(",\"%02d\":%.4f"), i, prices[i]);
|
||||
}
|
||||
}
|
||||
snprintf_P(buf+pos, BufferSize-pos, PSTR("}"));
|
||||
snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR("}"));
|
||||
|
||||
addConditionalCloudHeaders();
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
@@ -777,7 +763,7 @@ void AmsWebServer::priceJson(uint8_t direction) {
|
||||
prices[i] = ps->getPricePoint(direction, i);
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("{\"currency\":\"%s\",\"source\":\"%s\",\"resolution\":%d,\"direction\":\"%s\",\"cursor\":%d,\"importExportPriceDifferent\":%s,\"prices\":["),
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"currency\":\"%s\",\"source\":\"%s\",\"resolution\":%d,\"direction\":\"%s\",\"cursor\":%d,\"importExportPriceDifferent\":%s,\"prices\":["),
|
||||
ps->getCurrency(),
|
||||
ps->getSource(),
|
||||
ps->getResolutionInMinutes(),
|
||||
@@ -796,10 +782,10 @@ void AmsWebServer::priceJson(uint8_t direction) {
|
||||
|
||||
for(uint8_t i = 0;i < numberOfPoints; i++) {
|
||||
if(prices[i] == PRICE_NO_VALUE) {
|
||||
snprintf_P(buf, BufferSize, PSTR("%snull"), i == 0 ? "" : ",");
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("%snull"), i == 0 ? "" : ",");
|
||||
server.sendContent(buf);
|
||||
} else {
|
||||
snprintf_P(buf, BufferSize, PSTR("%s%.4f"), i == 0 ? "" : ",", prices[i]);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("%s%.4f"), i == 0 ? "" : ",", prices[i]);
|
||||
server.sendContent(buf);
|
||||
}
|
||||
}
|
||||
@@ -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, BUF_SIZE_COMMON);
|
||||
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, BUF_SIZE_COMMON, 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,
|
||||
@@ -1182,7 +938,7 @@ void AmsWebServer::priceConfigJson() {
|
||||
}
|
||||
}
|
||||
}
|
||||
snprintf_P(buf, BufferSize, PSTR("]}"));
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("]}"));
|
||||
server.sendContent(buf);
|
||||
}
|
||||
|
||||
@@ -1200,7 +956,7 @@ void AmsWebServer::translationsJson() {
|
||||
}
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("/translations-%s.json"), lang.c_str());
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("/translations-%s.json"), lang.c_str());
|
||||
if(!LittleFS.exists(buf)) {
|
||||
notFound();
|
||||
return;
|
||||
@@ -1217,7 +973,7 @@ void AmsWebServer::translationsJson() {
|
||||
|
||||
server.send(200, MIME_JSON);
|
||||
while(file.available() > 0) {
|
||||
int len = file.readBytes(buf, BufferSize);
|
||||
int len = file.readBytes(buf, BUF_SIZE_COMMON);
|
||||
server.sendContent(buf, len);
|
||||
}
|
||||
file.close();
|
||||
@@ -1232,7 +988,7 @@ void AmsWebServer::cloudkeyJson() {
|
||||
|
||||
String seed = cloud->generateSeed();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("{\"seed\":\"%s\"}"), seed.c_str());
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"seed\":\"%s\"}"), seed.c_str());
|
||||
|
||||
server.setContentLength(strlen(buf));
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
@@ -1629,12 +1385,12 @@ void AmsWebServer::handleSave() {
|
||||
}
|
||||
|
||||
if(server.hasArg(F("p")) && server.arg(F("p")) == F("true")) {
|
||||
priceRegion = server.arg(F("pr"));
|
||||
strncpy(priceRegion, server.arg(F("pr")).c_str(), sizeof(priceRegion) - 1);
|
||||
|
||||
PriceServiceConfig price;
|
||||
price.enabled = server.hasArg(F("pe")) && server.arg(F("pe")) == F("true");
|
||||
strcpy(price.entsoeToken, server.arg(F("pt")).c_str());
|
||||
strcpy(price.area, priceRegion.c_str());
|
||||
strcpy(price.area, priceRegion);
|
||||
strcpy(price.currency, server.arg(F("pc")).c_str());
|
||||
price.resolutionInMinutes = server.arg(F("pm")).toInt();
|
||||
config->setPriceServiceConfig(price);
|
||||
@@ -1681,19 +1437,19 @@ void AmsWebServer::handleSave() {
|
||||
uint8_t count = server.arg(F("rc")).toInt();
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
PriceConfig pc;
|
||||
snprintf_P(buf, BufferSize, PSTR("rt%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rt%d"), i);
|
||||
pc.type = server.arg(buf).toInt();
|
||||
snprintf_P(buf, BufferSize, PSTR("rd%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rd%d"), i);
|
||||
pc.direction = server.arg(buf).toInt();
|
||||
snprintf_P(buf, BufferSize, PSTR("rv%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rv%d"), i);
|
||||
pc.value = server.arg(buf).toDouble() * 10000.0;
|
||||
snprintf_P(buf, BufferSize, PSTR("rn%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rn%d"), i);
|
||||
String name = server.arg(buf);
|
||||
strcpy(pc.name, name.c_str());
|
||||
|
||||
int d = 0;
|
||||
pc.days = 0x00;
|
||||
snprintf_P(buf, BufferSize, PSTR("ra%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ra%d"), i);
|
||||
String days = server.arg(buf);
|
||||
char * pch = strtok ((char*) days.c_str(),",");
|
||||
while (pch != NULL && d < 7) {
|
||||
@@ -1705,7 +1461,7 @@ void AmsWebServer::handleSave() {
|
||||
|
||||
int h = 0;
|
||||
pc.hours = 0x00000000;
|
||||
snprintf_P(buf, BufferSize, PSTR("rh%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rh%d"), i);
|
||||
String hours = server.arg(buf);
|
||||
pch = strtok ((char*) hours.c_str(),",");
|
||||
while (pch != NULL && h < 24) {
|
||||
@@ -1715,16 +1471,16 @@ void AmsWebServer::handleSave() {
|
||||
h++;
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rsm%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rsm%d"), i);
|
||||
pc.start_month = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rsd%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rsd%d"), i);
|
||||
pc.start_dayofmonth = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("rem%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("rem%d"), i);
|
||||
pc.end_month = server.arg(buf).toInt();
|
||||
|
||||
snprintf_P(buf, BufferSize, PSTR("red%d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("red%d"), i);
|
||||
pc.end_dayofmonth = server.arg(buf).toInt();
|
||||
|
||||
ps->setPriceConfig(i, pc);
|
||||
@@ -1766,7 +1522,7 @@ void AmsWebServer::handleSave() {
|
||||
success = false;
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
success ? "true" : "false",
|
||||
"",
|
||||
performRestart ? "true" : "false"
|
||||
@@ -1818,7 +1574,7 @@ void AmsWebServer::upgrade() {
|
||||
SystemConfig sys;
|
||||
config->getSystemConfig(sys);
|
||||
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
sys.dataCollectionConsent == 1 ? "true" : "false",
|
||||
"",
|
||||
sys.dataCollectionConsent == 1 ? "true" : "false"
|
||||
@@ -1881,7 +1637,7 @@ void AmsWebServer::firmwareUpload() {
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR("Invalid file extension\n"));
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"Invalid file extension",
|
||||
"false"
|
||||
@@ -1895,7 +1651,7 @@ void AmsWebServer::firmwareUpload() {
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR("An error has occurred while starting firmware upload\n"));
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"Unable to start firmware upgrade",
|
||||
"false"
|
||||
@@ -1922,7 +1678,7 @@ void AmsWebServer::firmwareUpload() {
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR("An error has occurred while writing firmware to flash\n"));
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"Unable to write to flash",
|
||||
"false"
|
||||
@@ -1948,7 +1704,7 @@ void AmsWebServer::firmwareUpload() {
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR("An error has occurred while activating new firmware\n"));
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"Unable to activate new firmware",
|
||||
"false"
|
||||
@@ -1996,7 +1752,7 @@ HTTPUpload& AmsWebServer::uploadFile(const char* path) {
|
||||
if (debugger->isActive(RemoteDebug::ERROR))
|
||||
#endif
|
||||
debugger->printf_P(PSTR("An Error has occurred while writing file\n"));
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"File size does not match",
|
||||
"false"
|
||||
@@ -2011,7 +1767,7 @@ HTTPUpload& AmsWebServer::uploadFile(const char* path) {
|
||||
file.close();
|
||||
} else {
|
||||
debugger->printf_P(PSTR("File was not valid in the end... Write error: %d, \n"), file.getWriteError());
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"false",
|
||||
"Upload ended, but file is missing",
|
||||
"false"
|
||||
@@ -2051,7 +1807,7 @@ void AmsWebServer::factoryResetPost() {
|
||||
success = true;
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
success ? "true" : "false",
|
||||
"",
|
||||
"true"
|
||||
@@ -2191,7 +1947,7 @@ void AmsWebServer::tariffJson() {
|
||||
String peaks;
|
||||
for(uint8_t x = 0;x < min((uint8_t) 5, eac->hours); x++) {
|
||||
EnergyAccountingPeak peak = ea->getPeak(x+1);
|
||||
int len = snprintf_P(buf, BufferSize, PSTR("{\"d\":%d,\"h\":%d,\"v\":%.2f}"),
|
||||
int len = snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"d\":%d,\"h\":%d,\"v\":%.2f}"),
|
||||
peak.day,
|
||||
peak.hour,
|
||||
peak.value / 100.0
|
||||
@@ -2201,7 +1957,7 @@ void AmsWebServer::tariffJson() {
|
||||
peaks += String(buf);
|
||||
}
|
||||
|
||||
snprintf_P(buf, BufferSize, TARIFF_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, TARIFF_JSON,
|
||||
eac->thresholds[0],
|
||||
eac->thresholds[1],
|
||||
eac->thresholds[2],
|
||||
@@ -2254,20 +2010,20 @@ void AmsWebServer::realtimeJson() {
|
||||
offset = rtp->getSize();
|
||||
}
|
||||
|
||||
uint16_t pos = snprintf_P(buf, BufferSize, PSTR("{\"offset\":%d,\"size\":%d,\"total\":%d,\"data\":["), offset, size, rtp->getSize());
|
||||
uint16_t pos = snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"offset\":%d,\"size\":%d,\"total\":%d,\"data\":["), offset, size, rtp->getSize());
|
||||
bool first = true;
|
||||
for(uint16_t i = 0; i < size; i++) {
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR("%s%d"), first ? "" : ",", rtp->getValue(offset+i));
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR("%s%d"), first ? "" : ",", rtp->getValue(offset+i));
|
||||
first = false;
|
||||
delay(1);
|
||||
}
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR("]}"));
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR("]}"));
|
||||
server.send(200, MIME_JSON, buf);
|
||||
}
|
||||
|
||||
void AmsWebServer::setPriceSettings(String region, String currency) {
|
||||
this->priceRegion = region;
|
||||
this->priceCurrency = currency;
|
||||
strncpy(this->priceRegion, region.c_str(), sizeof(this->priceRegion) - 1);
|
||||
strncpy(this->priceCurrency, currency.c_str(), sizeof(this->priceCurrency) - 1);
|
||||
}
|
||||
|
||||
void AmsWebServer::configFileDownload() {
|
||||
@@ -2294,59 +2050,59 @@ void AmsWebServer::configFileDownload() {
|
||||
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
||||
|
||||
server.send_P(200, MIME_PLAIN, PSTR("amsconfig\n"));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("version %s\n"), FirmwareVersion::VersionString));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("boardType %d\n"), sys.boardType));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("version %s\n"), FirmwareVersion::VersionString));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("boardType %d\n"), sys.boardType));
|
||||
|
||||
if(includeWifi) {
|
||||
NetworkConfig network;
|
||||
config->getNetworkConfig(network);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("netmode %d\n"), network.mode));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("hostname %s\n"), network.hostname));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ssid %s\n"), network.ssid));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("psk %s\n"), network.psk));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("netmode %d\n"), network.mode));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("hostname %s\n"), network.hostname));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ssid %s\n"), network.ssid));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("psk %s\n"), network.psk));
|
||||
if(strlen(network.ip) > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ip %s\n"), network.ip));
|
||||
if(strlen(network.gateway) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gateway %s\n"), network.gateway));
|
||||
if(strlen(network.subnet) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("subnet %s\n"), network.subnet));
|
||||
if(strlen(network.dns1) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dns1 %s\n"), network.dns1));
|
||||
if(strlen(network.dns2) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dns2 %s\n"), network.dns2));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ip %s\n"), network.ip));
|
||||
if(strlen(network.gateway) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gateway %s\n"), network.gateway));
|
||||
if(strlen(network.subnet) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("subnet %s\n"), network.subnet));
|
||||
if(strlen(network.dns1) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("dns1 %s\n"), network.dns1));
|
||||
if(strlen(network.dns2) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("dns2 %s\n"), network.dns2));
|
||||
}
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mdns %d\n"), network.mdns ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("use11b %d\n"), network.use11b ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mdns %d\n"), network.mdns ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("use11b %d\n"), network.use11b ? 1 : 0));
|
||||
}
|
||||
|
||||
if(includeMqtt) {
|
||||
MqttConfig mqtt;
|
||||
config->getMqttConfig(mqtt);
|
||||
if(strlen(mqtt.host) > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttHost %s\n"), mqtt.host));
|
||||
if(mqtt.port > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPort %d\n"), mqtt.port));
|
||||
if(strlen(mqtt.clientId) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttClientId %s\n"), mqtt.clientId));
|
||||
if(strlen(mqtt.publishTopic) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPublishTopic %s\n"), mqtt.publishTopic));
|
||||
if(strlen(mqtt.subscribeTopic) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttSubscribeTopic %s\n"), mqtt.subscribeTopic));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttUsername %s\n"), mqtt.username));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPassword %s\n"), mqtt.password));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttPayloadFormat %d\n"), mqtt.payloadFormat));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttSsl %d\n"), mqtt.ssl ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttHost %s\n"), mqtt.host));
|
||||
if(mqtt.port > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttPort %d\n"), mqtt.port));
|
||||
if(strlen(mqtt.clientId) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttClientId %s\n"), mqtt.clientId));
|
||||
if(strlen(mqtt.publishTopic) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttPublishTopic %s\n"), mqtt.publishTopic));
|
||||
if(strlen(mqtt.subscribeTopic) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttSubscribeTopic %s\n"), mqtt.subscribeTopic));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttUsername %s\n"), mqtt.username));
|
||||
if(includeSecrets) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttPassword %s\n"), mqtt.password));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttPayloadFormat %d\n"), mqtt.payloadFormat));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttSsl %d\n"), mqtt.ssl ? 1 : 0));
|
||||
|
||||
if(mqtt.timeout > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttTimeout %d\n"), mqtt.timeout));
|
||||
if(mqtt.keepalive > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttKeepalive %d\n"), mqtt.keepalive));
|
||||
if(mqtt.rebootMinutes > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("mqttRebootMinutes %d\n"), mqtt.rebootMinutes));
|
||||
if(mqtt.timeout > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttTimeout %d\n"), mqtt.timeout));
|
||||
if(mqtt.keepalive > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttKeepalive %d\n"), mqtt.keepalive));
|
||||
if(mqtt.rebootMinutes > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("mqttRebootMinutes %d\n"), mqtt.rebootMinutes));
|
||||
|
||||
if(mqtt.payloadFormat == 3) {
|
||||
DomoticzConfig domo;
|
||||
config->getDomoticzConfig(domo);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzElidx %d\n"), domo.elidx));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl1idx %d\n"), domo.vl1idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl2idx %d\n"), domo.vl2idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzVl3idx %d\n"), domo.vl3idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("domoticzCl1idx %d\n"), domo.cl1idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("domoticzElidx %d\n"), domo.elidx));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("domoticzVl1idx %d\n"), domo.vl1idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("domoticzVl2idx %d\n"), domo.vl2idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("domoticzVl3idx %d\n"), domo.vl3idx));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("domoticzCl1idx %d\n"), domo.cl1idx));
|
||||
} else if(mqtt.payloadFormat == 4) {
|
||||
HomeAssistantConfig haconf;
|
||||
config->getHomeAssistantConfig(haconf);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("homeAssistantDiscoveryPrefix %s\n"), haconf.discoveryPrefix));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("homeAssistantDiscoveryHostname %s\n"), haconf.discoveryHostname));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("homeAssistantDiscoveryNameTag %s\n"), haconf.discoveryNameTag));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("homeAssistantDiscoveryPrefix %s\n"), haconf.discoveryPrefix));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("homeAssistantDiscoveryHostname %s\n"), haconf.discoveryHostname));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("homeAssistantDiscoveryNameTag %s\n"), haconf.discoveryNameTag));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2354,17 +2110,17 @@ void AmsWebServer::configFileDownload() {
|
||||
if(includeWeb && includeSecrets) {
|
||||
WebConfig web;
|
||||
config->getWebConfig(web);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webSecurity %d\n"), web.security));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("webSecurity %d\n"), web.security));
|
||||
if(web.security > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webUsername %s\n"), web.username));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("webPassword %s\n"), web.password));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("webUsername %s\n"), web.username));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("webPassword %s\n"), web.password));
|
||||
}
|
||||
}
|
||||
|
||||
if(includeMeter) {
|
||||
MeterConfig meter;
|
||||
config->getMeterConfig(meter);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterBaud %d\n"), meter.baud));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterBaud %d\n"), meter.baud));
|
||||
char parity[4] = "";
|
||||
switch(meter.parity) {
|
||||
case 2:
|
||||
@@ -2383,23 +2139,23 @@ void AmsWebServer::configFileDownload() {
|
||||
strcpy_P(parity, PSTR("8E1"));
|
||||
break;
|
||||
}
|
||||
if(strlen(parity) > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterParity %s\n"), parity));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterInvert %d\n"), meter.invert ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterDistributionSystem %d\n"), meter.distributionSystem));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterMainFuse %d\n"), meter.mainFuse));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterProductionCapacity %d\n"), meter.productionCapacity));
|
||||
if(strlen(parity) > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterParity %s\n"), parity));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterInvert %d\n"), meter.invert ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterDistributionSystem %d\n"), meter.distributionSystem));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterMainFuse %d\n"), meter.mainFuse));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterProductionCapacity %d\n"), meter.productionCapacity));
|
||||
if(includeSecrets) {
|
||||
if(meter.encryptionKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterEncryptionKey %s\n"), toHex(meter.encryptionKey, 16).c_str()));
|
||||
if(meter.authenticationKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterAuthenticationKey %s\n"), toHex(meter.authenticationKey, 16).c_str()));
|
||||
if(meter.encryptionKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterEncryptionKey %s\n"), toHex(meter.encryptionKey, 16).c_str()));
|
||||
if(meter.authenticationKey[0] != 0x00) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterAuthenticationKey %s\n"), toHex(meter.authenticationKey, 16).c_str()));
|
||||
}
|
||||
if(meter.wattageMultiplier != 1.0 && meter.wattageMultiplier != 0.0)
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterWattageMultiplier %.3f\n"), meter.wattageMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterWattageMultiplier %.3f\n"), meter.wattageMultiplier / 1000.0));
|
||||
if(meter.voltageMultiplier != 1.0 && meter.voltageMultiplier != 0.0)
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterVoltageMultiplier %.3f\n"), meter.voltageMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterVoltageMultiplier %.3f\n"), meter.voltageMultiplier / 1000.0));
|
||||
if(meter.amperageMultiplier != 1.0 && meter.amperageMultiplier != 0.0)
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterAmperageMultiplier %.3f\n"), meter.amperageMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterAmperageMultiplier %.3f\n"), meter.amperageMultiplier / 1000.0));
|
||||
if(meter.accumulatedMultiplier != 1.0 && meter.accumulatedMultiplier != 0.0)
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("meterAccumulatedMultiplier %.3f\n"), meter.accumulatedMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("meterAccumulatedMultiplier %.3f\n"), meter.accumulatedMultiplier / 1000.0));
|
||||
}
|
||||
|
||||
if(includeGpio) {
|
||||
@@ -2407,41 +2163,41 @@ void AmsWebServer::configFileDownload() {
|
||||
config->getMeterConfig(meter);
|
||||
GpioConfig gpio;
|
||||
config->getGpioConfig(gpio);
|
||||
if(meter.rxPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioHanPin %d\n"), meter.rxPin));
|
||||
if(meter.rxPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioHanPinPullup %d\n"), meter.rxPinPullup ? 1 : 0));
|
||||
if(gpio.apPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioApPin %d\n"), gpio.apPin));
|
||||
if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPin %d\n"), gpio.ledPin));
|
||||
if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedInverted %d\n"), gpio.ledInverted ? 1 : 0));
|
||||
if(gpio.ledPinRed != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinRed %d\n"), gpio.ledPinRed));
|
||||
if(gpio.ledPinGreen != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinGreen %d\n"), gpio.ledPinGreen));
|
||||
if(gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedPinBlue %d\n"), gpio.ledPinBlue));
|
||||
if(gpio.ledPinRed != 0xFF || gpio.ledPinGreen != 0xFF || gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioLedRgbInverted %d\n"), gpio.ledRgbInverted ? 1 : 0));
|
||||
if(gpio.tempSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioTempSensorPin %d\n"), gpio.tempSensorPin));
|
||||
if(gpio.tempAnalogSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioTempAnalogSensorPin %d\n"), gpio.tempAnalogSensorPin));
|
||||
if(gpio.vccPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccPin %d\n"), gpio.vccPin));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccOffset %.2f\n"), gpio.vccOffset / 100.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccMultiplier %.3f\n"), gpio.vccMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccBootLimit %.1f\n"), gpio.vccBootLimit / 10.0));
|
||||
if(gpio.vccPin != 0xFF && gpio.vccResistorGnd != 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccResistorGnd %d\n"), gpio.vccResistorGnd));
|
||||
if(gpio.vccPin != 0xFF && gpio.vccResistorVcc != 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("gpioVccResistorVcc %d\n"), gpio.vccResistorVcc));
|
||||
if(meter.rxPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioHanPin %d\n"), meter.rxPin));
|
||||
if(meter.rxPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioHanPinPullup %d\n"), meter.rxPinPullup ? 1 : 0));
|
||||
if(gpio.apPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioApPin %d\n"), gpio.apPin));
|
||||
if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedPin %d\n"), gpio.ledPin));
|
||||
if(gpio.ledPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedInverted %d\n"), gpio.ledInverted ? 1 : 0));
|
||||
if(gpio.ledPinRed != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedPinRed %d\n"), gpio.ledPinRed));
|
||||
if(gpio.ledPinGreen != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedPinGreen %d\n"), gpio.ledPinGreen));
|
||||
if(gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedPinBlue %d\n"), gpio.ledPinBlue));
|
||||
if(gpio.ledPinRed != 0xFF || gpio.ledPinGreen != 0xFF || gpio.ledPinBlue != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioLedRgbInverted %d\n"), gpio.ledRgbInverted ? 1 : 0));
|
||||
if(gpio.tempSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioTempSensorPin %d\n"), gpio.tempSensorPin));
|
||||
if(gpio.tempAnalogSensorPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioTempAnalogSensorPin %d\n"), gpio.tempAnalogSensorPin));
|
||||
if(gpio.vccPin != 0xFF) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccPin %d\n"), gpio.vccPin));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccOffset %.2f\n"), gpio.vccOffset / 100.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccMultiplier %.3f\n"), gpio.vccMultiplier / 1000.0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccBootLimit %.1f\n"), gpio.vccBootLimit / 10.0));
|
||||
if(gpio.vccPin != 0xFF && gpio.vccResistorGnd != 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccResistorGnd %d\n"), gpio.vccResistorGnd));
|
||||
if(gpio.vccPin != 0xFF && gpio.vccResistorVcc != 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("gpioVccResistorVcc %d\n"), gpio.vccResistorVcc));
|
||||
}
|
||||
|
||||
if(includeNtp) {
|
||||
NtpConfig ntp;
|
||||
config->getNtpConfig(ntp);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpEnable %d\n"), ntp.enable ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpDhcp %d\n"), ntp.dhcp ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpTimezone %s\n"), ntp.timezone));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("ntpServer %s\n"), ntp.server));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ntpEnable %d\n"), ntp.enable ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ntpDhcp %d\n"), ntp.dhcp ? 1 : 0));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ntpTimezone %s\n"), ntp.timezone));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("ntpServer %s\n"), ntp.server));
|
||||
}
|
||||
|
||||
if(includePrice) {
|
||||
PriceServiceConfig price;
|
||||
config->getPriceServiceConfig(price);
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceEnabled %d\n"), price.enabled ? 1 : 0));
|
||||
if(strlen(price.entsoeToken) == 36 && includeSecrets) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceEntsoeToken %s\n"), price.entsoeToken));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceArea %s\n"), price.area));
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceCurrency %s\n"), price.currency));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("priceEnabled %d\n"), price.enabled ? 1 : 0));
|
||||
if(strlen(price.entsoeToken) == 36 && includeSecrets) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("priceEntsoeToken %s\n"), price.entsoeToken));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("priceArea %s\n"), price.area));
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("priceCurrency %s\n"), price.currency));
|
||||
if(ps != NULL) {
|
||||
uint8_t i = 0;
|
||||
std::vector<PriceConfig> pc = ps->getPriceConfig();
|
||||
@@ -2507,7 +2263,7 @@ void AmsWebServer::configFileDownload() {
|
||||
if(strlen(hours) > 0) hours[strlen(hours)-1] = '\0';
|
||||
}
|
||||
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceModifier %i \"%s\" %s %s %.4f %s %s %02d-%02d %02d-%02d\n"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("priceModifier %i \"%s\" %s %s %.4f %s %s %02d-%02d %02d-%02d\n"),
|
||||
i,
|
||||
p.name,
|
||||
direction,
|
||||
@@ -2529,7 +2285,7 @@ void AmsWebServer::configFileDownload() {
|
||||
EnergyAccountingConfig eac;
|
||||
config->getEnergyAccountingConfig(eac);
|
||||
|
||||
if(eac.thresholds[9] > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("thresholds %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
if(eac.thresholds[9] > 0) server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("thresholds %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
eac.thresholds[0],
|
||||
eac.thresholds[1],
|
||||
eac.thresholds[2],
|
||||
@@ -2547,7 +2303,7 @@ void AmsWebServer::configFileDownload() {
|
||||
|
||||
if(ds != NULL) {
|
||||
DayDataPoints day = ds->getDayData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("dayplot %d %lu %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("dayplot %d %lu %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
day.version,
|
||||
(int32_t) day.lastMeterReadTime,
|
||||
day.activeImport / 1000.0,
|
||||
@@ -2578,7 +2334,7 @@ void AmsWebServer::configFileDownload() {
|
||||
ds->getHourImport(23)
|
||||
));
|
||||
if(day.activeExport > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR(" %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR(" %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
day.activeExport / 1000.0,
|
||||
ds->getHourExport(0),
|
||||
ds->getHourExport(1),
|
||||
@@ -2610,7 +2366,7 @@ void AmsWebServer::configFileDownload() {
|
||||
}
|
||||
|
||||
MonthDataPoints month = ds->getMonthData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("monthplot %d %lu %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("monthplot %d %lu %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"),
|
||||
month.version,
|
||||
(int32_t) month.lastMeterReadTime,
|
||||
month.activeImport / 1000.0,
|
||||
@@ -2648,7 +2404,7 @@ void AmsWebServer::configFileDownload() {
|
||||
ds->getDayImport(31)
|
||||
));
|
||||
if(month.activeExport > 0) {
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR(" %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR(" %.3f %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
month.activeExport / 1000.0,
|
||||
ds->getDayExport(1),
|
||||
ds->getDayExport(2),
|
||||
@@ -2691,7 +2447,7 @@ void AmsWebServer::configFileDownload() {
|
||||
EnergyAccountingConfig eac;
|
||||
config->getEnergyAccountingConfig(eac);
|
||||
EnergyAccountingData ead = ea->getData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %.2f %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %.2f %.2f"),
|
||||
server.sendContent(buf, snprintf_P(buf, BUF_SIZE_COMMON, PSTR("energyaccounting %d %d %.2f %.2f %.2f %.2f %.2f %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %d %d %.2f %.2f %.2f"),
|
||||
ead.version,
|
||||
ead.month,
|
||||
ea->getCostYesterday(),
|
||||
@@ -2723,7 +2479,7 @@ void AmsWebServer::configFileDownload() {
|
||||
}
|
||||
|
||||
void AmsWebServer::configFilePost() {
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"true",
|
||||
"",
|
||||
performRestart ? "true" : "false"
|
||||
@@ -2739,7 +2495,7 @@ void AmsWebServer::configFileUpload() {
|
||||
HTTPUpload& upload = uploadFile(FILE_CFG);
|
||||
if(upload.status == UPLOAD_FILE_END) {
|
||||
performRestart = true;
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"true",
|
||||
"",
|
||||
performRestart ? "true" : "false"
|
||||
@@ -2773,18 +2529,18 @@ void AmsWebServer::modifyDayPlot() {
|
||||
return;
|
||||
|
||||
for(uint8_t i = 0; i < 24; i++) {
|
||||
snprintf_P(buf, BufferSize, PSTR("i%02d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("i%02d"), i);
|
||||
if(server.hasArg(buf)) {
|
||||
ds->setHourImport(i, server.arg(buf).toDouble() * 1000);
|
||||
}
|
||||
snprintf_P(buf, BufferSize, PSTR("e%02d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("e%02d"), i);
|
||||
if(server.hasArg(buf)) {
|
||||
ds->setHourExport(i, server.arg(buf).toDouble() * 1000);
|
||||
}
|
||||
}
|
||||
bool ret = ds->save();
|
||||
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"true",
|
||||
"",
|
||||
ret ? "true" : "false"
|
||||
@@ -2798,18 +2554,18 @@ void AmsWebServer::modifyMonthPlot() {
|
||||
return;
|
||||
|
||||
for(uint8_t i = 1; i <= 31; i++) {
|
||||
snprintf_P(buf, BufferSize, PSTR("i%02d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("i%02d"), i);
|
||||
if(server.hasArg(buf)) {
|
||||
ds->setDayImport(i, server.arg(buf).toDouble() * 1000);
|
||||
}
|
||||
snprintf_P(buf, BufferSize, PSTR("e%02d"), i);
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, PSTR("e%02d"), i);
|
||||
if(server.hasArg(buf)) {
|
||||
ds->setDayExport(i, server.arg(buf).toDouble() * 1000);
|
||||
}
|
||||
}
|
||||
bool ret = ds->save();
|
||||
|
||||
snprintf_P(buf, BufferSize, RESPONSE_JSON,
|
||||
snprintf_P(buf, BUF_SIZE_COMMON, RESPONSE_JSON,
|
||||
"true",
|
||||
"",
|
||||
ret ? "true" : "false"
|
||||
@@ -2881,7 +2637,7 @@ void AmsWebServer::wifiScan() {
|
||||
return;
|
||||
|
||||
int16_t count = WiFi.scanNetworks();
|
||||
int pos = snprintf_P(buf, BufferSize, PSTR("{\"c\":%d,\"n\":["), count);
|
||||
int pos = snprintf_P(buf, BUF_SIZE_COMMON, PSTR("{\"c\":%d,\"n\":["), count);
|
||||
count = min(count, (int16_t) 25); // Max 25 so that we don't overflow the buffer size
|
||||
for (int16_t i = 0; i < count; i++) {
|
||||
uint8_t* bssid = WiFi.BSSID(i);
|
||||
@@ -2917,9 +2673,9 @@ void AmsWebServer::wifiScan() {
|
||||
|
||||
char bssidStr[18] = { 0 };
|
||||
sprintf(bssidStr, "%02X:%02X:%02X:%02X:%02X:%02X", bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR("{\"b\":\"%s\",\"s\":\"%s\",\"r\":%d,\"c\":%d,\"e\":\"%s\"}%s"), bssidStr, ssid.c_str(), rssi, chan, encStr, i == count-1 ? "" : ",");
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR("{\"b\":\"%s\",\"s\":\"%s\",\"r\":%d,\"c\":%d,\"e\":\"%s\"}%s"), bssidStr, ssid.c_str(), rssi, chan, encStr, i == count-1 ? "" : ",");
|
||||
}
|
||||
pos += snprintf_P(buf+pos, BufferSize-pos, PSTR("]}"));
|
||||
pos += snprintf_P(buf+pos, BUF_SIZE_COMMON-pos, PSTR("]}"));
|
||||
WiFi.scanDelete();
|
||||
|
||||
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
extra_configs = platformio-user.ini
|
||||
|
||||
[common]
|
||||
lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.2, OneWireNg@0.13.3, DallasTemperature@4.0.4, https://github.com/gskjold/RemoteDebug.git, PaulStoffregen/Time@1.6.1, JChristensen/Timezone@1.2.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, PriceService, EnergyAccounting, AmsFirmwareUpdater, AmsJsonGenerator, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, PassthroughMqttHandler, RealtimePlot, ConnectionHandler, MeterCommunicators
|
||||
lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.2, OneWireNg@0.13.3, DallasTemperature@4.0.4, https://github.com/gskjold/RemoteDebug.git, PaulStoffregen/Time@1.6.1, JChristensen/Timezone@1.2.4, FirmwareVersion, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, AmsDecoder, PriceService, EnergyAccounting, AmsFirmwareUpdater, AmsJsonGenerator, bblanchon/ArduinoJson@7.0.4, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, PassthroughMqttHandler, RealtimePlot, ConnectionHandler, MeterCommunicators
|
||||
lib_ignore = OneWire
|
||||
extra_scripts =
|
||||
pre:scripts/addversion.py
|
||||
@@ -19,7 +19,7 @@ build_flags =
|
||||
-fexceptions
|
||||
|
||||
[esp32]
|
||||
lib_deps = WiFi, Ethernet, ESPmDNS, WiFiClientSecure, HTTPClient, FS, WebServer, ESP32 Async UDP, ESP32SSDP, mulmer89/ESPRandom@1.5.0, ${common.lib_deps}, bblanchon/ArduinoJson@7.0.4, CloudConnector, ZmartCharge, SvelteUi
|
||||
lib_deps = WiFi, Ethernet, ESPmDNS, WiFiClientSecure, HTTPClient, FS, WebServer, ESP32 Async UDP, ESP32SSDP, mulmer89/ESPRandom@1.5.0, ${common.lib_deps}, CloudConnector, ZmartCharge, SvelteUi
|
||||
|
||||
[env:esp8266]
|
||||
platform = espressif8266@4.2.1
|
||||
|
||||
@@ -115,8 +115,6 @@ RemoteDebug Debug;
|
||||
HardwareSerial Debug = Serial;
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE_COMMON (2048)
|
||||
|
||||
#include "Timezones.h"
|
||||
|
||||
#include "AmsFirmwareUpdater.h"
|
||||
@@ -360,7 +358,7 @@ void resetBootCycleCounter(bool deepSleep) {
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
config.hasConfig(); // Need to run this to make sure all configuration have been migrated before we load GPIO config
|
||||
config.load(); // Need to run this to make sure all configuration have been migrated before we load GPIO config
|
||||
|
||||
if(!config.getGpioConfig(gpioConfig)) {
|
||||
config.clearGpio(gpioConfig);
|
||||
@@ -1751,7 +1749,7 @@ void MQTT_connect() {
|
||||
case 0:
|
||||
case 5:
|
||||
case 6:
|
||||
mqttHandler = new JsonMqttHandler(mqttConfig, &Debug, (char*) commonBuffer, &hw, &ds, &updater);
|
||||
mqttHandler = new JsonMqttHandler(&config, &Debug, (char*) commonBuffer, &hw, &ds, &updater);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
@@ -1852,8 +1850,8 @@ void configFileParse() {
|
||||
|
||||
size_t size;
|
||||
char* buf = (char*) commonBuffer;
|
||||
memset(buf, 0, 1024);
|
||||
while((size = file.readBytesUntil('\n', buf, 1024)) > 0) {
|
||||
memset(buf, 0, BUF_SIZE_COMMON);
|
||||
while((size = file.readBytesUntil('\n', buf, BUF_SIZE_COMMON)) > 0) {
|
||||
for(uint16_t i = 0; i < size; i++) {
|
||||
if(buf[i] < 32 || buf[i] > 126) {
|
||||
memset(buf+i, 0, size-i);
|
||||
|
||||
Reference in New Issue
Block a user