mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-29 13:30:56 +00:00
Added usage plots and ADC reading for Vcc
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_SYSTEM_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -12,7 +12,7 @@ bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_SYSTEM_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -21,7 +21,7 @@ bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_WIFI_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -45,7 +45,7 @@ bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
|
||||
} else {
|
||||
wifiChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_WIFI_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -85,7 +85,7 @@ void AmsConfiguration::ackWifiChange() {
|
||||
|
||||
bool AmsConfiguration::getMqttConfig(MqttConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_MQTT_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -110,7 +110,7 @@ bool AmsConfiguration::setMqttConfig(MqttConfig& config) {
|
||||
} else {
|
||||
mqttChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_MQTT_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -143,7 +143,7 @@ void AmsConfiguration::ackMqttChange() {
|
||||
|
||||
bool AmsConfiguration::getWebConfig(WebConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_WEB_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -154,7 +154,7 @@ bool AmsConfiguration::getWebConfig(WebConfig& config) {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::setWebConfig(WebConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_WEB_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -169,7 +169,7 @@ void AmsConfiguration::clearAuth(WebConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getMeterConfig(MeterConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_METER_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -193,7 +193,7 @@ bool AmsConfiguration::setMeterConfig(MeterConfig& config) {
|
||||
} else {
|
||||
meterChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_METER_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -221,7 +221,7 @@ void AmsConfiguration::ackMeterChanged() {
|
||||
|
||||
bool AmsConfiguration::getDebugConfig(DebugConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_DEBUG_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -232,7 +232,7 @@ bool AmsConfiguration::getDebugConfig(DebugConfig& config) {
|
||||
}
|
||||
|
||||
bool AmsConfiguration::setDebugConfig(DebugConfig& config) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_DEBUG_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -247,7 +247,7 @@ void AmsConfiguration::clearDebug(DebugConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getDomoticzConfig(DomoticzConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_DOMOTICZ_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -269,7 +269,7 @@ bool AmsConfiguration::setDomoticzConfig(DomoticzConfig& config) {
|
||||
domoChanged = true;
|
||||
}
|
||||
mqttChanged = domoChanged;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_DOMOTICZ_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -310,7 +310,7 @@ bool AmsConfiguration::pinUsed(uint8_t pin, GpioConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getGpioConfig(GpioConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_GPIO_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -366,7 +366,7 @@ bool AmsConfiguration::setGpioConfig(GpioConfig& config) {
|
||||
if(config.apPin >= 0)
|
||||
pinMode(config.apPin, INPUT_PULLUP);
|
||||
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_GPIO_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -388,11 +388,13 @@ void AmsConfiguration::clearGpio(GpioConfig& config) {
|
||||
config.vccOffset = 0;
|
||||
config.vccMultiplier = 1000;
|
||||
config.vccBootLimit = 0;
|
||||
config.vccResistorGnd = 0;
|
||||
config.vccResistorVcc = 0;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::getNtpConfig(NtpConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_NTP_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -419,7 +421,7 @@ bool AmsConfiguration::setNtpConfig(NtpConfig& config) {
|
||||
} else {
|
||||
ntpChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_NTP_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -444,7 +446,7 @@ void AmsConfiguration::clearNtp(NtpConfig& config) {
|
||||
|
||||
bool AmsConfiguration::getEntsoeConfig(EntsoeConfig& config) {
|
||||
if(hasConfig()) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_ENTSOE_START, config);
|
||||
EEPROM.end();
|
||||
return true;
|
||||
@@ -463,7 +465,7 @@ bool AmsConfiguration::setEntsoeConfig(EntsoeConfig& config) {
|
||||
} else {
|
||||
entsoeChanged = true;
|
||||
}
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(CONFIG_ENTSOE_START, config);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
@@ -486,7 +488,7 @@ void AmsConfiguration::ackEntsoeChange() {
|
||||
}
|
||||
|
||||
void AmsConfiguration::clear() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
MeterConfig meter;
|
||||
clearMeter(meter);
|
||||
EEPROM.put(CONFIG_METER_START, meter);
|
||||
@@ -522,7 +524,7 @@ void AmsConfiguration::clear() {
|
||||
|
||||
bool AmsConfiguration::hasConfig() {
|
||||
if(configVersion == 0) {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||
EEPROM.end();
|
||||
}
|
||||
@@ -553,6 +555,14 @@ bool AmsConfiguration::hasConfig() {
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
case 88:
|
||||
configVersion = -1; // Prevent loop
|
||||
if(relocateConfig88()) {
|
||||
configVersion = 89;
|
||||
} else {
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
case EEPROM_CHECK_SUM:
|
||||
return true;
|
||||
default:
|
||||
@@ -567,7 +577,7 @@ int AmsConfiguration::getConfigVersion() {
|
||||
}
|
||||
|
||||
void AmsConfiguration::loadTempSensors() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
TempSensorConfig* tempSensors[32];
|
||||
int address = EEPROM_TEMP_CONFIG_ADDRESS;
|
||||
int c = 0;
|
||||
@@ -606,7 +616,7 @@ void AmsConfiguration::saveTempSensors() {
|
||||
|
||||
bool AmsConfiguration::loadConfig83(int address) {
|
||||
ConfigObject83 c;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(address, c);
|
||||
|
||||
EntsoeConfig entsoe {"", "", "", 1000};
|
||||
@@ -644,7 +654,9 @@ bool AmsConfiguration::loadConfig83(int address) {
|
||||
c.vccPin,
|
||||
c.vccOffset,
|
||||
c.vccMultiplier,
|
||||
c.vccBootLimit
|
||||
c.vccBootLimit,
|
||||
0,
|
||||
0
|
||||
};
|
||||
EEPROM.put(CONFIG_GPIO_START, gpio);
|
||||
|
||||
@@ -715,7 +727,7 @@ bool AmsConfiguration::loadConfig83(int address) {
|
||||
bool AmsConfiguration::relocateConfig86() {
|
||||
MqttConfig86 mqtt86;
|
||||
MqttConfig mqtt;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_MQTT_START_86, mqtt86);
|
||||
strcpy(mqtt.host, mqtt86.host);
|
||||
mqtt.port = mqtt86.port;
|
||||
@@ -736,7 +748,7 @@ bool AmsConfiguration::relocateConfig86() {
|
||||
bool AmsConfiguration::relocateConfig87() {
|
||||
MeterConfig87 meter87;
|
||||
MeterConfig meter;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_METER_START_87, meter87);
|
||||
if(meter87.type < 5) {
|
||||
meter.baud = 2400;
|
||||
@@ -757,8 +769,38 @@ bool AmsConfiguration::relocateConfig87() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::relocateConfig88() {
|
||||
GpioConfig88 gpio88;
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.get(CONFIG_GPIO_START_88, gpio88);
|
||||
|
||||
GpioConfig gpio {
|
||||
gpio88.hanPin,
|
||||
gpio88.apPin,
|
||||
gpio88.ledPin,
|
||||
gpio88.ledInverted,
|
||||
gpio88.ledPinRed,
|
||||
gpio88.ledPinGreen,
|
||||
gpio88.ledPinBlue,
|
||||
gpio88.ledRgbInverted,
|
||||
gpio88.tempSensorPin,
|
||||
gpio88.tempAnalogSensorPin,
|
||||
gpio88.vccPin,
|
||||
gpio88.vccOffset,
|
||||
gpio88.vccMultiplier,
|
||||
gpio88.vccBootLimit,
|
||||
0,
|
||||
0
|
||||
};
|
||||
EEPROM.put(CONFIG_GPIO_START, gpio);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, 89);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::save() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.begin(SPI_FLASH_SEC_SIZE);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
||||
saveTempSensors();
|
||||
bool success = EEPROM.commit();
|
||||
@@ -938,9 +980,17 @@ void AmsConfiguration::print(Print* debugger)
|
||||
debugger->printf("Temperature pin: %i\r\n", gpio.tempSensorPin);
|
||||
debugger->printf("Temp analog pin: %i\r\n", gpio.tempAnalogSensorPin);
|
||||
debugger->printf("Vcc pin: %i\r\n", gpio.vccPin);
|
||||
if(gpio.vccMultiplier > 0) {
|
||||
debugger->printf("Vcc multiplier: %f\r\n", gpio.vccMultiplier / 1000.0);
|
||||
}
|
||||
if(gpio.vccOffset > 0) {
|
||||
debugger->printf("Vcc offset: %f\r\n", gpio.vccOffset / 100.0);
|
||||
}
|
||||
if(gpio.vccBootLimit > 0) {
|
||||
debugger->printf("Vcc boot limit: %f\r\n", gpio.vccBootLimit / 10.0);
|
||||
}
|
||||
debugger->printf("GND resistor: %i\r\n", gpio.vccResistorGnd);
|
||||
debugger->printf("Vcc resistor: %i\r\n", gpio.vccResistorVcc);
|
||||
debugger->println("");
|
||||
delay(10);
|
||||
Serial.flush();
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
#include <EEPROM.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#define EEPROM_SIZE 1024 * 3
|
||||
#define EEPROM_CHECK_SUM 88 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_CHECK_SUM 89 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_CONFIG_ADDRESS 0
|
||||
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
|
||||
|
||||
#define CONFIG_SYSTEM_START 8
|
||||
#define CONFIG_WIFI_START 16
|
||||
#define CONFIG_METER_START 224
|
||||
#define CONFIG_GPIO_START 266
|
||||
#define CONFIG_WEB_START 648
|
||||
#define CONFIG_DEBUG_START 824
|
||||
#define CONFIG_GPIO_START 832
|
||||
#define CONFIG_DOMOTICZ_START 856
|
||||
#define CONFIG_NTP_START 872
|
||||
#define CONFIG_ENTSOE_START 944
|
||||
@@ -21,6 +20,7 @@
|
||||
|
||||
#define CONFIG_MQTT_START_86 224
|
||||
#define CONFIG_METER_START_87 784
|
||||
#define CONFIG_GPIO_START_88 832
|
||||
|
||||
|
||||
struct SystemConfig {
|
||||
@@ -111,6 +111,25 @@ struct GpioConfig {
|
||||
int16_t vccOffset;
|
||||
uint16_t vccMultiplier;
|
||||
uint8_t vccBootLimit;
|
||||
uint16_t vccResistorGnd;
|
||||
uint16_t vccResistorVcc;
|
||||
}; // 20
|
||||
|
||||
struct GpioConfig88 {
|
||||
uint8_t hanPin;
|
||||
uint8_t apPin;
|
||||
uint8_t ledPin;
|
||||
bool ledInverted;
|
||||
uint8_t ledPinRed;
|
||||
uint8_t ledPinGreen;
|
||||
uint8_t ledPinBlue;
|
||||
bool ledRgbInverted;
|
||||
uint8_t tempSensorPin;
|
||||
uint8_t tempAnalogSensorPin;
|
||||
uint8_t vccPin;
|
||||
int16_t vccOffset;
|
||||
uint16_t vccMultiplier;
|
||||
uint8_t vccBootLimit;
|
||||
}; // 16
|
||||
|
||||
struct DomoticzConfig {
|
||||
@@ -295,6 +314,7 @@ private:
|
||||
bool loadConfig83(int address);
|
||||
bool relocateConfig86();
|
||||
bool relocateConfig87();
|
||||
bool relocateConfig88(); // dev 1.6
|
||||
|
||||
int readString(int pAddress, char* pString[]);
|
||||
int readInt(int pAddress, int *pValue);
|
||||
|
||||
308
src/AmsDataStorage.cpp
Normal file
308
src/AmsDataStorage.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#include "AmsDataStorage.h"
|
||||
#include <lwip/apps/sntp.h>
|
||||
#include "EEPROM.h"
|
||||
#include "LittleFS.h"
|
||||
#include "AmsStorage.h"
|
||||
|
||||
AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) {
|
||||
day.version = 3;
|
||||
month.version = 4;
|
||||
this->debugger = debugger;
|
||||
}
|
||||
|
||||
void AmsDataStorage::setTimezone(Timezone* tz) {
|
||||
this->tz = tz;
|
||||
}
|
||||
|
||||
bool AmsDataStorage::update(AmsData* data) {
|
||||
if(data->getListType() != 3) return false;
|
||||
time_t now = time(nullptr);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Time is: %d\n", now);
|
||||
}
|
||||
if(now < EPOCH_2021_01_01) {
|
||||
now = data->getMeterTimestamp();
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) New time is: %d\n", now);
|
||||
}
|
||||
}
|
||||
if(now-day.lastMeterReadTime < 3590) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||
debugger->printf("(AmsDataStorage) It is only %d seconds since last update, ignoring\n", (now-day.lastMeterReadTime));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
tmElements_t tm;
|
||||
breakTime(now, tm);
|
||||
|
||||
if(tm.Minute > 5) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Already %d minutes into the hour, ignoring\n", tm.Minute);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t val = (day.activeImport == 0 ? 0 : ((data->getActiveImportCounter()*1000) - day.activeImport) - ((data->getActiveExportCounter()*1000) - day.activeExport)) / 10;
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Usage for hour %d: %d", tm.Hour, val);
|
||||
}
|
||||
|
||||
if(tm.Hour == 1) {
|
||||
day.h00 = val;
|
||||
} else if(tm.Hour == 2) {
|
||||
day.h01 = val;
|
||||
} else if(tm.Hour == 3) {
|
||||
day.h02 = val;
|
||||
} else if(tm.Hour == 4) {
|
||||
day.h03 = val;
|
||||
} else if(tm.Hour == 5) {
|
||||
day.h04 = val;
|
||||
} else if(tm.Hour == 6) {
|
||||
day.h05 = val;
|
||||
} else if(tm.Hour == 7) {
|
||||
day.h06 = val;
|
||||
} else if(tm.Hour == 8) {
|
||||
day.h07 = val;
|
||||
} else if(tm.Hour == 9) {
|
||||
day.h08 = val;
|
||||
} else if(tm.Hour == 10) {
|
||||
day.h09 = val;
|
||||
} else if(tm.Hour == 11) {
|
||||
day.h10 = val;
|
||||
} else if(tm.Hour == 12) {
|
||||
day.h11 = val;
|
||||
} else if(tm.Hour == 13) {
|
||||
day.h12 = val;
|
||||
} else if(tm.Hour == 14) {
|
||||
day.h13 = val;
|
||||
} else if(tm.Hour == 15) {
|
||||
day.h14 = val;
|
||||
} else if(tm.Hour == 16) {
|
||||
day.h15 = val;
|
||||
} else if(tm.Hour == 17) {
|
||||
day.h16 = val;
|
||||
} else if(tm.Hour == 18) {
|
||||
day.h17 = val;
|
||||
} else if(tm.Hour == 19) {
|
||||
day.h18 = val;
|
||||
} else if(tm.Hour == 20) {
|
||||
day.h19 = val;
|
||||
} else if(tm.Hour == 21) {
|
||||
day.h20 = val;
|
||||
} else if(tm.Hour == 22) {
|
||||
day.h21 = val;
|
||||
} else if(tm.Hour == 23) {
|
||||
day.h22 = val;
|
||||
} else if(tm.Hour == 0) {
|
||||
day.h23 = val;
|
||||
}
|
||||
day.activeImport = data->getActiveImportCounter()*1000;
|
||||
day.activeExport = data->getActiveExportCounter()*1000;
|
||||
day.lastMeterReadTime = now;
|
||||
|
||||
// Update month plot
|
||||
if(tz != NULL) {
|
||||
time_t local = tz->toLocal(now);
|
||||
breakTime(local, tm);
|
||||
}
|
||||
|
||||
if(tm.Hour == 0) {
|
||||
val = (month.activeImport == 0 ? 0 : ((data->getActiveImportCounter()*1000) - month.activeImport) - ((data->getActiveExportCounter()*1000) - month.activeExport)) / 10;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
debugger->printf("(AmsDataStorage) Usage for day %d: %d", tm.Day, val);
|
||||
}
|
||||
|
||||
if(tm.Day == 1) {
|
||||
time_t yesterday = now-3600;
|
||||
breakTime(yesterday, tm);
|
||||
if(tm.Day == 29) {
|
||||
month.d28 = val;
|
||||
} else if(tm.Day == 30) {
|
||||
month.d29 = val;
|
||||
} else if(tm.Day == 31) {
|
||||
month.d30 = val;
|
||||
}
|
||||
} else if(tm.Day == 2) {
|
||||
month.d01 = val;
|
||||
} else if(tm.Day == 3) {
|
||||
month.d02 = val;
|
||||
} else if(tm.Day == 4) {
|
||||
month.d03 = val;
|
||||
} else if(tm.Day == 5) {
|
||||
month.d04 = val;
|
||||
} else if(tm.Day == 6) {
|
||||
month.d05 = val;
|
||||
} else if(tm.Day == 7) {
|
||||
month.d06 = val;
|
||||
} else if(tm.Day == 8) {
|
||||
month.d07 = val;
|
||||
} else if(tm.Day == 9) {
|
||||
month.d08 = val;
|
||||
} else if(tm.Day == 10) {
|
||||
month.d09 = val;
|
||||
} else if(tm.Day == 11) {
|
||||
month.d10 = val;
|
||||
} else if(tm.Day == 12) {
|
||||
month.d11 = val;
|
||||
} else if(tm.Day == 13) {
|
||||
month.d12 = val;
|
||||
} else if(tm.Day == 14) {
|
||||
month.d13 = val;
|
||||
} else if(tm.Day == 15) {
|
||||
month.d14 = val;
|
||||
} else if(tm.Day == 16) {
|
||||
month.d15 = val;
|
||||
} else if(tm.Day == 17) {
|
||||
month.d16 = val;
|
||||
} else if(tm.Day == 18) {
|
||||
month.d17 = val;
|
||||
} else if(tm.Day == 19) {
|
||||
month.d18 = val;
|
||||
} else if(tm.Day == 20) {
|
||||
month.d19 = val;
|
||||
} else if(tm.Day == 21) {
|
||||
month.d20 = val;
|
||||
} else if(tm.Day == 22) {
|
||||
month.d21 = val;
|
||||
} else if(tm.Day == 23) {
|
||||
month.d22 = val;
|
||||
} else if(tm.Day == 24) {
|
||||
month.d23 = val;
|
||||
} else if(tm.Day == 25) {
|
||||
month.d24 = val;
|
||||
} else if(tm.Day == 26) {
|
||||
month.d25 = val;
|
||||
} else if(tm.Day == 27) {
|
||||
month.d26 = val;
|
||||
} else if(tm.Day == 28) {
|
||||
month.d27 = val;
|
||||
} else if(tm.Day == 29) {
|
||||
month.d28 = val;
|
||||
} else if(tm.Day == 30) {
|
||||
month.d29 = val;
|
||||
} else if(tm.Day == 31) {
|
||||
month.d30 = val;
|
||||
}
|
||||
month.activeImport = data->getActiveImportCounter()*1000;
|
||||
month.activeExport = data->getActiveExportCounter()*1000;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DayDataPoints AmsDataStorage::getDayDataPoints() {
|
||||
return day;
|
||||
}
|
||||
|
||||
MonthDataPoints AmsDataStorage::getMonthDataPoints() {
|
||||
return month;
|
||||
}
|
||||
|
||||
bool AmsDataStorage::load(AmsData* meterState) {
|
||||
if(!LittleFS.begin()) {
|
||||
printE("Unable to load LittleFS");
|
||||
return false;
|
||||
}
|
||||
bool ret = false;
|
||||
if(LittleFS.exists(FILE_DAYPLOT)) {
|
||||
File file = LittleFS.open(FILE_DAYPLOT, "r");
|
||||
char buf[file.size()];
|
||||
file.readBytes(buf, file.size());
|
||||
DayDataPoints* day = (DayDataPoints*) buf;
|
||||
file.close();
|
||||
|
||||
if(day->version == 3) {
|
||||
memcpy(&this->day, day, sizeof(this->day));
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(LittleFS.exists(FILE_MONTHPLOT)) {
|
||||
File file = LittleFS.open(FILE_MONTHPLOT, "r");
|
||||
char buf[file.size()];
|
||||
file.readBytes(buf, file.size());
|
||||
MonthDataPoints* month = (MonthDataPoints*) buf;
|
||||
file.close();
|
||||
|
||||
if(month->version == 3) { // dev-1.6
|
||||
month->d25 = month->d26;
|
||||
month->d26 = month->d27;
|
||||
month->d27 = month->d28;
|
||||
month->d28 = month->d29;
|
||||
month->d29 = month->d30;
|
||||
month->d30 = month->d31;
|
||||
month->version = 4;
|
||||
}
|
||||
|
||||
if(month->version == 4) {
|
||||
memcpy(&this->month, month, sizeof(this->month));
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
LittleFS.end();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsDataStorage::save() {
|
||||
if(!LittleFS.begin()) {
|
||||
printE("Unable to load LittleFS");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
File file = LittleFS.open(FILE_DAYPLOT, "w");
|
||||
char buf[sizeof(day)];
|
||||
memcpy(buf, &day, sizeof(day));
|
||||
for(int i = 0; i < sizeof(day); i++) {
|
||||
file.write(buf[i]);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
{
|
||||
File file = LittleFS.open(FILE_MONTHPLOT, "w");
|
||||
char buf[sizeof(month)];
|
||||
memcpy(buf, &month, sizeof(month));
|
||||
for(int i = 0; i < sizeof(month); i++) {
|
||||
file.write(buf[i]);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
LittleFS.end();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AmsDataStorage::printD(String fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf(String("(AmsDataStorage)" + fmt + "\n").c_str(), args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void AmsDataStorage::printI(String fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf(String("(AmsDataStorage)" + fmt + "\n").c_str(), args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void AmsDataStorage::printW(String fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf(String("(AmsDataStorage)" + fmt + "\n").c_str(), args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void AmsDataStorage::printE(String fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(String("(AmsDataStorage)" + fmt + "\n").c_str(), args);
|
||||
va_end(args);
|
||||
}
|
||||
101
src/AmsDataStorage.h
Normal file
101
src/AmsDataStorage.h
Normal file
@@ -0,0 +1,101 @@
|
||||
#ifndef _AMSDATASTORAGE_H
|
||||
#define _AMSDATASTORAGE_H
|
||||
#include "Arduino.h"
|
||||
#include "AmsData.h"
|
||||
#include "RemoteDebug.h"
|
||||
#include "Timezone.h"
|
||||
|
||||
#define EPOCH_2021_01_01 1609459200
|
||||
|
||||
struct DayDataPoints {
|
||||
uint8_t version;
|
||||
int16_t h00;
|
||||
int16_t h01;
|
||||
int16_t h02;
|
||||
int16_t h03;
|
||||
int16_t h04;
|
||||
int16_t h05;
|
||||
int16_t h06;
|
||||
int16_t h07;
|
||||
int16_t h08;
|
||||
int16_t h09;
|
||||
int16_t h10;
|
||||
int16_t h11;
|
||||
int16_t h12;
|
||||
int16_t h13;
|
||||
int16_t h14;
|
||||
int16_t h15;
|
||||
int16_t h16;
|
||||
int16_t h17;
|
||||
int16_t h18;
|
||||
int16_t h19;
|
||||
int16_t h20;
|
||||
int16_t h21;
|
||||
int16_t h22;
|
||||
int16_t h23;
|
||||
time_t lastMeterReadTime;
|
||||
uint32_t activeImport;
|
||||
uint32_t activeExport;
|
||||
}; // 37 bytes
|
||||
|
||||
struct MonthDataPoints {
|
||||
uint8_t version;
|
||||
int16_t d01;
|
||||
int16_t d02;
|
||||
int16_t d03;
|
||||
int16_t d04;
|
||||
int16_t d05;
|
||||
int16_t d06;
|
||||
int16_t d07;
|
||||
int16_t d08;
|
||||
int16_t d09;
|
||||
int16_t d10;
|
||||
int16_t d11;
|
||||
int16_t d12;
|
||||
int16_t d13;
|
||||
int16_t d14;
|
||||
int16_t d15;
|
||||
int16_t d16;
|
||||
int16_t d17;
|
||||
int16_t d18;
|
||||
int16_t d19;
|
||||
int16_t d20;
|
||||
int16_t d21;
|
||||
int16_t d22;
|
||||
int16_t d23;
|
||||
int16_t d24;
|
||||
int16_t d25;
|
||||
int16_t d26;
|
||||
int16_t d27;
|
||||
int16_t d28;
|
||||
int16_t d29;
|
||||
int16_t d30;
|
||||
int16_t d31;
|
||||
time_t lastMeterReadTime;
|
||||
uint32_t activeImport;
|
||||
uint32_t activeExport;
|
||||
}; // 75 bytes
|
||||
|
||||
class AmsDataStorage {
|
||||
public:
|
||||
AmsDataStorage(RemoteDebug*);
|
||||
void setTimezone(Timezone*);
|
||||
bool update(AmsData*);
|
||||
DayDataPoints getDayDataPoints();
|
||||
MonthDataPoints getMonthDataPoints();
|
||||
bool load(AmsData*);
|
||||
bool save();
|
||||
|
||||
private:
|
||||
Timezone* tz;
|
||||
DayDataPoints day;
|
||||
MonthDataPoints month;
|
||||
RemoteDebug* debugger;
|
||||
|
||||
void printD(String fmt, ...);
|
||||
void printI(String fmt, ...);
|
||||
void printW(String fmt, ...);
|
||||
void printE(String fmt, ...);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,4 +7,7 @@
|
||||
#define FILE_MQTT_CERT "/mqtt-cert.pem"
|
||||
#define FILE_MQTT_KEY "/mqtt-key.pem"
|
||||
|
||||
#define FILE_DAYPLOT "/dayplot.bin"
|
||||
#define FILE_MONTHPLOT "/monthplot.bin"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#define INVALID_BUTTON_PIN 0xFFFFFFFF
|
||||
|
||||
#define EPOCH_2021_01_01 1609459200
|
||||
|
||||
#define MAX_PEM_SIZE 4096
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
@@ -18,14 +18,11 @@
|
||||
|
||||
#include "AmsToMqttBridge.h"
|
||||
#include "AmsStorage.h"
|
||||
#include "AmsDataStorage.h"
|
||||
#include <MQTT.h>
|
||||
#include <DNSServer.h>
|
||||
#include <lwip/apps/sntp.h>
|
||||
|
||||
#if defined(ESP8266)
|
||||
ADC_MODE(ADC_VCC);
|
||||
#endif
|
||||
|
||||
#include "HwTools.h"
|
||||
#include "entsoe/EntsoeApi.h"
|
||||
|
||||
@@ -74,6 +71,8 @@ String topic = "ams";
|
||||
AmsData meterState;
|
||||
bool ntpEnabled = false;
|
||||
|
||||
AmsDataStorage ds(&Debug);
|
||||
|
||||
void setup() {
|
||||
WiFiConfig wifi;
|
||||
Serial.begin(115200);
|
||||
@@ -143,7 +142,7 @@ void setup() {
|
||||
SerialConfig serialConfig;
|
||||
#elif defined(ESP32)
|
||||
uint32_t serialConfig;
|
||||
#endif;
|
||||
#endif
|
||||
switch(meterConfig.parity) {
|
||||
case 2:
|
||||
serialConfig = SERIAL_7N1;
|
||||
@@ -186,10 +185,10 @@ void setup() {
|
||||
}
|
||||
|
||||
float vccBootLimit = gpioConfig.vccBootLimit == 0 ? 0 : gpioConfig.vccBootLimit / 10.0;
|
||||
if(vccBootLimit > 0 && (gpioConfig.apPin == 0xFF || digitalRead(gpioConfig.apPin) == HIGH)) { // Skip if user is holding AP button while booting (HIGH = button is released)
|
||||
if(vccBootLimit > 2.5 && vccBootLimit < 3.3 && (gpioConfig.apPin == 0xFF || digitalRead(gpioConfig.apPin) == HIGH)) { // Skip if user is holding AP button while booting (HIGH = button is released)
|
||||
if (vcc < vccBootLimit) {
|
||||
if(Debug.isActive(RemoteDebug::INFO)) {
|
||||
debugI("Voltage is too low, sleeping");
|
||||
Debug.printf("(setup) Voltage is too low (%.2f < %.2f), sleeping\n", vcc, vccBootLimit);
|
||||
Serial.flush();
|
||||
}
|
||||
ESP.deepSleep(10000000); //Deep sleep to allow output cap to charge up
|
||||
@@ -214,7 +213,7 @@ void setup() {
|
||||
if(hasFs) {
|
||||
bool flashed = false;
|
||||
if(LittleFS.exists(FILE_FIRMWARE)) {
|
||||
if (digitalRead(gpioConfig.apPin) == HIGH) {
|
||||
if (gpioConfig.apPin == 0xFF || digitalRead(gpioConfig.apPin) == HIGH) {
|
||||
if(Debug.isActive(RemoteDebug::INFO)) debugI("Found firmware");
|
||||
#if defined(ESP8266)
|
||||
WiFi.setSleepMode(WIFI_LIGHT_SLEEP);
|
||||
@@ -286,7 +285,10 @@ void setup() {
|
||||
TimeChangeRule dst = {"DST", Last, Sun, Mar, 2, (ntp.offset + ntp.summerOffset) / 6};
|
||||
tz = new Timezone(dst, std);
|
||||
ws.setTimezone(tz);
|
||||
ds.setTimezone(tz);
|
||||
}
|
||||
|
||||
ds.load(&meterState);
|
||||
} else {
|
||||
if(Debug.isActive(RemoteDebug::INFO)) {
|
||||
debugI("No configuration, booting AP");
|
||||
@@ -294,7 +296,7 @@ void setup() {
|
||||
swapWifiMode();
|
||||
}
|
||||
|
||||
ws.setup(&config, &gpioConfig, &meterConfig, &meterState, &mqtt);
|
||||
ws.setup(&config, &gpioConfig, &meterConfig, &meterState, &ds, &mqtt);
|
||||
}
|
||||
|
||||
int buttonTimer = 0;
|
||||
@@ -472,7 +474,7 @@ void loop() {
|
||||
}
|
||||
|
||||
void setupHanPort(uint8_t pin, uint32_t baud, uint8_t parityOrdinal, bool invert) {
|
||||
debugI("Setting up HAN on pin %d with baud %d and parity %d", pin, baud, parityOrdinal);
|
||||
if(Debug.isActive(RemoteDebug::INFO)) Debug.printf("(setupHanPort) Setting up HAN on pin %d with baud %d and parity %d\n", pin, baud, parityOrdinal);
|
||||
|
||||
HardwareSerial *hwSerial = NULL;
|
||||
if(pin == 3) {
|
||||
@@ -630,6 +632,7 @@ void mqttMessageReceived(String &topic, String &payload)
|
||||
// Ideas could be to query for values or to initiate OTA firmware update
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
uint8_t buf[BUF_SIZE];
|
||||
HDLCConfig* hc = NULL;
|
||||
int currentMeterType = -1;
|
||||
@@ -648,12 +651,22 @@ void readHanPort() {
|
||||
hanSerial->readBytes(buf, BUF_SIZE);
|
||||
return;
|
||||
}
|
||||
CosemDateTime timestamp;
|
||||
CosemDateTime timestamp = {0};
|
||||
AmsData data;
|
||||
if(currentMeterType == 1) {
|
||||
size_t len = hanSerial->readBytes(buf, BUF_SIZE); // TODO: read one byte at the time. This blocks up the GUI
|
||||
while(hanSerial->available()) {
|
||||
buf[len++] = hanSerial->read();
|
||||
}
|
||||
if(len > 0) {
|
||||
int pos = HDLC_validate((uint8_t *) buf, len, hc, ×tamp);
|
||||
if(pos == HDLC_FRAME_INCOMPLETE) {
|
||||
if(len >= BUF_SIZE) {
|
||||
hanSerial->readBytes(buf, BUF_SIZE);
|
||||
len = 0;
|
||||
debugI("Buffer overflow, resetting");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(pos == HDLC_ENCRYPTION_CONFIG_MISSING) {
|
||||
hc = new HDLCConfig();
|
||||
memcpy(hc->encryption_key, meterConfig.encryptionKey, 16);
|
||||
@@ -673,6 +686,7 @@ void readHanPort() {
|
||||
debugPrint(hc->authentication_tag, 0, 8);
|
||||
}
|
||||
}
|
||||
len = 0;
|
||||
if(pos >= 0) {
|
||||
debugI("Valid HDLC, start at %d", pos);
|
||||
data = IEC6205675(((char *) (buf)) + pos, meterState.getMeterType(), timestamp);
|
||||
@@ -726,6 +740,14 @@ void readHanPort() {
|
||||
mqtt.loop();
|
||||
delay(10);
|
||||
}
|
||||
|
||||
if(ds.update(&data)) {
|
||||
debugI("Saving day plot");
|
||||
ds.save();
|
||||
} else if(data.getListType() == 3) {
|
||||
debugE("Unable to update day plot");
|
||||
}
|
||||
|
||||
meterState.apply(data);
|
||||
}
|
||||
}
|
||||
|
||||
147
src/HwTools.cpp
147
src/HwTools.cpp
@@ -1,4 +1,7 @@
|
||||
#include "HwTools.h"
|
||||
#if defined(ESP8266)
|
||||
ADC_MODE(ADC_VCC);
|
||||
#endif
|
||||
|
||||
void HwTools::setup(GpioConfig* config, AmsConfiguration* amsConf) {
|
||||
this->config = config;
|
||||
@@ -14,18 +17,35 @@ void HwTools::setup(GpioConfig* config, AmsConfiguration* amsConf) {
|
||||
config->tempSensorPin = 0xFF;
|
||||
}
|
||||
|
||||
if(config->vccPin > 0 && config->vccPin < 40) {
|
||||
getAdcChannel(config->vccPin, voltAdc);
|
||||
if(voltAdc.unit != 0xFF) {
|
||||
#if defined(ESP32)
|
||||
if(voltAdc.unit == ADC_UNIT_1) {
|
||||
voltAdcChar = (esp_adc_cal_characteristics_t*) calloc(1, sizeof(esp_adc_cal_characteristics_t));
|
||||
esp_adc_cal_value_t adcVal = esp_adc_cal_characterize((adc_unit_t) voltAdc.unit, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, 1100, voltAdcChar);
|
||||
adc1_config_channel_atten((adc1_channel_t) voltAdc.channel, ADC_ATTEN_DB_6);
|
||||
} else if(voltAdc.unit == ADC_UNIT_2) {
|
||||
voltAdcChar = (esp_adc_cal_characteristics_t*) calloc(1, sizeof(esp_adc_cal_characteristics_t));
|
||||
esp_adc_cal_value_t adcVal = esp_adc_cal_characterize((adc_unit_t) voltAdc.unit, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, 1100, voltAdcChar);
|
||||
adc2_config_channel_atten((adc2_channel_t) voltAdc.channel, ADC_ATTEN_DB_6);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
pinMode(config->vccPin, INPUT);
|
||||
}
|
||||
} else {
|
||||
voltAdc.unit = 0xFF;
|
||||
voltAdc.channel = 0xFF;
|
||||
config->vccPin = 0xFF;
|
||||
}
|
||||
|
||||
if(config->tempAnalogSensorPin > 0 && config->tempAnalogSensorPin < 40) {
|
||||
pinMode(config->tempAnalogSensorPin, INPUT);
|
||||
} else {
|
||||
config->tempAnalogSensorPin = 0xFF;
|
||||
}
|
||||
|
||||
if(config->vccPin > 0 && config->vccPin < 40) {
|
||||
pinMode(config->vccPin, INPUT);
|
||||
} else {
|
||||
config->vccPin = 0xFF;
|
||||
}
|
||||
|
||||
if(config->ledPin > 0 && config->ledPin < 40) {
|
||||
pinMode(config->ledPin, OUTPUT);
|
||||
ledOff(LED_INTERNAL);
|
||||
@@ -55,19 +75,128 @@ void HwTools::setup(GpioConfig* config, AmsConfiguration* amsConf) {
|
||||
}
|
||||
}
|
||||
|
||||
void HwTools::getAdcChannel(uint8_t pin, AdcConfig& config) {
|
||||
config.unit = 0xFF;
|
||||
config.channel = 0xFF;
|
||||
#if defined(ESP32)
|
||||
switch(pin) {
|
||||
case ADC1_CHANNEL_0_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_0;
|
||||
break;
|
||||
case ADC1_CHANNEL_1_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_1;
|
||||
break;
|
||||
case ADC1_CHANNEL_2_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_2;
|
||||
break;
|
||||
case ADC1_CHANNEL_3_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_3;
|
||||
break;
|
||||
case ADC1_CHANNEL_4_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_4;
|
||||
break;
|
||||
case ADC1_CHANNEL_5_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_5;
|
||||
break;
|
||||
case ADC1_CHANNEL_6_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_6;
|
||||
break;
|
||||
case ADC1_CHANNEL_7_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_1;
|
||||
config.channel = ADC1_CHANNEL_7;
|
||||
break;
|
||||
case ADC2_CHANNEL_0_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_0;
|
||||
break;
|
||||
case ADC2_CHANNEL_1_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_1;
|
||||
break;
|
||||
case ADC2_CHANNEL_2_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_2;
|
||||
break;
|
||||
case ADC2_CHANNEL_3_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_3;
|
||||
break;
|
||||
case ADC2_CHANNEL_4_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_4;
|
||||
break;
|
||||
case ADC2_CHANNEL_5_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_5;
|
||||
break;
|
||||
case ADC2_CHANNEL_6_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_6;
|
||||
break;
|
||||
case ADC2_CHANNEL_7_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_7;
|
||||
break;
|
||||
case ADC2_CHANNEL_8_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_8;
|
||||
break;
|
||||
case ADC2_CHANNEL_9_GPIO_NUM:
|
||||
config.unit = ADC_UNIT_2;
|
||||
config.channel = ADC2_CHANNEL_9;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
double HwTools::getVcc() {
|
||||
double volts = 0.0;
|
||||
if(config->vccPin != 0xFF) {
|
||||
#if defined(ESP8266)
|
||||
volts = (analogRead(config->vccPin) / 1024.0) * 3.3;
|
||||
uint32_t x = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x += analogRead(config->vccPin);
|
||||
}
|
||||
volts = x / 10240;
|
||||
#elif defined(ESP32)
|
||||
volts = (analogRead(config->vccPin) / 4095.0) * 3.3;
|
||||
if(voltAdc.unit != 0xFF) {
|
||||
uint32_t x = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if(voltAdc.unit == ADC_UNIT_1) {
|
||||
x += adc1_get_raw((adc1_channel_t) voltAdc.channel);
|
||||
} else if(voltAdc.unit == ADC_UNIT_2) {
|
||||
int v = 0;
|
||||
adc2_get_raw((adc2_channel_t) voltAdc.channel, ADC_WIDTH_BIT_12, &v);
|
||||
x += v;
|
||||
}
|
||||
}
|
||||
x = x / 10;
|
||||
uint32_t voltage = esp_adc_cal_raw_to_voltage(x, voltAdcChar);
|
||||
volts = voltage / 1000.0;
|
||||
} else {
|
||||
uint32_t x = 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
x += analogRead(config->vccPin);
|
||||
}
|
||||
volts = x / 40950;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(ESP8266)
|
||||
volts = ((double) ESP.getVcc()) / 1024.0;
|
||||
volts = ESP.getVcc() / 1024.0;
|
||||
#endif
|
||||
}
|
||||
if(config->vccResistorGnd > 0 && config->vccResistorVcc > 0) {
|
||||
volts *= ((double) (config->vccResistorGnd + config->vccResistorVcc) / config->vccResistorGnd);
|
||||
}
|
||||
|
||||
|
||||
float vccOffset = config->vccOffset / 100.0;
|
||||
float vccMultiplier = config->vccMultiplier / 1000.0;
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <driver/adc.h>
|
||||
#include <esp_adc_cal.h>
|
||||
#include <soc/adc_channel.h>
|
||||
#endif
|
||||
|
||||
#include <DallasTemperature.h>
|
||||
@@ -26,6 +29,11 @@ struct TempSensorData {
|
||||
bool changed;
|
||||
};
|
||||
|
||||
struct AdcConfig {
|
||||
uint8_t unit;
|
||||
uint8_t channel;
|
||||
};
|
||||
|
||||
class HwTools {
|
||||
public:
|
||||
void setup(GpioConfig*, AmsConfiguration*);
|
||||
@@ -43,6 +51,10 @@ public:
|
||||
|
||||
HwTools() {};
|
||||
private:
|
||||
AdcConfig voltAdc, tempAdc;
|
||||
#if defined(ESP32)
|
||||
esp_adc_cal_characteristics_t* voltAdcChar, tempAdcChar;
|
||||
#endif
|
||||
GpioConfig* config;
|
||||
AmsConfiguration* amsConf;
|
||||
bool tempSensorInit;
|
||||
@@ -53,6 +65,7 @@ private:
|
||||
|
||||
bool writeLedPin(uint8_t color, uint8_t state);
|
||||
bool isSensorAddressEqual(uint8_t a[8], uint8_t b[8]);
|
||||
void getAdcChannel(uint8_t pin, AdcConfig&);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "IEC6205675.h"
|
||||
#include "lwip/def.h"
|
||||
#include "Timezone.h"
|
||||
|
||||
IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packageTimestamp) {
|
||||
uint32_t u32;
|
||||
@@ -261,9 +262,21 @@ IEC6205675::IEC6205675(const char* d, uint8_t useMeterType, CosemDateTime packag
|
||||
}
|
||||
}
|
||||
|
||||
time_t ts = getTimestamp(AMS_OBIS_METER_TIMESTAMP, sizeof(AMS_OBIS_METER_TIMESTAMP), ((char *) (d)));
|
||||
if(ts > 0) {
|
||||
meterTimestamp = ts;
|
||||
CosemData* meterTs = findObis(AMS_OBIS_METER_TIMESTAMP, sizeof(AMS_OBIS_METER_TIMESTAMP), ((char *) (d)));
|
||||
if(meterTs != NULL) {
|
||||
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};
|
||||
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};
|
||||
Timezone tz(CEST, CET);
|
||||
|
||||
AmsOctetTimestamp* amst = (AmsOctetTimestamp*) meterTs;
|
||||
time_t ts = getTimestamp(amst->dt);
|
||||
if(meterType == AmsTypeKamstrup || meterType == AmsTypeAidon) {
|
||||
this->packageTimestamp = tz.toUTC(ts);
|
||||
this->meterTimestamp = tz.toUTC(ts);
|
||||
Serial.printf("\nKamstrup/Aidon time: %d\n", meterTimestamp);
|
||||
} else {
|
||||
meterTimestamp = ts;
|
||||
}
|
||||
}
|
||||
|
||||
u32 = getUnsignedNumber(AMS_OBIS_POWER_FACTOR, sizeof(AMS_OBIS_POWER_FACTOR), ((char *) (d)));
|
||||
@@ -425,7 +438,6 @@ time_t IEC6205675::getTimestamp(uint8_t* obis, int matchlength, const char* ptr)
|
||||
case CosemTypeOctetString: {
|
||||
if(item->oct.length == 0x0C) {
|
||||
AmsOctetTimestamp* ts = (AmsOctetTimestamp*) item;
|
||||
//Serial.printf("\nYear: %d, Month: %d, Day: %d, Hour: %d, Minutes %d, Second: %d, Deviation: %d\n", ntohs(ts->dt.year), ts->dt.month, ts->dt.dayOfMonth, ts->dt.hour, ts->dt.minute, ts->dt.second, ntohs(ts->dt.deviation));
|
||||
return getTimestamp(ts->dt);
|
||||
}
|
||||
}
|
||||
@@ -436,13 +448,17 @@ time_t IEC6205675::getTimestamp(uint8_t* obis, int matchlength, const char* ptr)
|
||||
|
||||
time_t IEC6205675::getTimestamp(CosemDateTime timestamp) {
|
||||
tmElements_t tm;
|
||||
tm.Year = ntohs(timestamp.year) - 1970;
|
||||
uint16_t year = ntohs(timestamp.year);
|
||||
if(year < 1970) return 0;
|
||||
tm.Year = year - 1970;
|
||||
tm.Month = timestamp.month;
|
||||
tm.Day = timestamp.dayOfMonth;
|
||||
tm.Hour = timestamp.hour;
|
||||
tm.Minute = timestamp.minute;
|
||||
tm.Second = timestamp.second;
|
||||
|
||||
Serial.printf("\nY: %d, M: %d, D: %d, h: %d, m: %d, s: %d, deviation: 0x%2X, status: 0x%1X\n", tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second, timestamp.deviation, timestamp.status);
|
||||
|
||||
time_t time = makeTime(tm);
|
||||
int16_t deviation = ntohs(timestamp.deviation);
|
||||
if(deviation >= -720 && deviation <= 720) {
|
||||
|
||||
@@ -15,13 +15,15 @@ void mbus_hexdump(const uint8_t* buf, int len) {
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config, CosemDateTime* timestamp) {
|
||||
int HDLC_validate(const uint8_t* d, int length, HDLCConfig* config, CosemDateTime* timestamp) {
|
||||
//mbus_hexdump(d, len);
|
||||
|
||||
HDLCHeader* h = (HDLCHeader*) d;
|
||||
|
||||
// Length field (11 lsb of format)
|
||||
len = (ntohs(h->format) & 0x7FF) + 2;
|
||||
int len = (ntohs(h->format) & 0x7FF) + 2;
|
||||
if(len > length)
|
||||
return -4;
|
||||
|
||||
HDLCFooter* f = (HDLCFooter*) (d + len - sizeof *f);
|
||||
|
||||
@@ -81,11 +83,12 @@ int HDLC_validate(const uint8_t* d, int len, HDLCConfig* config, CosemDateTime*
|
||||
}
|
||||
ptr += 2 + dateTime->base.length;
|
||||
} else if(dateTime->base.type == CosemTypeNull) {
|
||||
timestamp = 0;
|
||||
ptr++;
|
||||
} else if(dateTime->base.type == CosemTypeDateTime) {
|
||||
memcpy(timestamp, ptr, dateTime->base.length);
|
||||
} else if(dateTime->base.type == 0x0C) { // Kamstrup bug...
|
||||
memcpy(timestamp, ptr, dateTime->base.length);
|
||||
memcpy(timestamp, ptr, 0x0C);
|
||||
ptr += 13;
|
||||
} else {
|
||||
return -99;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define HDLC_FLAG 0x7E
|
||||
#define HDLC_BOUNDRY_FLAG_MISSING -1
|
||||
#define HDLC_FRAME_INCOMPLETE -4
|
||||
#define HDLC_ENCRYPTION_CONFIG_MISSING -90
|
||||
|
||||
struct HDLCConfig {
|
||||
|
||||
@@ -179,9 +179,9 @@ bool EntsoeApi::retrieve(const char* url, Stream* doc) {
|
||||
client.setBufferSizes(bufSize, bufSize);
|
||||
}
|
||||
*/
|
||||
|
||||
client.setInsecure();
|
||||
#endif
|
||||
|
||||
client.setInsecure();
|
||||
|
||||
HTTPClient https;
|
||||
https.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#include "root/restart_html.h"
|
||||
#include "root/restartwait_html.h"
|
||||
#include "root/boot_css.h"
|
||||
#include "root/gaugemeter_js.h"
|
||||
#include "root/github_svg.h"
|
||||
#include "root/upload_html.h"
|
||||
#include "root/firmware_html.h"
|
||||
#include "root/delete_html.h"
|
||||
#include "root/reset_html.h"
|
||||
#include "root/temperature_html.h"
|
||||
@@ -41,6 +41,8 @@
|
||||
#include "root/data_json.h"
|
||||
#include "root/tempsensor_json.h"
|
||||
#include "root/lowmem_html.h"
|
||||
#include "root/dayplot_json.h"
|
||||
#include "root/monthplot_json.h"
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
@@ -49,11 +51,12 @@ AmsWebServer::AmsWebServer(RemoteDebug* Debug, HwTools* hw) {
|
||||
this->hw = hw;
|
||||
}
|
||||
|
||||
void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, MeterConfig* meterConfig, AmsData* meterState, MQTTClient* mqtt) {
|
||||
void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, MeterConfig* meterConfig, AmsData* meterState, AmsDataStorage* ds, MQTTClient* mqtt) {
|
||||
this->config = config;
|
||||
this->gpioConfig = gpioConfig;
|
||||
this->meterConfig = meterConfig;
|
||||
this->meterState = meterState;
|
||||
this->ds = ds;
|
||||
this->mqtt = mqtt;
|
||||
|
||||
char jsuri[32];
|
||||
@@ -73,9 +76,10 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
|
||||
server.on("/domoticz",HTTP_GET, std::bind(&AmsWebServer::configDomoticzHtml, this));
|
||||
server.on("/entsoe",HTTP_GET, std::bind(&AmsWebServer::configEntsoeHtml, this));
|
||||
server.on("/boot.css", HTTP_GET, std::bind(&AmsWebServer::bootCss, this));
|
||||
server.on("/gaugemeter.js", HTTP_GET, std::bind(&AmsWebServer::gaugemeterJs, this));
|
||||
server.on("/github.svg", HTTP_GET, std::bind(&AmsWebServer::githubSvg, this));
|
||||
server.on("/data.json", HTTP_GET, std::bind(&AmsWebServer::dataJson, this));
|
||||
server.on("/dayplot.json", HTTP_GET, std::bind(&AmsWebServer::dayplotJson, this));
|
||||
server.on("/monthplot.json", HTTP_GET, std::bind(&AmsWebServer::monthplotJson, this));
|
||||
|
||||
server.on("/save", HTTP_POST, std::bind(&AmsWebServer::handleSave, this));
|
||||
|
||||
@@ -660,13 +664,6 @@ void AmsWebServer::bootCss() {
|
||||
server.send_P(200, "text/css", BOOT_CSS);
|
||||
}
|
||||
|
||||
void AmsWebServer::gaugemeterJs() {
|
||||
printD("Serving /gaugemeter.js over http...");
|
||||
|
||||
server.sendHeader("Cache-Control", "public, max-age=3600");
|
||||
server.send_P(200, "application/javascript", GAUGEMETER_JS);
|
||||
}
|
||||
|
||||
void AmsWebServer::githubSvg() {
|
||||
printD("Serving /github.svg over http...");
|
||||
|
||||
@@ -782,6 +779,95 @@ void AmsWebServer::dataJson() {
|
||||
server.send(200, "application/json", json);
|
||||
}
|
||||
|
||||
void AmsWebServer::dayplotJson() {
|
||||
printD("Serving /dayplot.json over http...");
|
||||
|
||||
DayDataPoints d = ds->getDayDataPoints();
|
||||
|
||||
char json[384];
|
||||
snprintf_P(json, sizeof(json), DAYPLOT_JSON,
|
||||
d.h00 / 100.0,
|
||||
d.h01 / 100.0,
|
||||
d.h02 / 100.0,
|
||||
d.h03 / 100.0,
|
||||
d.h04 / 100.0,
|
||||
d.h05 / 100.0,
|
||||
d.h06 / 100.0,
|
||||
d.h07 / 100.0,
|
||||
d.h08 / 100.0,
|
||||
d.h09 / 100.0,
|
||||
d.h10 / 100.0,
|
||||
d.h11 / 100.0,
|
||||
d.h12 / 100.0,
|
||||
d.h13 / 100.0,
|
||||
d.h14 / 100.0,
|
||||
d.h15 / 100.0,
|
||||
d.h16 / 100.0,
|
||||
d.h17 / 100.0,
|
||||
d.h18 / 100.0,
|
||||
d.h19 / 100.0,
|
||||
d.h20 / 100.0,
|
||||
d.h21 / 100.0,
|
||||
d.h22 / 100.0,
|
||||
d.h23 / 100.0
|
||||
);
|
||||
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
server.setContentLength(strlen(json));
|
||||
server.send(200, "application/json", json);
|
||||
}
|
||||
|
||||
void AmsWebServer::monthplotJson() {
|
||||
printD("Serving /monthplot.json over http...");
|
||||
|
||||
MonthDataPoints m = ds->getMonthDataPoints();
|
||||
|
||||
char json[512];
|
||||
snprintf_P(json, sizeof(json), MONTHPLOT_JSON,
|
||||
m.d01 / 100.0,
|
||||
m.d02 / 100.0,
|
||||
m.d03 / 100.0,
|
||||
m.d04 / 100.0,
|
||||
m.d05 / 100.0,
|
||||
m.d06 / 100.0,
|
||||
m.d07 / 100.0,
|
||||
m.d08 / 100.0,
|
||||
m.d09 / 100.0,
|
||||
m.d10 / 100.0,
|
||||
m.d11 / 100.0,
|
||||
m.d12 / 100.0,
|
||||
m.d13 / 100.0,
|
||||
m.d14 / 100.0,
|
||||
m.d15 / 100.0,
|
||||
m.d16 / 100.0,
|
||||
m.d17 / 100.0,
|
||||
m.d18 / 100.0,
|
||||
m.d19 / 100.0,
|
||||
m.d20 / 100.0,
|
||||
m.d21 / 100.0,
|
||||
m.d22 / 100.0,
|
||||
m.d23 / 100.0,
|
||||
m.d24 / 100.0,
|
||||
m.d25 / 100.0,
|
||||
m.d26 / 100.0,
|
||||
m.d27 / 100.0,
|
||||
m.d28 / 100.0,
|
||||
m.d29 / 100.0,
|
||||
m.d30 / 100.0,
|
||||
m.d31 / 100.0
|
||||
);
|
||||
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
server.sendHeader("Expires", "-1");
|
||||
|
||||
server.setContentLength(strlen(json));
|
||||
server.send(200, "application/json", json);
|
||||
}
|
||||
|
||||
void AmsWebServer::handleSetup() {
|
||||
printD("Handling setup method from http");
|
||||
|
||||
@@ -796,9 +882,6 @@ void AmsWebServer::handleSetup() {
|
||||
|
||||
config->clear();
|
||||
|
||||
config->clearGpio(*gpioConfig);
|
||||
config->clearMeter(*meterConfig);
|
||||
|
||||
switch(sys.boardType) {
|
||||
case 0: // roarfred
|
||||
gpioConfig->hanPin = 3;
|
||||
@@ -922,10 +1005,6 @@ void AmsWebServer::handleSetup() {
|
||||
printD("Unable to set web config");
|
||||
success = false;
|
||||
}
|
||||
if(!config->setMeterConfig(*meterConfig)) {
|
||||
printD("Unable to set meter config");
|
||||
success = false;
|
||||
}
|
||||
if(!config->setGpioConfig(*gpioConfig)) {
|
||||
printD("Unable to set GPIO config");
|
||||
success = false;
|
||||
@@ -1066,6 +1145,8 @@ void AmsWebServer::handleSave() {
|
||||
gpioConfig->vccOffset = server.hasArg("vccOffset") && !server.arg("vccOffset").isEmpty() ? server.arg("vccOffset").toFloat() * 100 : 0;
|
||||
gpioConfig->vccMultiplier = server.hasArg("vccMultiplier") && !server.arg("vccMultiplier").isEmpty() ? server.arg("vccMultiplier").toFloat() * 1000 : 1000;
|
||||
gpioConfig->vccBootLimit = server.hasArg("vccBootLimit") && !server.arg("vccBootLimit").isEmpty() ? server.arg("vccBootLimit").toFloat() * 10 : 0;
|
||||
gpioConfig->vccResistorGnd = server.hasArg("vccResistorGnd") && !server.arg("vccResistorGnd").isEmpty() ? server.arg("vccResistorGnd").toInt() : 0;
|
||||
gpioConfig->vccResistorVcc = server.hasArg("vccResistorVcc") && !server.arg("vccResistorVcc").isEmpty() ? server.arg("vccResistorVcc").toInt() : 0;
|
||||
config->setGpioConfig(*gpioConfig);
|
||||
}
|
||||
|
||||
@@ -1201,6 +1282,9 @@ void AmsWebServer::configGpioHtml() {
|
||||
html.replace("${config.vccMultiplier}", gpioConfig->vccMultiplier > 0 ? String(gpioConfig->vccMultiplier / 1000.0, 2) : "");
|
||||
html.replace("${config.vccBootLimit}", gpioConfig->vccBootLimit > 0 ? String(gpioConfig->vccBootLimit / 10.0, 1) : "");
|
||||
|
||||
html.replace("${config.vccResistorGnd}", gpioConfig->vccResistorGnd > 0 ? String(gpioConfig->vccResistorGnd) : "");
|
||||
html.replace("${config.vccResistorVcc}", gpioConfig->vccResistorVcc > 0 ? String(gpioConfig->vccResistorVcc) : "");
|
||||
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
|
||||
@@ -1372,7 +1456,21 @@ void AmsWebServer::firmwareHtml() {
|
||||
if(!checkSecurity(1))
|
||||
return;
|
||||
|
||||
uploadHtml("Firmware", "/firmware", "system");
|
||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
server.sendHeader("Pragma", "no-cache");
|
||||
|
||||
String html = String((const __FlashStringHelper*) FIRMWARE_HTML);
|
||||
|
||||
#if defined(ESP8266)
|
||||
html.replace("{chipset}", "ESP8266");
|
||||
#elif defined(ESP32)
|
||||
html.replace("{chipset}", "ESP32");
|
||||
#endif
|
||||
|
||||
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
|
||||
server.send_P(200, "text/html", HEAD_HTML);
|
||||
server.sendContent(html);
|
||||
server.sendContent_P(FOOT_HTML);
|
||||
}
|
||||
|
||||
void AmsWebServer::firmwareUpload() {
|
||||
@@ -1519,7 +1617,7 @@ void AmsWebServer::restartWaitHtml() {
|
||||
|
||||
yield();
|
||||
if(performRestart) {
|
||||
LittleFS.end();
|
||||
ds->save();
|
||||
printI("Rebooting");
|
||||
delay(1000);
|
||||
#if defined(ESP8266)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "AmsConfiguration.h"
|
||||
#include "HwTools.h"
|
||||
#include "AmsData.h"
|
||||
#include "AmsDataStorage.h"
|
||||
#include "Uptime.h"
|
||||
#include "RemoteDebug.h"
|
||||
#include "entsoe/EntsoeApi.h"
|
||||
@@ -29,7 +30,7 @@
|
||||
class AmsWebServer {
|
||||
public:
|
||||
AmsWebServer(RemoteDebug* Debug, HwTools* hw);
|
||||
void setup(AmsConfiguration*, GpioConfig*, MeterConfig*, AmsData*, MQTTClient*);
|
||||
void setup(AmsConfiguration*, GpioConfig*, MeterConfig*, AmsData*, AmsDataStorage* ds, MQTTClient*);
|
||||
void loop();
|
||||
void setTimezone(Timezone* tz);
|
||||
void setMqttEnabled(bool);
|
||||
@@ -47,6 +48,7 @@ private:
|
||||
MeterConfig* meterConfig;
|
||||
WebConfig webConfig;
|
||||
AmsData* meterState;
|
||||
AmsDataStorage* ds;
|
||||
MQTTClient* mqtt;
|
||||
bool uploading = false;
|
||||
File file;
|
||||
@@ -76,9 +78,10 @@ private:
|
||||
void configGpioHtml();
|
||||
void configDebugHtml();
|
||||
void bootCss();
|
||||
void gaugemeterJs();
|
||||
void githubSvg();
|
||||
void dataJson();
|
||||
void dayplotJson();
|
||||
void monthplotJson();
|
||||
|
||||
void handleSetup();
|
||||
void handleSave();
|
||||
|
||||
Reference in New Issue
Block a user