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
This commit is contained in:
Nic Limper
2024-10-28 17:40:40 +01:00
parent d9a3bf8aac
commit 0cd76eebf0
8 changed files with 80 additions and 28 deletions

Binary file not shown.

View File

@@ -1541,18 +1541,37 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
int units = cfgobj["units"].as<int>();
if (units == 0) units = 1;
double tarifkwh = cfgobj["tariffkwh"].as<double>();
double tarifkwh;
double tariftax = cfgobj["tarifftax"].as<double>();
double minPrice = (doc[0]["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
double maxPrice = minPrice;
double minPrice = std::numeric_limits<double>::max();
double maxPrice = std::numeric_limits<double>::lowest();
double prices[n];
DynamicJsonDocument doc2(500);
JsonArray tariffArray;
std::string tariffString = cfgobj["tariffkwh"].as<std::string>();
if (tariffString.front() == '[') {
if (deserializeJson(doc2, tariffString) == DeserializationError::Ok) {
tariffArray = doc2.as<JsonArray>();
} 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<double>() / 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<double>();
} else {
tarifkwh = cfgobj["tariffkwh"].as<double>();
}
prices[i] = (obj["price"].as<double>() / 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<int>());
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<int>() / n;
uint16_t barheight = loc["bars"][2].as<int>() / (maxPrice - minPrice);
uint16_t arrowY = 0;
if (loc["bars"].size() >= 5) arrowY = loc["bars"][4].as<int>();
uint16_t barX = loc["bars"][0].as<int>();
double pricenow = std::numeric_limits<double>::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<double>();
} else {
tarifkwh = cfgobj["tariffkwh"].as<double>();
}
const double price = (obj["price"].as<double>() / 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<int>());
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();

View File

@@ -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);

View File

@@ -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"
}
}
]
},
{

View File

@@ -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) {

View File

@@ -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" ]
}
}
}

View File

@@ -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" ]