From 1a92cd197808f8b1e0b54e980e4dde53a76ae380 Mon Sep 17 00:00:00 2001 From: Gunnar Skjold Date: Fri, 12 Aug 2022 20:41:53 +0200 Subject: [PATCH] Fetch prices from hub --- platformio.ini | 2 +- src/AmsDataStorage.cpp | 4 +- src/AmsToMqttBridge.ino | 19 +-- src/entsoe/EntsoeA44Parser.cpp | 32 ++++ src/entsoe/EntsoeA44Parser.h | 2 + src/entsoe/EntsoeApi.cpp | 250 +++++++++++++++++++---------- src/entsoe/EntsoeApi.h | 10 +- src/entsoe/PricesContainer.h | 8 + src/entsoe/PricesFromHubStream.cpp | 4 + src/entsoe/PricesFromHubStream.h | 2 + src/web/AmsWebServer.cpp | 50 +++--- 11 files changed, 255 insertions(+), 128 deletions(-) create mode 100644 src/entsoe/PricesContainer.h diff --git a/platformio.ini b/platformio.ini index 37670bed..9e7a9d04 100755 --- a/platformio.ini +++ b/platformio.ini @@ -10,7 +10,7 @@ platform = espressif8266@3.2.0 framework = arduino board = esp12e board_build.ldscript = eagle.flash.4m2m.ld -build_flags = -D WEBSOCKET_DISABLED=1 +build_flags = -D WEBSOCKET_DISABLED=1 -fexceptions lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} extra_scripts = diff --git a/src/AmsDataStorage.cpp b/src/AmsDataStorage.cpp index 091eef04..75bf4b56 100644 --- a/src/AmsDataStorage.cpp +++ b/src/AmsDataStorage.cpp @@ -67,7 +67,7 @@ bool AmsDataStorage::update(AmsData* data) { } tmElements_t last; breakTime(day.lastMeterReadTime, last); - for(int i = last.Hour; i < utc.Hour; i++) { + for(int i = last.Hour; i <= utc.Hour; i++) { if(debugger->isActive(RemoteDebug::VERBOSE)) { debugger->printf("(AmsDataStorage) Clearing hour: %d\n", i); } @@ -90,7 +90,7 @@ bool AmsDataStorage::update(AmsData* data) { } tmElements_t last; breakTime(tz->toLocal(month.lastMeterReadTime), last); - for(int i = last.Day; i < ltz.Day; i++) { + for(int i = last.Day; i <= ltz.Day; i++) { if(debugger->isActive(RemoteDebug::VERBOSE)) { debugger->printf("(AmsDataStorage) Clearing day: %d\n", i); } diff --git a/src/AmsToMqttBridge.ino b/src/AmsToMqttBridge.ino index e40d4e25..3e8ede72 100644 --- a/src/AmsToMqttBridge.ino +++ b/src/AmsToMqttBridge.ino @@ -195,14 +195,11 @@ void setup() { hw.ledBlink(LED_GREEN, 1); hw.ledBlink(LED_BLUE, 1); - #if defined(ESP32) EntsoeConfig entsoe; - if(config.getEntsoeConfig(entsoe) && strlen(entsoe.token) > 0) { - eapi = new EntsoeApi(&Debug); - eapi->setup(entsoe); - ws.setEntsoeApi(eapi); - } - #endif + eapi = new EntsoeApi(&Debug); + config.getEntsoeConfig(entsoe); + eapi->setup(entsoe); + ws.setEntsoeApi(eapi); bool shared = false; config.getMeterConfig(meterConfig); @@ -514,7 +511,6 @@ void loop() { mqtt->disconnect(); } - #if defined(ESP32) try { if(eapi != NULL && ntpEnabled) { if(eapi->loop() && mqtt != NULL && mqttHandler != NULL && mqtt->connected()) { @@ -524,24 +520,19 @@ void loop() { if(config.isEntsoeChanged()) { EntsoeConfig entsoe; - if(config.getEntsoeConfig(entsoe) && strlen(entsoe.token) > 0) { + if(config.getEntsoeConfig(entsoe)) { if(eapi == NULL) { eapi = new EntsoeApi(&Debug); ea.setEapi(eapi); ws.setEntsoeApi(eapi); } eapi->setup(entsoe); - } else if(eapi != NULL) { - delete eapi; - eapi = NULL; - ws.setEntsoeApi(NULL); } config.ackEntsoeChange(); } } catch(const std::exception& e) { debugE("Exception in ENTSO-E loop (%s)", e.what()); } - #endif ws.loop(); } if(mqtt != NULL) { diff --git a/src/entsoe/EntsoeA44Parser.cpp b/src/entsoe/EntsoeA44Parser.cpp index 1d7fa9b2..c08b5cb0 100644 --- a/src/entsoe/EntsoeA44Parser.cpp +++ b/src/entsoe/EntsoeA44Parser.cpp @@ -102,3 +102,35 @@ size_t EntsoeA44Parser::write(uint8_t byte) { } return 1; } + +void EntsoeA44Parser::get(PricesContainer* container) { + strcpy(container->currency, currency); + strcpy(container->measurementUnit, measurementUnit); + + container->points[0] = points[0] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[0] * 10000; + container->points[1] = points[1] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[1] * 10000; + container->points[2] = points[2] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[2] * 10000; + container->points[3] = points[3] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[3] * 10000; + container->points[4] = points[4] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[4] * 10000; + container->points[5] = points[5] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[5] * 10000; + container->points[6] = points[6] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[6] * 10000; + container->points[7] = points[7] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[7] * 10000; + container->points[8] = points[8] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[8] * 10000; + container->points[9] = points[9] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[9] * 10000; + + container->points[10] = points[10] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[10] * 10000; + container->points[11] = points[11] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[11] * 10000; + container->points[12] = points[12] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[12] * 10000; + container->points[13] = points[13] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[13] * 10000; + container->points[14] = points[14] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[14] * 10000; + container->points[15] = points[15] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[15] * 10000; + container->points[16] = points[16] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[16] * 10000; + container->points[17] = points[17] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[17] * 10000; + container->points[18] = points[18] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[18] * 10000; + container->points[19] = points[19] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[19] * 10000; + + container->points[20] = points[20] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[20] * 10000; + container->points[21] = points[21] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[21] * 10000; + container->points[22] = points[22] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[22] * 10000; + container->points[23] = points[23] == ENTSOE_NO_VALUE ? ENTSOE_NO_VALUE : points[23] * 10000; +} \ No newline at end of file diff --git a/src/entsoe/EntsoeA44Parser.h b/src/entsoe/EntsoeA44Parser.h index 4d860214..33154d63 100644 --- a/src/entsoe/EntsoeA44Parser.h +++ b/src/entsoe/EntsoeA44Parser.h @@ -2,6 +2,7 @@ #define _ENTSOEA44PARSER_H #include "Stream.h" +#include "PricesContainer.h" #define DOCPOS_SEEK 0 #define DOCPOS_CURRENCY 1 @@ -25,6 +26,7 @@ public: void flush(); size_t write(const uint8_t *buffer, size_t size); size_t write(uint8_t); + void get(PricesContainer*); private: char currency[4]; diff --git a/src/entsoe/EntsoeApi.cpp b/src/entsoe/EntsoeApi.cpp index 886e7201..e5c6b010 100644 --- a/src/entsoe/EntsoeApi.cpp +++ b/src/entsoe/EntsoeApi.cpp @@ -5,6 +5,8 @@ #include "DnbCurrParser.h" #include "version.h" +#include "ams/GcmParser.h" + #if defined(ESP32) #include #endif @@ -31,6 +33,12 @@ void EntsoeApi::setup(EntsoeConfig& config) { if(today != NULL) delete today; if(tomorrow != NULL) delete tomorrow; today = tomorrow = NULL; + + http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); + http.setReuse(false); + http.setTimeout(60000); + http.setUserAgent("ams2mqtt/" + String(VERSION)); + http.useHTTP10(true); } char* EntsoeApi::getToken() { @@ -60,25 +68,33 @@ float EntsoeApi::getValueForHour(time_t cur, int8_t hour) { if(pos > 23) { if(tomorrow == NULL) return ENTSOE_NO_VALUE; - value = tomorrow->getPoint(pos-24); - if(value != ENTSOE_NO_VALUE && strcmp(tomorrow->getMeasurementUnit(), "MWH") == 0) { + if(tomorrow->points[pos-24] == ENTSOE_NO_VALUE) + return ENTSOE_NO_VALUE; + value = tomorrow->points[pos-24] / 10000.0; + if(strcmp(tomorrow->measurementUnit, "KWH") == 0) { + // Multiplier is 1 + } else if(strcmp(tomorrow->measurementUnit, "MWH") == 0) { multiplier *= 0.001; } else { return ENTSOE_NO_VALUE; } - float mult = getCurrencyMultiplier(tomorrow->getCurrency(), config->currency); + float mult = getCurrencyMultiplier(tomorrow->currency, config->currency); if(mult == 0) return ENTSOE_NO_VALUE; multiplier *= mult; } else if(pos >= 0) { if(today == NULL) return ENTSOE_NO_VALUE; - value = today->getPoint(pos); - if(value != ENTSOE_NO_VALUE && strcmp(today->getMeasurementUnit(), "MWH") == 0) { + if(today->points[pos] == ENTSOE_NO_VALUE) + return ENTSOE_NO_VALUE; + value = today->points[pos] / 10000.0; + if(strcmp(today->measurementUnit, "KWH") == 0) { + // Multiplier is 1 + } else if(strcmp(today->measurementUnit, "MWH") == 0) { multiplier *= 0.001; } else { return ENTSOE_NO_VALUE; } - float mult = getCurrencyMultiplier(today->getCurrency(), config->currency); + float mult = getCurrencyMultiplier(today->currency, config->currency); if(mult == 0) return ENTSOE_NO_VALUE; multiplier *= mult; } @@ -86,15 +102,22 @@ float EntsoeApi::getValueForHour(time_t cur, int8_t hour) { } bool EntsoeApi::loop() { - if(strlen(getToken()) == 0) - return false; - uint64_t now = millis64(); if(now < 10000) return false; // Grace period time_t t = time(nullptr); if(t < BUILD_EPOCH) return false; + #ifndef AMS2MQTT_PRICE_KEY + if(strlen(getToken()) == 0) { + return false; + } + #endif + if(strlen(config->area) == 0) + return false; + if(strlen(config->currency) == 0) + return false; + bool ret = false; tmElements_t tm; breakTime(tz->toLocal(t), tm); @@ -120,39 +143,10 @@ bool EntsoeApi::loop() { midnightMillis = 0; // Force new midnight millis calculation return true; } else { - breakTime(t, tm); // Break UTC to find UTC midnight if(today == NULL && (lastTodayFetch == 0 || now - lastTodayFetch > 60000)) { lastTodayFetch = now; - time_t e1 = t - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second; // UTC midnight - time_t e2 = e1 + SECS_PER_DAY; - tmElements_t d1, d2; - breakTime(tz->toUTC(e1), d1); // To get day and hour for CET/CEST at UTC midnight - breakTime(tz->toUTC(e2), d2); - - snprintf(buf, BufferSize, "%s?securityToken=%s&documentType=A44&periodStart=%04d%02d%02d%02d%02d&periodEnd=%04d%02d%02d%02d%02d&in_Domain=%s&out_Domain=%s", - "https://transparency.entsoe.eu/api", getToken(), - d1.Year+1970, d1.Month, d1.Day, d1.Hour, 00, - d2.Year+1970, d2.Month, d2.Day, d2.Hour, 00, - config->area, config->area); - - #if defined(ESP32) - esp_task_wdt_reset(); - #elif defined(ESP8266) - ESP.wdtFeed(); - #endif - - - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Fetching prices for today\n"); - if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EntsoeApi) url: %s\n", buf); - EntsoeA44Parser* a44 = new EntsoeA44Parser(); - if(retrieve(buf, a44) && a44->getPoint(0) != ENTSOE_NO_VALUE) { - today = a44; - return true; - } else if(a44 != NULL) { - delete a44; - today = NULL; - return false; - } + today = fetchPrices(t); + return today != NULL; } // Prices for next day are published at 13:00 CE(S)T, but to avoid heavy server traffic at that time, we will @@ -161,49 +155,18 @@ bool EntsoeApi::loop() { && midnightMillis - now < tomorrowFetchMillis && (lastTomorrowFetch == 0 || now - lastTomorrowFetch > 900000) ) { + breakTime(t+SECS_PER_DAY, tm); // Break UTC tomorrow to find UTC midnight lastTomorrowFetch = now; - time_t e1 = t - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second + (SECS_PER_DAY); - time_t e2 = e1 + SECS_PER_DAY; - tmElements_t d1, d2; - breakTime(tz->toUTC(e1), d1); - breakTime(tz->toUTC(e2), d2); - - snprintf(buf, BufferSize, "%s?securityToken=%s&documentType=A44&periodStart=%04d%02d%02d%02d%02d&periodEnd=%04d%02d%02d%02d%02d&in_Domain=%s&out_Domain=%s", - "https://transparency.entsoe.eu/api", getToken(), - d1.Year+1970, d1.Month, d1.Day, d1.Hour, 00, - d2.Year+1970, d2.Month, d2.Day, d2.Hour, 00, - config->area, config->area); - - #if defined(ESP32) - esp_task_wdt_reset(); - #elif defined(ESP8266) - ESP.wdtFeed(); - #endif - - if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Fetching prices for tomorrow\n"); - if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EntsoeApi) url: %s\n", buf); - EntsoeA44Parser* a44 = new EntsoeA44Parser(); - if(retrieve(buf, a44) && a44->getPoint(0) != ENTSOE_NO_VALUE) { - tomorrow = a44; - return true; - } else if(a44 != NULL) { - delete a44; - tomorrow = NULL; - return false; - } + tomorrow = fetchPrices(t+SECS_PER_DAY); + return tomorrow != NULL; } } return ret; } bool EntsoeApi::retrieve(const char* url, Stream* doc) { - HTTPClient https; - https.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); - https.setReuse(false); - https.setTimeout(50000); - https.setUserAgent("ams2mqtt/" + String(VERSION)); #if defined(ESP32) - if(https.begin(url)) { + if(http.begin(url)) { printD("Connection established"); #if defined(ESP32) @@ -212,7 +175,7 @@ bool EntsoeApi::retrieve(const char* url, Stream* doc) { ESP.wdtFeed(); #endif - int status = https.GET(); + int status = http.GET(); #if defined(ESP32) esp_task_wdt_reset(); @@ -222,15 +185,15 @@ bool EntsoeApi::retrieve(const char* url, Stream* doc) { if(status == HTTP_CODE_OK) { printD("Receiving data"); - https.writeToStream(doc); - https.end(); + http.writeToStream(doc); + http.end(); return true; } else { if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf("(EntsoeApi) Communication error, returned status: %d\n", status); - printE(https.errorToString(status)); - printD(https.getString()); + printE(http.errorToString(status)); + printD(http.getString()); - https.end(); + http.end(); return false; } } else { @@ -282,6 +245,115 @@ float EntsoeApi::getCurrencyMultiplier(const char* from, const char* to) { return currencyMultiplier; } +PricesContainer* EntsoeApi::fetchPrices(time_t t) { + tmElements_t tm; + breakTime(t, tm); + if(strlen(getToken()) == 0) { + String data; + snprintf(buf, BufferSize, "%s/%s/%d/%d/%d?currency=%s", + "http://ams2mqtt.rewiredinvent.no/hub/price", + config->area, + tm.Year+1970, + tm.Month, + tm.Day, + config->currency + ); + #if defined(ESP8266) + WiFiClient client; + client.setTimeout(5000); + if(http.begin(client, buf)) { + #elif defined(ESP32) + if(http.begin(buf)) { + #endif + int status = http.GET(); + + #if defined(ESP32) + esp_task_wdt_reset(); + #elif defined(ESP8266) + ESP.wdtFeed(); + #endif + + if(status == HTTP_CODE_OK) { + printD("Receiving data"); + data = http.getString(); + http.end(); + } else { + if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf("(EntsoeApi) Communication error, returned status: %d\n", status); + printE(http.errorToString(status)); + printD(http.getString()); + + http.end(); + } + } + uint8_t* content = (uint8_t*) (data.c_str()); + if(debugger->isActive(RemoteDebug::DEBUG)) { + printD("Received content for prices:"); + debugPrint(content, 0, data.length()); + } + + #if defined(AMS2MQTT_PRICE_KEY) + uint8_t key[] = AMS2MQTT_PRICE_KEY; + #else + uint8_t key[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + #endif + #if defined(AMS2MQTT_PRICE_AUTHENTICATION) + uint8_t auth[] = AMS2MQTT_PRICE_AUTHENTICATION; + #else + uint8_t auth[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + #endif + + DataParserContext ctx; + ctx.length = data.length(); + GCMParser gcm(key, auth); + int8_t gcmRet = gcm.parse(content, ctx); + if(debugger->isActive(RemoteDebug::DEBUG)) { + printD("Decrypted content for prices:"); + debugPrint(content, 0, data.length()); + } + if(gcmRet > 0) { + if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EntsoeApi) Price data starting at: %d\n", gcmRet); + PricesContainer* ret = new PricesContainer(); + memcpy(ret, content+gcmRet, sizeof(*ret)); + for(uint8_t i = 0; i < 24; i++) { + ret->points[i] = ntohl(ret->points[i]); + } + return ret; + } else { + if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf("(EntsoeApi) Error code while decrypting prices: %d\n", gcmRet); + } + } else { + time_t e1 = t - (tm.Hour * 3600) - (tm.Minute * 60) - tm.Second; // UTC midnight + time_t e2 = e1 + SECS_PER_DAY; + tmElements_t d1, d2; + breakTime(tz->toUTC(e1), d1); // To get day and hour for CET/CEST at UTC midnight + breakTime(tz->toUTC(e2), d2); + + snprintf(buf, BufferSize, "%s?securityToken=%s&documentType=A44&periodStart=%04d%02d%02d%02d%02d&periodEnd=%04d%02d%02d%02d%02d&in_Domain=%s&out_Domain=%s", + "https://transparency.entsoe.eu/api", getToken(), + d1.Year+1970, d1.Month, d1.Day, d1.Hour, 00, + d2.Year+1970, d2.Month, d2.Day, d2.Hour, 00, + config->area, config->area); + + #if defined(ESP32) + esp_task_wdt_reset(); + #elif defined(ESP8266) + ESP.wdtFeed(); + #endif + + if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(EntsoeApi) Fetching prices for %d.%d.%d\n", tm.Day, tm.Month, tm.Year+1970); + if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("(EntsoeApi) url: %s\n", buf); + EntsoeA44Parser a44; + if(retrieve(buf, &a44) && a44.getPoint(0) != ENTSOE_NO_VALUE) { + PricesContainer* ret = new PricesContainer(); + a44.get(ret); + return ret; + } else { + return NULL; + } + } + return NULL; +} + void EntsoeApi::printD(String fmt, ...) { va_list args; va_start(args, fmt); @@ -295,3 +367,19 @@ void EntsoeApi::printE(String fmt, ...) { if(debugger->isActive(RemoteDebug::ERROR)) debugger->printf(String("(EntsoeApi)" + fmt + "\n").c_str(), args); va_end(args); } + +void EntsoeApi::debugPrint(byte *buffer, int start, int length) { + for (int i = start; i < start + length; i++) { + if (buffer[i] < 0x10) + debugger->print("0"); + debugger->print(buffer[i], HEX); + debugger->print(" "); + if ((i - start + 1) % 16 == 0) + debugger->println(""); + else if ((i - start + 1) % 4 == 0) + debugger->print(" "); + + yield(); // Let other get some resources too + } + debugger->println(""); +} diff --git a/src/entsoe/EntsoeApi.h b/src/entsoe/EntsoeApi.h index b382719c..28b270ed 100644 --- a/src/entsoe/EntsoeApi.h +++ b/src/entsoe/EntsoeApi.h @@ -4,8 +4,9 @@ #include "TimeLib.h" #include "Timezone.h" #include "RemoteDebug.h" -#include "EntsoeA44Parser.h" #include "AmsConfiguration.h" +#include "PricesFromHubStream.h" +#include "EntsoeA44Parser.h" #if defined(ESP8266) #include @@ -31,6 +32,7 @@ public: private: RemoteDebug* debugger; EntsoeConfig* config = NULL; + HTTPClient http; uint8_t currentDay = 0, currentHour = 0; uint32_t tomorrowFetchMillis = 36000000; // Number of ms before midnight. Default fetch 10hrs before midnight (14:00 CE(S)T) @@ -38,8 +40,8 @@ private: uint64_t lastTodayFetch = 0; uint64_t lastTomorrowFetch = 0; uint64_t lastCurrencyFetch = 0; - EntsoeA44Parser* today = NULL; - EntsoeA44Parser* tomorrow = NULL; + PricesContainer* today = NULL; + PricesContainer* tomorrow = NULL; Timezone* tz = NULL; @@ -48,10 +50,12 @@ private: float currencyMultiplier = 0; + PricesContainer* fetchPrices(time_t); bool retrieve(const char* url, Stream* doc); float getCurrencyMultiplier(const char* from, const char* to); void printD(String fmt, ...); void printE(String fmt, ...); + void debugPrint(byte *buffer, int start, int length); }; #endif diff --git a/src/entsoe/PricesContainer.h b/src/entsoe/PricesContainer.h new file mode 100644 index 00000000..cb6d687a --- /dev/null +++ b/src/entsoe/PricesContainer.h @@ -0,0 +1,8 @@ +#ifndef _PRICESCONTAINER_H +#define _PRICESCONTAINER_H +struct PricesContainer { + char currency[4]; + char measurementUnit[4]; + int32_t points[24]; +}; +#endif diff --git a/src/entsoe/PricesFromHubStream.cpp b/src/entsoe/PricesFromHubStream.cpp index f82f27c0..2e1e0ff3 100644 --- a/src/entsoe/PricesFromHubStream.cpp +++ b/src/entsoe/PricesFromHubStream.cpp @@ -27,3 +27,7 @@ size_t PricesFromHubStream::write(uint8_t b) { buf[pos++] = b; return 1; } + +void PricesFromHubStream::get(PricesContainer* container) { + memcpy(container, buf, pos); +} \ No newline at end of file diff --git a/src/entsoe/PricesFromHubStream.h b/src/entsoe/PricesFromHubStream.h index b672393d..ab25252a 100644 --- a/src/entsoe/PricesFromHubStream.h +++ b/src/entsoe/PricesFromHubStream.h @@ -2,6 +2,7 @@ #define _PRICESFROMHUBSTREAM_H #include "Stream.h" +#include "PricesContainer.h" class PricesFromHubStream: public Stream { public: @@ -9,6 +10,7 @@ public: int read(); int peek(); void flush(); + void get(PricesContainer*); size_t write(const uint8_t *buffer, size_t size); size_t write(uint8_t); diff --git a/src/web/AmsWebServer.cpp b/src/web/AmsWebServer.cpp index 13770818..e9522349 100644 --- a/src/web/AmsWebServer.cpp +++ b/src/web/AmsWebServer.cpp @@ -547,38 +547,34 @@ void AmsWebServer::configEntsoeHtml() { EntsoeConfig entsoe; config->getEntsoeConfig(entsoe); - if(ESP.getFreeHeap() > 25000) { - String html = String((const __FlashStringHelper*) ENTSOE_HTML); + String html = String((const __FlashStringHelper*) ENTSOE_HTML); - html.replace("{et}", entsoe.token); - html.replace("{em}", String(entsoe.multiplier / 1000.0, 3)); + html.replace("{et}", entsoe.token); + html.replace("{em}", String(entsoe.multiplier / 1000.0, 3)); - html.replace("{eaNo1}", strcmp(entsoe.area, "10YNO-1--------2") == 0 ? "selected" : ""); - html.replace("{eaNo2}", strcmp(entsoe.area, "10YNO-2--------T") == 0 ? "selected" : ""); - html.replace("{eaNo3}", strcmp(entsoe.area, "10YNO-3--------J") == 0 ? "selected" : ""); - html.replace("{eaNo4}", strcmp(entsoe.area, "10YNO-4--------9") == 0 ? "selected" : ""); - html.replace("{eaNo5}", strcmp(entsoe.area, "10Y1001A1001A48H") == 0 ? "selected" : ""); + html.replace("{eaNo1}", strcmp(entsoe.area, "10YNO-1--------2") == 0 ? "selected" : ""); + html.replace("{eaNo2}", strcmp(entsoe.area, "10YNO-2--------T") == 0 ? "selected" : ""); + html.replace("{eaNo3}", strcmp(entsoe.area, "10YNO-3--------J") == 0 ? "selected" : ""); + html.replace("{eaNo4}", strcmp(entsoe.area, "10YNO-4--------9") == 0 ? "selected" : ""); + html.replace("{eaNo5}", strcmp(entsoe.area, "10Y1001A1001A48H") == 0 ? "selected" : ""); - html.replace("{eaSe1}", strcmp(entsoe.area, "10Y1001A1001A44P") == 0 ? "selected" : ""); - html.replace("{eaSe2}", strcmp(entsoe.area, "10Y1001A1001A45N") == 0 ? "selected" : ""); - html.replace("{eaSe3}", strcmp(entsoe.area, "10Y1001A1001A46L") == 0 ? "selected" : ""); - html.replace("{eaSe4}", strcmp(entsoe.area, "10Y1001A1001A47J") == 0 ? "selected" : ""); + html.replace("{eaSe1}", strcmp(entsoe.area, "10Y1001A1001A44P") == 0 ? "selected" : ""); + html.replace("{eaSe2}", strcmp(entsoe.area, "10Y1001A1001A45N") == 0 ? "selected" : ""); + html.replace("{eaSe3}", strcmp(entsoe.area, "10Y1001A1001A46L") == 0 ? "selected" : ""); + html.replace("{eaSe4}", strcmp(entsoe.area, "10Y1001A1001A47J") == 0 ? "selected" : ""); - html.replace("{eaDk1}", strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : ""); - html.replace("{eaDk2}", strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : ""); + html.replace("{eaDk1}", strcmp(entsoe.area, "10YDK-1--------W") == 0 ? "selected" : ""); + html.replace("{eaDk2}", strcmp(entsoe.area, "10YDK-2--------M") == 0 ? "selected" : ""); - html.replace("{ecNOK}", strcmp(entsoe.currency, "NOK") == 0 ? "selected" : ""); - html.replace("{ecSEK}", strcmp(entsoe.currency, "SEK") == 0 ? "selected" : ""); - html.replace("{ecDKK}", strcmp(entsoe.currency, "DKK") == 0 ? "selected" : ""); - html.replace("{ecEUR}", strcmp(entsoe.currency, "EUR") == 0 ? "selected" : ""); + html.replace("{ecNOK}", strcmp(entsoe.currency, "NOK") == 0 ? "selected" : ""); + html.replace("{ecSEK}", strcmp(entsoe.currency, "SEK") == 0 ? "selected" : ""); + html.replace("{ecDKK}", strcmp(entsoe.currency, "DKK") == 0 ? "selected" : ""); + html.replace("{ecEUR}", strcmp(entsoe.currency, "EUR") == 0 ? "selected" : ""); - server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); - server.send_P(200, MIME_HTML, HEAD_HTML); - server.sendContent(html); - server.sendContent_P(FOOT_HTML); - } else { - notFound(); - } + server.setContentLength(html.length() + HEAD_HTML_LEN + FOOT_HTML_LEN); + server.send_P(200, MIME_HTML, HEAD_HTML); + server.sendContent(html); + server.sendContent_P(FOOT_HTML); } void AmsWebServer::configThresholdsHtml() { @@ -705,7 +701,7 @@ void AmsWebServer::dataJson() { } float price = ENTSOE_NO_VALUE; - if(eapi != NULL && strlen(eapi->getToken()) > 0) + if(eapi != NULL) price = eapi->getValueForHour(0); snprintf_P(buf, BufferSize, DATA_JSON,