From 6197b8962ec98cc8b32b3b711332b4b6eadc3bda Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Tue, 26 Mar 2024 01:13:02 +0100 Subject: [PATCH] color table and various fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - use the actual color table in tagtype json for rendering images (until now, that color table was ignored) - added proper ordered dithering (works with all colors now, not just gray and pink) - on the static image content card, you can now choose floyd-steinberg or ordered dithering (or turn dithering off) - added ÅÄÖ to twcondensed20 font - small bugfixes - fix serial passthrough via UART in OEPL-flasher.py --- ESP32_AP-Flasher/data/fonts/twcondensed20.vlw | Bin 4177 -> 4645 bytes .../data/www/content_cards.json.gz | Bin 4574 -> 4598 bytes ESP32_AP-Flasher/data/www/index.html.gz | Bin 6348 -> 6354 bytes ESP32_AP-Flasher/data/www/main.js.gz | Bin 14449 -> 14468 bytes ESP32_AP-Flasher/include/makeimage.h | 6 +- ESP32_AP-Flasher/include/tag_db.h | 11 ++++ ESP32_AP-Flasher/src/contentmanager.cpp | 29 ++++++--- ESP32_AP-Flasher/src/makeimage.cpp | 58 ++++++------------ ESP32_AP-Flasher/src/newproto.cpp | 30 ++++----- ESP32_AP-Flasher/src/tag_db.cpp | 28 ++++++--- ESP32_AP-Flasher/src/truetype.cpp | 3 +- ESP32_AP-Flasher/src/web.cpp | 5 ++ ESP32_AP-Flasher/wwwroot/content_cards.json | 6 +- ESP32_AP-Flasher/wwwroot/index.html | 2 +- ESP32_AP-Flasher/wwwroot/main.js | 8 ++- Tag_Flasher/OEPL-Flasher.py | 10 +-- .../render_bitmapfonts/render_bitmapfonts.pde | 2 +- resources/tagtypes/00.json | 6 +- resources/tagtypes/01.json | 6 +- resources/tagtypes/02.json | 6 +- resources/tagtypes/05.json | 6 +- resources/tagtypes/11.json | 6 +- resources/tagtypes/21.json | 6 +- resources/tagtypes/22.json | 6 +- resources/tagtypes/26.json | 3 +- resources/tagtypes/27.json | 4 +- resources/tagtypes/2E.json | 6 +- resources/tagtypes/2F.json | 6 +- resources/tagtypes/30.json | 6 +- resources/tagtypes/31.json | 4 +- resources/tagtypes/32.json | 6 +- resources/tagtypes/33.json | 6 +- resources/tagtypes/34.json | 6 +- resources/tagtypes/35.json | 6 +- resources/tagtypes/36.json | 6 +- resources/tagtypes/41.json | 6 +- resources/tagtypes/42.json | 8 +-- resources/tagtypes/43.json | 19 ++++++ resources/tagtypes/55.json | 6 +- resources/tagtypes/60.json | 6 +- resources/tagtypes/61.json | 6 +- resources/tagtypes/62.json | 6 +- resources/tagtypes/80.json | 47 +------------- resources/tagtypes/81.json | 6 +- resources/tagtypes/82.json | 6 +- resources/tagtypes/83.json | 49 ++------------- resources/tagtypes/B2.json | 3 +- resources/tagtypes/B3.json | 6 +- resources/tagtypes/B5.json | 6 +- resources/tagtypes/BD.json | 6 +- resources/tagtypes/BE.json | 8 +-- resources/tagtypes/E0.json | 6 +- resources/tagtypes/E1.json | 6 +- resources/tagtypes/F0.json | 3 +- 54 files changed, 207 insertions(+), 301 deletions(-) create mode 100644 resources/tagtypes/43.json diff --git a/ESP32_AP-Flasher/data/fonts/twcondensed20.vlw b/ESP32_AP-Flasher/data/fonts/twcondensed20.vlw index 01bda1fa351309a2e81320585ffcfbe0e6c4c320..39a9758ed80a78f7050a1679b74e44a3d46ca9e9 100644 GIT binary patch delta 169 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 delta 4452 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 DzT!cF diff --git a/ESP32_AP-Flasher/include/makeimage.h b/ESP32_AP-Flasher/include/makeimage.h index c3a65e27..1214e531 100644 --- a/ESP32_AP-Flasher/include/makeimage.h +++ b/ESP32_AP-Flasher/include/makeimage.h @@ -3,6 +3,8 @@ #pragma once +#include "tag_db.h" + extern TFT_eSPI tft; #define SHORTLUT_DISABLED 0 @@ -10,10 +12,12 @@ extern TFT_eSPI tft; #define SHORTLUT_ALLOWED 2 struct imgParam { + HwType hwdata; + bool hasRed; uint8_t dataType; uint8_t dither; - bool grayLut = false; + // bool grayLut = false; uint8_t bufferbpp = 8; uint8_t rotate = 0; uint16_t highlightColor = 2; diff --git a/ESP32_AP-Flasher/include/tag_db.h b/ESP32_AP-Flasher/include/tag_db.h index 3abae83b..42a44097 100644 --- a/ESP32_AP-Flasher/include/tag_db.h +++ b/ESP32_AP-Flasher/include/tag_db.h @@ -76,7 +76,15 @@ struct Config { String env; }; +struct Color { + uint8_t r, g, b; + Color() : r(0), g(0), b(0) {} + Color(uint16_t value_) : r((value_ >> 8) & 0xF8 | (value_ >> 13) & 0x07), g((value_ >> 3) & 0xFC | (value_ >> 9) & 0x03), b((value_ << 3) & 0xF8 | (value_ >> 2) & 0x07) {} + Color(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {} +}; + struct HwType { + uint8_t id; uint16_t width; uint16_t height; uint8_t rotatebuffer; @@ -84,6 +92,7 @@ struct HwType { uint8_t shortlut; uint8_t zlib; uint16_t highlightColor; + std::vector colortable; }; struct varStruct { @@ -109,6 +118,7 @@ extern void clearPending(tagRecord* taginfo); extern void initAPconfig(); extern void saveAPconfig(); extern HwType getHwType(const uint8_t id); + /// @brief Update a variable with the given key and value /// /// @param key Variable key @@ -117,6 +127,7 @@ extern HwType getHwType(const uint8_t id); /// @return true If variable was created/updated /// @return false If not extern bool setVarDB(const std::string& key, const String& value, const bool notify = true); + extern void cleanupCurrent(); extern void pushTagInfo(tagRecord* taginfo); extern void popTagInfo(const uint8_t mac[8] = nullptr); diff --git a/ESP32_AP-Flasher/src/contentmanager.cpp b/ESP32_AP-Flasher/src/contentmanager.cpp index ce1a29e9..a4434648 100644 --- a/ESP32_AP-Flasher/src/contentmanager.cpp +++ b/ESP32_AP-Flasher/src/contentmanager.cpp @@ -201,16 +201,18 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { taginfo->nextupdate = now + 60; imgParam imageParams; + imageParams.hwdata = hwdata; imageParams.width = hwdata.width; imageParams.height = hwdata.height; imageParams.bpp = hwdata.bpp; imageParams.rotatebuffer = hwdata.rotatebuffer; + imageParams.shortlut = hwdata.shortlut; imageParams.highlightColor = getColor(String(hwdata.highlightColor)); imageParams.hasRed = false; imageParams.dataType = DATATYPE_IMG_RAW_1BPP; imageParams.dither = 2; - if (taginfo->hasCustomLUT && taginfo->lut != 1) imageParams.grayLut = true; + // if (taginfo->hasCustomLUT && taginfo->lut != 1) imageParams.grayLut = true; imageParams.invert = taginfo->invert; imageParams.symbols = 0; @@ -220,7 +222,6 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) { } else { imageParams.zlib = 0; } - imageParams.shortlut = hwdata.shortlut; imageParams.lut = EPD_LUT_NO_REPEATS; if (taginfo->lut == 2) imageParams.lut = EPD_LUT_FAST_NO_REDS; @@ -655,7 +656,11 @@ void drawString(TFT_eSprite &spr, String content, int16_t posx, int16_t posy, St posx -= truetype.getStringWidth(content); } truetype.setTextBoundary(posx, spr.width(), spr.height()); - truetype.setTextColor(spr.color16to8(color), spr.color16to8(color)); + if (spr.getColorDepth() == 8) { + truetype.setTextColor(spr.color16to8(color), spr.color16to8(color)); + } else { + truetype.setTextColor(color, color); + } truetype.textDraw(posx, posy, content); truetype.end(); } break; @@ -716,9 +721,14 @@ void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy } void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams) { - spr.setColorDepth(8); + spr.setColorDepth(16); spr.createSprite(w, h); - spr.setRotation(3); + if (spr.getPointer() == nullptr) { + wsErr("low on memory. Fallback to 8bpp"); + util::printLargestFreeBlock(); + spr.setColorDepth(8); + spr.createSprite(w, h); + } if (spr.getPointer() == nullptr) { wsErr("low on memory. Fallback to 1bpp"); util::printLargestFreeBlock(); @@ -730,6 +740,7 @@ void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams) { if (spr.getPointer() == nullptr) { wsErr("Failed to create sprite"); } + spr.setRotation(3); spr.fillSprite(TFT_WHITE); } @@ -1266,9 +1277,9 @@ bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgPa drawString(spr, String(languageDaysShort[dayInfo->tm_wday]) + " " + String(dayInfo->tm_mday), colStart + colWidth / 2, calTop, loc["gridparam"][3], TC_DATUM, TFT_BLACK); if (dayInfo->tm_wday == 0 || dayInfo->tm_wday == 6) { - spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, TFT_DARKGREY); + spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, getColor("darkgray")); } else { - spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, TFT_LIGHTGREY); + spr.fillRect(colStart + 1, calTop + calYOffset, colWidth - 1, calHeight - 1, getColor("lightgray")); } } @@ -2153,9 +2164,9 @@ uint16_t getColor(const String &color) { if (color == "1" || color == "" || color == "black") return TFT_BLACK; if (color == "2" || color == "red") return TFT_RED; if (color == "3" || color == "yellow") return TFT_YELLOW; - if (color == "4" || color == "lightgray") return TFT_LIGHTGREY; + if (color == "4" || color == "lightgray") return 0xBDF7; if (color == "5" || color == "darkgray") return TFT_DARKGREY; - if (color == "6" || color == "pink") return TFT_PINK; + if (color == "6" || color == "pink") return 0xFBCF; uint16_t r, g, b; if (color.length() == 7 && color[0] == '#' && sscanf(color.c_str(), "#%2hx%2hx%2hx", &r, &g, &b) == 3) { diff --git a/ESP32_AP-Flasher/src/makeimage.cpp b/ESP32_AP-Flasher/src/makeimage.cpp index 24d79f5a..89b36584 100644 --- a/ESP32_AP-Flasher/src/makeimage.cpp +++ b/ESP32_AP-Flasher/src/makeimage.cpp @@ -8,6 +8,7 @@ #include "leds.h" #include "miniz-oepl.h" #include "storage.h" +#include "tag_db.h" #include "util.h" #ifdef HAS_TFT @@ -62,13 +63,6 @@ void jpg2buffer(String filein, String fileout, imgParam &imageParams) { } } -struct Color { - uint8_t r, g, b; - Color() : r(0), g(0), b(0) {} - Color(uint16_t value_) : r((value_ >> 8) & 0xF8 | (value_ >> 13) & 0x07), g((value_ >> 3) & 0xFC | (value_ >> 9) & 0x03), b((value_ << 3) & 0xF8 | (value_ >> 2) & 0x07) {} - Color(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {} -}; - struct Error { int32_t r; int32_t g; @@ -102,32 +96,22 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t memset(buffer, 0, buffer_size); - std::vector palette = { - {255, 255, 255}, // White - {0, 0, 0}, // Black - {255, 0, 0} // Red - }; + std::vector palette = imageParams.hwdata.colortable; if (imageParams.invert == 1) { std::swap(palette[0], palette[1]); } Color color; - if (imageParams.dither == 2) { - color = {128, 128, 128}; - palette.push_back(color); - color = {211, 211, 211}; - palette.push_back(color); - color = {255, 192, 203}; - palette.push_back(color); - } else if (imageParams.grayLut) { - color = {160, 160, 160}; - palette.push_back(color); - Serial.println("rendering with gray"); - } int num_colors = palette.size(); if (imageParams.bufferbpp == 1) num_colors = 2; Error *error_bufferold = new Error[bufw + 4]; Error *error_buffernew = new Error[bufw + 4]; + const uint8_t ditherMatrix[4][4] = { + {0, 9, 2, 10}, + {12, 5, 14, 6}, + {3, 11, 1, 8}, + {15, 7, 13, 4}}; + memset(error_bufferold, 0, bufw * sizeof(Error)); for (uint16_t y = 0; y < bufh; y++) { memset(error_buffernew, 0, bufw * sizeof(Error)); @@ -147,8 +131,17 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t break; } + if (imageParams.dither == 2) { + // Ordered dithering + uint8_t ditherValue = ditherMatrix[y % 4][x % 4]; + error_bufferold[x].r = (ditherValue << 4) - 120; // * 256 / 16 - 128 + 8 + error_bufferold[x].g = (ditherValue << 4) - 120; + error_bufferold[x].b = (ditherValue << 4) - 120; + } + int best_color_index = 0; uint32_t best_color_distance = colorDistance(color, palette[0], error_bufferold[x]); + for (int i = 1; i < num_colors; i++) { if (best_color_distance == 0) break; uint32_t distance = colorDistance(color, palette[i], error_bufferold[x]); @@ -157,7 +150,6 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t best_color_index = i; } } - uint8_t bitIndex = 7 - (x % 8); uint32_t byteIndex = (y * bufw + x) / 8; @@ -173,29 +165,19 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer[byteIndex] |= (1 << bitIndex); break; case 3: - if (imageParams.grayLut) { - buffer[byteIndex] |= (1 << bitIndex); - imageParams.hasRed = true; - } else { - if (!is_red && (x + y) % 2) buffer[byteIndex] |= (1 << bitIndex); - } - break; - case 4: - if (!is_red && ((x + y / 2) % 2 == 0) && (y % 2 == 0)) buffer[byteIndex] |= (1 << bitIndex); - break; - case 5: - if (is_red && (x + y) % 2) buffer[byteIndex] |= (1 << bitIndex); imageParams.hasRed = true; + buffer[byteIndex] |= (1 << bitIndex); break; } if (imageParams.dither == 1) { + // Burkes Dithering + Error error = { color.r + error_bufferold[x].r - palette[best_color_index].r, color.g + error_bufferold[x].g - palette[best_color_index].g, color.b + error_bufferold[x].b - palette[best_color_index].b}; - // Burkes Dithering error_buffernew[x].r += error.r >> 2; error_buffernew[x].g += error.g >> 2; error_buffernew[x].b += error.b >> 2; diff --git a/ESP32_AP-Flasher/src/newproto.cpp b/ESP32_AP-Flasher/src/newproto.cpp index c236dc66..d1eab0cb 100644 --- a/ESP32_AP-Flasher/src/newproto.cpp +++ b/ESP32_AP-Flasher/src/newproto.cpp @@ -526,12 +526,12 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP if (taginfo == nullptr) { if (config.lock == 1 || (config.lock == 2 && eadr->adr.wakeupReason != WAKEUP_REASON_FIRSTBOOT)) return; #ifdef HAS_SUBGHZ - if(apInfo.hasSubGhz && eadr->adr.currentChannel > 0 && eadr->adr.currentChannel == apInfo.SubGhzChannel) { - // Empty intentionally + if (apInfo.hasSubGhz && eadr->adr.currentChannel > 0 && eadr->adr.currentChannel == apInfo.SubGhzChannel) { + // Empty intentionally } else #endif - if (eadr->adr.currentChannel > 0 && eadr->adr.currentChannel != apInfo.channel) { - Serial.printf("Tag %s reports illegal channel %d\n", hexmac, eadr->adr.currentChannel); + if (local == true && eadr->adr.currentChannel > 0 && eadr->adr.currentChannel != apInfo.channel) { + Serial.printf("Tag %s reports illegal channel %d\n", hexmac, eadr->adr.currentChannel); return; } taginfo = new tagRecord; @@ -662,23 +662,23 @@ void setAPchannel() { udpsync.getAPList(); } else { if (curChannel.channel != config.channel) { - curChannel.channel = config.channel; - bSendRadioLayer = true; + curChannel.channel = config.channel; + bSendRadioLayer = true; } } #ifdef HAS_SUBGHZ - if(curChannel.subghzchannel != config.subghzchannel) { - curChannel.subghzchannel = config.subghzchannel; - apInfo.SubGhzChannel = config.subghzchannel; - bSendRadioLayer = true; + if (curChannel.subghzchannel != config.subghzchannel) { + curChannel.subghzchannel = config.subghzchannel; + apInfo.SubGhzChannel = config.subghzchannel; + bSendRadioLayer = true; } #endif - if(bSendRadioLayer) { - tmp = curChannel; - if(config.channel == 0) { - tmp.channel = 0; // don't set the 802.15.4 channel + if (bSendRadioLayer) { + tmp = curChannel; + if (config.channel == 0) { + tmp.channel = 0; // don't set the 802.15.4 channel } - sendChannelPower(&tmp); + sendChannelPower(&tmp); } } diff --git a/ESP32_AP-Flasher/src/tag_db.cpp b/ESP32_AP-Flasher/src/tag_db.cpp index 02d5b766..f71fd2b0 100644 --- a/ESP32_AP-Flasher/src/tag_db.cpp +++ b/ESP32_AP-Flasher/src/tag_db.cpp @@ -388,6 +388,7 @@ HwType getHwType(const uint8_t id) { filter["shortlut"] = true; filter["zlib_compression"] = true; filter["highlight_color"] = true; + filter["colortable"] = true; StaticJsonDocument<1000> doc; DeserializationError error = deserializeJson(doc, jsonFile, DeserializationOption::Filter(filter)); jsonFile.close(); @@ -395,17 +396,28 @@ HwType getHwType(const uint8_t id) { Serial.println("json error in " + String(filename)); Serial.println(error.c_str()); } else { - hwdata[id].width = doc["width"]; - hwdata[id].height = doc["height"]; - hwdata[id].rotatebuffer = doc["rotatebuffer"]; - hwdata[id].bpp = doc["bpp"]; - hwdata[id].shortlut = doc["shortlut"]; + HwType& hwType = hwdata[id]; + hwType.id = id; + hwType.width = doc["width"]; + hwType.height = doc["height"]; + hwType.rotatebuffer = doc["rotatebuffer"]; + hwType.bpp = doc["bpp"]; + hwType.shortlut = doc["shortlut"]; if (doc.containsKey("zlib_compression")) { - hwdata[id].zlib = strtol(doc["zlib_compression"], nullptr, 16); + hwType.zlib = strtol(doc["zlib_compression"], nullptr, 16); } else { - hwdata[id].zlib = 0; + hwType.zlib = 0; + } + hwType.highlightColor = doc.containsKey("highlight_color") ? doc["highlight_color"].as() : 2; + JsonObject colorTable = doc["colortable"]; + for (auto kv : colorTable) { + JsonArray color = kv.value(); + Color c; + c.r = color[0]; + c.g = color[1]; + c.b = color[2]; + hwType.colortable.push_back(c); } - hwdata[id].highlightColor = doc.containsKey("highlight_color") ? doc["highlight_color"].as() : 2; return hwdata.at(id); } } diff --git a/ESP32_AP-Flasher/src/truetype.cpp b/ESP32_AP-Flasher/src/truetype.cpp index d37b5d46..273c89eb 100644 --- a/ESP32_AP-Flasher/src/truetype.cpp +++ b/ESP32_AP-Flasher/src/truetype.cpp @@ -1023,7 +1023,8 @@ void truetypeClass::addPixel(int16_t _x, int16_t _y, uint16_t _colorCode) { switch (framebufferBit) { case 16: // 16bit horizontal { - uint16_t *p = (uint16_t *)&userFrameBuffer[(uint16_t)_x + (uint16_t)_y * displayWidthFrame]; + uint16_t *p = (uint16_t *)&userFrameBuffer[(uint16_t)_x * 2 + (uint16_t)_y * displayWidthFrame]; + _colorCode = (_colorCode >> 8) | (_colorCode << 8); *p = _colorCode; } break; case 8: // 8bit Horizontal diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index 09dbde34..9cd0a20e 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -290,6 +290,11 @@ void init_web() { uint8_t md5[8]; if (hex2mac(request->getParam("md5")->value(), md5)) { PendingItem *queueItem = getQueueItem(mac, *reinterpret_cast(md5)); + if (queueItem == nullptr) { + Serial.println("getQueueItem: no queue item"); + request->send(404, "text/plain", "File not found"); + return; + } if (queueItem->data == nullptr) { fs::File file = contentFS->open(queueItem->filename); if (file) { diff --git a/ESP32_AP-Flasher/wwwroot/content_cards.json b/ESP32_AP-Flasher/wwwroot/content_cards.json index 51d80263..0c897ade 100644 --- a/ESP32_AP-Flasher/wwwroot/content_cards.json +++ b/ESP32_AP-Flasher/wwwroot/content_cards.json @@ -23,7 +23,8 @@ "type": "select", "options": { "0": "off", - "1": "on" + "1": "floyd-steinberg dithering", + "2": "ordered dithering" } } ] @@ -479,7 +480,8 @@ "type": "select", "options": { "0": "off", - "1": "on" + "1": "floyd-steinberg dithering", + "2": "ordered dithering" } }, { diff --git a/ESP32_AP-Flasher/wwwroot/index.html b/ESP32_AP-Flasher/wwwroot/index.html index c6b5a52a..2d52661d 100644 --- a/ESP32_AP-Flasher/wwwroot/index.html +++ b/ESP32_AP-Flasher/wwwroot/index.html @@ -238,7 +238,7 @@ It sets the mac automatically, tries to recognize the type, and starts flashing. Currently, Solum M2 tags only.



- Using
OEPL-Flasher.py, you have full control over the flashing of the tag.
+ Using OEPL-Flasher.py, you have full control over the flashing of the tag.
Use the --ip argument to connect to the flasher.

Usage:
diff --git a/ESP32_AP-Flasher/wwwroot/main.js b/ESP32_AP-Flasher/wwwroot/main.js index 2356971e..f62daa42 100644 --- a/ESP32_AP-Flasher/wwwroot/main.js +++ b/ESP32_AP-Flasher/wwwroot/main.js @@ -1012,7 +1012,7 @@ function populateSelectTag(hwtype, capabilities) { let option; cardconfig.forEach(item => { const capcheck = item.capabilities ?? 0; - if (tagTypes[hwtype].contentids.includes(item.id) && (capabilities & capcheck || capcheck == 0) && (apConfig.savespace == 0 || !item.properties?.includes("savespace"))) { + if (tagTypes[hwtype].contentids?.includes(item.id) && (capabilities & capcheck || capcheck == 0) && (apConfig.savespace == 0 || !item.properties?.includes("savespace"))) { option = document.createElement("option"); option.value = item.id; option.text = item.name; @@ -1327,6 +1327,10 @@ const downloadTagtype = async (hwtype) => { console.log(url); const response = await fetch(url); + if (!response.ok) { + console.log("github download error " + response.status); + return response; + } const clonedResponse = response.clone(); const fileContent = await clonedResponse.blob(); @@ -1398,7 +1402,7 @@ async function getTagtype(hwtype) { } if (!response.ok) { - let data = { name: 'unknown id ' + hwtype.toString(16), width: 0, height: 0, bpp: 0, rotatebuffer: 0, colortable: [], busy: false }; + let data = { name: 'unknown id ' + hwtype.toString(16).toUpperCase(), width: 0, height: 0, bpp: 0, rotatebuffer: 0, colortable: [], busy: false }; tagTypes[hwtype] = data; getTagtypeBusy = false; return data; diff --git a/Tag_Flasher/OEPL-Flasher.py b/Tag_Flasher/OEPL-Flasher.py index 9793862f..81d704a5 100644 --- a/Tag_Flasher/OEPL-Flasher.py +++ b/Tag_Flasher/OEPL-Flasher.py @@ -418,17 +418,19 @@ def main(): if transport == TRANSPORT_TCP: try: data = tcp_socket.recv(1) + data_str = data.decode('utf-8') except socket.timeout: - data = "" + data_str = "" pass else: try: data = ser.read(1) + data_str = data.decode('utf-8') except UnicodeDecodeError: - data = "" + data_str = "" pass - print(data, end='') - if chr(0x04) in data: + print(data_str, end='') + if chr(0x04) in data_str: break except KeyboardInterrupt: diff --git a/miscellaneous/render_bitmapfonts/render_bitmapfonts.pde b/miscellaneous/render_bitmapfonts/render_bitmapfonts.pde index cfdd2cf6..5457ff8c 100644 --- a/miscellaneous/render_bitmapfonts/render_bitmapfonts.pde +++ b/miscellaneous/render_bitmapfonts/render_bitmapfonts.pde @@ -56,7 +56,7 @@ void setup() { String str = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~°ÄÅÆÖØÚÜßáäåæéíöøúüýąČěľłńŘřŚŠź"; char[] charsetbasic = str.toCharArray(); - str = "ACDEFHIJLMNOPRSTUVWZiortzÁØÚČŚŠ0123456789-"; + str = "ACDEFHIJLMNOPRSTUVWZiortzÁÅÄÖØÚČŚŠ0123456789-"; char[] charsetdaynames = str.toCharArray(); str = "0123456789.°-"; char[] charsetnumbers = str.toCharArray(); diff --git a/resources/tagtypes/00.json b/resources/tagtypes/00.json index b4a4a875..2fbf8724 100644 --- a/resources/tagtypes/00.json +++ b/resources/tagtypes/00.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 1.54\"", "width": 152, "height": 152, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 2, "options": [ "button", "customlut" ], diff --git a/resources/tagtypes/01.json b/resources/tagtypes/01.json index c352251f..ead6d55e 100644 --- a/resources/tagtypes/01.json +++ b/resources/tagtypes/01.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 2, "options": [ "button", "customlut" ], diff --git a/resources/tagtypes/02.json b/resources/tagtypes/02.json index 9ef822f9..8bd6fba5 100644 --- a/resources/tagtypes/02.json +++ b/resources/tagtypes/02.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 4.2\"", "width": 400, "height": 300, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 1, "options": [ "button" ], diff --git a/resources/tagtypes/05.json b/resources/tagtypes/05.json index 69738b9f..b35d98ec 100644 --- a/resources/tagtypes/05.json +++ b/resources/tagtypes/05.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 7.4\"", "width": 640, "height": 384, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 1, "zlib_compression": "27", diff --git a/resources/tagtypes/11.json b/resources/tagtypes/11.json index 3ea87e6c..96aa3051 100644 --- a/resources/tagtypes/11.json +++ b/resources/tagtypes/11.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 2.9\" (UC8151)", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ "button" ], diff --git a/resources/tagtypes/21.json b/resources/tagtypes/21.json index 5968ace4..9e863aae 100644 --- a/resources/tagtypes/21.json +++ b/resources/tagtypes/21.json @@ -1,15 +1,13 @@ { - "version": 0, + "version": 1, "name": "ST‐GM29XXF 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], - "black": [ 0, 0, 0 ], - "gray": [ 150, 150, 150 ] + "black": [ 0, 0, 0 ] }, "highlight_color": 5, "shortlut": 0, diff --git a/resources/tagtypes/22.json b/resources/tagtypes/22.json index 84d6b972..dd7bcb77 100644 --- a/resources/tagtypes/22.json +++ b/resources/tagtypes/22.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M2 2.7\"", "width": 264, "height": 176, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ "button" ], diff --git a/resources/tagtypes/26.json b/resources/tagtypes/26.json index ef96c4b6..ece9cbc6 100644 --- a/resources/tagtypes/26.json +++ b/resources/tagtypes/26.json @@ -1,11 +1,10 @@ { - "version": 0, + "version": 1, "name": "M2 7.5\" BW", "width": 640, "height": 384, "rotatebuffer": 0, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ] diff --git a/resources/tagtypes/27.json b/resources/tagtypes/27.json index a417127c..2fb9f78e 100644 --- a/resources/tagtypes/27.json +++ b/resources/tagtypes/27.json @@ -1,15 +1,15 @@ { - "version": 0, + "version": 1, "name": "ST‐GM29MT1 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ] }, + "highlight_color": 5, "shortlut": 0, "options": [ "button", "customlut" ], "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21 ], diff --git a/resources/tagtypes/2E.json b/resources/tagtypes/2E.json index 736d97f7..61ded3df 100644 --- a/resources/tagtypes/2E.json +++ b/resources/tagtypes/2E.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 9.7\"", "width": 960, "height": 672, "rotatebuffer": 2, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/2F.json b/resources/tagtypes/2F.json index 6db2d566..da4f5eb3 100644 --- a/resources/tagtypes/2F.json +++ b/resources/tagtypes/2F.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 4.3\"", "width": 522, "height": 152, "rotatebuffer": 3, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/30.json b/resources/tagtypes/30.json index d636caf8..993f0b5b 100644 --- a/resources/tagtypes/30.json +++ b/resources/tagtypes/30.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 1.6\"", "width": 200, "height": 200, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/31.json b/resources/tagtypes/31.json index d1903d3a..7f822a1f 100644 --- a/resources/tagtypes/31.json +++ b/resources/tagtypes/31.json @@ -5,12 +5,10 @@ "height": 160, "rotatebuffer": 3, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/32.json b/resources/tagtypes/32.json index 40e34c89..329ed6fd 100644 --- a/resources/tagtypes/32.json +++ b/resources/tagtypes/32.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 2.6\"", "width": 360, "height": 184, "rotatebuffer": 3, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/33.json b/resources/tagtypes/33.json index 3cccccbf..dd08928b 100644 --- a/resources/tagtypes/33.json +++ b/resources/tagtypes/33.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 2.9\"", "width": 384, "height": 168, "rotatebuffer": 3, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/34.json b/resources/tagtypes/34.json index f5698d61..dc9d42be 100644 --- a/resources/tagtypes/34.json +++ b/resources/tagtypes/34.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 4.2\"", "width": 400, "height": 300, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/35.json b/resources/tagtypes/35.json index bd8f1df4..1ac5551d 100644 --- a/resources/tagtypes/35.json +++ b/resources/tagtypes/35.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 6.0\"", "width": 600, "height": 448, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/36.json b/resources/tagtypes/36.json index 6faf463e..376eff7d 100644 --- a/resources/tagtypes/36.json +++ b/resources/tagtypes/36.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 7.5\"", "width": 800, "height": 480, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/41.json b/resources/tagtypes/41.json index 2ebdf4be..39ec4917 100644 --- a/resources/tagtypes/41.json +++ b/resources/tagtypes/41.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "M3 5.85\"", "width": 792, "height": 272, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/42.json b/resources/tagtypes/42.json index 1ecbb38f..e8909052 100644 --- a/resources/tagtypes/42.json +++ b/resources/tagtypes/42.json @@ -1,15 +1,13 @@ { - "version": 0, - "name": "M3 5.85\" FREEZER", + "version": 1, + "name": "M3 5.85\" BW", "width": 792, "height": 272, "rotatebuffer": 0, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], - "black": [ 0, 0, 0 ], - "gray": [ 150, 150, 150 ] + "black": [ 0, 0, 0 ] }, "shortlut": 0, "zlib_compression": "27", diff --git a/resources/tagtypes/43.json b/resources/tagtypes/43.json new file mode 100644 index 00000000..9068c611 --- /dev/null +++ b/resources/tagtypes/43.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "name": "M3 1.3\" Peghook", + "width": 200, + "height": 144, + "rotatebuffer": 3, + "bpp": 2, + "colors": 3, + "colortable": { + "white": [ 255, 255, 255 ], + "black": [ 0, 0, 0 ], + "red": [ 255, 0, 0 ] + }, + "shortlut": 0, + "zlib_compression": "27", + "options": [ "button" ], + "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27 ], + "usetemplate": 0 +} \ No newline at end of file diff --git a/resources/tagtypes/55.json b/resources/tagtypes/55.json index 8c555b6b..0abbf2be 100644 --- a/resources/tagtypes/55.json +++ b/resources/tagtypes/55.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "HS BWR 2.13\"", "width": 256, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ "led" ], diff --git a/resources/tagtypes/60.json b/resources/tagtypes/60.json index 24e7bfd1..46f5bdab 100644 --- a/resources/tagtypes/60.json +++ b/resources/tagtypes/60.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "HS BWY 3.5\"", "width": 384, "height": 184, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "yellow": [ 200, 200, 0 ], - "gray": [ 150, 150, 150 ] + "yellow": [ 255, 255, 0 ] }, "highlight_color": 2, "shortlut": 0, diff --git a/resources/tagtypes/61.json b/resources/tagtypes/61.json index 7134c4ef..de4dca92 100644 --- a/resources/tagtypes/61.json +++ b/resources/tagtypes/61.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "HS BWR 3.5\"", "width": 384, "height": 184, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ "led" ], diff --git a/resources/tagtypes/62.json b/resources/tagtypes/62.json index 81e1fb9c..db5ea8ca 100644 --- a/resources/tagtypes/62.json +++ b/resources/tagtypes/62.json @@ -1,15 +1,13 @@ { - "version": 0, + "version": 1, "name": "HS BW 3.5\"", "width": 384, "height": 184, "rotatebuffer": 1, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], - "black": [ 0, 0, 0 ], - "gray": [ 150, 150, 150 ] + "black": [ 0, 0, 0 ] }, "highlight_color": 5, "shortlut": 0, diff --git a/resources/tagtypes/80.json b/resources/tagtypes/80.json index 026bafa4..44280c5a 100644 --- a/resources/tagtypes/80.json +++ b/resources/tagtypes/80.json @@ -1,58 +1,17 @@ { - "version": 0, + "version": 1, "name": "Chroma 7.4\"", "width": 640, "height": 384, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 1, "options": [ ], "contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ], - "template": { - "1": { - "weekday": [ 320, -5, "Signika-SB.ttf", 100 ], - "month": [ 320, 265, "Signika-SB.ttf", 100 ], - "day": [ 320, 60, "Signika-SB.ttf", 220 ] - }, - "4": { - "location": [ 20, 20, "fonts/calibrib30" ], - "wind": [ 90, 83, "fonts/calibrib30" ], - "temp": [ 20, 170, "fonts/calibrib30" ], - "icon": [ 385, 0, 100, 2 ], - "dir": [ 40, 50, 80 ], - "umbrella": [ 325, 155, 78 ] - }, - "8": { - "location": [ 10, 10, "fonts/calibrib30" ], - "column": [ 6, 66 ], - "day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ], - "rain": [ 34, 260 ], - "icon": [ 32, 145, 30 ], - "wind": [ 17, 90 ], - "line": [ 50, 300 ] - }, - "9": { - "title": [ 6, 0, "Signika-SB.ttf", 32 ], - "items": 5, - "line": [ 9, 40, "calibrib16.vlw" ], - "desc": [ 2, 8, "REFSAN12.vlw", 1.2 ] - }, - "10": { - "title": [ 320, 10, "fonts/bahnschrift20" ], - "pos": [ 320, 40 ] - }, - "11": { - "rotate": 0, - "mode": 1, - "days": 7, - "gridparam": [ 3, 17, 30, "calibrib16.vlw", "BellCent10.vlw", 14 ] - } - } + "usetemplate": 5 } diff --git a/resources/tagtypes/81.json b/resources/tagtypes/81.json index 1e84a867..3f52f89b 100644 --- a/resources/tagtypes/81.json +++ b/resources/tagtypes/81.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "Chroma29 2.9\" (UC8154)", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [255, 255, 255], "black": [0, 0, 0], - "red": [255, 0, 0], - "gray": [150, 150, 150] + "red": [255, 0, 0] }, "shortlut": 0, "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27], diff --git a/resources/tagtypes/82.json b/resources/tagtypes/82.json index 0f1d2e67..9ffc7ead 100644 --- a/resources/tagtypes/82.json +++ b/resources/tagtypes/82.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "Chroma29 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [255, 255, 255], "black": [0, 0, 0], - "red": [255, 0, 0], - "gray": [150, 150, 150] + "red": [255, 0, 0] }, "shortlut": 0, "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 27], diff --git a/resources/tagtypes/83.json b/resources/tagtypes/83.json index c4a3bef6..b0b3bfd0 100644 --- a/resources/tagtypes/83.json +++ b/resources/tagtypes/83.json @@ -1,57 +1,16 @@ { - "version": 0, + "version": 1, "name": "Chroma42 4.2\"", "width": 400, "height": 300, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [255, 255, 255], "black": [0, 0, 0], - "red": [255, 0, 0], - "gray": [150, 150, 150] + "red": [255, 0, 0] }, "shortlut": 0, - "contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20], - "template": { - "1": { - "weekday": [ 200, 0, "Signika-SB.ttf", 70 ], - "month": [ 200, 210, "Signika-SB.ttf", 70 ], - "day": [ 200, 45, "Signika-SB.ttf", 170 ] - }, - "4": { - "location": [ 20, 20, "fonts/calibrib30" ], - "wind": [ 90, 83, "fonts/calibrib50" ], - "temp": [ 20, 170, "fonts/calibrib100" ], - "icon": [ 385, 0, 100, 2 ], - "dir": [ 40, 50, 80 ], - "umbrella": [ 325, 155, 78 ] - }, - "8": { - "location": [ 10, 10, "fonts/calibrib30" ], - "column": [ 6, 66 ], - "day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ], - "rain": [ 34, 260 ], - "icon": [ 32, 145, 30 ], - "wind": [ 17, 90 ], - "line": [ 50, 300 ] - }, - "9": { - "title": [ 6, 0, "Signika-SB.ttf", 25 ], - "items": 4, - "line": [ 9, 40, "calibrib16.vlw" ], - "desc": [ 2, 8, "REFSAN12.vlw", 1.2 ] - }, - "10": { - "title": [ 200, 10, "fonts/bahnschrift20" ], - "pos": [ 200, 35 ] - }, - "11": { - "rotate": 0, - "mode": 1, - "days": 4, - "gridparam": [ 5, 17, 20, "calibrib16.vlw", "BellCent10.vlw", 14 ] - } - } + "contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ], + "usetemplate": 2 } diff --git a/resources/tagtypes/B2.json b/resources/tagtypes/B2.json index cddf1925..e252c02d 100644 --- a/resources/tagtypes/B2.json +++ b/resources/tagtypes/B2.json @@ -1,11 +1,10 @@ { - "version": 0, + "version": 1, "name": "Gicisky BLE EPD BW 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 1, - "colors": 2, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ] diff --git a/resources/tagtypes/B3.json b/resources/tagtypes/B3.json index 55663a28..e574269e 100644 --- a/resources/tagtypes/B3.json +++ b/resources/tagtypes/B3.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "Gicisky BLE EPD BWR 2.9\"", "width": 296, "height": 128, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 27 ], "usetemplate": 1 diff --git a/resources/tagtypes/B5.json b/resources/tagtypes/B5.json index c52c333b..1e669596 100644 --- a/resources/tagtypes/B5.json +++ b/resources/tagtypes/B5.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "Gicisky BLE EPD BWR 4.2\"", "width": 400, "height": 300, "rotatebuffer": 0, "bpp": 2, - "colors": 3, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20 ], "usetemplate": 2 diff --git a/resources/tagtypes/BD.json b/resources/tagtypes/BD.json index e80eb9b1..8b476055 100644 --- a/resources/tagtypes/BD.json +++ b/resources/tagtypes/BD.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "BLE EPD BWR 2.9\" Silabs", "width": 384, "height": 168, "rotatebuffer": 1, "bpp": 2, - "colors": 3, "colortable": { "white": [255, 255, 255], "black": [0, 0, 0], - "red": [255, 0, 0], - "gray": [150, 150, 150] + "red": [255, 0, 0] }, "contentids": [ 22, 23, 1, 4, 5, 7, 8, 9, 10, 11, 17, 18, 19, 20], "usetemplate": 1, diff --git a/resources/tagtypes/BE.json b/resources/tagtypes/BE.json index fdb60886..76052014 100644 --- a/resources/tagtypes/BE.json +++ b/resources/tagtypes/BE.json @@ -1,15 +1,11 @@ { - "version": 0, + "version": 1, "name": "ATC MiThermometer BLE", "width": 6, "height": 8, "rotatebuffer": 1, "bpp": 1, - "colors": 1, - "colortable": { - "white": [ 255, 255, 255 ], - "black": [ 0, 0, 0 ] - }, + "colortable": {}, "shortlut": 0, "options": [ ], "contentids": [ 22 ], diff --git a/resources/tagtypes/E0.json b/resources/tagtypes/E0.json index c07412e2..c8ce1f42 100644 --- a/resources/tagtypes/E0.json +++ b/resources/tagtypes/E0.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "TFT 320x172", "width": 320, "height": 172, "rotatebuffer": 0, "bpp": 16, - "colors": 4, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ ], diff --git a/resources/tagtypes/E1.json b/resources/tagtypes/E1.json index ebd2fcaf..2cbdb01a 100644 --- a/resources/tagtypes/E1.json +++ b/resources/tagtypes/E1.json @@ -1,16 +1,14 @@ { - "version": 0, + "version": 1, "name": "TFT 160x80", "width": 160, "height": 80, "rotatebuffer": 1, "bpp": 16, - "colors": 4, "colortable": { "white": [ 255, 255, 255 ], "black": [ 0, 0, 0 ], - "red": [ 255, 0, 0 ], - "gray": [ 150, 150, 150 ] + "red": [ 255, 0, 0 ] }, "shortlut": 0, "options": [ ], diff --git a/resources/tagtypes/F0.json b/resources/tagtypes/F0.json index ab747222..f75f5c0d 100644 --- a/resources/tagtypes/F0.json +++ b/resources/tagtypes/F0.json @@ -1,11 +1,10 @@ { - "version": 0, + "version": 1, "name": "SLT‐EM007 Segmented", "width": 0, "height": 0, "rotatebuffer": 0, "bpp": 1, - "colors": 0, "colortable": { }, "shortlut": 0, "options": [ ],