這篇主要介紹如何在手機端修改設備參數,比如設備名稱,且實現掉電不丟失。
思路:把需要修改的參數發送給設備,設備根據uuid來分辨是參數,並保存在flash中,重啓服務,這樣下次上電修改不會丟失。
1.flash的操作
在pstorage.c
中是官方提供操作flash的庫函數,下面介紹幾個要用的
說明:初始化flash模塊,在調用flash模塊之前必須先調用他一次
uint32_t pstorage_init(void);
說明:註冊flash接口
[in] p_module_param 註冊參數
[out] p_block_id 註冊成功時標識flash存儲塊
uint32_t pstorage_register(pstorage_module_param_t p_module_param,
pstorage_handle_t * p_block_id);
說明:根據塊編號(block_num)獲得你要操作的地址(p_block_id)
[in] p_base_id 註冊成功時標識flash存儲塊(基塊ID)
[in] block_num塊編號,第一塊編號爲零
[out] p_block_id ,block_num編號塊對應的地址
uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
pstorage_size_t block_num,
pstorage_handle_t * p_block_id);
說明:在指定位置更新寫入存儲相應大小的數據
[in] p_dest 更新數據的目的地址
[in] p_src 待寫入數據buff首地址
[in] size,寫入長度
[in] offset,存儲地址的相應偏移量
uint32_t pstorage_update(pstorage_handle_t * p_dest,
uint8_t * p_src,
pstorage_size_t size,
pstorage_size_t offset);
說明:在指定位置讀取存儲區相應大小的數據
[in] p_dest 讀取數據的源地址
[in] p_src 讀取存放數據buff首地址
[in] size,讀取長度
[in] offset,讀取數據的源地址的相應偏移量
uint32_t pstorage_load(pstorage_handle_t * p_dest,
uint8_t * p_src,
pstorage_size_t size,
pstorage_size_t offset);
第一步,在系統的派發函數裏註冊官方提供的flash的callback
static void sys_evt_dispatch(uint32_t sys_evt)
{
//這個函數時在 pstorage 模塊中實現的
pstorage_sys_event_handler(sys_evt);
}
第二步,flash初始化
void flash_init(void)
{
uint32_t err_code;
err_code = pstorage_init(); //初始化flash
APP_ERROR_CHECK(err_code);
pstorage_module_param_t module_param;
module_param.block_count = 1; // 申請了一個塊
module_param.block_size = 512;//(最小要求是 16)
module_param.cb = flash_callback;// //操作回調
err_code =pstorage_register(&module_param, &block_id);//註冊申請
APP_ERROR_CHECK(err_code);
}
flash_callback我理解是相應操作成功、失敗、完成、未完成的判斷依據(可以根據op_code分辨哪種狀態機,根據result分辨成功失敗)如下
static void flash_callback(pstorage_handle_t * handle,uint8_t op_code,uint32_t result,uint8_t * p_data,uint32_t data_len)
{
switch(op_code)
{
case PSTORAGE_UPDATE_OP_CODE:
if (result == NRF_SUCCESS)
{
printf("update end");
advertising_init();//重新啓動廣播
}
break;
}
}
這裏只判斷PSTORAGE_UPDATE_OP_CODE操作成功(result == NRF_SUCCESS)則打印輸出update end
2.怎麼判斷是操作藍牙名稱呢?
可以根據uuid,GAP GATT這種服務的uuid都是SIG定義好的固定的
在ble_types.h
中80行可以看到設備名稱uuid是0x2A00
/* GATT specific UUIDs */
#define BLE_UUID_GATT 0x1801 /**< Generic Attribute Profile. */
#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED 0x2A05 /**< Service Changed Characteristic. */
/* GAP specific UUIDs */
#define BLE_UUID_GAP 0x1800 /**< Generic Access Profile. */
#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME 0x2A00 /**< Device Name Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE 0x2A01 /**< Appearance Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPF 0x2A02 /**< Peripheral Privacy Flag Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */
/** @} */
手機連接設備後,對BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME屬性(uuid 0x2A00)寫操作,設備判斷是不是對這個uuid寫,是的話就把寫數據保存在flash中,這樣下次重啓就可以加載flash數據作爲設備名稱
static void name_change(ble_evt_t * p_ble_evt)
{
ble_gatts_evt_write_t *p_evt_write=&p_ble_evt->evt.gatts_evt.params.write;
//判斷是對BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME這個uuid進行寫操作
if((p_evt_write->uuid.uuid==BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME)
&& (p_ble_evt->header.evt_id== BLE_GATTS_EVT_WRITE))
{
printf("name change \r\n");
device_name[0] = 0xaa;
//寫的長度
device_name[1] = p_evt_write->len;
//寫的數據
memcpy(device_name+2, p_evt_write->data, p_evt_write->len);
//保存在flash中
pstorage_update(&my_name_addr, device_name, NAME_SIZE, 0 );
}
}
然後在藍牙派發函數ble_evt_dispatch
裏包含name_change
在gap_params_init
函數裏要對從flash加載的數據進行判斷有沒有手機下發的設備名字,有就用手機下發的,沒有就用默認的