From 0cd76eebf0214665276962b220070e7e6643161f Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Mon, 28 Oct 2024 17:40:40 +0100 Subject: [PATCH] smaller improvements - dayahead Fixed surcharge now takes either one value (old behaviour) or an array with 24 elements for each hour, to add a surcharge depending on the time of day (as apparently they use in Denmark). The array should be entered like `[n,n,...,n]` - added 1.54" template for dayahead prices - in dayahead content, added option to only display the graph, without the current time/price/arrow. With this, the display only has to refresh one a day, which will save battery - added the number of timedout tags to the 'sys' websocket message. The timeoutcount key/value is only present once a minute. `{"sys":{"currtime":1730133055,"heap":194124,"recordcount":27,"dbsize":5488,"littlefsfree":5246976,"psfree":8350371,"apstate":1,"runstate":2,"rssi":-70,"wifistatus":3,"wifissid":"sensors","uptime":72,"timeoutcount":0}}` - cosmetic: tagtype update now doesn't give an error when it tries to process readme.md --- .../data/www/content_cards.json.gz | Bin 4709 -> 4814 bytes ESP32_AP-Flasher/data/www/ota.js.gz | Bin 5459 -> 5463 bytes ESP32_AP-Flasher/src/contentmanager.cpp | 71 +++++++++++++----- ESP32_AP-Flasher/src/web.cpp | 2 + ESP32_AP-Flasher/wwwroot/content_cards.json | 14 +++- ESP32_AP-Flasher/wwwroot/ota.js | 5 +- resources/tagtypes/00.json | 12 ++- resources/tagtypes/02.json | 4 +- 8 files changed, 80 insertions(+), 28 deletions(-) diff --git a/ESP32_AP-Flasher/data/www/content_cards.json.gz b/ESP32_AP-Flasher/data/www/content_cards.json.gz index 247844d8cb6c11569e26dc02bfc3ebf161218178..6878c8877a9e1dc0d655fe203a6b36206e011df6 100644 GIT binary patch delta 4805 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 E0JP$?761SM delta 354 zcmV-o0iFKWD$^>k`xAdRAL_@~v!%FInk7TtXi$H6YThZ^4BUp9ly9<+j0F^itNAbp z%N$$`B9j|Oj`)h#$lz5Zp~UG>U}wvZZi#_{?nSS4vwNaa!GD7D`|(+iK(Xh@4d(2U z%&G92+Zd2QMc~@&-0o)L4eg-bL<#{5=SfDef>9)UWWDaI(); if (units == 0) units = 1; - double tarifkwh = cfgobj["tariffkwh"].as(); + double tarifkwh; double tariftax = cfgobj["tarifftax"].as(); - double minPrice = (doc[0]["price"].as() / 10 + tarifkwh) * (1 + tariftax / 100) / units; - double maxPrice = minPrice; + double minPrice = std::numeric_limits::max(); + double maxPrice = std::numeric_limits::lowest(); double prices[n]; + DynamicJsonDocument doc2(500); + JsonArray tariffArray; + std::string tariffString = cfgobj["tariffkwh"].as(); + if (tariffString.front() == '[') { + if (deserializeJson(doc2, tariffString) == DeserializationError::Ok) { + tariffArray = doc2.as(); + } else { + Serial.println("Error in tariffkwh array"); + } + } for (int i = 0; i < n; i++) { const JsonObject &obj = doc[i]; - const double price = (obj["price"].as() / 10 + tarifkwh) * (1 + tariftax / 100) / units; - minPrice = min(minPrice, price); - maxPrice = max(maxPrice, price); - prices[i] = price; + + if (tariffArray.size() == 24) { + const time_t item_time = obj["time"]; + struct tm item_timeinfo; + localtime_r(&item_time, &item_timeinfo); + + tarifkwh = tariffArray[item_timeinfo.tm_hour].as(); + } else { + tarifkwh = cfgobj["tariffkwh"].as(); + } + prices[i] = (obj["price"].as() / 10 + tarifkwh) * (1 + tariftax / 100) / units; + minPrice = std::min(minPrice, prices[i]); + maxPrice = std::max(maxPrice, prices[i]); } std::sort(prices, prices + n); @@ -1565,14 +1584,17 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, for (double i = minPrice; i <= maxPrice; i += yAxisScale.step) { int y = mapDouble(i, minPrice, maxPrice, spr.height() - barBottom, spr.height() - barBottom - loc["bars"][2].as()); spr.drawLine(0, y, spr.width(), y, TFT_BLACK); - drawString(spr, String(int(i * units)), yAxisX, y - 9, loc["yaxis"][0], TL_DATUM, TFT_BLACK); + if (loc["yaxis"][0]) drawString(spr, String(int(i * units)), yAxisX, y - 9, loc["yaxis"][0], TL_DATUM, TFT_BLACK); } uint16_t barwidth = loc["bars"][1].as() / n; uint16_t barheight = loc["bars"][2].as() / (maxPrice - minPrice); - + uint16_t arrowY = 0; + if (loc["bars"].size() >= 5) arrowY = loc["bars"][4].as(); uint16_t barX = loc["bars"][0].as(); double pricenow = std::numeric_limits::quiet_NaN(); + bool showcurrent = true; + if (cfgobj["showcurr"] && cfgobj["showcurr"] == "0") showcurrent = false; for (int i = 0; i < n; i++) { const JsonObject &obj = doc[i]; @@ -1580,27 +1602,40 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, struct tm item_timeinfo; localtime_r(&item_time, &item_timeinfo); + if (tariffArray.size() == 24) { + tarifkwh = tariffArray[item_timeinfo.tm_hour].as(); + } else { + tarifkwh = cfgobj["tariffkwh"].as(); + } + const double price = (obj["price"].as() / 10 + tarifkwh) * (1 + tariftax / 100) / units; uint16_t barcolor = getPercentileColor(prices, n, price, imageParams.hwdata); uint16_t thisbarh = mapDouble(price, minPrice, maxPrice, 0, loc["bars"][2].as()); spr.fillRect(barX + i * barwidth, spr.height() - barBottom - thisbarh, barwidth - 1, thisbarh, barcolor); - if (i % 2 == 0) { + if (i % 2 == 0 && loc["time"][0]) { drawString(spr, String(item_timeinfo.tm_hour), barX + i * barwidth + barwidth / 3 + 1, spr.height() - barBottom + 3, loc["time"][0], TC_DATUM, TFT_BLACK); } - if (now - item_time < 3600 && std::isnan(pricenow)) { - spr.fillRect(barX + i * barwidth + 3, 5, barwidth - 6, 10, imageParams.highlightColor); - spr.fillTriangle(barX + i * barwidth, 15, - barX + i * barwidth + barwidth - 1, 15, - barX + i * barwidth + (barwidth - 1) / 2, 15 + barwidth, imageParams.highlightColor); - spr.drawLine(barX + i * barwidth + (barwidth - 1) / 2, 20 + barwidth, barX + i * barwidth + (barwidth - 1) / 2, spr.height(), getColor("pink")); + if (now - item_time < 3600 && std::isnan(pricenow) && showcurrent) { + spr.fillRect(barX + i * barwidth + (barwidth > 6 ? 3 : 1), 5 + arrowY, (barwidth > 6 ? barwidth - 6 : barwidth - 2), 10, imageParams.highlightColor); + spr.fillTriangle(barX + i * barwidth, 15 + arrowY, + barX + i * barwidth + barwidth - 1, 15 + arrowY, + barX + i * barwidth + (barwidth - 1) / 2, 15 + barwidth + arrowY, imageParams.highlightColor); + spr.drawLine(barX + i * barwidth + (barwidth - 1) / 2, 20 + barwidth + arrowY, barX + i * barwidth + (barwidth - 1) / 2, spr.height(), getColor("pink")); pricenow = price; } } - drawString(spr, String(timeinfo.tm_hour) + ":00", barX, 5, loc["head"][0], TL_DATUM, TFT_BLACK, 30); - drawString(spr, String(pricenow) + "/kWh", spr.width() - barX, 5, loc["head"][0], TR_DATUM, TFT_BLACK, 30); + if (showcurrent) { + if (barwidth < 5) { + drawString(spr, String(timeinfo.tm_hour) + ":00", spr.width() / 2, 5, "calibrib16.vlw", TC_DATUM, TFT_BLACK, 30); + drawString(spr, String(pricenow) + "/kWh", spr.width() / 2, 25, loc["head"][0], TC_DATUM, TFT_BLACK, 30); + } else { + drawString(spr, String(timeinfo.tm_hour) + ":00", barX, 5, loc["head"][0], TL_DATUM, TFT_BLACK, 30); + drawString(spr, String(pricenow) + "/kWh", spr.width() - barX, 5, loc["head"][0], TR_DATUM, TFT_BLACK, 30); + } + } spr2buffer(spr, filename, imageParams); spr.deleteSprite(); diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index c267c383..bc566ce1 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -147,8 +147,10 @@ void wsSendSysteminfo() { uint32_t tagcount = getTagCount(timeoutcount); char result[40]; if (timeoutcount > 0) { + sys["timeoutcount"] = timeoutcount; snprintf(result, sizeof(result), "%lu/%lu, %lu timeout", tagcount, tagDB.size(), timeoutcount); } else { + sys["timeoutcount"] = 0; snprintf(result, sizeof(result), "%lu / %lu", tagcount, tagDB.size()); } setVarDB("ap_tagcount", result); diff --git a/ESP32_AP-Flasher/wwwroot/content_cards.json b/ESP32_AP-Flasher/wwwroot/content_cards.json index fa5b0d7f..ded082c3 100644 --- a/ESP32_AP-Flasher/wwwroot/content_cards.json +++ b/ESP32_AP-Flasher/wwwroot/content_cards.json @@ -403,7 +403,7 @@ { "key": "tariffkwh", "name": "Fixed surcharge", - "desc": "Fixed surcharge per kWh, in 1/100 units (cents/öre/øre)", + "desc": "Fixed surcharge per kWh, in 1/100 units (cents/öre/øre). Enter one value, or an array of exactly 24 elements for each hour in the form of '[n,n,...,n]'", "type": "text" }, { @@ -421,7 +421,17 @@ "100": "1/1 units (EUR/NOK/DKK)", "1": "1/100 units (cents/öre/øre)" } - } + }, + { + "key": "showcurr", + "name": "Show current", + "desc": "Hourly refresh to show current price (less battery friendly)", + "type": "select", + "options": { + "0": "No", + "1": "-Yes" + } + } ] }, { diff --git a/ESP32_AP-Flasher/wwwroot/ota.js b/ESP32_AP-Flasher/wwwroot/ota.js index d9450b2b..8c09245c 100644 --- a/ESP32_AP-Flasher/wwwroot/ota.js +++ b/ESP32_AP-Flasher/wwwroot/ota.js @@ -594,13 +594,12 @@ async function fetchAndCheckTagtypes(cleanup) { for (const file of fileList) { const filename = file.name; print(filename, "green"); - let check = true; + let check = filename.endsWith('.json'); let hwtype = parseInt(filename, 16); - if (cleanup) { + if (check && cleanup) { let isInUse = Array.from(gridItems).some(element => element.dataset.hwtype == hwtype); if (!isInUse) { - isInUse = Array.from(gridItems).some(element => element.dataset.usetemplate == hwtype); } if (!isInUse) { diff --git a/resources/tagtypes/00.json b/resources/tagtypes/00.json index 2fbf8724..440b55be 100644 --- a/resources/tagtypes/00.json +++ b/resources/tagtypes/00.json @@ -1,5 +1,5 @@ { - "version": 1, + "version": 2, "name": "M2 1.54\"", "width": 152, "height": 152, @@ -12,7 +12,7 @@ }, "shortlut": 2, "options": [ "button", "customlut" ], - "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 10, 14, 15, 17, 18, 19, 20, 21 ], + "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 10, 14, 15, 17, 18, 19, 20, 21, 27 ], "template": { "1": { "weekday": [ 76, 9, "fonts/calibrib30" ], @@ -44,6 +44,12 @@ { "text": [ 10, 110, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] }, { "text": [ 3, 125, "Tag count:", "glasstown_nbp_tf", 1, 0, 0 ] }, { "text": [ 10, 140, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] } - ] + ], + "27": { + "bars": [ 4, 152, 70, 1, 50 ], + "time": [ "" ], + "yaxis": [ "tahoma9.vlw", 3, 6 ], + "head": [ "calibrib30.vlw" ] + } } } diff --git a/resources/tagtypes/02.json b/resources/tagtypes/02.json index a92a59b8..02f9c4b3 100644 --- a/resources/tagtypes/02.json +++ b/resources/tagtypes/02.json @@ -1,5 +1,5 @@ { - "version": 3, + "version": 4, "name": "M2 4.2\"", "width": 400, "height": 300, @@ -53,7 +53,7 @@ "gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ] }, "27": { - "bars": [ 15, 385, 240, 20 ], + "bars": [ 15, 385, 225, 20, 22 ], "time": [ "calibrib16.vlw" ], "yaxis": [ "tahoma9.vlw", 3, 6 ], "head": [ "calibrib30.vlw" ]