diff --git a/ESP32_AP-Flasher/data/tagtypes/B2.json b/ESP32_AP-Flasher/data/tagtypes/B2.json new file mode 100644 index 00000000..0f135afa --- /dev/null +++ b/ESP32_AP-Flasher/data/tagtypes/B2.json @@ -0,0 +1,16 @@ +{ + "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] + }, + "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 ], + "usetemplate": 1 +} diff --git a/ESP32_AP-Flasher/data/tagtypes/B3.json b/ESP32_AP-Flasher/data/tagtypes/B3.json new file mode 100644 index 00000000..58eb1cb6 --- /dev/null +++ b/ESP32_AP-Flasher/data/tagtypes/B3.json @@ -0,0 +1,81 @@ +{ + "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] + }, + "contentids": [ 22, 23, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 20, 21, 27 ], + "template": { + "1": { + "weekday": [ 148, -3, "Signika-SB.ttf", 60 ], + "date": [ 148, 65, "Signika-SB.ttf", 48 ] + }, + "2": { + "fonts": [ "Signika-SB.ttf", 150, 150, 150, 120, 100, 80 ], + "xy": [ 148, 53 ] + }, + "16": { + "location": [ 5, 5, "fonts/bahnschrift30" ], + "title": [ 247, 11, "glasstown_nbp_tf" ], + "cols": [ 1, 125, 12, "glasstown_nbp_tf" ], + "bars": [ 5, 111, 10 ] + }, + "4": { + "location": [5, 5, "fonts/bahnschrift30"], + "wind": [280, 5, "fonts/bahnschrift30"], + "temp": [5, 65, "fonts/bahnschrift70"], + "icon": [285, 20, 70, 2], + "dir": [235, -12, 40], + "umbrella": [190, -50, 25] + }, + "8": { + "location": [5, 12, "t0_14b_tf"], + "column": [5, 59], + "day": [30, 18, "fonts/twcondensed20", 41, 108], + "icon": [30, 55, 30], + "wind": [18, 26], + "line": [20, 128] + }, + "9": { + "title": [ 2, 0, "bahnschrift20.vlw", 25 ], + "items": 8, + "line": [ 1, 25, "REFSAN12.vlw" ], + "desc": [ 0, 5, "", 1 ] + }, + "10": { + "title": [149, 5, "fonts/bahnschrift20"], + "pos": [149, 27] + }, + "11": { + "mode": 0, + "days": 1, + "title": [5, 2, "fonts/bahnschrift20"], + "date": [290, 2], + "items": 7, + "red": [0, 21, 296, 14], + "line": [5, 32, 15, "t0_14b_tf", 50] + }, + "21": [ + { "text": [ 5, 5, "OpenEpaperLink AP", "bahnschrift20", 1, 0, 0 ] }, + { "text": [ 5, 50, "IP address:", "t0_14b_tf", 1, 0, 0 ] }, + { "text": [ 120, 50, "{ap_ip}", "t0_14b_tf", 1, 0, 0 ] }, + { "text": [ 5, 70, "Channel:", "t0_14b_tf", 1, 0, 0 ] }, + { "text": [ 120, 70, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] }, + { "text": [ 5, 90, "Tag count:", "t0_14b_tf", 1, 0, 0 ] }, + { "text": [ 120, 90, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] } + ], + "27": { + "bars": [ 9, 288, 90, 10 ], + "time": [ "BellCent10.vlw" ], + "yaxis": [ "BellCent10.vlw", 0, 6 ], + "head": [ "calibrib30.vlw" ] + } + } +} diff --git a/ESP32_AP-Flasher/data/tagtypes/B5.json b/ESP32_AP-Flasher/data/tagtypes/B5.json new file mode 100644 index 00000000..1eb366b3 --- /dev/null +++ b/ESP32_AP-Flasher/data/tagtypes/B5.json @@ -0,0 +1,55 @@ +{ + "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] + }, + "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 ] + } + } +} diff --git a/ESP32_AP-Flasher/include/ble_filter.h b/ESP32_AP-Flasher/include/ble_filter.h new file mode 100644 index 00000000..b2b3f7d0 --- /dev/null +++ b/ESP32_AP-Flasher/include/ble_filter.h @@ -0,0 +1,10 @@ +#pragma once +#ifdef HAS_BLE_WRITER +#include "BLEDevice.h" + +uint8_t gicToOEPLtype(uint8_t gicType); +bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice); +bool BLE_is_image_pending(uint8_t address[8]); +uint32_t compress_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len); + +#endif diff --git a/ESP32_AP-Flasher/include/ble_writer.h b/ESP32_AP-Flasher/include/ble_writer.h new file mode 100644 index 00000000..381975c5 --- /dev/null +++ b/ESP32_AP-Flasher/include/ble_writer.h @@ -0,0 +1,6 @@ +#pragma once +#ifdef HAS_BLE_WRITER + +void BLETask(void* parameter); + +#endif diff --git a/ESP32_AP-Flasher/platformio.ini b/ESP32_AP-Flasher/platformio.ini index da739e78..a06a602f 100644 --- a/ESP32_AP-Flasher/platformio.ini +++ b/ESP32_AP-Flasher/platformio.ini @@ -279,6 +279,7 @@ lib_deps = build_flags = -std=gnu++17 ${env.build_flags} + -D HAS_BLE_WRITER -D CORE_DEBUG_LEVEL=0 -D ARDUINO_USB_CDC_ON_BOOT -D CONFIG_ESP32S3_SPIRAM_SUPPORT=1 diff --git a/ESP32_AP-Flasher/src/ble_filter.cpp b/ESP32_AP-Flasher/src/ble_filter.cpp new file mode 100644 index 00000000..cae00cef --- /dev/null +++ b/ESP32_AP-Flasher/src/ble_filter.cpp @@ -0,0 +1,209 @@ +#ifdef HAS_BLE_WRITER +#include +#include + +#include "BLEDevice.h" +#include "newproto.h" +#include "serialap.h" +#include "settings.h" +#include "storage.h" +#include "system.h" +#include "tag_db.h" +#include "tagdata.h" +#include "udp.h" +#include "util.h" +#include "web.h" + +uint8_t gicToOEPLtype(uint8_t gicType) { + switch (gicType) { + case 0x08: + return GICI_BLE_EPD_21_BW; + break; + case 0x0B: + return GICI_BLE_EPD_21_BWR; + break; + case 0x28: + case 0x30: + return GICI_BLE_EPD_29_BW; + break; + case 0x2B: + return GICI_BLE_EPD_29_BWR; + break; + case 0x33: + return GICI_BLE_EPD_29_BWR1; + break; + case 0x48: + return GICI_BLE_EPD_BW_42; + break; + case 0x4B: + return GICI_BLE_EPD_BWR_42; + break; + case 0x40: + return GICI_BLE_TFT_BW_42; + break; + case 0x42: + return GICI_BLE_TFT_BWR_42; + break; + case 0x68: + return GICI_BLE_EPD_BW_74; + break; + case 0x6A: + return GICI_BLE_EPD_BWR_74; + break; + default: + return GICI_BLE_UNKNOWN; // Should never happen, return 1.54" + break; + } +} + +bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) { + if (advertisedDevice.haveManufacturerData()) { + int manuDatalen = advertisedDevice.getManufacturerData().length(); + uint8_t manuData[100]; + if (manuDatalen > sizeof(manuData)) + return false; // Manu data too big, could never happen but better make sure here + memcpy(&manuData, (uint8_t*)advertisedDevice.getManufacturerData().data(), manuDatalen); + if (manuDatalen == 7 && manuData[0] == 0x53 && manuData[1] == 0x50) { + Serial.print("BLE Advertised Device found: "); + Serial.println(advertisedDevice.toString().c_str()); + Serial.printf(" Address type: %02X Manu data: ", advertisedDevice.getAddressType()); + for (int i = 0; i < advertisedDevice.getManufacturerData().length(); i++) + Serial.printf("%02X", manuData[i]); + Serial.printf("\r\n"); + + struct espAvailDataReq theAdvData; + memset((uint8_t*)&theAdvData, 0x00, sizeof(espAvailDataReq)); + + uint8_t macReversed[6]; + memcpy(&macReversed, (uint8_t*)advertisedDevice.getAddress().getNative(), 6); + theAdvData.src[0] = macReversed[5]; + theAdvData.src[1] = macReversed[4]; + theAdvData.src[2] = macReversed[3]; + theAdvData.src[3] = macReversed[2]; + theAdvData.src[4] = macReversed[1]; + theAdvData.src[5] = macReversed[0]; + theAdvData.src[6] = manuData[2]; // We use this do find out what type of display we got for compression^^ + theAdvData.src[7] = 0x00; + theAdvData.adr.batteryMv = manuData[3] * 100; + theAdvData.adr.lastPacketRSSI = advertisedDevice.getRSSI(); + theAdvData.adr.hwType = gicToOEPLtype(manuData[2]); + theAdvData.adr.tagSoftwareVersion = manuData[4] << 8 | manuData[5]; + theAdvData.adr.capabilities = 0x00; + + processDataReq(&theAdvData, true); + return true; + } + } + + return false; +} + +bool BLE_is_image_pending(uint8_t address[8]) { + for (int16_t c = 0; c < tagDB.size(); c++) { + tagRecord* taginfo = tagDB.at(c); + if (taginfo->pendingCount > 0 && taginfo->version == 0 && (taginfo->hwType & 0xB0)) { + memcpy(address, taginfo->mac, 8); + return true; + } + } + return false; +} + +uint32_t compress_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len) { + uint32_t t = millis(); + PendingItem* queueItem = getQueueItem(address, 0); + if (queueItem == nullptr) { + prepareCancelPending(address); + Serial.printf("blockrequest: couldn't find taginfo %02X%02X%02X%02X%02X%02X%02X%02X\n", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]); + return 0; + } + if (queueItem->data == nullptr) { + fs::File file = contentFS->open(queueItem->filename); + if (!file) { + Serial.print("No current file. " + String(queueItem->filename) + " Canceling request\n"); + prepareCancelPending(address); + return 0; + } + queueItem->data = getDataForFile(file); + Serial.println("Reading file " + String(queueItem->filename) + " in " + String(millis() - t) + "ms"); + file.close(); + } + + uint8_t giciType = address[6]; // here we "extract" the display info again + + bool extra_color = false; + uint16_t width_display = 104; + uint16_t height_display = 212; + switch ((giciType >> 5) & 7) // Resolution + { + default: + case 0: + width_display = 104; + height_display = 212; + break; + case 1: + width_display = 296; + height_display = 128; + break; + case 2: + width_display = 300; + height_display = 400; + break; + case 3: + width_display = 384; + height_display = 640; + break; + } + switch ((giciType >> 1) & 3) // Extra color + { + default: + case 0: + extra_color = false; + break; + case 1: + case 2: + extra_color = true; + break; + } + + // Yeah, this is no real compression, but maybe it will be solved in the future to the "real" RLE Compression + uint32_t len_compressed = 4; + uint32_t curr_input_posi = 0; + uint32_t byte_per_line = (height_display / 8); + for (int i = 0; i < width_display; i++) { + buffer[len_compressed++] = 0x75; + buffer[len_compressed++] = byte_per_line + 7; + buffer[len_compressed++] = byte_per_line; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + for (int b = 0; b < byte_per_line; b++) { + buffer[len_compressed++] = ~queueItem->data[curr_input_posi++]; + } + } + if (extra_color) { + for (int i = 0; i < width_display; i++) { + buffer[len_compressed++] = 0x75; + buffer[len_compressed++] = byte_per_line + 7; + buffer[len_compressed++] = byte_per_line; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + buffer[len_compressed++] = 0x00; + for (int b = 0; b < byte_per_line; b++) { + if (queueItem->len <= curr_input_posi) + buffer[len_compressed++] = 0x00; + else + buffer[len_compressed++] = queueItem->data[curr_input_posi++]; + } + } + } + buffer[0] = len_compressed & 0xff; + buffer[1] = (len_compressed >> 8) & 0xff; + buffer[2] = (len_compressed >> 16) & 0xff; + buffer[3] = (len_compressed >> 24) & 0xff; + return len_compressed; +} + +#endif diff --git a/ESP32_AP-Flasher/src/ble_writer.cpp b/ESP32_AP-Flasher/src/ble_writer.cpp new file mode 100644 index 00000000..ac2bf133 --- /dev/null +++ b/ESP32_AP-Flasher/src/ble_writer.cpp @@ -0,0 +1,262 @@ +#ifdef HAS_BLE_WRITER +#include + +#include "BLEDevice.h" +#include "ble_filter.h" +#include "newproto.h" + +#define INTERVAL_BLE_SCANNING_SECONDS 60 +#define INTERVAL_HANDLE_PENDING_SECONDS 10 + +#define BUFFER_MAX_SIZE_COMPRESSING 100000 + +#define BLE_MAIN_STATE_IDLE 0 +#define BLE_MAIN_STATE_PREPARE 1 +#define BLE_MAIN_STATE_CONNECT 2 +#define BLE_MAIN_STATE_UPLOAD 3 + +int ble_main_state = BLE_MAIN_STATE_IDLE; +uint32_t last_ble_scan = 0; + +#define BLE_UPLOAD_STATE_INIT 0 +#define BLE_UPLOAD_STATE_SIZE 1 +#define BLE_UPLOAD_STATE_START 2 +#define BLE_UPLOAD_STATE_UPLOAD 5 +int BLE_upload_state = BLE_UPLOAD_STATE_INIT; + +bool BLE_connected = false; +bool BLE_new_notify = false; + +static BLEUUID gicServiceUUID((uint16_t)0xfef0); +static BLEUUID gicCtrlUUID((uint16_t)0xfef1); +static BLEUUID gicImgUUID((uint16_t)0xfef2); + +BLERemoteCharacteristic* ctrlChar; +BLERemoteCharacteristic* imgChar; +BLEAdvertisedDevice* myDevice; + +BLEClient* pClient; + +uint8_t BLE_notify_buffer[255] = {0}; + +uint32_t curr_part = 0; +uint8_t BLE_buff[255]; + +uint32_t BLE_last_notify = 0; +uint32_t BLE_last_pending_check = 0; +uint8_t BLE_curr_address[8] = {0}; + +uint32_t compressed_len = 0; +uint8_t* buffer; + +static void notifyCallback( + BLERemoteCharacteristic* pBLERemoteCharacteristic, + uint8_t* pData, + size_t length, + bool isNotify) { + Serial.print("Notify callback for characteristic "); + Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str()); + Serial.print(" of data length "); + Serial.println(length); + Serial.print("data: "); + for (int i = 0; i < length; i++) { + Serial.printf("%02X", pData[i]); + BLE_notify_buffer[1 + i] = pData[i]; + } + BLE_notify_buffer[0] = length; + Serial.println(); + BLE_new_notify = true; +} + +class MyClientCallback : public BLEClientCallbacks { + void onConnect(BLEClient* pclient) { + Serial.println("BLE onConnect"); + BLE_connected = true; + } + + void onDisconnect(BLEClient* pclient) { + Serial.println("BLE onDisconnect"); + pclient->disconnect(); + BLE_connected = false; + ble_main_state = BLE_MAIN_STATE_IDLE; + } +}; + +bool BLE_connect(uint8_t addr[8]) { + uint8_t temp_Address[] = {addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]}; + Serial.printf("BLE Connecting to: %02X:%02X:%02X:%02X:%02X:%02X\r\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + pClient = BLEDevice::createClient(); + pClient->setClientCallbacks(new MyClientCallback()); + if (!pClient->connect(BLEAddress(temp_Address))) { + Serial.printf("BLE connection failed\r\n"); + pClient->disconnect(); + return false; + } + vTaskDelay(100 / portTICK_PERIOD_MS); + if (!BLE_connected) + return false; + Serial.printf("BLE starting to get service\r\n"); + BLERemoteService* pRemoteService = pClient->getService(gicServiceUUID); + if (pRemoteService == nullptr) { + Serial.printf("BLE Service failed\r\n"); + pClient->disconnect(); + return false; + } + imgChar = pRemoteService->getCharacteristic(gicImgUUID); + if (imgChar == nullptr) { + Serial.printf("BLE IMG Char failed\r\n"); + pClient->disconnect(); + return false; + } + ctrlChar = pRemoteService->getCharacteristic(gicCtrlUUID); + if (ctrlChar == nullptr) { + Serial.printf("BLE ctrl Char failed\r\n"); + pClient->disconnect(); + return false; + } + if (ctrlChar->canNotify()) { + ctrlChar->registerForNotify(notifyCallback); + } else { + Serial.printf("BLE Notify failed\r\n"); + pClient->disconnect(); + return false; + } + if (pClient->setMTU(255) == false) { + Serial.printf("BLE MTU failed\r\n"); + pClient->disconnect(); + return false; + } + Serial.printf("BLE Connected fully to: %02X:%02X:%02X:%02X:%02X:%02X\r\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + return true; +} + +class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { + void onResult(BLEAdvertisedDevice advertisedDevice) { + BLE_filter_add_device(advertisedDevice); + } +}; + +void BLE_startScan(uint32_t timeout) { + BLEScan* pBLEScan = BLEDevice::getScan(); + pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); + pBLEScan->setInterval(1349); + pBLEScan->setWindow(449); + pBLEScan->setActiveScan(true); + pBLEScan->start(timeout, false); +} + +void BLETask(void* parameter) { + vTaskDelay(5000 / portTICK_PERIOD_MS); + BLEDevice::init(""); + while (1) { + switch (ble_main_state) { + default: + case BLE_MAIN_STATE_IDLE: + if (millis() - last_ble_scan > (INTERVAL_BLE_SCANNING_SECONDS * 1000)) { + last_ble_scan = millis(); + Serial.println("Doing the BLE Scan"); + BLE_startScan(5); // timeout in seconds, this is blocking but only for this thread! + } + if (millis() - BLE_last_pending_check >= (INTERVAL_HANDLE_PENDING_SECONDS * 1000)) { + if (BLE_is_image_pending(BLE_curr_address)) { + delay(4000); // We better wait here, since the pending image needs to be created first + Serial.println("BLE Image is pending"); + // Here we create the compressed buffer + buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING); + if (buffer == nullptr) { + Serial.println("BLE Could not create buffer!"); + compressed_len = 0; + } else { + compressed_len = compress_image(BLE_curr_address, buffer, BUFFER_MAX_SIZE_COMPRESSING); + Serial.printf("BLE Compressed Length: %i\r\n", compressed_len); + // then we connect to BLE to send the compressed data + if (compressed_len && BLE_connect(BLE_curr_address)) { + curr_part = 0; + memset(BLE_notify_buffer, 0x00, sizeof(BLE_notify_buffer)); + BLE_upload_state = BLE_UPLOAD_STATE_INIT; + ble_main_state = BLE_MAIN_STATE_UPLOAD; + BLE_new_notify = true; // trigger the upload here + } else { + free(buffer); + } + } + BLE_last_pending_check = millis(); + } + } + break; + case BLE_MAIN_STATE_UPLOAD: { + if (BLE_connected && BLE_new_notify) { + BLE_new_notify = false; + BLE_last_notify = millis(); + BLE_upload_state = BLE_notify_buffer[1]; + + switch (BLE_upload_state) { + default: + case BLE_UPLOAD_STATE_INIT: + BLE_buff[0] = 1; + ctrlChar->writeValue(BLE_buff, 1); + break; + case BLE_UPLOAD_STATE_SIZE: + BLE_buff[0] = 0x02; + BLE_buff[1] = compressed_len & 0xff; + BLE_buff[2] = (compressed_len >> 8) & 0xff; + BLE_buff[3] = (compressed_len >> 16) & 0xff; + BLE_buff[4] = (compressed_len >> 24) & 0xff; + BLE_buff[5] = 0x00; + ctrlChar->writeValue(BLE_buff, 6); + break; + case BLE_UPLOAD_STATE_START: + BLE_buff[0] = 0x03; + ctrlChar->writeValue(BLE_buff, 1); + break; + case BLE_UPLOAD_STATE_UPLOAD: + if (BLE_notify_buffer[2] == 0x08) { + free(buffer); + pClient->disconnect(); + ble_main_state = BLE_MAIN_STATE_IDLE; + BLE_last_pending_check = millis(); + // Done and the image is refreshing now + struct espXferComplete reportStruct; + memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8); + processXferComplete(&reportStruct, true); + curr_part = 0; + } else { + uint32_t req_curr_part = (BLE_notify_buffer[6] << 24) | (BLE_notify_buffer[5] << 24) | (BLE_notify_buffer[4] << 24) | BLE_notify_buffer[3]; + if (req_curr_part != curr_part) { + Serial.printf("Something went wrong, expected req part: %i but got: %i we better abort here.\r\n", req_curr_part, curr_part); + free(buffer); + pClient->disconnect(); + ble_main_state = BLE_MAIN_STATE_IDLE; + BLE_last_pending_check = millis(); + } + uint32_t curr_len = 240; + if (compressed_len - (curr_part * 240) < 240) + curr_len = compressed_len - (curr_part * 240); + BLE_buff[0] = curr_part & 0xff; + BLE_buff[1] = (curr_part >> 8) & 0xff; + BLE_buff[2] = (curr_part >> 16) & 0xff; + BLE_buff[3] = (curr_part >> 24) & 0xff; + memcpy((uint8_t*)&BLE_buff[4], (uint8_t*)&buffer[curr_part * 240], curr_len); + imgChar->writeValue(BLE_buff, curr_len + 4); + Serial.printf("BLE sending part: %i\r\n", curr_part); + curr_part++; + } + break; + } + } else { + if (millis() - BLE_last_notify > 30000) { // Something odd, better reset connection! + Serial.println("BLE err going back to IDLE"); + free(buffer); + pClient->disconnect(); + ble_main_state = BLE_MAIN_STATE_IDLE; + BLE_last_pending_check = millis(); + } + } + break; + } + } + vTaskDelay(15 / portTICK_PERIOD_MS); + } +} + +#endif diff --git a/ESP32_AP-Flasher/src/main.cpp b/ESP32_AP-Flasher/src/main.cpp index fa360274..1cb6d807 100644 --- a/ESP32_AP-Flasher/src/main.cpp +++ b/ESP32_AP-Flasher/src/main.cpp @@ -26,6 +26,7 @@ #include "udp.h" #include "util.h" #include "web.h" +#include "ble_writer.h" util::Timer intervalContentRunner(seconds(1)); util::Timer intervalSysinfo(seconds(5)); @@ -134,6 +135,10 @@ void setup() { xTaskCreate(APTask, "AP Process", 6000, NULL, 5, NULL); vTaskDelay(10 / portTICK_PERIOD_MS); +#ifdef HAS_BLE_WRITER + xTaskCreate(BLETask, "BLE Writer", 12000, NULL, 5, NULL); +#endif + #ifdef HAS_USB // We'll need to start the 'usbflasher' task for boards with a second (USB) port. This can be used as a 'flasher' interface, using a python script on the host xTaskCreate(usbFlasherTask, "usbflasher", 10000, NULL, 5, NULL); diff --git a/oepl-definitions.h b/oepl-definitions.h index 666012de..a8153721 100755 --- a/oepl-definitions.h +++ b/oepl-definitions.h @@ -55,6 +55,20 @@ #define HS_NEBULAR_BWR_35 0x61 #define HS_NEBULAR_BW_35 0x62 +// Gicisky / PICKSMART BLE Types +#define GICI_BLE_EPD_21_BW 0xB0 +#define GICI_BLE_EPD_21_BWR 0xB1 +#define GICI_BLE_EPD_29_BW 0xB2 +#define GICI_BLE_EPD_29_BWR 0xB3 +#define GICI_BLE_EPD_29_BWR1 0xB3 +#define GICI_BLE_EPD_BW_42 0xB4 +#define GICI_BLE_EPD_BWR_42 0xB5 +#define GICI_BLE_TFT_BW_42 0xB6 +#define GICI_BLE_TFT_BWR_42 0xB7 +#define GICI_BLE_EPD_BW_74 0xB8 +#define GICI_BLE_EPD_BWR_74 0xB9 +#define GICI_BLE_UNKNOWN 0xBF + // Solum types - customer data byte 16 in M3 (nRF) UICR #define STYPE_SIZE_016 0x40 #define STYPE_SIZE_022 0x41