mirror of
https://github.com/UtilitechAS/amsreader-firmware.git
synced 2026-01-17 09:02:11 +00:00
Limit threshold average to use a single peak per day
This commit is contained in:
parent
a90ed40aee
commit
7f3e0e6089
@ -1677,9 +1677,14 @@ void configFileParse() {
|
||||
sDs = true;
|
||||
} else if(strncmp(buf, "energyaccounting ", 17) == 0) {
|
||||
uint8_t i = 0;
|
||||
EnergyAccountingData ead = { 2 };
|
||||
long hours = 0;
|
||||
uint16_t *maxHours = NULL;
|
||||
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 == 0) {
|
||||
@ -1689,7 +1694,9 @@ void configFileParse() {
|
||||
ead.month = val;
|
||||
} else if(i == 2) {
|
||||
double val = String(pch).toDouble();
|
||||
ead.unused = 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;
|
||||
@ -1699,33 +1706,20 @@ void configFileParse() {
|
||||
} else if(i == 5) {
|
||||
double val = String(pch).toDouble();
|
||||
ead.costLastMonth = val * 100;
|
||||
} else if(i == 6) {
|
||||
hours = String(pch).toInt();
|
||||
debugD("Got %d max hours", hours);
|
||||
Serial.flush();
|
||||
if(hours > 0 && hours < 6) {
|
||||
maxHours = new uint16_t[hours];
|
||||
for(uint8_t x = 0; x < hours; x++) {
|
||||
maxHours[x] = 0;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
} else if(i >= 7 && i < hours+7) {
|
||||
uint8_t hour = i-7;
|
||||
double val = String(pch).toDouble();
|
||||
debugD(" hour %d: %.2f", hour, val);
|
||||
maxHours[hour] = val * 100;
|
||||
}
|
||||
pch = strtok (NULL, " ");
|
||||
i++;
|
||||
}
|
||||
ea.setData(ead);
|
||||
if(maxHours == NULL) {
|
||||
maxHours = new uint16_t[3];
|
||||
for(i = 0; i < 3; i++) {
|
||||
maxHours[i] = 0;
|
||||
}
|
||||
}
|
||||
ea.setMaxHours(maxHours);
|
||||
sEa = true;
|
||||
}
|
||||
memset(buf, 0, 1024);
|
||||
|
||||
@ -12,17 +12,6 @@ void EnergyAccounting::setup(AmsDataStorage *ds, EnergyAccountingConfig *config)
|
||||
this->ds = ds;
|
||||
this->config = config;
|
||||
this->currentThresholdIdx = 0;
|
||||
uint16_t *maxHours = new uint16_t[config->hours];
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
maxHours[i] = 0;
|
||||
}
|
||||
if(this->maxHours != NULL) {
|
||||
for(uint8_t i = 0; i < sizeof(this->maxHours)/2 && i < config->hours; i++) {
|
||||
maxHours[i] = this->maxHours[i];
|
||||
}
|
||||
delete(this->maxHours);
|
||||
}
|
||||
this->maxHours = maxHours;
|
||||
}
|
||||
|
||||
void EnergyAccounting::setEapi(EntsoeApi *eapi) {
|
||||
@ -56,15 +45,17 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
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\n");
|
||||
data = { 2, local.Month, 0, 0, 0, 0 };
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
maxHours[i] = 0;
|
||||
break;
|
||||
}
|
||||
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)) {
|
||||
debugger->printf("(EnergyAccounting) Loaded max calculated from %d hours with highest consumption\n", config->hours);
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
debugger->printf("(EnergyAccounting) hour %d: %d\n", i+1, maxHours[i]*10);
|
||||
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);
|
||||
}
|
||||
@ -81,21 +72,8 @@ bool EnergyAccounting::update(AmsData* amsData) {
|
||||
|
||||
tmElements_t oneHrAgo;
|
||||
breakTime(now-3600, oneHrAgo);
|
||||
uint32_t val = ds->getHourImport(oneHrAgo.Hour) / 10;
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
if(val > maxHours[i]) {
|
||||
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EnergyAccounting) Adding new max (%d) which is larger than %d\n", val*10, maxHours[i]*10);
|
||||
maxHours[i] = val;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||
debugger->printf("(EnergyAccounting) Current max calculated from %d hours with highest consumption\n", config->hours);
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
debugger->printf("(EnergyAccounting) hour %d: %.2f\n", i+1, maxHours[i]/100.0);
|
||||
}
|
||||
}
|
||||
uint16_t val = ds->getHourImport(oneHrAgo.Hour) / 10;
|
||||
ret |= updateMax(val, local.Day);
|
||||
|
||||
if(local.Hour > 0) {
|
||||
calcDayCost();
|
||||
@ -118,8 +96,8 @@ 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;
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
maxHours[i] = 0;
|
||||
for(uint8_t i = 0; i < 5; i++) {
|
||||
data.peaks[i] = { 0, 0 };
|
||||
}
|
||||
data.month = local.Month;
|
||||
currentThresholdIdx = 0;
|
||||
@ -230,10 +208,26 @@ uint8_t EnergyAccounting::getCurrentThreshold() {
|
||||
float EnergyAccounting::getMonthMax() {
|
||||
uint8_t count = 0;
|
||||
uint32_t maxHour = 0.0;
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
if(maxHours[i] > 0) {
|
||||
maxHour += maxHours[i];
|
||||
count++;
|
||||
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;
|
||||
@ -252,30 +246,48 @@ bool EnergyAccounting::load() {
|
||||
File file = LittleFS.open(FILE_ENERGYACCOUNTING, "r");
|
||||
char buf[file.size()];
|
||||
file.readBytes(buf, file.size());
|
||||
EnergyAccountingData* data = (EnergyAccountingData*) buf;
|
||||
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Data version %d\n", data->version);
|
||||
if(data->version == 2) {
|
||||
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));
|
||||
uint8_t b = 0;
|
||||
for(uint8_t i = sizeof(this->data); i < file.size(); i+=2) {
|
||||
memcpy(&this->maxHours[b], buf+i, 2);
|
||||
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EnergyAccounting) Loading max hour %d: %.2f\n", b, this->maxHours[b] / 100.0);
|
||||
b++;
|
||||
if(b >= config->hours) break;
|
||||
}
|
||||
ret = true;
|
||||
} else if(data->version == 1) {
|
||||
memcpy(&this->data, data, sizeof(this->data));
|
||||
for(uint8_t i = 0; i < config->hours; i++) {
|
||||
maxHours[i] = data->unused;
|
||||
}
|
||||
data->unused = 0;
|
||||
data->version = 2;
|
||||
ret = true;
|
||||
} else {
|
||||
if(debugger->isActive(RemoteDebug::WARNING)) debugger->printf("(EnergyAccounting) Unknown version\n");
|
||||
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();
|
||||
@ -297,11 +309,8 @@ bool EnergyAccounting::save() {
|
||||
}
|
||||
{
|
||||
File file = LittleFS.open(FILE_ENERGYACCOUNTING, "w");
|
||||
char buf[sizeof(data)+sizeof(this->maxHours)];
|
||||
char buf[sizeof(data)];
|
||||
memcpy(buf, &data, sizeof(data));
|
||||
for(uint8_t i = 0; i < sizeof(this->maxHours)/2; i++) {
|
||||
memcpy(buf+sizeof(data)+(i*2), &this->maxHours[i], 2);
|
||||
}
|
||||
for(uint8_t i = 0; i < sizeof(buf); i++) {
|
||||
file.write(buf[i]);
|
||||
}
|
||||
@ -320,19 +329,33 @@ void EnergyAccounting::setData(EnergyAccountingData& data) {
|
||||
this->data = data;
|
||||
}
|
||||
|
||||
uint16_t * EnergyAccounting::getMaxHours() {
|
||||
return maxHours;
|
||||
}
|
||||
|
||||
void EnergyAccounting::setMaxHours(uint16_t * maxHours) {
|
||||
if(this->maxHours == NULL) {
|
||||
if(config == NULL) {
|
||||
this->maxHours = new uint16_t[sizeof(maxHours)/2];
|
||||
} else {
|
||||
this->maxHours = new uint16_t[config->hours];
|
||||
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;
|
||||
}
|
||||
}
|
||||
for(uint8_t i = 0; i < sizeof(this->maxHours)/2; i++) {
|
||||
this->maxHours[i] = maxHours[i];
|
||||
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,15 +6,30 @@
|
||||
#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 unused;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
EnergyAccountingPeak peaks[5];
|
||||
};
|
||||
|
||||
struct EnergyAccountingData1 {
|
||||
uint8_t version;
|
||||
uint8_t month;
|
||||
uint16_t maxHour;
|
||||
uint16_t costYesterday;
|
||||
uint16_t costThisMonth;
|
||||
uint16_t costLastMonth;
|
||||
};
|
||||
|
||||
|
||||
class EnergyAccounting {
|
||||
public:
|
||||
EnergyAccounting(RemoteDebug*);
|
||||
@ -40,8 +55,6 @@ public:
|
||||
|
||||
EnergyAccountingData getData();
|
||||
void setData(EnergyAccountingData&);
|
||||
uint16_t * getMaxHours();
|
||||
void setMaxHours(uint16_t * maxHours);
|
||||
|
||||
private:
|
||||
RemoteDebug* debugger = NULL;
|
||||
@ -54,9 +67,9 @@ private:
|
||||
uint8_t currentHour = 0, currentDay = 0, currentThresholdIdx = 0;
|
||||
double use, costHour, costDay;
|
||||
EnergyAccountingData data = { 0, 0, 0, 0, 0, 0 };
|
||||
uint16_t *maxHours = NULL;
|
||||
|
||||
void calcDayCost();
|
||||
bool updateMax(uint16_t val, uint8_t day);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -2430,21 +2430,24 @@ void AmsWebServer::configFileDownload() {
|
||||
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,
|
||||
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
|
||||
));
|
||||
if(eac.hours > 0) {
|
||||
uint16_t *maxHours = ea->getMaxHours();
|
||||
server.sendContent(buf, snprintf(buf, BufferSize, " %d", eac.hours));
|
||||
for(int i = 0; i < eac.hours; i++) {
|
||||
server.sendContent(buf, snprintf(buf, BufferSize, " %.2f", maxHours[i]/100.0));
|
||||
}
|
||||
}
|
||||
server.sendContent("\n");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user