Trước tiên, hãy tải thư viện ble ota:
Các bạn tham khảo ví dụ mẫu trong phần example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h>
#include "IOT47_BLE_OTA.h"
#define SERVICE_UUID "55072829-bc9e-4c53-0003-74a6d4c78751" String bleServerName;
static BLEUUID BLE_UUID(SERVICE_UUID); BLECharacteristic ch1_BLECharacteristic(SERVICE_UUID, BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE); BLEDescriptor ch1_Descriptor(BLEUUID((uint16_t)0x2902));
static BLERemoteCharacteristic* ch1_Characteristic;
bool deviceConnected = false; class MyServerCallbacks: public BLEServerCallbacks { void onConnect(BLEServer* pServer) { deviceConnected = true; Serial.println("Client connect"); }; void onDisconnect(BLEServer* pServer) { deviceConnected = false; iot47_stop_ota(); Serial.println("Client disconnect"); pServer->startAdvertising(); } };
class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { std::string rxValue = pCharacteristic->getValue(); if(iot47_ota_task((uint8_t *)&(rxValue[0]),rxValue.length()))return; //bắt buộc phải gọi ở đây
//phần này xử lí nhận data ble của user if (rxValue.length() > 0) { Serial.println("ble len: " + String(rxValue.length())); Serial.print("Received Value: "); for (int i = 0; i < rxValue.length(); i++) Serial.print(rxValue[i]);
Serial.println(); Serial.println("*********"); } } }; void setup() { Serial.begin(115200); bleServerName = "IOT47 BLE OTA TEST";
Serial.println("Starting BLE work!");
BLEDevice::init(bleServerName.c_str()); BLEDevice::setMTU(512); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks());
//Create the BLE Service BLEService *bmeService = pServer->createService(SERVICE_UUID);
// Create BLE Characteristics and Create a BLE Descriptor bmeService->addCharacteristic(&ch1_BLECharacteristic); ch1_Descriptor.setValue("BLE chanel 1"); ch1_BLECharacteristic.addDescriptor(&ch1_Descriptor);
ch1_BLECharacteristic.setCallbacks(new MyCallbacks());
// Start the service bmeService->start();
// Start advertising BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pServer->getAdvertising()->start();
//ch1_Characteristic = bmeService->getCharacteristic(BLE_UUID); //ch1_BLECharacteristic->registerForNotify(notifyCallback); Serial.println("Waiting a client connection to notify...");
iot47_ble_ota_begin(&ch1_BLECharacteristic); //bắt buộc phải gọi
//đăng kí callback, tùy user iot47_ble_ota_set_begin_callback([](uint32_t curen, uint32_t totol){ Serial.println("Begin ota"); }); iot47_ble_ota_set_proces_callback([](uint32_t curen, uint32_t totol){ Serial.print(curen); Serial.print("/"); Serial.println(totol); }); iot47_ble_ota_set_end_callback([](uint32_t curen, uint32_t totol){ Serial.println("Download done"); }); iot47_ble_ota_set_error_callback([](uint32_t curen, uint32_t totol){ Serial.println("Download error"); }); }
void loop() {
} |
Vào sdk config, bật bluetooth
Add thư viện espidf_ble_ota.h và easy_ble.h
Phiên bản cho esp-idf mình có suport thêm 1 lớp bọc giúp khởi tạo ble nên việc sử dụng còn dễ dàng hơn
easy_ble là lớp bọc khởi tạo bluetooth giúp bạn nhanh chóng sử dụng thư viện chỉ với 3 dòng khởi tạo. Tuy nhiên bạn sẽ ít có quyền can thiệp vào việc khởi tạo ble hơn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#include <esp_wifi.h> #include <esp_event.h> #include <esp_log.h> #include <esp_system.h> #include <nvs_flash.h> #include <sys/param.h> #include "nvs_flash.h" #include "espidf_ble_ota.h" #include "easy_ble.h" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init());
uint8_t mac[6]; esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); easy_ble_init(mac);
ble_ota_init(); } |
Đăng kí các callback
Dưới dây là các callback trong quá trình ota, bạn có thể sử dụng để biết qua trình ota đang diễn ra như nào ( Ví dụ in % download ra màn hình LCD hoặc thông báo lỗi …)
1 2 3 4 5 |
typedef void (*ota_callback_t)(uint32_t curen, uint32_t totol); void iot47_ble_ota_set_begin_callback(ota_callback_t c); void iot47_ble_ota_set_proces_callback(ota_callback_t c); void iot47_ble_ota_set_end_callback(ota_callback_t c); void iot47_ble_ota_set_error_callback(ota_callback_t c); |
1 2 |
typedef void (*easy_ble_callback_t)(uint8_t *rxValue, uint8_t len,esp_gatt_if_t *gatts_if, uint16_t conn_id, uint16_t attr_handle); void easy_ble_set_rx_callback(easy_ble_callback_t c); |
Không sử dụng lớp bọc easy_ble
Bằng cách sử dụng trực tiếp các api của espidf_ble_ota, bạn có thể toàn quyền khởi tạo ble và sử dụng ble theo ý muốn bạn, tuy nhiên sẽ cần 1 chút kiến thức về ble. Chỉ cần đặt hàm iot47_ble_ota_task vào trong sự kiện ESP_GATTS_WRITE_EVT Ví dụ:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
case ESP_GATTS_WRITE_EVT: { if (!param->write.is_prep){ if(iot47_ble_ota_task(param->write.value,param->write.len,&gatts_if,param->write.conn_id,param->write.handle) == 0) { //user code ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT A, conn_id %d, trans_id %d, handle %d", param->write.conn_id, param->write.trans_id, param->write.handle); ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT A, value len %d, value :", param->write.len); esp_log_buffer_hex(GATTS_TAG, param->write.value, param->write.len); } } example_write_event_env(gatts_if, &a_prepare_write_env, param); break; } |
Hàm này là hàm ưu tiên nên hãy đặt nó ở đầu. Nếu nó trả về khác 0 , tức là quá trình OTA đang diễn ra, do vậy bạn chỉ xử lí các tác vụ ble của user nếu hàm này trả về 0 Và để an toàn hơn, hãy đặt iot47_stop_ota(); vào sự kiện ESP_GATTS_DISCONNECT_EVT. Sau khi khởi tạo ble xong, chỉ cần gọi ble_ota_init();