BLE-NRF51822教程11-手机动态修改设备名
該教程講解如何實現用手機來動態修改設備名,達到手機連接設備后修改設備名稱,然后斷開連接再掃描能夠看到新的設備名。
?
教程基于sdk9.0?下的uartdemo,如下目錄中xxx\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_uart
?
Nordic的協議棧實現中默認都會有一個?Generic Access服務和Generic Attribute服務(有的BLE app可能顯示不了名字,只顯示這兩個服務的UUID,分別是0x1800和0x1801)。
即一個工程中即使沒有定義任何服務,燒寫到板子上后,手機連接上也能看到這兩個服務。
?
我們動態修改設備名就是利用了第一個服務Generic Access。
該服務為通用屬性規范服務,改服務為設備提供了一種確定信息的方式,包括設備自身的名稱,外觀特性,首先連接參數等。
使用其中的 設備名屬性,就能實現我們需要的動態修改設備名。
實現方式就是??手機連接上設備后訪問這個服務下的設備名屬性,然后通過這個屬性寫新的名字,設備這邊判斷手機發送過來的寫是不是對Generic Access服務下的 設備名 屬性的寫操作。如果是就保存名字到flash中。并且更新設備名,這樣當設備重啟或者斷開連接后 手機這邊再掃描就能看到新的設備名字了。
?
PS:當然你也可以專門建立一個服務然后添加一個特征值用來當做修改名字用。接收手機發送過來的新名字然后存儲修改。 不過既然默認存在的Generic Access服務中已經有了設備名屬性,這里就直接用,不再去專門創建服務
?
?
因為涉及到flash的存儲首先 添加flash相關的處理(關于flash的操作看前面的教程 如何在協議棧中使用flash)
?
//添加?sys_evt事件處理
static void sys_evt_dispatch(uint32_t sys_evt)
{
??? pstorage_sys_event_handler(sys_evt);
}
?
//協議棧初始化中注冊上面的派發函數
static void ble_stack_init(void)
{
??? uint32_t err_code;
???
??? // Initialize SoftDevice.
??? SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL);
??? ………………
??? ………………
??? ………………
??? // Subscribe for BLE events.
??? err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
??? APP_ERROR_CHECK(err_code);
???
?? //添加?sys_evt事件處理函數 注冊。?flash需要用到
?? err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
??? APP_ERROR_CHECK(err_code);
}
?
?
首先初始化flash,并且定義自己的flash操作完成后的回調函數,在main.c文件的最上面添加如下代碼
?
//第一個字節存放的是標識符表示?flash中的數據是否是有效的?name
//device_name[0]=0xAA 表示是有效name,device_name[1]表示name的長度
?
#define NAME_SIZE 32
uint8_t device_name[NAME_SIZE];
pstorage_handle_t my_name_addr; //記錄name存放的flash地址
?
?
//flash操作完成后的回調函數。 并沒有做什么有用的事,但是注冊flash塊//的時候需要有回調函數所以這里需要定義
static void my_cb(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");?
?????????? }
?????????? break;
??? }
}
?
?
//定義flash初始化函數
void my_flash_init(void){
??? uint32_t err_code;
??? pstorage_module_param_t param;
//申請一個塊 用來存放name
??? param.block_count = 1;
??? param.block_size = NAME_SIZE;
??? param.cb = my_cb;
???
??? err_code = pstorage_init();
??? printf("init err_code:%d\r\n",err_code);
??? err_code = pstorage_register(¶m, &my_name_addr);
??? printf("register err_code:%d\r\n",err_code);
??? //加載flash內容。后面會判斷name是否有效,如果有效就會用改name
??? //否則使用默認name
??? err_code = pstorage_load(device_name, &my_name_addr, NAME_SIZE, 0);
??? printf("load err_code:%d\r\n",err_code);
?
}
?
?
然后將該flash初始化函數放到main函數中
?
int main(void)
{
??? uint32_t err_code;
??? bool erase_bonds;
??? uint8_t? start_string[] = START_STRING;
???
??? // Initialize.
??? APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
????uart_init();
???
?? //添加flash初始化,因為用到了打印需要放到uart_init函數之后
?? //因為gap_params_init函數中會判斷使用flash中的名字還是默認名字
?? //所以需要放到該函數之前
???my_flash_init();
???
??? buttons_leds_init(&erase_bonds);
??? ble_stack_init();
????gap_params_init();
??? services_init();
? ??advertising_init();
??? conn_params_init();
?? ?printf("%s\r\n",start_string);
??? err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
??? APP_ERROR_CHECK(err_code);
??? // Enter main loop.
??? for (;;)
??? {
??????? power_manage();
??? }
}
?
然后修改?main函數中調用的gap_params_init函數。該函數中判斷my_flash_init?函數中加載的flash內容是否是有效name,是就使用,不是就用默認name.
?
static void gap_params_init(void)
{
??? uint32_t??????????????? err_code;
??? ble_gap_conn_params_t?? gap_conn_params;
??? ble_gap_conn_sec_mode_t sec_mode;
??? BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
???
?
??? //flash數據有效則使用flash中的名字
??? if ( device_name[0] == 0xaa ){
?????? //有效 使用新名字
?????? //device_name[1]為名字長度
?????? printf("update name\r\n");
?????? err_code = sd_ble_gap_device_name_set(&sec_mode,
?????????? ?????????????????????????(const uint8_t *) device_name+2,
???????? ??????????????????????????????device_name[1]);
???
??? }else{
?????? printf("default name\r\n");
?????? err_code = sd_ble_gap_device_name_set(&sec_mode,
????????????? ?????????????????????????(const uint8_t *) DEVICE_NAME,
????????????????????????????????????????? strlen(DEVICE_NAME));
??? }
?????????????????????????????????? ?
??? APP_ERROR_CHECK(err_code);
?? ? memset(&gap_conn_params, 0, sizeof(gap_conn_params));
? ? gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
? ? gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
?? ……………
??? …………
}
?
?
關于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;
???
??? //通過UUID來判斷事件是不是寫Generic Access服務中的名字屬性
??? if((p_evt_write->context.char_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);
?????? pstorage_update(&my_name_addr, device_name, NAME_SIZE, 0 );
?
??? }
?
}
?
?
然后再將這個事件處理函數加到 事件派發函數ble_evt_dispatch中
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
????name_change(p_ble_evt);
???
??? ble_conn_params_on_ble_evt(p_ble_evt);
??? ble_nus_on_ble_evt(&m_nus, p_ble_evt);
??? on_ble_evt(p_ble_evt);
??? ble_advertising_on_ble_evt(p_ble_evt);
??? bsp_btn_ble_on_ble_evt(p_ble_evt);?
}
?
到這里基本實現了 手機修改設備名字。不過連接上修改名字后斷開然后點擊掃描發現名字并未更新,需要復位一下硬件設備才能看到設備名字變了。
?
想在不復位的情況下,斷開連接然后點掃描就能看到新的設備名還需要在斷開連接后重新初始化 廣播數據。
?
?
繼續修改事件派發函數ble_evt_dispatch
?
//應為該函數是在下面定義的,這里使用到,所以要聲明一下
void advertising_init(void);
?
static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
{
????name_change(p_ble_evt);
???
????//添加代碼,在斷開連接事件后初始化廣播數據
?? if ( p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED ){
????? advertising_init();
?? }
??
??? ble_conn_params_on_ble_evt(p_ble_evt);
??? ble_nus_on_ble_evt(&m_nus, p_ble_evt);
??? on_ble_evt(p_ble_evt);
??? ble_advertising_on_ble_evt(p_ble_evt);
??? bsp_btn_ble_on_ble_evt(p_ble_evt);
? ?
}
?
?
現在編譯后燒寫到板子,手機連接后進入?Generic Access服務(有的可能只看到UUID 0x1800),然后點擊device name(UUID?0x2A00)屬性,寫新名字。
然后斷開連接。 點擊掃描按鍵就可以看到新的設備名字了
總結
以上是生活随笔為你收集整理的BLE-NRF51822教程11-手机动态修改设备名的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝牙协议分析(6)_BLE地址类型(蜗窝
- 下一篇: BLE-NRF51822教程4-串口BL