Fixed backup and restore of price modifiers (#925) (#932)

* Fix: #925 - Backup/restore of price modifiers

* Removed unused importy
This commit is contained in:
Gunnar Skjold
2025-03-24 08:58:31 +01:00
committed by GitHub
parent 792ae4c935
commit 8a35346fcf
3 changed files with 187 additions and 54 deletions

View File

@@ -336,17 +336,17 @@ bool PriceService::retrieve(const char* url, Stream* doc) {
nextFetchDelayMinutes = 2;
}
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Communication error, returned status: %d\n"), status);
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Communication error, returned status: %d\n"), status);
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf(http->errorToString(status).c_str());
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf(http->errorToString(status).c_str());
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf(http->getString().c_str());
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf(http->getString().c_str());
http->end();
return false;
@@ -393,18 +393,18 @@ float PriceService::getCurrencyMultiplier(const char* from, const char* to, time
}
if(currencyMultiplier != 0) {
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) Resulting currency multiplier: %.4f\n"), currencyMultiplier);
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) Resulting currency multiplier: %.4f\n"), currencyMultiplier);
tmElements_t tm;
breakTime(t, tm);
lastCurrencyFetch = now + (SECS_PER_DAY * 1000) - (((((tm.Hour * 60) + tm.Minute) * 60) + tm.Second) * 1000) + (3600000 * 6) + (tomorrowFetchMinute * 60);
this->currencyMultiplier = currencyMultiplier;
} else {
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::WARNING))
#endif
debugger->printf_P(PSTR("(PriceService) Multiplier ended in success, but without value\n"));
if (debugger->isActive(RemoteDebug::WARNING))
#endif
debugger->printf_P(PSTR("(PriceService) Multiplier ended in success, but without value\n"));
lastCurrencyFetch = now + (SECS_PER_HOUR * 1000);
if(this->currencyMultiplier == 1) return 0;
}
@@ -435,13 +435,13 @@ PricesContainer* PriceService::fetchPrices(time_t t) {
#endif
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Fetching prices for %02d.%02d.%04d\n"), tm.Day, tm.Month, tm.Year+1970);
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Fetching prices for %02d.%02d.%04d\n"), tm.Day, tm.Month, tm.Year+1970);
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
EntsoeA44Parser a44;
if(retrieve(buf, &a44) && a44.getPoint(0) != PRICE_NO_VALUE) {
PricesContainer* ret = new PricesContainer();
@@ -463,13 +463,13 @@ debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
config->currency
);
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Fetching prices for %02d.%02d.%04d\n"), tm.Day, tm.Month, tm.Year+1970);
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Fetching prices for %02d.%02d.%04d\n"), tm.Day, tm.Month, tm.Year+1970);
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
#if defined(ESP8266)
WiFiClient client;
client.setTimeout(5000);
@@ -511,9 +511,9 @@ debugger->printf_P(PSTR("(PriceService) url: %s\n"), buf);
lastError = gcmRet;
nextFetchDelayMinutes = 60;
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Error code while decrypting prices: %d\n"), gcmRet);
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Error code while decrypting prices: %d\n"), gcmRet);
}
} else {
lastError = status;
@@ -525,20 +525,20 @@ debugger->printf_P(PSTR("(PriceService) Error code while decrypting prices: %d\n
nextFetchDelayMinutes = 5;
}
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Communication error, returned status: %d\n"), status);
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Communication error, returned status: %d\n"), status);
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
{
if (debugger->isActive(RemoteDebug::ERROR))
#endif
{
debugger->printf(http->errorToString(status).c_str());
debugger->println();
}
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf(http->getString().c_str());
if (debugger->isActive(RemoteDebug::DEBUG))
#endif
debugger->printf(http->getString().c_str());
http->end();
}
@@ -575,16 +575,16 @@ void PriceService::cropPriceConfig(uint8_t size) {
bool PriceService::save() {
if(!LittleFS.begin()) {
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Unable to load LittleFS\n"));
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Unable to load LittleFS\n"));
return false;
}
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Saving price config\n"));
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Saving price config\n"));
PriceConfig pc;
File file = LittleFS.open(FILE_PRICE_CONF, "w");
@@ -607,18 +607,18 @@ debugger->printf_P(PSTR("(PriceService) Saving price config\n"));
bool PriceService::load() {
if(!LittleFS.begin()) {
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Unable to load LittleFS\n"));
if (debugger->isActive(RemoteDebug::ERROR))
#endif
debugger->printf_P(PSTR("(PriceService) Unable to load LittleFS\n"));
return false;
}
if(!LittleFS.exists(FILE_PRICE_CONF)) {
return false;
}
#if defined(AMS_REMOTE_DEBUG)
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Loading price config\n"));
if (debugger->isActive(RemoteDebug::INFO))
#endif
debugger->printf_P(PSTR("(PriceService) Loading price config\n"));
this->priceConfig.clear();

View File

@@ -2342,6 +2342,8 @@ void AmsWebServer::configFileDownload() {
case PRICE_DIRECTION_BOTH:
strcpy_P(direction, PSTR("both"));
break;
default:
strcpy_P(direction, PSTR("--"));
}
char type[9] = "";
switch(p.type) {
@@ -2357,11 +2359,38 @@ void AmsWebServer::configFileDownload() {
case PRICE_TYPE_SUBTRACT:
strcpy_P(type, PSTR("subtract"));
break;
default:
strcpy_P(direction, PSTR("--"));
}
char days[3*7] = "";
if(p.days == 0x7F) {
strcpy_P(days, PSTR("all"));
} else {
if((p.days >> 0) & 0x01) strcat_P(days, PSTR("mo,"));
if((p.days >> 1) & 0x01) strcat_P(days, PSTR("tu,"));
if((p.days >> 2) & 0x01) strcat_P(days, PSTR("we,"));
if((p.days >> 3) & 0x01) strcat_P(days, PSTR("th,"));
if((p.days >> 4) & 0x01) strcat_P(days, PSTR("fr,"));
if((p.days >> 5) & 0x01) strcat_P(days, PSTR("sa,"));
if((p.days >> 6) & 0x01) strcat_P(days, PSTR("su,"));
if(strlen(days) > 0) days[strlen(days)-1] = '\0';
}
char days[12] = "";
char hours[12] = "";
server.sendContent(buf, snprintf_P(buf, BufferSize, PSTR("priceModifier %i %s %s %s %.4f %s %s %02d-%02d %02d-%02d\n"),
char hours[3*24] = "";
if(p.hours == 0xFFFFFF) {
strcpy_P(hours, PSTR("all"));
} else {
for(uint8_t i = 0; i < 24; i++) {
if((p.hours >> i) & 0x01) {
char h[4];
snprintf_P(h, 4, PSTR("%02d,"), i);
strcat(hours, h);
}
}
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"),
i,
p.name,
direction,

View File

@@ -1550,6 +1550,22 @@ void MQTT_connect() {
}
}
String getSplit(String input, int index) {
char separator = ' ';
String ret = input;
ret.trim();
for(int i = 0; i < index; i++) {
int pos = ret.indexOf(separator);
if(pos == -1) {
return "";
}
ret = ret.substring(pos+1);
}
ret = ret.substring(0, ret.indexOf(separator));
ret.trim();
return ret;
}
void configFileParse() {
debugD_P(PSTR("Parsing config file"));
@@ -1587,6 +1603,7 @@ void configFileParse() {
NtpConfig ntp;
PriceServiceConfig price;
EnergyAccountingConfig eac;
uint8_t priceModifierCount = 0;
size_t size;
char* buf = (char*) commonBuffer;
@@ -1821,6 +1838,92 @@ void configFileParse() {
} else if(strncmp_P(buf, PSTR("priceFixedPrice "), 16) == 0) {
if(!lPrice) { config.getPriceServiceConfig(price); lPrice = true; };
price.unused2 = String(buf+16).toFloat() * 1000;
} else if(strncmp_P(buf, PSTR("priceModifier "), 14) == 0) {
PriceConfig pc;
memset(&pc, 0, sizeof(PriceConfig));
String line = String(buf+14);
uint8_t priceIndex = line.substring(0, line.indexOf(" ")).toInt();
int nameStart = line.indexOf("\"");
if(nameStart < 0) {
debugW_P(PSTR("Price modifier without name start"));
continue;
}
int nameEnd = line.indexOf("\"", nameStart+1);
if(nameEnd < nameStart) {
debugW_P(PSTR("Price modifier without name end"));
continue;
}
String name = line.substring(nameStart+1, nameEnd);
strcpy(pc.name, name.c_str());
String rest = line.substring(nameEnd+1);
String direction = getSplit(rest, 0);
if(direction.equals("import")) {
pc.direction = PRICE_DIRECTION_IMPORT;
} else if(direction.equals("export")) {
pc.direction = PRICE_DIRECTION_EXPORT;
} else if(direction.equals("both")) {
pc.direction = PRICE_DIRECTION_BOTH;
} else {
debugW_P(PSTR("Price modifier with unknown direction \"%s\""), direction.c_str());
continue;
}
String type = getSplit(rest, 1);
if(type.equals("fixed")) {
pc.type = PRICE_TYPE_FIXED;
} else if(type.equals("add")) {
pc.type = PRICE_TYPE_ADD;
} else if(type.equals("percent")) {
pc.type = PRICE_TYPE_PCT;
} else if(type.equals("subtract")) {
pc.type = PRICE_TYPE_SUBTRACT;
} else {
debugW_P(PSTR("Price modifier unknown type"));
continue;
}
pc.value = getSplit(rest, 2).toFloat() * 10000;
String days = getSplit(rest, 3);
if(days.equals("all")) {
pc.days = 0x7F;
} else {
pc.days = 0;
if(days.indexOf("mo") >= 0) pc.days |= 1 << 0;
if(days.indexOf("tu") >= 0) pc.days |= 1 << 1;
if(days.indexOf("we") >= 0) pc.days |= 1 << 2;
if(days.indexOf("th") >= 0) pc.days |= 1 << 3;
if(days.indexOf("fr") >= 0) pc.days |= 1 << 4;
if(days.indexOf("sa") >= 0) pc.days |= 1 << 5;
if(days.indexOf("su") >= 0) pc.days |= 1 << 6;
}
String hours = getSplit(rest, 4);
if(hours.equals("all")) {
pc.hours = 0xFFFFFF;
} else {
pc.hours = 0;
for(uint8_t i = 0; i < 24; i++) {
char h[4];
snprintf_P(h, 4, PSTR("%02d"), i);
if(hours.indexOf(String(h)) >= 0) pc.hours |= 1 << i;
}
}
String start = getSplit(rest, 5);
pc.start_dayofmonth = start.substring(0, start.indexOf("-")).toInt();
pc.start_month = start.substring(start.indexOf("-")+1).toInt();
String end = getSplit(rest, 6);
pc.end_dayofmonth = end.substring(0, end.indexOf("-")).toInt();
pc.end_month = end.substring(end.indexOf("-")+1).toInt();
ps->setPriceConfig(priceIndex, pc);
priceModifierCount = priceIndex+1;
} else if(strncmp_P(buf, PSTR("thresholds "), 11) == 0) {
if(!lEac) { config.getEnergyAccountingConfig(eac); lEac = true; };
int i = 0;
@@ -2057,6 +2160,7 @@ void configFileParse() {
if(lEac) config.setEnergyAccountingConfig(eac);
if(sDs) ds.save();
if(sEa) ea.save();
if(priceModifierCount > 0) ps->save();
config.save();
LittleFS.end();
}