fix duplicate data and timeout in apfw

+ implement pinging AP
+ fix some timings
This commit is contained in:
Nic Limper
2023-02-09 22:11:58 +01:00
parent 8410eb0a53
commit 33316c1f3f
7 changed files with 102 additions and 19 deletions

Binary file not shown.

View File

@@ -138,7 +138,7 @@ struct espAvailDataReq {
} __packed;
#define TIMER_TICKS_PER_MS 1333UL
uint16_t __xdata version = 0x0006;
uint16_t __xdata version = 0x0007;
#define RAW_PKT_PADDING 2
static uint8_t __xdata mRxBuf[COMMS_MAX_PACKET_SZ];
@@ -245,7 +245,8 @@ uint8_t getBlockDataLength() {
// pendingdata slot stuff
int8_t findSlotForMac(const uint8_t *mac) {
for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) {
if (u64_isEq((uint64_t __xdata *)mac, (uint64_t __xdata *)&(pendingDataArr[c].targetMac))) { // this costs 1 sloc :(
//if (u64_isEq((uint64_t __xdata *)mac, (uint64_t __xdata *)&(pendingDataArr[c].targetMac))) { // this costs 1 sloc :(
if (memcmp(mac, ((uint8_t __xdata *)&(pendingDataArr[c].targetMac)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) {
return c;
}
@@ -320,7 +321,9 @@ void processSerial(uint8_t lastchar) {
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
int8_t slot = findFreeSlot();
struct pendingData *pd = (struct pendingData *)serialbuffer;
int8_t slot = findSlotForMac(pd->targetMac);
if (slot == -1) slot = findFreeSlot();
if (slot != -1) {
xMemCopyShort(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
pr("ACK>\n");
@@ -396,7 +399,17 @@ void espNotifyXferComplete(const uint8_t *src) {
uartTx(((uint8_t *)exfc)[c]);
}
}
void espNotifyTimeOut() {
void espNotifyTimeOut(const uint8_t *src) {
struct espXferComplete exfc;
xMemCopy8(&exfc.src, src);
uartTx('X');
uartTx('T');
uartTx('O');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)exfc)[c]);
}
}
// process data from tag
@@ -738,7 +751,7 @@ void main(void) {
for (uint8_t __xdata c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft == 1) {
espNotifyTimeOut();
espNotifyTimeOut(pendingDataArr[c].targetMac);
pendingDataArr[c].attemptsLeft = 0;
} else if (pendingDataArr[c].attemptsLeft > 1) {
pendingDataArr[c].attemptsLeft--;

View File

@@ -139,7 +139,7 @@ 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 - 60 > item.dataset.nextcheckin) {
if ((Date.now() / 1000) + servertimediff - 300 > item.dataset.nextcheckin) {
$('#tag' + tagmac + ' .warningicon').style.display='inline-block';
$('#tag' + tagmac).classList.remove("tagpending")
$('#tag' + tagmac).style.background = '#ffffcc';

View File

@@ -8,4 +8,5 @@ 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);
extern void processXferTimeout(struct espXferComplete* xfc);
extern void processDataReq(struct espAvailDataReq* adr);

View File

@@ -88,26 +88,26 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
case Today:
drawDate(filename, taginfo);
updateTagImage(filename, mac, (midnight - now) / 60 - 10);
taginfo->nextupdate = midnight;
updateTagImage(filename, mac, (midnight - now) / 60 - 10);
break;
case CountDays:
if (buttonPressed) cfgobj["counter"] = 0;
drawNumber(filename, (int32_t)cfgobj["counter"], (int32_t)cfgobj["thresholdred"], taginfo);
updateTagImage(filename, mac, (buttonPressed?0:15));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
taginfo->nextupdate = midnight;
updateTagImage(filename, mac, (buttonPressed ? 0 : 15));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
break;
case CountHours:
if (buttonPressed) cfgobj["counter"] = 0;
drawNumber(filename, (int32_t)cfgobj["counter"], (int32_t)cfgobj["thresholdred"], taginfo);
updateTagImage(filename, mac, (buttonPressed?0:5));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
taginfo->nextupdate = now + 3600;
updateTagImage(filename, mac, (buttonPressed ? 0 : 5));
cfgobj["counter"] = (int32_t)cfgobj["counter"] + 1;
break;
case Weather:
@@ -118,8 +118,8 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
// https://github.com/erikflowers/weather-icons
drawWeather(filename, cfgobj["location"], taginfo);
updateTagImage(filename, mac, 15);
taginfo->nextupdate = now + 3600;
updateTagImage(filename, mac, 15);
break;
case Firmware:
@@ -142,16 +142,16 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
case Memo:
drawIdentify(filename, taginfo);
taginfo->nextupdate = now + 12 * 3600;
updateTagImage(filename, mac, 0);
taginfo->nextupdate = now + 12*3600;
break;
case ImageUrl:
if (getImgURL(filename, cfgobj["url"], (time_t)cfgobj["#fetched"])) {
taginfo->nextupdate = now + 60 * (cfgobj["interval"].as<int>() < 5 ? 5 : cfgobj["interval"].as<int>());
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;
}

View File

@@ -58,7 +58,7 @@ void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
memcpy(pending.targetMac, dst, 8);
pending.availdatainfo.dataType = DATATYPE_NOUPDATE;
pending.availdatainfo.nextCheckIn = nextCheckin;
pending.attemptsLeft = 10;
pending.attemptsLeft = 10 + MIN_RESPONSE_TIME;
char buffer[64];
uint8_t src[8];
@@ -124,6 +124,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
md5.getBytes(md5bytes);
}
uint16_t attempts = 60;
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)dst));
uint8_t mac[6];
@@ -131,11 +132,20 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
if (memcmp(md5bytes, taginfo->md5pending, 16) == 0) {
wsLog("new image is the same as current image. not updating tag.");
wsSendTaginfo(mac);
return true;
}
time_t now;
time(&now);
uint16_t minutesUntilNextCheckin = 0;
if (taginfo->expectedNextCheckin > now) minutesUntilNextCheckin = (taginfo->expectedNextCheckin - now) / 60;
attempts += minutesUntilNextCheckin;
} else {
wsErr("Tag not found, this shouldn't happen.");
}
// the message that will be sent to the AP to tell the tag there is data pending
@@ -145,7 +155,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
pending.availdatainfo.dataVer = *((uint64_t*)md5bytes);
pending.availdatainfo.dataSize = file.size();
pending.availdatainfo.nextCheckIn = nextCheckin;
pending.attemptsLeft = 10;
pending.attemptsLeft = attempts;
sendDataAvail(&pending);
// data for the cache on the esp32; needs to hold the data longer than the maximum timeout on the AP
@@ -284,6 +294,29 @@ void processXferComplete(struct espXferComplete* xfc) {
wsSendTaginfo(mac);
}
void processXferTimeout(struct espXferComplete* xfc) {
char buffer[64];
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)xfc->src));
sprintf(buffer, "< %02X%02X%02X%02X%02X%02X xfer timeout\n\0", src[2], src[3], src[4], src[5], src[6], src[7]);
wsErr((String)buffer);
Serial.print(buffer);
uint8_t mac[6];
memcpy(mac, src + 2, sizeof(mac));
time_t now;
time(&now);
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
taginfo->expectedNextCheckin = now + 60;
taginfo->CheckinInMinPending = 0;
taginfo->pending = false;
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
}
wsSendTaginfo(mac);
}
void processDataReq(struct espAvailDataReq* eadr) {
digitalWrite(ONBOARD_LED, LOW);

View File

@@ -19,6 +19,7 @@
#define ZBS_RX_WAIT_XFERCOMPLETE 8
#define ZBS_RX_WAIT_DATA_REQ 9
#define ZBS_RX_WAIT_JOINNETWORK 10
#define ZBS_RX_WAIT_XFERTIMEOUT 11
uint8_t restartBlockRequest = 0;
@@ -111,6 +112,7 @@ void Ping() {
void SerialRXLoop() {
if (Serial1.available()) {
lastchar = Serial1.read();
//Serial.write(lastchar);
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
Serial.write(lastchar);
@@ -119,8 +121,7 @@ void SerialRXLoop() {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if ((strncmp(cmdbuffer, "VER>", 4) == 0) && waitingForVersion) {
waitingForVersion = 0;
if ((strncmp(cmdbuffer, "VER>", 4) == 0)) {
pktindex = 0;
RXState = ZBS_RX_WAIT_VER;
charindex = 0;
@@ -151,6 +152,12 @@ void SerialRXLoop() {
packetp = (uint8_t*)calloc(sizeof(struct espXferComplete) + 8, 1);
memset(cmdbuffer, 0x00, 4);
}
if (strncmp(cmdbuffer, "XTO>", 4) == 0) {
RXState = ZBS_RX_WAIT_XFERTIMEOUT;
pktindex = 0;
packetp = (uint8_t*)calloc(sizeof(struct espXferComplete) + 8, 1);
memset(cmdbuffer, 0x00, 4);
}
break;
case ZBS_RX_BLOCK_REQUEST:
packetp[pktindex] = lastchar;
@@ -171,6 +178,16 @@ void SerialRXLoop() {
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_XFERTIMEOUT:
packetp[pktindex] = lastchar;
pktindex++;
if (pktindex == sizeof(struct espXferComplete)) {
struct espXferComplete* xfc = (struct espXferComplete*)packetp;
processXferTimeout(xfc);
free(packetp);
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_DATA_REQ:
packetp[pktindex] = lastchar;
pktindex++;
@@ -182,6 +199,7 @@ void SerialRXLoop() {
}
break;
case ZBS_RX_WAIT_VER:
waitingForVersion = 0;
cmdbuffer[charindex] = lastchar;
charindex++;
if (charindex == 4) {
@@ -214,6 +232,8 @@ void zbsRxTask(void* parameter) {
Serial1.begin(230400, SERIAL_8N1, RXD1, TXD1);
simplePowerOn();
bool firstrun = true;
Serial1.print("VER?");
waitingForVersion = esp_timer_get_time();
while (1) {
@@ -223,14 +243,30 @@ void zbsRxTask(void* parameter) {
Serial1.write(Serial.read());
}
vTaskDelay(1 / portTICK_PERIOD_MS);
if (waitingForVersion) {
if (esp_timer_get_time() - waitingForVersion > 10000*1000ULL) {
waitingForVersion = esp_timer_get_time();
waitingForVersion = 0;
//performDeviceFlash();
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();
}
}
if (version && firstrun) {
Serial.printf("ZBS/Zigbee FW version: %04X\n", version);
uint16_t fsversion;
lookupFirmwareFile(fsversion);
if ((fsversion) && (version != fsversion)) {
Serial.printf("Firmware version on LittleFS: %04X\n", fsversion);
Serial.printf("Performing flash update in about 30 seconds");
vTaskDelay(30000 / portTICK_PERIOD_MS);
performDeviceFlash();
} else if (!fsversion) {
Serial.println("No ZBS/Zigbee FW binary found on SPIFFS, please upload a zigbeebase000X.bin - format binary to enable flashing");
}
firstrun = false;
}
}
}