mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-26 20:23:41 +00:00
Merge branch 'master' into new-parser
This commit is contained in:
@@ -657,6 +657,14 @@ bool AmsConfiguration::hasConfig() {
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
case 94:
|
||||
configVersion = -1; // Prevent loop
|
||||
if(relocateConfig94()) {
|
||||
configVersion = 95;
|
||||
} else {
|
||||
configVersion = 0;
|
||||
return false;
|
||||
}
|
||||
case EEPROM_CHECK_SUM:
|
||||
return true;
|
||||
default:
|
||||
@@ -822,6 +830,18 @@ bool AmsConfiguration::relocateConfig93() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::relocateConfig94() {
|
||||
EnergyAccountingConfig eac;
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.get(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||
eac.hours = 1;
|
||||
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, 95);
|
||||
bool ret = EEPROM.commit();
|
||||
EEPROM.end();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AmsConfiguration::save() {
|
||||
EEPROM.begin(EEPROM_SIZE);
|
||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
#define EEPROM_SIZE 1024*3
|
||||
#define EEPROM_CHECK_SUM 94 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_CHECK_SUM 95 // Used to check if config is stored. Change if structure changes
|
||||
#define EEPROM_CONFIG_ADDRESS 0
|
||||
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
|
||||
|
||||
@@ -163,7 +163,8 @@ struct EntsoeConfig {
|
||||
|
||||
struct EnergyAccountingConfig {
|
||||
uint8_t thresholds[10];
|
||||
}; // 10
|
||||
uint8_t hours;
|
||||
}; // 11
|
||||
|
||||
struct TempSensorConfig {
|
||||
uint8_t address[8];
|
||||
@@ -266,7 +267,8 @@ private:
|
||||
bool relocateConfig90(); // 2.0.0
|
||||
bool relocateConfig91(); // 2.0.2
|
||||
bool relocateConfig92(); // 2.0.3
|
||||
bool relocateConfig93(); // 2.1 beta
|
||||
bool relocateConfig93(); // 2.1.0
|
||||
bool relocateConfig94(); // 2.1.4
|
||||
|
||||
void saveToFs();
|
||||
bool loadFromFs(uint8_t version);
|
||||
|
||||
@@ -383,17 +383,17 @@ bool AmsDataStorage::isDayHappy() {
|
||||
tmElements_t tm, last;
|
||||
|
||||
if(now < day.lastMeterReadTime) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Day %lld < %lld\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld < %lld\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
||||
return false;
|
||||
}
|
||||
if(now-day.lastMeterReadTime > 3600) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Day %lld - %lld > 3600\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld - %lld > 3600\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
||||
return false;
|
||||
}
|
||||
breakTime(tz->toLocal(now), tm);
|
||||
breakTime(tz->toLocal(day.lastMeterReadTime), last);
|
||||
if(tm.Hour > last.Hour) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Day %d > %d\n", tm.Hour, last.Hour);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %d > %d\n", tm.Hour, last.Hour);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -411,17 +411,17 @@ bool AmsDataStorage::isMonthHappy() {
|
||||
tmElements_t tm, last;
|
||||
|
||||
if(now < month.lastMeterReadTime) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Month %lld < %lld\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld < %lld\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
||||
return false;
|
||||
}
|
||||
if(now-month.lastMeterReadTime > 86400) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Month %lld - %lld > 3600\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld - %lld > 3600\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
||||
return false;
|
||||
}
|
||||
breakTime(tz->toLocal(now), tm);
|
||||
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||
if(tm.Day > last.Day) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(AmsDataStorage) Month %d > %d\n", tm.Day, last.Day);
|
||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %d > %d\n", tm.Day, last.Day);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -377,7 +377,8 @@ void setup() {
|
||||
config.setEnergyAccountingConfig(*eac);
|
||||
config.ackEnergyAccountingChange();
|
||||
}
|
||||
ea.setup(&ds, eapi, eac);
|
||||
ea.setup(&ds, eac);
|
||||
ea.setEapi(eapi);
|
||||
ws.setup(&config, &gpioConfig, &meterConfig, &meterState, &ds, &ea);
|
||||
|
||||
#if defined(ESP32)
|
||||
@@ -523,6 +524,7 @@ void loop() {
|
||||
if(config.getEntsoeConfig(entsoe) && strlen(entsoe.token) > 0) {
|
||||
if(eapi == NULL) {
|
||||
eapi = new EntsoeApi(&Debug);
|
||||
ea.setEapi(eapi);
|
||||
ws.setEntsoeApi(eapi);
|
||||
}
|
||||
eapi->setup(entsoe);
|
||||
@@ -567,7 +569,7 @@ void loop() {
|
||||
if(config.isEnergyAccountingChanged()) {
|
||||
EnergyAccountingConfig *eac = ea.getConfig();
|
||||
config.getEnergyAccountingConfig(*eac);
|
||||
ea.setup(&ds, eapi, eac);
|
||||
ea.setup(&ds, eac);
|
||||
config.ackEnergyAccountingChange();
|
||||
}
|
||||
|
||||
@@ -884,14 +886,14 @@ bool readHanPort() {
|
||||
|
||||
bool saveData = false;
|
||||
if(!ds.isHappy() && now > BUILD_EPOCH) {
|
||||
debugD("Its time to update data storage");
|
||||
debugV("Its time to update data storage");
|
||||
tmElements_t tm;
|
||||
breakTime(now, tm);
|
||||
if(tm.Minute == 0) {
|
||||
debugD(" using actual data");
|
||||
debugV(" using actual data");
|
||||
saveData = ds.update(&data);
|
||||
} else if(meterState.getListType() >= 3) {
|
||||
debugD(" using estimated data");
|
||||
debugV(" using estimated data");
|
||||
saveData = ds.update(&meterState);
|
||||
}
|
||||
if(saveData) {
|
||||
@@ -1406,6 +1408,8 @@ void configFileParse() {
|
||||
bool lNtp = false;
|
||||
bool lEntsoe = false;
|
||||
bool lEac = false;
|
||||
bool sEa = false;
|
||||
bool sDs = false;
|
||||
|
||||
SystemConfig sys;
|
||||
WiFiConfig wifi;
|
||||
@@ -1632,6 +1636,7 @@ void configFileParse() {
|
||||
i++;
|
||||
}
|
||||
ds.setDayData(day);
|
||||
sDs = true;
|
||||
} else if(strncmp(buf, "monthplot ", 10) == 0) {
|
||||
int i = 0;
|
||||
MonthDataPoints month = { 5 }; // Use a version we know the multiplier of the data points
|
||||
@@ -1654,17 +1659,29 @@ void configFileParse() {
|
||||
i++;
|
||||
}
|
||||
ds.setMonthData(month);
|
||||
sDs = true;
|
||||
} else if(strncmp(buf, "energyaccounting ", 17) == 0) {
|
||||
int i = 0;
|
||||
EnergyAccountingData ead = { 1 };
|
||||
uint8_t i = 0;
|
||||
EnergyAccountingData ead = { 3, 0,
|
||||
0, 0, 0,
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
};
|
||||
char * pch = strtok (buf+17," ");
|
||||
while (pch != NULL) {
|
||||
if(i == 1) {
|
||||
if(i == 0) {
|
||||
// Ignore version
|
||||
} else if(i == 1) {
|
||||
long val = String(pch).toInt();
|
||||
ead.month = val;
|
||||
} else if(i == 2) {
|
||||
double val = String(pch).toDouble();
|
||||
ead.maxHour = val * 100;
|
||||
if(val > 0.0) {
|
||||
ead.peaks[0] = { 1, (uint16_t) (val*100) };
|
||||
}
|
||||
} else if(i == 3) {
|
||||
double val = String(pch).toDouble();
|
||||
ead.costYesterday = val * 100;
|
||||
@@ -1674,11 +1691,21 @@ void configFileParse() {
|
||||
} else if(i == 5) {
|
||||
double val = String(pch).toDouble();
|
||||
ead.costLastMonth = val * 100;
|
||||
} else if(i >= 6 && i < 18) {
|
||||
uint8_t hour = i-6;
|
||||
if(hour%2 == 0) {
|
||||
long val = String(pch).toInt();
|
||||
ead.peaks[hour/2].day = val;
|
||||
} else {
|
||||
double val = String(pch).toDouble();
|
||||
ead.peaks[hour/2].value = val * 100;
|
||||
}
|
||||
}
|
||||
pch = strtok (NULL, " ");
|
||||
i++;
|
||||
}
|
||||
ea.setData(ead);
|
||||
sEa = true;
|
||||
}
|
||||
memset(buf, 0, 1024);
|
||||
}
|
||||
@@ -1698,7 +1725,7 @@ void configFileParse() {
|
||||
if(lDomo) config.setDomoticzConfig(domo);
|
||||
if(lNtp) config.setNtpConfig(ntp);
|
||||
if(lEntsoe) config.setEntsoeConfig(entsoe);
|
||||
ds.save();
|
||||
ea.save();
|
||||
if(sDs) ds.save();
|
||||
if(sEa) ea.save();
|
||||
config.save();
|
||||
}
|
||||
|
||||
@@ -8,13 +8,16 @@ EnergyAccounting::EnergyAccounting(RemoteDebug* debugger) {
|
||||
this->debugger = debugger;
|
||||
}
|
||||
|
||||
void EnergyAccounting::setup(AmsDataStorage *ds, EntsoeApi *eapi, EnergyAccountingConfig *config) {
|
||||
void EnergyAccounting::setup(AmsDataStorage *ds, EnergyAccountingConfig *config) {
|
||||
this->ds = ds;
|
||||
this->eapi = eapi;
|
||||
this->config = config;
|
||||
this->currentThresholdIdx = 0;
|
||||
}
|
||||
|
||||
void EnergyAccounting::setEapi(EntsoeApi *eapi) {
|
||||
this->eapi = eapi;
|
||||
}
|
||||
|
||||
EnergyAccountingConfig* EnergyAccounting::getConfig() {
|
||||
return config;
|
||||
}
|
||||
@@ -24,6 +27,7 @@ void EnergyAccounting::setTimezone(Timezone* tz) {
|
||||
}
|
||||
|
||||
bool EnergyAccounting::update(AmsData* amsData) {
|
||||
if(config == NULL) return false;
|
||||
time_t now = time(nullptr);
|
||||
if(now < BUILD_EPOCH) return false;
|
||||
if(tz == NULL) {
|
||||
@@ -38,24 +42,39 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
if(!init) {
|
||||
currentHour = local.Hour;
|
||||
currentDay = local.Day;
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Initializing data at %lld\n", (int64_t) now);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing data at %lld\n", (int64_t) now);
|
||||
if(!load()) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Unable to load existing data");
|
||||
data = { 1, local.Month, 0, 0, 0, 0 };
|
||||
if(calcDayUse()) ret = true;
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Unable to load existing data\n");
|
||||
data = { 3, local.Month,
|
||||
0, 0, 0,
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
};
|
||||
} else if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
debugger->printf("(EnergyAccounting) Peak hour from day %d: %d\n", data.peaks[i].day, data.peaks[i].value*10);
|
||||
}
|
||||
debugger->printf("(EnergyAccounting) Loaded cost yesterday: %d, this month: %d, last month: %d\n", data.costYesterday, data.costThisMonth, data.costLastMonth);
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
if(!initPrice && eapi != NULL && eapi->getValueForHour(0) != ENTSOE_NO_VALUE) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Initializing prices at %lld\n", (int64_t) now);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Initializing prices at %lld\n", (int64_t) now);
|
||||
calcDayCost();
|
||||
}
|
||||
|
||||
if(local.Hour != currentHour && (amsData->getListType() >= 3 || local.Minute == 1)) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) New local hour %d\n", local.Hour);
|
||||
|
||||
if(calcDayUse()) ret = true;
|
||||
tmElements_t oneHrAgo;
|
||||
breakTime(now-3600, oneHrAgo);
|
||||
uint16_t val = ds->getHourImport(oneHrAgo.Hour) / 10;
|
||||
ret |= updateMax(val, local.Day);
|
||||
|
||||
if(local.Hour > 0) {
|
||||
calcDayCost();
|
||||
}
|
||||
@@ -77,7 +96,9 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) New month %d\n", local.Month);
|
||||
data.costLastMonth = data.costThisMonth;
|
||||
data.costThisMonth = 0;
|
||||
data.maxHour = 0;
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
data.peaks[i] = { 0, 0 };
|
||||
}
|
||||
data.month = local.Month;
|
||||
currentThresholdIdx = 0;
|
||||
ret = true;
|
||||
@@ -108,24 +129,6 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EnergyAccounting::calcDayUse() {
|
||||
time_t now = time(nullptr);
|
||||
tmElements_t local, utc;
|
||||
breakTime(tz->toLocal(now), local);
|
||||
|
||||
bool ret = false;
|
||||
uint8_t lim = local.Day == 1 ? local.Hour : 24;
|
||||
for(int i = 0; i < lim; i++) {
|
||||
breakTime(now - ((lim - i) * 3600), utc);
|
||||
int16_t val = ds->getHourImport(utc.Hour) / 10.0;
|
||||
if(val > data.maxHour) {
|
||||
data.maxHour = val;
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EnergyAccounting::calcDayCost() {
|
||||
time_t now = time(nullptr);
|
||||
tmElements_t local, utc;
|
||||
@@ -203,7 +206,31 @@ uint8_t EnergyAccounting::getCurrentThreshold() {
|
||||
}
|
||||
|
||||
float EnergyAccounting::getMonthMax() {
|
||||
return data.maxHour / 100.0;
|
||||
uint8_t count = 0;
|
||||
uint32_t maxHour = 0.0;
|
||||
bool included[5] = { false, false, false, false, false };
|
||||
|
||||
while(count < config->hours) {
|
||||
uint8_t maxIdx = 0;
|
||||
uint16_t maxVal = 0;
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
if(included[i]) continue;
|
||||
if(data.peaks[i].value > maxVal) {
|
||||
maxVal = data.peaks[i].value;
|
||||
maxIdx = i;
|
||||
}
|
||||
}
|
||||
included[maxIdx] = true;
|
||||
count++;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
if(!included[i]) continue;
|
||||
if(data.peaks[i].day > 0) {
|
||||
maxHour += data.peaks[i].value;
|
||||
}
|
||||
}
|
||||
return maxHour > 0 ? maxHour / count / 100.0 : 0.0;
|
||||
}
|
||||
|
||||
bool EnergyAccounting::load() {
|
||||
@@ -219,15 +246,53 @@ bool EnergyAccounting::load() {
|
||||
File file = LittleFS.open(FILE_ENERGYACCOUNTING, "r");
|
||||
char buf[file.size()];
|
||||
file.readBytes(buf, file.size());
|
||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||
file.close();
|
||||
|
||||
if(data->version == 1) {
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Data version %d\n", buf[0]);
|
||||
if(buf[0] == 3) {
|
||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||
memcpy(&this->data, data, sizeof(this->data));
|
||||
ret = true;
|
||||
} else {
|
||||
ret = false;
|
||||
data = { 3, 0,
|
||||
0, 0, 0,
|
||||
0, 0, // Peak 1
|
||||
0, 0, // Peak 2
|
||||
0, 0, // Peak 3
|
||||
0, 0, // Peak 4
|
||||
0, 0 // Peak 5
|
||||
};
|
||||
if(buf[0] == 2) {
|
||||
EnergyAccountingData1* data = (EnergyAccountingData1*) buf;
|
||||
this->data.month = data->month;
|
||||
this->data.costYesterday = data->costYesterday;
|
||||
this->data.costThisMonth = data->costThisMonth;
|
||||
this->data.costLastMonth = data->costLastMonth;
|
||||
uint8_t b = 0;
|
||||
for(uint8_t i = sizeof(this->data); i < file.size(); i+=2) {
|
||||
this->data.peaks[b].day = b;
|
||||
memcpy(&this->data.peaks[b].value, buf+i, 2);
|
||||
b++;
|
||||
if(b >= config->hours) break;
|
||||
}
|
||||
ret = true;
|
||||
} else if(buf[0] == 1) {
|
||||
EnergyAccountingData1* data = (EnergyAccountingData1*) buf;
|
||||
this->data.month = data->month;
|
||||
this->data.costYesterday = data->costYesterday;
|
||||
this->data.costThisMonth = data->costThisMonth;
|
||||
this->data.costLastMonth = data->costLastMonth;
|
||||
this->data.peaks[0].day = 1;
|
||||
this->data.peaks[0].value = data->maxHour;
|
||||
ret = true;
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf("(EnergyAccounting) Unknown version\n");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf("(EnergyAccounting) File not found\n");
|
||||
}
|
||||
|
||||
LittleFS.end();
|
||||
@@ -246,7 +311,7 @@ bool EnergyAccounting::save() {
|
||||
File file = LittleFS.open(FILE_ENERGYACCOUNTING, "w");
|
||||
char buf[sizeof(data)];
|
||||
memcpy(buf, &data, sizeof(data));
|
||||
for(unsigned long i = 0; i < sizeof(data); i++) {
|
||||
for(uint8_t i = 0; i < sizeof(buf); i++) {
|
||||
file.write(buf[i]);
|
||||
}
|
||||
file.close();
|
||||
@@ -263,3 +328,34 @@ EnergyAccountingData EnergyAccounting::getData() {
|
||||
void EnergyAccounting::setData(EnergyAccountingData& data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
bool EnergyAccounting::updateMax(uint16_t val, uint8_t day) {
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
if(data.peaks[i].day == day || data.peaks[i].day == 0) {
|
||||
if(val > data.peaks[i].value) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Adding new max %d for day %d which is larger than %d\n", val*10, day, data.peaks[i].value*10);
|
||||
data.peaks[i].day = day;
|
||||
data.peaks[i].value = val;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
uint16_t test = 0;
|
||||
uint8_t idx = 255;
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
if(val > data.peaks[i].value) {
|
||||
if(test < data.peaks[i].value) {
|
||||
test = data.peaks[i].value;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(idx < 5) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Adding new max %d for day %d\n", val*10, day);
|
||||
data.peaks[idx].value = val;
|
||||
data.peaks[idx].day = day;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -6,7 +6,21 @@
|
||||
#include "AmsDataStorage.h"
|
||||
#include "entsoe/EntsoeApi.h"
|
||||
|
||||
struct EnergyAccountingPeak {
|
||||
uint8_t day;
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
struct EnergyAccountingData {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
EnergyAccountingPeak peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingData1 {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t maxHour;
|
||||
@@ -15,13 +29,16 @@ struct EnergyAccountingData {
|
||||
uint16_t costLastMonth;
|
||||
};
|
||||
|
||||
|
||||
class EnergyAccounting {
|
||||
public:
|
||||
EnergyAccounting(RemoteDebug*);
|
||||
void setup(AmsDataStorage *ds, EntsoeApi *eapi, EnergyAccountingConfig *config);
|
||||
void setup(AmsDataStorage *ds, EnergyAccountingConfig *config);
|
||||
void setEapi(EntsoeApi *eapi);
|
||||
void setTimezone(Timezone*);
|
||||
EnergyAccountingConfig* getConfig();
|
||||
bool update(AmsData* amsData);
|
||||
bool load();
|
||||
bool save();
|
||||
|
||||
double getUseThisHour();
|
||||
@@ -51,9 +68,8 @@ private:
|
||||
double use, costHour, costDay;
|
||||
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
bool load();
|
||||
bool calcDayUse();
|
||||
void calcDayCost();
|
||||
bool updateMax(uint16_t val, uint8_t day);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -606,6 +606,7 @@ void AmsWebServer::configThresholdsHtml() {
|
||||
for(int i = 0; i < 9; i++) {
|
||||
html.replace("{t" + String(i) + "}", String(config->thresholds[i]));
|
||||
}
|
||||
html.replace("{h}", String(config->hours));
|
||||
|
||||
server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN);
|
||||
server.send_P(200, MIME_HTML, HEAD_HTML);
|
||||
@@ -1353,6 +1354,7 @@ void AmsWebServer::handleSave() {
|
||||
eac.thresholds[6] = server.arg("t6").toInt();
|
||||
eac.thresholds[7] = server.arg("t7").toInt();
|
||||
eac.thresholds[8] = server.arg("t8").toInt();
|
||||
eac.hours = server.arg("h").toInt();
|
||||
config->setEnergyAccountingConfig(eac);
|
||||
}
|
||||
|
||||
@@ -2268,7 +2270,7 @@ void AmsWebServer::configFileDownload() {
|
||||
EnergyAccountingConfig eac;
|
||||
config->getEnergyAccountingConfig(eac);
|
||||
|
||||
if(eac.thresholds[9] > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("thresholds %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
if(eac.thresholds[9] > 0) server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("thresholds %d %d %d %d %d %d %d %d %d %d %d\n"),
|
||||
eac.thresholds[0],
|
||||
eac.thresholds[1],
|
||||
eac.thresholds[2],
|
||||
@@ -2278,7 +2280,8 @@ void AmsWebServer::configFileDownload() {
|
||||
eac.thresholds[6],
|
||||
eac.thresholds[7],
|
||||
eac.thresholds[8],
|
||||
eac.thresholds[9]
|
||||
eac.thresholds[9],
|
||||
eac.hours
|
||||
));
|
||||
}
|
||||
|
||||
@@ -2424,15 +2427,28 @@ void AmsWebServer::configFileDownload() {
|
||||
}
|
||||
|
||||
if(ea != NULL) {
|
||||
EnergyAccountingConfig eac;
|
||||
config->getEnergyAccountingConfig(eac);
|
||||
EnergyAccountingData ead = ea->getData();
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("energyaccounting %d %d %.2f %.2f %.2f %.2f"),
|
||||
server.sendContent(buf, snprintf_P(buf, BufferSize, (char*) F("energyaccounting %d %d %.2f %.2f %.2f %.2f %d %.2f %d %.2f %d %.2f %d %.2f %d %.2f"),
|
||||
ead.version,
|
||||
ead.month,
|
||||
ead.maxHour / 100.0,
|
||||
0.0, // Old max
|
||||
ead.costYesterday / 100.0,
|
||||
ead.costThisMonth / 100.0,
|
||||
ead.costLastMonth / 100.0
|
||||
ead.costLastMonth / 100.0,
|
||||
ead.peaks[0].day,
|
||||
ead.peaks[0].value / 100.0,
|
||||
ead.peaks[1].day,
|
||||
ead.peaks[1].value / 100.0,
|
||||
ead.peaks[2].day,
|
||||
ead.peaks[2].value / 100.0,
|
||||
ead.peaks[3].day,
|
||||
ead.peaks[3].value / 100.0,
|
||||
ead.peaks[4].day,
|
||||
ead.peaks[4].value / 100.0
|
||||
));
|
||||
server.sendContent("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user