From f4025fb18f5a91b42ae313e98d5129cf7864bf70 Mon Sep 17 00:00:00 2001 From: atc1441 Date: Thu, 5 Dec 2024 09:45:58 +0100 Subject: [PATCH] Added ATC BLE OEPL Sending --- ESP32_AP-Flasher/include/ble_filter.h | 1 + ESP32_AP-Flasher/src/ble_filter.cpp | 88 +++++++- ESP32_AP-Flasher/src/ble_writer.cpp | 314 +++++++++++++++++++++----- oepl-definitions.h | 1 + tag_types.h | 1 + 5 files changed, 343 insertions(+), 62 deletions(-) diff --git a/ESP32_AP-Flasher/include/ble_filter.h b/ESP32_AP-Flasher/include/ble_filter.h index b2b3f7d0..7fa4e693 100644 --- a/ESP32_AP-Flasher/include/ble_filter.h +++ b/ESP32_AP-Flasher/include/ble_filter.h @@ -6,5 +6,6 @@ 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); +uint32_t get_ATC_BLE_OEPL_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len, uint8_t* dataType, uint8_t* dataTypeArgument, uint16_t* nextCheckIn); #endif diff --git a/ESP32_AP-Flasher/src/ble_filter.cpp b/ESP32_AP-Flasher/src/ble_filter.cpp index 61815146..5a074738 100644 --- a/ESP32_AP-Flasher/src/ble_filter.cpp +++ b/ESP32_AP-Flasher/src/ble_filter.cpp @@ -64,6 +64,16 @@ uint8_t gicToOEPLtype(uint8_t gicType) { } } +struct BleAdvDataStruct { + uint16_t manu_id; // 0x1337 for us + uint8_t version; + uint16_t hw_type; + uint16_t fw_version; + uint16_t capabilities; + uint16_t battery_mv; + uint8_t counter; +} __packed; + bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); @@ -103,10 +113,46 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) { theAdvData.src[7] = manuData[6]; theAdvData.adr.batteryMv = manuData[3] * 100; theAdvData.adr.lastPacketRSSI = advertisedDevice.getRSSI(); + theAdvData.adr.lastPacketLQI = 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; + } else if (manuDatalen >= sizeof(BleAdvDataStruct) && manuData[0] == 0x37 && manuData[1] == 0x13) { // Lets check for a Gicisky E-Paper display + Serial.printf("ATC BLE OEPL Detected\r\n"); + struct espAvailDataReq theAdvData; + struct BleAdvDataStruct inAdvData; + + memset((uint8_t*)&theAdvData, 0x00, sizeof(espAvailDataReq)); + memcpy(&inAdvData, manuData, sizeof(BleAdvDataStruct)); + /*Serial.printf("manu_id %04X\r\n", inAdvData.manu_id); + Serial.printf("version %04X\r\n", inAdvData.version); + Serial.printf("hw_type %04X\r\n", inAdvData.hw_type); + Serial.printf("fw_version %04X\r\n", inAdvData.fw_version); + Serial.printf("capabilities %04X\r\n", inAdvData.capabilities); + Serial.printf("battery_mv %u\r\n", inAdvData.battery_mv); + Serial.printf("counter %u\r\n", inAdvData.counter);*/ + if (inAdvData.version != 1) { + printf("Version currently not supported!\r\n"); + return false; + } + 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[0]; // We use this do find out what type of display we got for compression^^ + theAdvData.src[7] = manuData[1]; + theAdvData.adr.batteryMv = inAdvData.battery_mv; + theAdvData.adr.lastPacketRSSI = advertisedDevice.getRSSI(); + theAdvData.adr.hwType = inAdvData.hw_type & 0xff; + theAdvData.adr.tagSoftwareVersion = inAdvData.fw_version; + theAdvData.adr.capabilities = inAdvData.capabilities & 0xff; processDataReq(&theAdvData, true); return true; } @@ -133,7 +179,6 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) { theAdvData.adr.hwType = ATC_MI_THERMOMETER; theAdvData.adr.tagSoftwareVersion = 0x00; theAdvData.adr.capabilities = 0x00; - processDataReq(&theAdvData, true); Serial.printf("We got an ATC_MiThermometer via BLE\r\n"); return true; @@ -150,6 +195,14 @@ bool BLE_is_image_pending(uint8_t address[8]) { return true; } } + for (int16_t c = 0; c < tagDB.size(); c++) { + tagRecord* taginfo = tagDB.at(c); + if (taginfo->pendingCount > 0 && taginfo->version == 0 && (taginfo->mac[7] == 0x13) && (taginfo->mac[6] == 0x37)) { + memcpy(address, taginfo->mac, 8); + Serial.printf("ATC BLE OEPL data Waiting\r\n"); + return true; + } + } return false; } @@ -374,4 +427,37 @@ uint32_t compress_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len) { return len_compressed; } +uint32_t get_ATC_BLE_OEPL_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len, uint8_t* dataType, uint8_t* dataTypeArgument, uint16_t* nextCheckIn) { + 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\r\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\r\n"); + prepareCancelPending(address); + return 0; + } + queueItem->data = getDataForFile(file); + Serial.println("Reading file " + String(queueItem->filename) + " in " + String(millis() - t) + "ms"); + file.close(); + } + if (queueItem->len > max_len) { + Serial.print("The upload is too big better cencel it\r\n"); + prepareCancelPending(address); + return 0; + } + *dataType = queueItem->pendingdata.availdatainfo.dataType; + *dataTypeArgument = queueItem->pendingdata.availdatainfo.dataTypeArgument; + *nextCheckIn = queueItem->pendingdata.availdatainfo.nextCheckIn; + uint32_t len_compressed = queueItem->len; + memcpy(buffer, queueItem->data, queueItem->len); + Serial.print("Data is prepared Len: " + String(queueItem->len) + "\r\n"); + return queueItem->len; +} + #endif diff --git a/ESP32_AP-Flasher/src/ble_writer.cpp b/ESP32_AP-Flasher/src/ble_writer.cpp index 19f796c6..cb88fbb9 100644 --- a/ESP32_AP-Flasher/src/ble_writer.cpp +++ b/ESP32_AP-Flasher/src/ble_writer.cpp @@ -1,5 +1,6 @@ #ifdef HAS_BLE_WRITER #include +#include #include "BLEDevice.h" #include "ble_filter.h" @@ -7,12 +8,13 @@ #define INTERVAL_BLE_SCANNING_SECONDS 60 #define INTERVAL_HANDLE_PENDING_SECONDS 10 -#define BUFFER_MAX_SIZE_COMPRESSING 100000 +#define BUFFER_MAX_SIZE_COMPRESSING 135000 #define BLE_MAIN_STATE_IDLE 0 #define BLE_MAIN_STATE_PREPARE 1 #define BLE_MAIN_STATE_CONNECT 2 #define BLE_MAIN_STATE_UPLOAD 3 +#define BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD 4 int ble_main_state = BLE_MAIN_STATE_IDLE; uint32_t last_ble_scan = 0; @@ -23,9 +25,25 @@ uint32_t last_ble_scan = 0; #define BLE_UPLOAD_STATE_UPLOAD 5 int BLE_upload_state = BLE_UPLOAD_STATE_INIT; +#define BLE_CMD_ACK_CMD 99 +#define BLE_CMD_AVAILDATA 100 +#define BLE_CMD_BLK_DATA 101 +#define BLE_CMD_ERR_BLKPRT 196 +#define BLE_CMD_ACK_BLKPRT 197 +#define BLE_CMD_REQ 198 +#define BLE_CMD_ACK 199 +#define BLE_CMD_ACK_IS_SHOWN 200 +#define BLE_CMD_ACK_FW_UPDATED 201 + +struct AvailDataInfo BLEavaildatainfo = {0}; +struct blockRequest BLEblkRequst = {0}; + bool BLE_connected = false; bool BLE_new_notify = false; +static BLEUUID ATC_BLE_OEPL_ServiceUUID((uint16_t)0x1337); +static BLEUUID ATC_BLE_OEPL_CtrlUUID((uint16_t)0x1337); + static BLEUUID gicServiceUUID((uint16_t)0xfef0); static BLEUUID gicCtrlUUID((uint16_t)0xfef1); static BLEUUID gicImgUUID((uint16_t)0xfef2); @@ -33,20 +51,21 @@ static BLEUUID gicImgUUID((uint16_t)0xfef2); BLERemoteCharacteristic* ctrlChar; BLERemoteCharacteristic* imgChar; BLEAdvertisedDevice* myDevice; - BLEClient* pClient; -uint8_t BLE_notify_buffer[255] = {0}; +uint8_t BLE_notify_buffer[256] = {0}; -uint32_t curr_part = 0; -uint8_t BLE_buff[255]; +uint32_t BLE_err_counter = 0; +uint32_t BLE_curr_part = 0; +uint32_t BLE_max_block_parts = 0; +uint8_t BLE_mini_buff[256]; 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; +uint32_t BLE_compressed_len = 0; +uint8_t* BLE_image_buffer; static void notifyCallback( BLERemoteCharacteristic* pBLERemoteCharacteristic, @@ -81,7 +100,13 @@ class MyClientCallback : public BLEClientCallbacks { } }; -bool BLE_connect(uint8_t addr[8]) { +enum BLE_CONNECTION_TYPE { + BLE_TYPE_GICISKY = 0, + BLE_TYPE_ATC_BLE_OEPL +}; + +bool BLE_connect(uint8_t addr[8], BLE_CONNECTION_TYPE conn_type) { + BLE_err_counter = 0; 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(); @@ -92,25 +117,27 @@ bool BLE_connect(uint8_t addr[8]) { return false; } uint32_t timeStart = millis(); - while (millis() - timeStart <= 5000) {// We wait for a few seconds as otherwise the connection might not be ready! + while (millis() - timeStart <= 5000) { // We wait for a few seconds as otherwise the connection might not be ready! delay(100); } if (!BLE_connected) return false; Serial.printf("BLE starting to get service\r\n"); - BLERemoteService* pRemoteService = pClient->getService(gicServiceUUID); + BLERemoteService* pRemoteService = pClient->getService((conn_type == BLE_TYPE_GICISKY) ? gicServiceUUID : ATC_BLE_OEPL_ServiceUUID); 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; + if (conn_type == BLE_TYPE_GICISKY) { + imgChar = pRemoteService->getCharacteristic(gicImgUUID); + if (imgChar == nullptr) { + Serial.printf("BLE IMG Char failed\r\n"); + pClient->disconnect(); + return false; + } } - ctrlChar = pRemoteService->getCharacteristic(gicCtrlUUID); + ctrlChar = pRemoteService->getCharacteristic((conn_type == BLE_TYPE_GICISKY) ? gicCtrlUUID : ATC_BLE_OEPL_CtrlUUID); if (ctrlChar == nullptr) { Serial.printf("BLE ctrl Char failed\r\n"); pClient->disconnect(); @@ -147,6 +174,49 @@ void BLE_startScan(uint32_t timeout) { pBLEScan->start(timeout, false); } +#define BLOCK_DATA_SIZE_BLE 4096 +#define BLOCK_PART_DATA_SIZE_BLE 230 +uint8_t tempBlockBuffer[BLOCK_DATA_SIZE_BLE + 4]; +uint8_t tempPacketBuffer[2 + 3 + BLOCK_PART_DATA_SIZE_BLE]; +void ATC_BLE_OEPL_PrepareBlk(uint8_t indexBlockId) { + if (BLE_image_buffer == nullptr) { + return; + } + uint32_t bufferPosition = (BLOCK_DATA_SIZE_BLE * indexBlockId); + uint32_t lenNow = BLOCK_DATA_SIZE_BLE; + uint16_t crcCalc = 0; + if ((BLE_compressed_len - bufferPosition) < BLOCK_DATA_SIZE_BLE) + lenNow = (BLE_compressed_len - bufferPosition); + tempBlockBuffer[0] = lenNow & 0xff; + tempBlockBuffer[1] = (lenNow >> 8) & 0xff; + for (uint16_t c = 0; c < lenNow; c++) { + tempBlockBuffer[4 + c] = BLE_image_buffer[c + bufferPosition]; + crcCalc += tempBlockBuffer[4 + c]; + } + tempBlockBuffer[2] = crcCalc & 0xff; + tempBlockBuffer[3] = (crcCalc >> 8) & 0xff; + BLE_max_block_parts = (4 + lenNow) / BLOCK_PART_DATA_SIZE_BLE; + if ((4 + lenNow) % BLOCK_PART_DATA_SIZE_BLE) + BLE_max_block_parts++; + Serial.println("Preparing block: " + String(indexBlockId) + " BuffPos: " + String(bufferPosition) + " LenNow: " + String(lenNow) + " MaxBLEparts: " + String(BLE_max_block_parts)); + BLE_curr_part = 0; +} + +void ATC_BLE_OEPL_SendPart(uint8_t indexBlockId, uint8_t indexPkt) { + uint8_t crcCalc = indexBlockId + indexPkt; + for (uint16_t c = 0; c < BLOCK_PART_DATA_SIZE_BLE; c++) { + tempPacketBuffer[5 + c] = tempBlockBuffer[c + (BLOCK_PART_DATA_SIZE_BLE * indexPkt)]; + crcCalc += tempPacketBuffer[5 + c]; + } + tempPacketBuffer[0] = 0x00; + tempPacketBuffer[1] = 0x65; + tempPacketBuffer[2] = crcCalc; + tempPacketBuffer[3] = indexBlockId; + tempPacketBuffer[4] = indexPkt; + Serial.println("BLE Sending packet Len " + String(sizeof(tempPacketBuffer))); + ctrlChar->writeValue(tempPacketBuffer, sizeof(tempPacketBuffer), true); +} + void BLETask(void* parameter) { vTaskDelay(5000 / portTICK_PERIOD_MS); Serial.println("BLE task started"); @@ -162,25 +232,79 @@ void BLETask(void* parameter) { } 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 + Serial.println("BLE Image is pending but we wait a bit"); + delay(5000); // We better wait here, since the pending image needs to be created first + if (BLE_curr_address[7] == 0x13 && BLE_curr_address[6] == 0x37) { // This is an ATC BLE OEPL display + // Here we create the compressed buffer + BLE_image_buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING); + if (BLE_image_buffer == nullptr) { + Serial.println("BLE Could not create buffer!"); + BLE_compressed_len = 0; } else { - free(buffer); + uint8_t dataType = 0x00; + uint8_t dataTypeArgument = 0x00; + uint16_t nextCheckin = 0x00; + BLE_compressed_len = get_ATC_BLE_OEPL_image(BLE_curr_address, BLE_image_buffer, BUFFER_MAX_SIZE_COMPRESSING, &dataType, &dataTypeArgument, &nextCheckin); + Serial.printf("BLE data Length: %i\r\n", BLE_compressed_len); + // then we connect to BLE to send the compressed data + if (BLE_compressed_len && BLE_connect(BLE_curr_address, BLE_TYPE_ATC_BLE_OEPL)) { + BLE_err_counter = 0; + BLE_curr_part = 0; + memset(BLE_notify_buffer, 0x00, sizeof(BLE_notify_buffer)); + + uint8_t md5bytes[16]; + MD5Builder md5; + md5.begin(); + md5.add(BLE_image_buffer, BLE_compressed_len); + md5.calculate(); + md5.getBytes(md5bytes); + + BLEavaildatainfo.dataType = dataType; + BLEavaildatainfo.dataVer = *((uint64_t*)md5bytes); + BLEavaildatainfo.dataSize = BLE_compressed_len; + BLEavaildatainfo.dataTypeArgument = dataTypeArgument; + BLEavaildatainfo.nextCheckIn = nextCheckin; + BLEavaildatainfo.checksum = 0; + for (uint16_t c = 1; c < sizeof(struct AvailDataInfo); c++) { + BLEavaildatainfo.checksum += (uint8_t)((uint8_t*)&BLEavaildatainfo)[c]; + } + BLE_upload_state = BLE_UPLOAD_STATE_INIT; + ble_main_state = BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD; + BLE_new_notify = true; // trigger the upload here + } else { + free(BLE_image_buffer); + if (BLE_err_counter++ >= 5) { // 5 Retries for a BLE Connection + struct espXferComplete reportStruct; + memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8); + processXferComplete(&reportStruct, true); + } + } + } + } else { // This is a Gicisky display + // Here we create the compressed buffer + BLE_image_buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING); + if (BLE_image_buffer == nullptr) { + Serial.println("BLE Could not create buffer!"); + BLE_compressed_len = 0; + } else { + BLE_compressed_len = compress_image(BLE_curr_address, BLE_image_buffer, BUFFER_MAX_SIZE_COMPRESSING); + Serial.printf("BLE Compressed Length: %i\r\n", BLE_compressed_len); + // then we connect to BLE to send the compressed data + if (BLE_compressed_len && BLE_connect(BLE_curr_address, BLE_TYPE_GICISKY)) { + BLE_err_counter = 0; + BLE_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(BLE_image_buffer); + if (BLE_err_counter++ >= 5) { // 5 Retries for a BLE Connection + struct espXferComplete reportStruct; + memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8); + processXferComplete(&reportStruct, true); + } + } } } BLE_last_pending_check = millis(); @@ -196,25 +320,25 @@ void BLETask(void* parameter) { switch (BLE_upload_state) { default: case BLE_UPLOAD_STATE_INIT: - BLE_buff[0] = 1; - ctrlChar->writeValue(BLE_buff, 1); + BLE_mini_buff[0] = 1; + ctrlChar->writeValue(BLE_mini_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); + BLE_mini_buff[0] = 0x02; + BLE_mini_buff[1] = BLE_compressed_len & 0xff; + BLE_mini_buff[2] = (BLE_compressed_len >> 8) & 0xff; + BLE_mini_buff[3] = (BLE_compressed_len >> 16) & 0xff; + BLE_mini_buff[4] = (BLE_compressed_len >> 24) & 0xff; + BLE_mini_buff[5] = 0x00; + ctrlChar->writeValue(BLE_mini_buff, 6); break; case BLE_UPLOAD_STATE_START: - BLE_buff[0] = 0x03; - ctrlChar->writeValue(BLE_buff, 1); + BLE_mini_buff[0] = 0x03; + ctrlChar->writeValue(BLE_mini_buff, 1); break; case BLE_UPLOAD_STATE_UPLOAD: if (BLE_notify_buffer[2] == 0x08) { - free(buffer); + free(BLE_image_buffer); pClient->disconnect(); ble_main_state = BLE_MAIN_STATE_IDLE; BLE_last_pending_check = millis(); @@ -222,35 +346,103 @@ void BLETask(void* parameter) { struct espXferComplete reportStruct; memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8); processXferComplete(&reportStruct, true); - curr_part = 0; + BLE_err_counter = 0; + BLE_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); + if (req_curr_part != BLE_curr_part) { + Serial.printf("Something went wrong, expected req part: %i but got: %i we better abort here.\r\n", req_curr_part, BLE_curr_part); + free(BLE_image_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++; + if (BLE_compressed_len - (BLE_curr_part * 240) < 240) + curr_len = BLE_compressed_len - (BLE_curr_part * 240); + BLE_mini_buff[0] = BLE_curr_part & 0xff; + BLE_mini_buff[1] = (BLE_curr_part >> 8) & 0xff; + BLE_mini_buff[2] = (BLE_curr_part >> 16) & 0xff; + BLE_mini_buff[3] = (BLE_curr_part >> 24) & 0xff; + memcpy((uint8_t*)&BLE_mini_buff[4], (uint8_t*)&BLE_image_buffer[BLE_curr_part * 240], curr_len); + imgChar->writeValue(BLE_mini_buff, curr_len + 4); + Serial.printf("BLE sending part: %i\r\n", BLE_curr_part); + BLE_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); + free(BLE_image_buffer); pClient->disconnect(); + BLE_err_counter = 0; + ble_main_state = BLE_MAIN_STATE_IDLE; + BLE_last_pending_check = millis(); + } + } + break; + } + case BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD: { + if (BLE_connected && BLE_new_notify) { + BLE_new_notify = false; + BLE_last_notify = millis(); + switch (BLE_upload_state) { + default: + case BLE_UPLOAD_STATE_INIT: + BLE_mini_buff[0] = 0x00; + BLE_mini_buff[1] = 0x64; + memcpy((uint8_t*)&BLE_mini_buff[2], &BLEavaildatainfo, sizeof(struct AvailDataInfo)); + ctrlChar->writeValue(BLE_mini_buff, sizeof(struct AvailDataInfo) + 2); + BLE_upload_state = BLE_UPLOAD_STATE_UPLOAD; + break; + case BLE_UPLOAD_STATE_UPLOAD: { + uint8_t notifyLen = BLE_notify_buffer[0]; + uint16_t notifyCMD = (BLE_notify_buffer[1] << 8) | BLE_notify_buffer[2]; + Serial.println("BLE CMD " + String(notifyCMD)); + switch (notifyCMD) { + case BLE_CMD_REQ: + if (notifyLen == (sizeof(struct blockRequest) + 2)) { + Serial.println("We got a request for a BLK"); + memcpy(&BLEblkRequst, &BLE_notify_buffer[3], sizeof(struct blockRequest)); + BLE_curr_part = 0; + ATC_BLE_OEPL_PrepareBlk(BLEblkRequst.blockId); + ATC_BLE_OEPL_SendPart(BLEblkRequst.blockId, BLE_curr_part); + } + break; + case BLE_CMD_ACK_BLKPRT: + BLE_curr_part++; + BLE_err_counter = 0; + case BLE_CMD_ERR_BLKPRT: + if (BLE_curr_part <= BLE_max_block_parts && BLE_err_counter++ < 15) { + ATC_BLE_OEPL_SendPart(BLEblkRequst.blockId, BLE_curr_part); + break; + } // FALLTROUGH!!! We cancel the upload if we land here since we dont have so many parts of a block! + case BLE_CMD_ACK: + case BLE_CMD_ACK_IS_SHOWN: + case BLE_CMD_ACK_FW_UPDATED: + Serial.println("BLE Upload done"); + free(BLE_image_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); + BLE_err_counter = 0; + BLE_max_block_parts = 0; + BLE_curr_part = 0; + break; + } + } break; + } + } else { + if (millis() - BLE_last_notify > 30000) { // Something odd, better reset connection! + Serial.println("BLE err going back to IDLE"); + free(BLE_image_buffer); + pClient->disconnect(); + BLE_err_counter = 0; ble_main_state = BLE_MAIN_STATE_IDLE; BLE_last_pending_check = millis(); } diff --git a/oepl-definitions.h b/oepl-definitions.h index e3cae105..8238f060 100755 --- a/oepl-definitions.h +++ b/oepl-definitions.h @@ -110,6 +110,7 @@ #define CAPABILITY_HAS_WAKE_BUTTON 0x20 #define CAPABILITY_HAS_NFC 0x40 #define CAPABILITY_NFC_WAKE 0x80 +#define CAPABILITY_IS_BLE 0x0100 #define DATATYPE_NOUPDATE 0 #define DATATYPE_IMG_BMP 2 // ** deprecated diff --git a/tag_types.h b/tag_types.h index a4fbdbae..476c497a 100755 --- a/tag_types.h +++ b/tag_types.h @@ -40,6 +40,7 @@ #define CAPABILITY_HAS_WAKE_BUTTON 0x20 #define CAPABILITY_HAS_NFC 0x40 #define CAPABILITY_NFC_WAKE 0x80 +#define CAPABILITY_IS_BLE 0x0100 #define DATATYPE_NOUPDATE 0 #define DATATYPE_IMG_BMP 2