Merge pull request #12 from nlimper/development

timing improvements and bugfixes
This commit is contained in:
Nic Limper
2023-02-09 19:42:47 +01:00
committed by GitHub
18 changed files with 132 additions and 61 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -595,6 +595,7 @@
case "jpg":
case "gif":
case "bmp":
case "pending":
return true;
}
}

View File

@@ -139,8 +139,9 @@ function updatecards() {
if (item.dataset.lastseen && item.dataset.lastseen > 1672531200) {
let idletime = (Date.now() / 1000) + servertimediff - item.dataset.lastseen;
$('#tag' + tagmac + ' .lastseen').innerHTML = "<span>last seen</span>"+displayTime(Math.floor(idletime))+" ago";
if ((Date.now() / 1000) + servertimediff > item.dataset.nextcheckin) {
if ((Date.now() / 1000) + servertimediff - 60 > item.dataset.nextcheckin) {
$('#tag' + tagmac + ' .warningicon').style.display='inline-block';
$('#tag' + tagmac).classList.remove("tagpending")
$('#tag' + tagmac).style.background = '#ffffcc';
}
if (idletime > 24*3600) {

View File

@@ -4,6 +4,7 @@ extern void addCRC(void* p, uint8_t len);
extern bool checkCRC(void* p, uint8_t len);
extern void processBlockRequest(struct espBlockRequest* br);
extern void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin);
extern bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin);
extern void processJoinNetwork(struct espJoinNetwork* xjn);
extern void processXferComplete(struct espXferComplete* xfc);

View File

@@ -11,7 +11,7 @@ class pendingdata {
//uint8_t dst[8];
uint64_t ver;
String md5;
uint16_t timeout;
uint32_t timeout;
uint8_t datatimeout;
uint8_t* data = nullptr;
uint32_t len;

View File

@@ -4,4 +4,5 @@ void zbsTx(uint8_t* packetdata, uint8_t len);
void zbsRxTask(void* parameter);
void sendCancelPending(struct pendingData* pending);
void sendDataAvail(struct pendingData* pending);
void sendDataAvail(struct pendingData* pending);
void Ping();

View File

@@ -1,19 +1,16 @@
#include <Arduino.h>
#define CHECK_IN_DELAY 900000
#define RETRY_DELAY 1000
#define FAILED_TILL_BLANK 2
#define FAILED_TILL_REASSOCIATE 1
// how long the we should keep the transfer metadata
#define PENDING_TIMEOUT 600
#define PENDING_TIMEOUT 24*3600
// this determines how long images will be cached;
#define PENDING_DATA_TIMEOUT 60
// maximum time (in minutes) that a tag is put to sleep if no update is expected.
#define MIN_RESPONSE_TIME 10
// flasher options
#define CUSTOM_MAC_HDR 0x0000
/*
/* Lolin32 lite connections to AP tag
#define RXD1 16
#define TXD1 17
@@ -24,10 +21,13 @@
#define ZBS_Reset 2
#define ZBS_POWER1 13
#define ZBS_POWER2 15
*/
#define RXD1 13
#define TXD1 12
#define ONBOARD_LED 22
//*/
//*
#define RXD1 13
#define TXD1 12
#define ZBS_SS 21
#define ZBS_CLK 18
@@ -37,5 +37,8 @@
#define ZBS_POWER1 15
#define ZBS_POWER2 2
#define ONBOARD_LED 22
//*/
#define MAX_WRITE_ATTEMPTS 5

View File

@@ -6,17 +6,6 @@
#pragma pack(push, 1)
#pragma once
enum contentModes {
Image,
Today,
CountDays,
CountHours,
Weather,
Firmware,
Memo,
ImageUrl,
};
#define SOLUM_154_033 0
#define SOLUM_29_033 1
#define SOLUM_42_033 2
@@ -29,13 +18,13 @@ enum contentModes {
class tagRecord {
public:
uint16_t nextCheckinpending;
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(Image), pending(false), md5{0}, md5pending{0}, CheckinInMinPending(0), expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0) {}
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, CheckinInMinPending(0), expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0) {}
uint8_t mac[6];
String alias;
uint32_t lastseen;
uint32_t nextupdate;
contentModes contentMode;
uint8_t contentMode;
bool pending;
uint8_t md5[16];
uint8_t md5pending[16];

View File

@@ -12,6 +12,18 @@
#include "makeimage.h"
#include "web.h"
enum contentModes {
Image,
Today,
CountDays,
CountHours,
Weather,
Firmware,
Memo,
ImageUrl,
};
void contentRunner() {
time_t now;
time(&now);
@@ -76,8 +88,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
case Today:
drawDate(filename, taginfo);
// updateTagImage(filename, mac, (midnight - now) / 60 - 10);
updateTagImage(filename, mac, 600);
updateTagImage(filename, mac, (midnight - now) / 60 - 10);
taginfo->nextupdate = midnight;
break;
@@ -85,7 +96,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
if (buttonPressed) cfgobj["counter"] = 0;
drawNumber(filename, (int32_t)cfgobj["counter"], (int32_t)cfgobj["thresholdred"], taginfo);
updateTagImage(filename, mac, (buttonPressed?0:600));
updateTagImage(filename, mac, (buttonPressed?0:15));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
taginfo->nextupdate = midnight;
break;
@@ -94,9 +105,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
if (buttonPressed) cfgobj["counter"] = 0;
drawNumber(filename, (int32_t)cfgobj["counter"], (int32_t)cfgobj["thresholdred"], taginfo);
// updateTagImage(&filename, mac, (3600 - now % 3600) / 60);
// taginfo->nextupdate = now + 3600 - (now % 3600);
updateTagImage(filename, mac, (buttonPressed?0:600));
updateTagImage(filename, mac, (buttonPressed?0:5));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
taginfo->nextupdate = now + 3600;
break;
@@ -109,7 +118,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
// https://github.com/erikflowers/weather-icons
drawWeather(filename, cfgobj["location"], taginfo);
updateTagImage(filename, mac, 600);
updateTagImage(filename, mac, 15);
taginfo->nextupdate = now + 3600;
break;
@@ -134,7 +143,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
drawIdentify(filename, taginfo);
updateTagImage(filename, mac, 0);
taginfo->nextupdate = now + 24*3600;
taginfo->nextupdate = now + 12*3600;
break;
case ImageUrl:
@@ -142,8 +151,10 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
if (getImgURL(filename, cfgobj["url"], (time_t)cfgobj["#fetched"])) {
updateTagImage(filename, mac, cfgobj["interval"].as<int>());
cfgobj["#fetched"] = now;
taginfo->nextupdate = now + 60 * (cfgobj["interval"].as<int>() < 5 ? 5 : cfgobj["interval"].as<int>());
} else {
taginfo->nextupdate = now + 300;
}
taginfo->nextupdate = now + 60 * (cfgobj["interval"].as<int>() < 5 ? 5 : cfgobj["interval"].as<int>()) ;
break;
}
@@ -449,7 +460,7 @@ bool getImgURL(String &filename, String URL, time_t fetched) {
}
}
http.end();
return (httpCode == 200);
return (httpCode == 200 || httpCode == 304);
}
char *formatHttpDate(time_t t) {

View File

@@ -8,6 +8,7 @@
#include "makeimage.h"
#include "pendingdata.h"
#include "serial.h"
#include "settings.h"
#include "soc/rtc_wdt.h"
#include "tag_db.h"
#include "web.h"
@@ -21,7 +22,9 @@ void timeTask(void* parameter) {
Serial.println("Waiting for valid time from NTP-server");
} else {
if (now % 10 == 0) wsSendSysteminfo();
if (now % 300 == 0) saveDB("/current/tagDB.json");
if (now % 60 == 3) Ping();
if (now % 300 == 6) saveDB("/current/tagDB.json");
contentRunner();
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
@@ -32,6 +35,9 @@ void setup() {
Serial.begin(115200);
Serial.print(">\n");
pinMode(ONBOARD_LED, OUTPUT);
digitalWrite(ONBOARD_LED, HIGH);
configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "0.nl.pool.ntp.org", "europe.pool.ntp.org", "time.nist.gov");
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv

View File

@@ -29,7 +29,7 @@ void jpg2grays(String filein, String fileout) {
}
spr.setColorDepth(8);
spr.fillSprite(TFT_WHITE);
TJpgDec.drawFsJpg(0, 0, filein);
TJpgDec.drawFsJpg(0, 0, filein, LittleFS);
spr2grays(spr, w, h, fileout);
spr.deleteSprite();
@@ -236,8 +236,7 @@ void spr2grays(TFT_eSprite &spr, long w, long h, String &fileout) {
f_out.write(0);
}
f_out.close();
Serial.println(millis() - t);
Serial.println("finished writing BMP");
Serial.println("finished writing BMP " + String(millis() - t) + "ms");
}
void bmp2grays(String filein, String fileout) {
@@ -429,6 +428,5 @@ void bmp2grays(String filein, String fileout) {
}
f_in.close();
f_out.close();
Serial.println(millis() - t);
Serial.println("finished writing BMP2");
Serial.println("finished converting BMP " + String(millis() - t) + "ms");
}

View File

@@ -49,14 +49,34 @@ void prepareCancelPending(uint64_t ver) {
sendCancelPending(&pending);
}
bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin) {
void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
if (nextCheckin > MIN_RESPONSE_TIME) {
// to prevent very long sleeps of the tag
nextCheckin = MIN_RESPONSE_TIME;
}
struct pendingData pending = {0};
memcpy(pending.targetMac, dst, 8);
pending.availdatainfo.dataType = DATATYPE_NOUPDATE;
pending.availdatainfo.nextCheckIn = nextCheckin;
pending.attemptsLeft = 10;
if (nextCheckin > 1440) {
char buffer[64];
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)dst));
sprintf(buffer, "idle request %02X%02X%02X%02X%02X%02X %d minutes\n\0", src[2], src[3], src[4], src[5], src[6], src[7], nextCheckin);
Serial.print(buffer);
sendDataAvail(&pending);
}
bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin) {
if (nextCheckin > MIN_RESPONSE_TIME) {
//to prevent very long sleeps of the tag
nextCheckin = 0;
nextCheckin = MIN_RESPONSE_TIME;
}
*filename = "/" + *filename;
LittleFS.begin();
if (!LittleFS.exists(*filename)) return false;
fs::File file = LittleFS.open(*filename);
@@ -137,7 +157,6 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
pendinginfo->data = nullptr;
pendinginfo->timeout = PENDING_TIMEOUT;
//pendinginfo->data = getDataForFile(&file);
pendinginfo->timeout = 1800; // ***fixme... a tag can sleep for a long time when ttl is used.
pendingfiles.push_back(pendinginfo);
if (dataType != DATATYPE_UPDATE) {
@@ -157,7 +176,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
wsLog("new image pending: " + String(dst_path));
if (taginfo != nullptr) {
taginfo->pending = true;
taginfo->CheckinInMinPending = nextCheckin + 1;
taginfo->CheckinInMinPending = nextCheckin;
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
}
}
@@ -244,14 +263,31 @@ void processXferComplete(struct espXferComplete* xfc) {
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
uint16_t minutesUntilNextUpdate = 0;
if (taginfo->nextupdate > now + 60 * taginfo->CheckinInMinPending + 3) {
minutesUntilNextUpdate = (taginfo->nextupdate - now) / 60 - taginfo->CheckinInMinPending;
if (minutesUntilNextUpdate > taginfo->CheckinInMinPending) minutesUntilNextUpdate = taginfo->CheckinInMinPending;
if (minutesUntilNextUpdate > MIN_RESPONSE_TIME) minutesUntilNextUpdate = MIN_RESPONSE_TIME;
taginfo->expectedNextCheckin = now + 60 * minutesUntilNextUpdate + 60;
if (minutesUntilNextUpdate > 0) prepareIdleReq (xfc->src, minutesUntilNextUpdate);
taginfo->CheckinInMinPending = minutesUntilNextUpdate;
} else {
taginfo->expectedNextCheckin = now + 60;
taginfo->CheckinInMinPending = 0;
}
taginfo->pending = false;
taginfo->expectedNextCheckin = now + 60 * taginfo->CheckinInMinPending + 30;
memcpy(taginfo->md5, taginfo->md5pending, sizeof(taginfo->md5pending));
}
wsSendTaginfo(mac);
}
void processDataReq(struct espAvailDataReq* eadr) {
digitalWrite(ONBOARD_LED, LOW);
char buffer[64];
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)eadr->src));
@@ -270,7 +306,19 @@ void processDataReq(struct espAvailDataReq* eadr) {
time_t now;
time(&now);
taginfo->lastseen = now;
taginfo->expectedNextCheckin = now + 300;
uint16_t minutesUntilNextUpdate = 0;
if (taginfo->nextupdate > now + 60 * taginfo->CheckinInMinPending + 3 && taginfo->pending == false) {
minutesUntilNextUpdate = (taginfo->nextupdate - now) / 60 - taginfo->CheckinInMinPending;
if (minutesUntilNextUpdate > taginfo->CheckinInMinPending) minutesUntilNextUpdate = taginfo->CheckinInMinPending;
if (minutesUntilNextUpdate > MIN_RESPONSE_TIME) minutesUntilNextUpdate = MIN_RESPONSE_TIME;
taginfo->expectedNextCheckin = now + 60 * minutesUntilNextUpdate + 60;
if (minutesUntilNextUpdate > 0) prepareIdleReq(eadr->src, minutesUntilNextUpdate);
taginfo->CheckinInMinPending = minutesUntilNextUpdate;
} else {
taginfo->expectedNextCheckin = now + 60 * taginfo->CheckinInMinPending + 60;
}
if (eadr->adr.lastPacketRSSI != 0) {
taginfo->LQI = eadr->adr.lastPacketLQI;
taginfo->hwType = eadr->adr.hwType;
@@ -287,4 +335,6 @@ void processDataReq(struct espAvailDataReq* eadr) {
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X\n\0", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.print(buffer);
wsSendTaginfo(mac);
digitalWrite(ONBOARD_LED, HIGH);
}

View File

@@ -88,7 +88,7 @@ uint8_t pktlen = 0;
uint8_t pktindex = 0;
char lastchar = 0;
uint8_t charindex = 0;
bool waitingForVersion = true;
uint64_t waitingForVersion = 0;
uint16_t version;
void ShortRXWaitLoop() {
@@ -103,19 +103,24 @@ void ShortRXWaitLoop() {
}
}
void Ping() {
Serial1.print("VER?");
waitingForVersion = esp_timer_get_time();
}
void SerialRXLoop() {
if (Serial1.available()) {
lastchar = Serial1.read();
Serial.write(lastchar);
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
Serial.write(lastchar);
// shift characters in
for (uint8_t c = 0; c < 3; c++) {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if ((strncmp(cmdbuffer, "VER>", 4) == 0) && waitingForVersion) {
waitingForVersion = false;
waitingForVersion = 0;
pktindex = 0;
RXState = ZBS_RX_WAIT_VER;
charindex = 0;
@@ -182,7 +187,8 @@ void SerialRXLoop() {
if (charindex == 4) {
charindex = 0;
version = (uint16_t)strtoul(cmdbuffer, NULL, 16);
uint16_t fsversion; // BREAK here! break;
/*
uint16_t fsversion;
lookupFirmwareFile(fsversion);
if ((fsversion) && (version != fsversion)) {
Serial.printf("ZBS/Zigbee FW version: %04X, version on SPIFFS: %04X\n", version, fsversion);
@@ -194,6 +200,7 @@ void SerialRXLoop() {
} else {
Serial.printf("ZBS/Zigbee FW version: %04X\n", version);
}
*/
RXState = ZBS_RX_WAIT_HEADER;
}
break;
@@ -208,6 +215,7 @@ void zbsRxTask(void* parameter) {
simplePowerOn();
Serial1.print("VER?");
waitingForVersion = esp_timer_get_time();
while (1) {
SerialRXLoop();
@@ -216,13 +224,12 @@ void zbsRxTask(void* parameter) {
}
vTaskDelay(1 / portTICK_PERIOD_MS);
if (waitingForVersion) {
if (millis() > 30000) {
waitingForVersion = false;
performDeviceFlash();
// Serial.printf("We've been waiting for communication from the tag, but got nothing. This is expected if this tag hasn't been flashed yet. We'll try to flash it.\n");
// doAPUpdate();
if (esp_timer_get_time() - waitingForVersion > 10000*1000ULL) {
waitingForVersion = esp_timer_get_time();
//performDeviceFlash();
// SDAtest();
Serial.println("I wasn't able to connect to a ZBS tag, trying to reboot the tag.");
Serial.println("If this problem persists, please check wiring and definitions in the settings.h file, and presence of the right firmware");
simplePowerOn();
}
}
}

View File

@@ -149,7 +149,7 @@ void loadDB(String filename) {
}
taginfo->pending = false;
taginfo->alias = tag["alias"].as<String>();
taginfo->contentMode = static_cast<contentModes>(tag["contentMode"]);
taginfo->contentMode = tag["contentMode"];
taginfo->LQI = tag["LQI"];
taginfo->RSSI = tag["RSSI"];
taginfo->temperature = tag["temperature"];

View File

@@ -282,8 +282,11 @@ void init_web() {
if (taginfo != nullptr) {
taginfo->alias = request->getParam("alias", true)->value();
taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value();
taginfo->contentMode = (contentModes)atoi(request->getParam("contentmode", true)->value().c_str());
taginfo->contentMode = atoi(request->getParam("contentmode", true)->value().c_str());
taginfo->nextupdate = 0;
taginfo->CheckinInMinPending = 0;
memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
wsSendTaginfo(mac);
saveDB("/current/tagDB.json");
request->send(200, "text/plain", "Ok, saved");