raw buffer

still some work to do:
- 1.54" img url breaks communication with the tag_fw... why???
- generate canvas from raw on webpage
- dithering in spr2buffer
This commit is contained in:
Nic Limper
2023-02-25 20:26:31 +01:00
parent dca8507dba
commit ea7a76be89
8 changed files with 176 additions and 159 deletions

View File

@@ -47,9 +47,12 @@ struct espAvailDataReq {
} __packed;
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG 1
#define DATATYPE_IMGRAW 2
#define DATATYPE_UPDATE 3
#define DATATYPE_IMG_BMP 2
#define DATATYPE_FW_UPDATE 3
#define DATATYPE_IMG_DIFF 0x10 // always 1BPP
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD
#define EPD_LUT_DEFAULT 0
#define EPD_LUT_NO_REPEATS 1

View File

@@ -30,6 +30,7 @@ enum EinkClut {
};
void spr2grays(TFT_eSprite &spr, long w, long h, String &fileout);
void jpg2grays(String filein, String fileout);
void spr2buffer(TFT_eSprite &spr, String &fileout);
void jpg2buffer(String filein, String fileout);
void bmp2grays(String filein, String fileout);

View File

@@ -58,7 +58,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
sprintf(buffer, "%02X%02X%02X%02X%02X%02X\0", src[2], src[3], src[4], src[5], src[6], src[7]);
String dst = (String)buffer;
String filename = "/" + dst + ".bmp";
String filename = "/" + dst + ".raw";
struct tm time_info;
getLocalTime(&time_info);
@@ -79,8 +79,9 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
case Image:
filename = cfgobj["filename"].as<String>();
//***FIXME... convert jpg to raw
if (filename && filename !="null" && !cfgobj["#fetched"].as<bool>()) {
if (prepareDataAvail(&filename, DATATYPE_IMGRAW, mac, cfgobj["timetolive"].as<int>())) {
if (prepareDataAvail(&filename, DATATYPE_IMG_BMP, mac, cfgobj["timetolive"].as<int>())) {
cfgobj["#fetched"] = true;
} else {
wsErr("Error accessing " + filename);
@@ -137,7 +138,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
filename = cfgobj["filename"].as<String>();
if (filename && filename != "null" && !cfgobj["#fetched"].as<bool>()) {
if (prepareDataAvail(&filename, DATATYPE_UPDATE, mac, cfgobj["timetolive"].as<int>())) {
if (prepareDataAvail(&filename, DATATYPE_FW_UPDATE, mac, cfgobj["timetolive"].as<int>())) {
cfgobj["#fetched"] = true;
} else {
wsErr("Error accessing " + filename);
@@ -183,7 +184,7 @@ void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo) {
}
bool updateTagImage(String &filename, uint8_t *dst, uint16_t nextCheckin) {
prepareDataAvail(&filename, DATATYPE_IMGRAW, dst, nextCheckin);
prepareDataAvail(&filename, DATATYPE_IMG_RAW_2BPP, dst, nextCheckin);
return true;
}
@@ -229,13 +230,13 @@ void drawDate(String &filename, tagRecord *&taginfo) {
} else if (taginfo->hwType == SOLUM_154_033) {
initSprite(spr, 154, 154);
drawString(spr, Dag[timeinfo.tm_wday], 154 / 2, 10, "fonts/calibrib30", TC_DATUM);
drawString(spr, String(Maand[timeinfo.tm_mon]), 154 / 2, 120, "fonts/calibrib30", TC_DATUM);
drawString(spr, String(timeinfo.tm_mday), 154 / 2, 42, "fonts/numbers2-1", TC_DATUM, TFT_RED);
initSprite(spr, 152, 152);
drawString(spr, Dag[timeinfo.tm_wday], 152 / 2, 10, "fonts/calibrib30", TC_DATUM);
drawString(spr, String(Maand[timeinfo.tm_mon]), 152 / 2, 120, "fonts/calibrib30", TC_DATUM);
drawString(spr, String(timeinfo.tm_mday), 152 / 2, 42, "fonts/numbers2-1", TC_DATUM, TFT_RED);
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
}
@@ -263,7 +264,7 @@ void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord
} else if (taginfo->hwType == SOLUM_154_033) {
initSprite(spr, 154, 154);
initSprite(spr, 152, 152);
spr.setTextDatum(MC_DATUM);
if (count > thresholdred) {
spr.setTextColor(TFT_RED, TFT_WHITE);
@@ -274,12 +275,12 @@ void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord
if (count > 99) font = "fonts/numbers2-1";
if (count > 999) font = "fonts/numbers3-1";
spr.loadFont(font, LittleFS);
spr.drawString(String(count), 154 / 2, 154 / 2 + 10);
spr.drawString(String(count), 152 / 2, 152 / 2 + 10);
spr.unloadFont();
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
}
@@ -377,7 +378,7 @@ void drawWeather(String &filename, String location, tagRecord *&taginfo) {
} else if (taginfo->hwType == SOLUM_154_033) {
initSprite(spr, 154, 154);
initSprite(spr, 152, 152);
spr.setTextDatum(TL_DATUM);
spr.setTextFont(2);
@@ -414,7 +415,7 @@ void drawWeather(String &filename, String location, tagRecord *&taginfo) {
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
}
}
@@ -517,7 +518,7 @@ void drawForecast(String &filename, String location, tagRecord *&taginfo) {
}
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
}
}
@@ -536,12 +537,12 @@ void drawIdentify(String &filename, tagRecord *&taginfo) {
drawString(spr, mac62hex(taginfo->mac), 10, 50, "fonts/bahnschrift20", TL_DATUM, TFT_RED);
} else if (taginfo->hwType == SOLUM_154_033) {
initSprite(spr, 154, 154);
initSprite(spr, 152, 152);
drawString(spr, taginfo->alias, 5, 5, "fonts/bahnschrift20");
drawString(spr, mac62hex(taginfo->mac), 10, 50, "fonts/bahnschrift20", TL_DATUM, TFT_RED);
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
}
@@ -557,11 +558,11 @@ bool getImgURL(String &filename, String URL, time_t fetched) {
http.setTimeout(5000); //timeout in ms
int httpCode = http.GET();
if (httpCode == 200) {
File f = LittleFS.open(filename, "w");
File f = LittleFS.open("/temp/temp.jpg", "w");
if (f) {
http.writeToStream(&f);
f.close();
jpg2grays(filename, filename);
jpg2buffer("/temp/temp.jpg", filename);
}
} else {
if (httpCode!=304) {
@@ -624,7 +625,7 @@ bool getRSSfeed(String &filename, String URL, String title, tagRecord *&taginfo)
}
}
spr2grays(spr, spr.width(), spr.height(), filename);
spr2buffer(spr, filename);
spr.deleteSprite();
return true;

View File

@@ -22,7 +22,7 @@ void timeTask(void* parameter) {
Serial.println("Waiting for valid time from NTP-server");
} else {
if (now % 10 == 0) wsSendSysteminfo();
if (now % 60 == 3) Ping();
if (now % 30 == 3) Ping();
if (now % 300 == 6) saveDB("/current/tagDB.json");
contentRunner();

View File

@@ -14,7 +14,7 @@ bool spr_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)
return 1;
}
void jpg2grays(String filein, String fileout) {
void jpg2buffer(String filein, String fileout) {
LittleFS.begin();
TJpgDec.setSwapBytes(true);
TJpgDec.setJpgScale(1);
@@ -23,15 +23,15 @@ void jpg2grays(String filein, String fileout) {
TJpgDec.getFsJpgSize(&w, &h, filein, LittleFS);
Serial.println("jpeg conversion " + String(w) + "x" + String(h));
spr.setColorDepth(8);
spr.createSprite(w, h);
if (spr.getPointer() == nullptr) {
wsErr("Failed to create sprite in jpg2grays");
wsErr("Failed to create sprite in jpg2buffer");
}
spr.setColorDepth(8);
spr.fillSprite(TFT_WHITE);
TJpgDec.drawFsJpg(0, 0, filein, LittleFS);
spr2grays(spr, w, h, fileout);
spr2buffer(spr, fileout);
spr.deleteSprite();
}
@@ -45,8 +45,6 @@ static uint32_t repackPackedVals(uint32_t val, uint32_t pixelsPerPackedUnit, uin
}
void spr2grays(TFT_eSprite &spr, long w, long h, String &fileout) {
// based on bmp2grays function by Dmitry.GR
long t = millis();
LittleFS.begin();
@@ -247,6 +245,55 @@ void spr2grays(TFT_eSprite &spr, long w, long h, String &fileout) {
Serial.println("finished writing BMP " + String(millis() - t) + "ms");
}
void spr2buffer(TFT_eSprite &spr, String &fileout) {
long t = millis();
LittleFS.begin();
fs::File f_out = LittleFS.open(fileout, "w");
bool dither = true, rotated = false;
long bufw = spr.width(), bufh = spr.height();
if (bufw > bufh) {
rotated = true;
bufw = spr.height();
bufh = spr.width();
}
int bufferSize = (bufw * bufh) / 8;
uint16_t color;
uint8_t *blackBuffer = new uint8_t[bufferSize];
uint8_t *redBuffer = new uint8_t[bufferSize];
memset(blackBuffer, 0, bufferSize);
memset(redBuffer, 0, bufferSize);
for (uint16_t y = 0; y < bufh; y++) {
for (uint16_t x = 0; x < bufw; x++) {
if (rotated) {
color = spr.readPixel(bufh - 1 - y, x);
} else {
color = spr.readPixel(x, y);
}
uint16_t bitIndex = 7 - (x % 8);
uint16_t byteIndex = (y * bufw + x) / 8;
if (color == TFT_BLACK) {
blackBuffer[byteIndex] |= (1 << bitIndex);
} else if (color == TFT_RED) {
redBuffer[byteIndex] |= (1 << bitIndex);
}
}
}
f_out.write(blackBuffer, bufferSize);
f_out.write(redBuffer, bufferSize);
delete[] blackBuffer;
delete[] redBuffer;
f_out.close();
Serial.println("finished writing buffer " + String(millis() - t) + "ms");
}
void bmp2grays(String filein, String fileout) {
// based on bmp2grays function by Dmitry.GR

View File

@@ -13,7 +13,7 @@
#include "tag_db.h"
#include "web.h"
extern void sendBlock(const void* data, const uint16_t len);
extern uint16_t sendBlock(const void* data, const uint16_t len);
void addCRC(void* p, uint8_t len) {
uint8_t total = 0;
@@ -74,80 +74,79 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
nextCheckin = MIN_RESPONSE_TIME;
}
*filename = "/" + *filename;
LittleFS.begin();
if (!LittleFS.exists(*filename)) return false;
fs::File file = LittleFS.open(*filename);
if (file.size() == 0) {
Serial.print("opened a file with size 0??\n");
return false;
}
if (filename->endsWith(".bmp") || filename->endsWith(".BMP")) {
struct BitmapFileHeader hdr;
file.read((uint8_t*)&hdr, sizeof(hdr));
if (hdr.width == 296 && hdr.height == 128) {
//sorry, can't rotate
Serial.println("when using BMP files, remember to only use 128px width and 296px height");
wsErr("when using BMP files, remember to only use 128px width and 296px height");
return false;
}
if (hdr.sig[0] == 'B' && hdr.sig[1] == 'M' && hdr.bpp == 24) {
Serial.println("converting 24bpp bmp to grays");
char fileout[64];
sprintf(fileout, "/temp/%02X%02X%02X%02X%02X%02X.bmp\0", dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
bmp2grays(*filename,(String)fileout);
*filename = (String)fileout;
file.close();
file = LittleFS.open(*filename);
}
}
if (filename->endsWith(".jpg") || filename->endsWith(".JPG")) {
Serial.println("converting jpg to grays");
char fileout[64];
sprintf(fileout, "/temp/%02X%02X%02X%02X%02X%02X.bmp\0", dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
jpg2grays(*filename, (String)fileout);
*filename = (String)fileout;
file.close();
file = LittleFS.open(*filename);
}
uint8_t md5bytes[16];
{
MD5Builder md5;
md5.begin();
md5.addStream(file, file.size());
md5.calculate();
md5.getBytes(md5bytes);
}
uint16_t attempts = 60 * 24;
uint8_t lut = EPD_LUT_NO_REPEATS;
uint8_t src[8];
*((uint64_t*)src) = swap64(*((uint64_t*)dst));
uint8_t mac[6];
memcpy(mac, src + 2, sizeof(mac));
tagRecord* taginfo = nullptr;
taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
if (taginfo == nullptr) {
wsErr("Tag not found, this shouldn't happen.");
return true;
}
if (memcmp(md5bytes, taginfo->md5pending, 16) == 0) {
wsLog("new image is the same as current or already pending image. not updating tag.");
wsSendTaginfo(mac);
return true;
*filename = "/" + *filename;
LittleFS.begin();
if (!LittleFS.exists(*filename)) {
wsErr("File not found. " + *filename);
return false;
}
fs::File file = LittleFS.open(*filename);
uint32_t filesize = file.size();
if (filesize == 0) {
file.close();
wsErr("File has size 0. " + *filename);
return false;
}
uint8_t md5bytes[16];
{
MD5Builder md5;
md5.begin();
md5.addStream(file, filesize);
md5.calculate();
md5.getBytes(md5bytes);
}
file.close();
uint16_t attempts = 60 * 24;
uint8_t lut = EPD_LUT_NO_REPEATS;
if (memcmp(md5bytes, taginfo->md5pending, 16) == 0) {
wsLog("new image is the same as current or already pending image. not updating tag.");
wsSendTaginfo(mac);
return true;
}
time_t now;
time(&now);
time_t last_midnight = now - now % (24 * 60 * 60) + 3 * 3600; // somewhere in the middle of the night
if (taginfo->lastfullupdate < last_midnight) {
lut = EPD_LUT_DEFAULT; // full update once a day
taginfo->lastfullupdate = now;
}
if (dataType != DATATYPE_FW_UPDATE) {
char dst_path[64];
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X.pending\0", dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
if (LittleFS.exists(dst_path)) {
LittleFS.remove(dst_path);
}
LittleFS.rename(*filename, dst_path);
*filename = String(dst_path);
wsLog("new image pending: " + String(dst_path));
time_t now;
time(&now);
time_t last_midnight = now - now % (24 * 60 * 60) + 3 * 3600; // somewhere in the middle of the night
if (taginfo->lastfullupdate < last_midnight) {
lut = EPD_LUT_DEFAULT; // full update once a day
taginfo->lastfullupdate = now;
}
taginfo->pending = true;
taginfo->expectedNextCheckin = now + nextCheckin * 60 + 60;
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
} else {
wsErr("Tag not found, this shouldn't happen.");
wsLog("firmware upload pending");
}
// the message that will be sent to the AP to tell the tag there is data pending
@@ -155,7 +154,7 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
memcpy(pending.targetMac, dst, 8);
pending.availdatainfo.dataType = dataType;
pending.availdatainfo.dataVer = *((uint64_t*)md5bytes);
pending.availdatainfo.dataSize = file.size();
pending.availdatainfo.dataSize = filesize;
pending.availdatainfo.dataTypeArgument = lut;
pending.availdatainfo.nextCheckIn = nextCheckin;
pending.attemptsLeft = attempts;
@@ -169,36 +168,8 @@ bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t
pendinginfo->len = pending.availdatainfo.dataSize;
pendinginfo->data = nullptr;
pendinginfo->timeout = PENDING_TIMEOUT;
//pendinginfo->data = getDataForFile(&file);
pendingfiles.push_back(pendinginfo);
if (dataType != DATATYPE_UPDATE) {
char dst_path[64];
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X.pending\0", dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
fs::File dstfile = LittleFS.open(dst_path, "w");
//int bytes_written = dstfile.write(pendinginfo->data, pendinginfo->len);
file.seek(0);
const int chunkSize = 512;
uint8_t buffer[chunkSize];
size_t bytesRead = 0;
while ((bytesRead = file.read(buffer, chunkSize)) > 0) {
dstfile.write(buffer, bytesRead);
}
dstfile.close();
wsLog("new image pending: " + String(dst_path));
if (taginfo != nullptr) {
time_t now;
time(&now);
taginfo->pending = true;
taginfo->expectedNextCheckin = now + nextCheckin * 60 + 60;
memcpy(taginfo->md5pending, md5bytes, sizeof(md5bytes));
}
} else {
wsLog("firmware upload pending");
}
file.close();
wsSendTaginfo(mac);
return true;
@@ -229,7 +200,7 @@ void processBlockRequest(struct espBlockRequest* br) {
file.close();
} else {
// file is already cached, refresh the timeout
pd->datatimeout = PENDING_DATA_TIMEOUT;
//pd->datatimeout = PENDING_DATA_TIMEOUT;
}
}
// check if we're not exceeding max blocks (to prevent sendBlock from exceeding its boundary)
@@ -241,11 +212,11 @@ void processBlockRequest(struct espBlockRequest* br) {
uint32_t len = pd->len - (BLOCK_DATA_SIZE * br->blockId);
if (len > BLOCK_DATA_SIZE) len = BLOCK_DATA_SIZE;
sendBlock(pd->data + (br->blockId * BLOCK_DATA_SIZE), len);
char buffer[64];
sprintf(buffer, "< Block Request received for MD5 %llu, block %d\n\0", br->ver, br->blockId);
uint16_t checksum = sendBlock(pd->data + (br->blockId * BLOCK_DATA_SIZE), len);
char buffer[150];
sprintf(buffer, "< Block Request received for file %s block %d, len %d checksum %u\0", pd->filename.c_str(), br->blockId, len, checksum);
wsLog((String)buffer);
Serial.printf("<BlockId=%d\n", br->blockId);
Serial.printf("< Block Request received for MD5 %llu, file %s block %d, len %d checksum %u\n", br->ver, pd->filename.c_str(), br->blockId, len, checksum);
}
void processXferComplete(struct espXferComplete* xfc) {
@@ -260,10 +231,8 @@ void processXferComplete(struct espXferComplete* xfc) {
char src_path[64];
char dst_path[64];
char tmp_path[64];
sprintf(src_path, "/current/%02X%02X%02X%02X%02X%02X.pending\0", src[2], src[3], src[4], src[5], src[6], src[7]);
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X.bmp\0", src[2], src[3], src[4], src[5], src[6], src[7]);
sprintf(tmp_path, "/temp/%02X%02X%02X%02X%02X%02X.bmp\0", src[2], src[3], src[4], src[5], src[6], src[7]);
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X.raw\0", src[2], src[3], src[4], src[5], src[6], src[7]);
if (LittleFS.exists(dst_path) && LittleFS.exists(src_path)) {
LittleFS.remove(dst_path);
}
@@ -272,9 +241,6 @@ void processXferComplete(struct espXferComplete* xfc) {
} else {
wsErr("hm, weird, no pending image found after xfercomplete.");
}
if (LittleFS.exists(tmp_path)) {
LittleFS.remove(tmp_path);
}
time_t now;
time(&now);
@@ -362,6 +328,11 @@ void processDataReq(struct espAvailDataReq* eadr) {
taginfo->hwType = eadr->adr.hwType;
taginfo->wakeupReason = eadr->adr.wakeupReason;
taginfo->capabilities = eadr->adr.capabilities;
if (eadr->adr.wakeupReason == WAKEUP_REASON_FIRSTBOOT && !taginfo->pending) {
taginfo->nextupdate = 0;
memset(taginfo->md5, 0, 16 * sizeof(uint8_t));
memset(taginfo->md5pending, 0, 16 * sizeof(uint8_t));
}
}
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X\n\0", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

View File

@@ -90,6 +90,7 @@ uint8_t pktindex = 0;
char lastchar = 0;
uint8_t charindex = 0;
uint64_t waitingForVersion = 0;
uint8_t crashcounter = 0;
uint16_t version;
void ShortRXWaitLoop() {
@@ -200,25 +201,12 @@ void SerialRXLoop() {
break;
case ZBS_RX_WAIT_VER:
waitingForVersion = 0;
crashcounter = 0;
cmdbuffer[charindex] = lastchar;
charindex++;
if (charindex == 4) {
charindex = 0;
version = (uint16_t)strtoul(cmdbuffer, NULL, 16);
/*
uint16_t fsversion;
lookupFirmwareFile(fsversion);
if ((fsversion) && (version != fsversion)) {
Serial.printf("ZBS/Zigbee FW version: %04X, version on SPIFFS: %04X\n", version, 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");
} else {
Serial.printf("ZBS/Zigbee FW version: %04X\n", version);
}
*/
RXState = ZBS_RX_WAIT_HEADER;
}
break;
@@ -229,13 +217,14 @@ void SerialRXLoop() {
extern uint8_t* getDataForFile(File* file);
void zbsRxTask(void* parameter) {
Serial1.begin(230400, SERIAL_8N1, RXD1, TXD1);
Serial1.begin(228571, SERIAL_8N1, RXD1, TXD1);
simplePowerOn();
bool firstrun = true;
Serial1.print("VER?");
waitingForVersion = esp_timer_get_time();
while (1) {
SerialRXLoop();
@@ -245,14 +234,19 @@ void zbsRxTask(void* parameter) {
vTaskDelay(1 / portTICK_PERIOD_MS);
if (waitingForVersion) {
if (esp_timer_get_time() - waitingForVersion > 10000*1000ULL) {
if (esp_timer_get_time() - waitingForVersion > 5000*1000ULL) {
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();
wsErr("The AP tag crashed. Restarting tag, regenerating all pending info.");
refreshAllPending();
wsLog("AP doesn't respond... "+String(crashcounter + 1));
if (++crashcounter >= 4) {
crashcounter = 0;
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();
wsErr("The AP tag crashed. Restarting tag, regenerating all pending info.");
refreshAllPending();
} else {
Ping();
}
}
}

View File

@@ -70,12 +70,12 @@ void showSplashScreen() {
setColorMode(EPD_MODE_NORMAL, EPD_MODE_INVERT);
#if (SCREEN_WIDTH == 152) // 1.54"
epdPrintBegin(12, 2, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdPrintBegin(5, 55, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
epdpr("Starting");
epdPrintEnd();
loadRawBitmap(oepli, 0, 12, EPD_COLOR_BLACK);
loadRawBitmap(cloud, 0, 0, EPD_COLOR_RED);
loadRawBitmap(oepli, 12, 12, EPD_COLOR_BLACK);
loadRawBitmap(cloud, 12, 0, EPD_COLOR_RED);
epdPrintBegin(5, 136, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
epdpr("%02X%02X", mSelfMac[7], mSelfMac[6]);