mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-28 05:08:29 +01:00
various fixes
- added last updated time of a tag in tagdb - day ahead prices choice of whole money units or cents - optimization of file upload during updates - show mac address in wifi setup - fixed reload of display after unexpected reboot of tag
This commit is contained in:
@@ -33,8 +33,8 @@
|
||||
"4": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"wind": [ 280, 5, "fonts/bahnschrift30" ],
|
||||
"temp": [ 5, 65, "fonts/bahnschrift70" ],
|
||||
"icon": [ 285, 20, 70, 2 ],
|
||||
"temp": [ 5, 65, "fonts/calibrib80" ],
|
||||
"icon": [ 275, 20, 90, 2 ],
|
||||
"dir": [ 245, -12, 40 ],
|
||||
"umbrella": [ 190, -50, 25 ]
|
||||
},
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -15,7 +15,7 @@
|
||||
#define NO_SUBGHZ_CHANNEL 255
|
||||
class tagRecord {
|
||||
public:
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0) {}
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0), updateLast(0) {}
|
||||
|
||||
uint8_t mac[8];
|
||||
uint8_t version;
|
||||
@@ -45,6 +45,7 @@ class tagRecord {
|
||||
uint8_t currentChannel;
|
||||
uint8_t invert;
|
||||
uint32_t updateCount;
|
||||
uint32_t updateLast;
|
||||
|
||||
uint8_t dataType;
|
||||
String filename;
|
||||
|
||||
@@ -235,9 +235,10 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
imageParams.lut = EPD_LUT_OTA;
|
||||
}
|
||||
|
||||
int32_t interval = 60 * 60;
|
||||
interval = cfgobj["interval"].as<int>() * 60;
|
||||
if (interval < 0) {
|
||||
int32_t interval = cfgobj["interval"].as<int>() * 60;
|
||||
if (interval == -1440 * 60) {
|
||||
interval = util::getMidnightTime() - now;
|
||||
} else if (interval < 0) {
|
||||
interval = -interval;
|
||||
unsigned int secondsUntilNext = (interval - (now % interval)) % interval;
|
||||
interval = secondsUntilNext;
|
||||
@@ -341,8 +342,8 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
|
||||
case 8: // Forecast
|
||||
|
||||
drawForecast(filename, cfgobj, taginfo, imageParams);
|
||||
taginfo->nextupdate = now + 3600;
|
||||
updateTagImage(filename, mac, 15, taginfo, imageParams);
|
||||
taginfo->nextupdate = now + interval;
|
||||
updateTagImage(filename, mac, interval / 60, taginfo, imageParams);
|
||||
break;
|
||||
|
||||
case 5: // Firmware
|
||||
@@ -1513,15 +1514,17 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
|
||||
|
||||
int n = doc.size();
|
||||
|
||||
int units = cfgobj["units"].as<int>();
|
||||
if (units == 0) units = 1;
|
||||
double tarifkwh = cfgobj["tariffkwh"].as<double>();
|
||||
double tariftax = cfgobj["tarifftax"].as<double>();
|
||||
double minPrice = (doc[0]["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100);
|
||||
double minPrice = (doc[0]["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
|
||||
double maxPrice = minPrice;
|
||||
double prices[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
const JsonObject &obj = doc[i];
|
||||
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100);
|
||||
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
|
||||
minPrice = min(minPrice, price);
|
||||
maxPrice = max(maxPrice, price);
|
||||
prices[i] = price;
|
||||
@@ -1537,7 +1540,7 @@ 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)), yAxisX, y - 8, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
|
||||
drawString(spr, String(int(i * units)), yAxisX, y - 8, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
|
||||
}
|
||||
|
||||
uint16_t barwidth = loc["bars"][1].as<int>() / n;
|
||||
@@ -1552,7 +1555,7 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
|
||||
struct tm item_timeinfo;
|
||||
localtime_r(&item_time, &item_timeinfo);
|
||||
|
||||
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100);
|
||||
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
|
||||
|
||||
uint16_t barcolor = getPercentileColor(prices, n, price);
|
||||
uint16_t thisbarh = mapDouble(price, minPrice, maxPrice, 0, loc["bars"][2].as<int>());
|
||||
|
||||
@@ -461,6 +461,7 @@ void processXferComplete(struct espXferComplete* xfc, bool local) {
|
||||
clearPending(taginfo);
|
||||
memcpy(taginfo->md5, md5bytes, sizeof(md5bytes));
|
||||
taginfo->updateCount++;
|
||||
taginfo->updateLast = now;
|
||||
taginfo->pendingCount = countQueueItem(xfc->src);
|
||||
taginfo->wakeupReason = 0;
|
||||
if (taginfo->contentMode == 12 && local == false) {
|
||||
@@ -568,7 +569,10 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
|
||||
|
||||
if (eadr->adr.lastPacketRSSI != 0) {
|
||||
if (eadr->adr.wakeupReason >= 0xE0) {
|
||||
if (taginfo->pendingCount == 0) taginfo->nextupdate = 0;
|
||||
if (taginfo->pendingCount == 0) {
|
||||
taginfo->nextupdate = 0;
|
||||
memset(taginfo->md5, 0, sizeof(taginfo->md5));
|
||||
}
|
||||
|
||||
if (local) {
|
||||
const char* reason = "";
|
||||
@@ -643,6 +647,7 @@ void updateContent(const uint8_t* dst) {
|
||||
tagRecord* taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo != nullptr) {
|
||||
clearPending(taginfo);
|
||||
memset(taginfo->md5, 0, sizeof(taginfo->md5));
|
||||
taginfo->nextupdate = 0;
|
||||
wsSendTaginfo(taginfo->mac, SYNC_TAGSTATUS);
|
||||
}
|
||||
|
||||
@@ -93,34 +93,80 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
request->send(200, "application/json", jsonResponse);
|
||||
}
|
||||
|
||||
#define UPLOAD_BUFFER_SIZE 32768
|
||||
|
||||
struct UploadInfo {
|
||||
String filename;
|
||||
uint8_t buffer[UPLOAD_BUFFER_SIZE];
|
||||
size_t bufferSize;
|
||||
};
|
||||
|
||||
void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final) {
|
||||
String uploadfilename;
|
||||
bool error = false;
|
||||
if (!index) {
|
||||
String path;
|
||||
if (!request->hasParam("path", true)) {
|
||||
path = "/temp/null.bin";
|
||||
final = true;
|
||||
error = true;
|
||||
} else {
|
||||
path = request->getParam("path", true)->value();
|
||||
Serial.println("update " + path);
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
request->_tempFile = contentFS->open(path, "w", true);
|
||||
uploadfilename = request->getParam("path", true)->value();
|
||||
Serial.println("update " + uploadfilename);
|
||||
File file = contentFS->open(uploadfilename, "w");
|
||||
file.close();
|
||||
UploadInfo* uploadInfo = new UploadInfo{uploadfilename, {}, 0};
|
||||
request->_tempObject = (void*)uploadInfo;
|
||||
}
|
||||
}
|
||||
if (len) {
|
||||
if (!request->_tempFile.write(data, len)) {
|
||||
error = true;
|
||||
final = true;
|
||||
|
||||
UploadInfo* uploadInfo = static_cast<UploadInfo*>(request->_tempObject);
|
||||
|
||||
if (uploadInfo != nullptr) {
|
||||
uploadfilename = uploadInfo->filename;
|
||||
|
||||
if (len) {
|
||||
if (uploadInfo->bufferSize + len <= UPLOAD_BUFFER_SIZE) {
|
||||
memcpy(&uploadInfo->buffer[uploadInfo->bufferSize], data, len);
|
||||
uploadInfo->bufferSize += len;
|
||||
} else {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
File file = contentFS->open(uploadfilename, "a");
|
||||
if (file) {
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
uploadInfo->bufferSize = 0;
|
||||
} else {
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
final = true;
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
|
||||
memcpy(uploadInfo->buffer, data, len);
|
||||
uploadInfo->bufferSize = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (final) {
|
||||
request->_tempFile.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
if (error) {
|
||||
request->send(507, "text/plain", "Error. Disk full?");
|
||||
} else {
|
||||
request->send(200, "text/plain", "Ok, file written");
|
||||
if (final) {
|
||||
if (uploadInfo->bufferSize > 0) {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
File file = contentFS->open(uploadfilename, "a");
|
||||
if (file) {
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
} else {
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
request->_tempObject = nullptr;
|
||||
delete uploadInfo;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
request->send(507, "text/plain", "Error. Disk full?");
|
||||
} else {
|
||||
request->send(200, "text/plain", "Ok, file written");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ void fillNode(JsonObject& tag, const tagRecord* taginfo) {
|
||||
tag["lut"] = taginfo->lut;
|
||||
tag["invert"] = taginfo->invert;
|
||||
tag["updatecount"] = taginfo->updateCount;
|
||||
tag["updatelast"] = taginfo->updateLast;
|
||||
tag["ch"] = taginfo->currentChannel;
|
||||
tag["ver"] = taginfo->tagSoftwareVersion;
|
||||
}
|
||||
@@ -228,6 +229,7 @@ bool loadDB(const String& filename) {
|
||||
taginfo->lut = tag["lut"] | 0;
|
||||
taginfo->invert = tag["invert"] | 0;
|
||||
taginfo->updateCount = tag["updatecount"] | 0;
|
||||
taginfo->updateLast = tag["updatelast"] | 0;
|
||||
taginfo->currentChannel = tag["ch"] | 0;
|
||||
taginfo->tagSoftwareVersion = tag["ver"] | 0;
|
||||
}
|
||||
|
||||
@@ -651,6 +651,7 @@ void init_web() {
|
||||
for (size_t i = 0; i < numKeys; i++) {
|
||||
doc[keys[i]] = preferences.getString(keys[i], "");
|
||||
}
|
||||
doc["mac"] = WiFi.macAddress();
|
||||
serializeJson(doc, *response);
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
@@ -146,6 +146,17 @@
|
||||
"1": "Fahrenheit / mph / millimeters"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "interval",
|
||||
"name": "Interval",
|
||||
"desc": "How often the forecast is being refreshed.",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"60": "Every hour",
|
||||
"180": "-Every three hours",
|
||||
"-1440": "At midnight"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "#lat",
|
||||
"name": "Lat",
|
||||
@@ -380,7 +391,7 @@
|
||||
{
|
||||
"key": "tariffkwh",
|
||||
"name": "Fixed surcharge",
|
||||
"desc": "Fixed surcharge per kWh, in 1/100 units (cents)",
|
||||
"desc": "Fixed surcharge per kWh, in 1/100 units (cents/öre/øre)",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
@@ -388,7 +399,17 @@
|
||||
"name": "Tax percentage",
|
||||
"desc": "Percentage to add to the total (for example, 21, for 21% VAT)",
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
{
|
||||
"key": "units",
|
||||
"name": "Price units",
|
||||
"desc": "Display whole units (EUR/NOK/DKK) or cents",
|
||||
"type": "select",
|
||||
"options": {
|
||||
"100": "1/1 units (EUR/NOK/DKK)",
|
||||
"1": "1/100 units (cents/öre/øre)"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
<link rel="stylesheet" href="main.css" type="text/css" />
|
||||
<link rel="icon" type="image/vnd.icon" href="favicon.ico">
|
||||
<style>
|
||||
.window {
|
||||
margin-left: 10px;
|
||||
}
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.window input {
|
||||
width: 120px;
|
||||
}
|
||||
@@ -29,6 +35,7 @@
|
||||
<div class="container">
|
||||
<div class="window">
|
||||
<h1>WiFi config</h1>
|
||||
<p>WiFi mac address: <span id="mac">-</span></p>
|
||||
<pre>
|
||||
SSID <input type="text" id="ssid"> <button id="listssid">find SSID</button>
|
||||
Password <input type="password" id="pw">
|
||||
@@ -40,7 +47,6 @@ Subnet mask <input type="text" id="mask">
|
||||
Gateway <input type="text" id="gw">
|
||||
DNS <input type="text" id="dns">
|
||||
</pre>
|
||||
|
||||
<button id="connect">Save WiFi settings and reboot</button><br>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@ window.addEventListener("load", function () {
|
||||
$('#mask').value = data.mask || "";
|
||||
$('#gw').value = data.gw || "";
|
||||
$('#dns').value = data.dns || "";
|
||||
$('#mac').innerHTML = data.mac || "";
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user