1.目的
ancs接收ios信息
2.分析
上面一章已经介绍了基本的信息,现在来实战吧。
3.平台:
协议栈版本:SDK8.0.0
编译软件:keil 5.14
Apple APP:lightblue(手机工具)
硬件平台:nrf51822最小系统
例子:SDK 10.0.0\SDK10.0\examples\ble_peripheral\ble_app_ancs_c\pca10028\s110\arm4
4.步骤
a.把固件烧入到开发板里面
b.打开了蓝牙,打开lightblue 连接名字为 “ANCS” 的设备,会出现配对界面,如下:
3。点击配对,就好了。这个时候ancs功能已经打开了,推出lightblue。
注意:如果不点击配对,则ancs失效。ancs必须配对才能有效
4.打电话测试:
电话来了。电话断开都会产生事件。
4.这个时候要怎么获得,电话号码等属性呢。
在"ANCS(1)"(请查看上面一章内容) 中我们知道,需要通过
3、Data Source:
UUID 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB(notifiable)
数据源,用于提供详细数据,在控制信息写入后通过此characteristic返回;
来获得数据源。
官方的开发板子上面一个案件,可以获取数据源。 如下:BSP_EVENT_KEY_1
注意:官方例子只能获得最后一次事件的数据属性
可以在程序里面保存UID来获取多次数据属性
static void bsp_event_handler(bsp_event_t event) { uint32_t err_code; switch (event) { case BSP_EVENT_SLEEP: sleep_mode_enter(); break; case BSP_EVENT_DISCONNECT: err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } break; case BSP_EVENT_WHITELIST_OFF: err_code = ble_advertising_restart_without_whitelist(); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } break; case BSP_EVENT_KEY_1: err_code = ble_ancs_c_request_attrs(&m_notification_latest); APP_ERROR_CHECK(err_code); break; default: break; } }我自己的板子上面没有怎么办呢?在如下添加 ble_ancs_c_request_attrs(&m_notification_latest);
static void notif_print(ble_ancs_c_evt_notif_t * p_notif) { printf("\n\rNotification\n\r"); printf("Event: %s\n", lit_eventid[p_notif->evt_id]); printf("Category ID: %s\n", lit_catid[p_notif->category_id]); printf("Category Cnt:%u\n", (unsigned int) p_notif->category_count); printf("UID: %u\n\r", (unsigned int) p_notif->notif_uid); printf("Flags:\n\r"); if(p_notif->evt_flags.silent == 1) { printf(" Silent\n\r"); } if(p_notif->evt_flags.important == 1) { printf(" Important\n\r"); } if(p_notif->evt_flags.pre_existing == 1) { printf(" Pre-existing\n\r"); } if(p_notif->evt_flags.positive_action == 1) { printf(" Positive Action\n\r"); } if(p_notif->evt_flags.negative_action == 1) { printf(" Positive Action\n\r"); } ble_ancs_c_request_attrs(&m_notification_latest); }
好了。打电话测试:
上面,电话号码 和 时间 都出现了。。。
4.刚才在修改代码的时候,是不是出现,下载进去后程序一直复位,
原因是设备这边清掉了绑定信息,而手机没有清掉 ,出现了 0x08错误。导致跳到了
__WEAK void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { // On assert, the system can only recover with a reset. #ifndef DEBUG NVIC_SystemReset(); #else
解决办法。1.手机忽略此设备
5.ios和设备连上后。复位设备,是不是有出现了复位。。也是0x08错误
这个是因为,复位的时候以上的绑定信息,全部软件擦出了。
static void buttons_leds_init(bool * p_erase_bonds) { bsp_event_t startup_event; uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), bsp_event_handler); APP_ERROR_CHECK(err_code); err_code = bsp_btn_ble_init(NULL, &startup_event); APP_ERROR_CHECK(err_code); *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); }
擦出全部绑定信息。
把词句屏蔽 ,
static void buttons_leds_init(bool * p_erase_bonds) { bsp_event_t startup_event; uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), bsp_event_handler); APP_ERROR_CHECK(err_code); err_code = bsp_btn_ble_init(NULL, &startup_event); APP_ERROR_CHECK(err_code); // *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); }bool erase_bonds = 0;
这样就不会擦出信息了。
ret_code_t dm_init(dm_init_param_t const * const p_init_param) { pstorage_module_param_t param; pstorage_handle_t block_handle; ret_code_t err_code; uint32_t index; DM_LOG("[DM]: >> dm_init.\r\n"); NULL_PARAM_CHECK(p_init_param); SDK_MUTEX_INIT(m_dm_mutex); DM_MUTEX_LOCK(); for (index = 0; index < DEVICE_MANAGER_MAX_APPLICATIONS; index++) { application_instance_init(index); } for (index = 0; index < DEVICE_MANAGER_MAX_CONNECTIONS; index++) { connection_instance_init(index); } memset(m_gatts_table, 0, sizeof(m_gatts_table)); //Initialization of all device instances. for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++) { peer_instance_init(index); m_irk_index_table[index] = DM_INVALID_ID; } //All context with respect to a particular device is stored contiguously. param.block_size = ALL_CONTEXT_SIZE; param.block_count = DEVICE_MANAGER_MAX_BONDS; param.cb = dm_pstorage_cb_handler; err_code = pstorage_register(¶m, &m_storage_handle); if (err_code == NRF_SUCCESS) { m_module_initialized = true; printf("p_init_param->clear_persistent_data=%d\r\n",p_init_param->clear_persistent_data); if (p_init_param->clear_persistent_data == false) { DM_LOG("[DM]: Storage handle 0x%08X.\r\n", m_storage_handle.block_id); //Copy bonded peer device address and IRK to RAM table. //Bonded devices are stored in range (0,DEVICE_MANAGER_MAX_BONDS-1). The remaining //range is for active connections that may or may not be bonded. for (index = 0; index < DEVICE_MANAGER_MAX_BONDS; index++) { err_code = pstorage_block_identifier_get(&m_storage_handle, index, &block_handle); //Issue read request if you successfully get the block identifier. if (err_code == NRF_SUCCESS) { DM_TRC("[DM]:[0x%02X]: Block handle 0x%08X.\r\n", index, block_handle.block_id); err_code = pstorage_load((uint8_t *)&m_peer_table[index], &block_handle, sizeof(peer_id_t), 0); if (err_code != NRF_SUCCESS) { // In case a peer device could not be loaded successfully, rest of the // initialization procedure are skipped and an error is sent to the // application. DM_ERR( "[DM]: Failed to load peer device %08X from storage, reason %08X.\r\n", index, err_code); m_module_initialized = false; break; } else { // printf("\r\nBLE ANCS\r\n"); DM_TRC("[DM]:[DI 0x%02X]: Device type 0x%02X.\r\n", index, m_peer_table[index].peer_id.id_addr_info.addr_type); DM_TRC("[DM]: Device Addr 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X.\r\n", m_peer_table[index].peer_id.id_addr_info.addr[0], m_peer_table[index].peer_id.id_addr_info.addr[1], m_peer_table[index].peer_id.id_addr_info.addr[2], m_peer_table[index].peer_id.id_addr_info.addr[3], m_peer_table[index].peer_id.id_addr_info.addr[4], m_peer_table[index].peer_id.id_addr_info.addr[5]); } } else { //In case a peer device could not be loaded successfully, rest of the //initialization procedure are skipped and an error is sent to the application. DM_LOG("[DM]: Failed to get block handle for instance %08X, reason %08X.\r\n", index, err_code); m_module_initialized = false; break; } } } else { err_code = pstorage_clear(&m_storage_handle, (param.block_size * param.block_count)); DM_ERR("[DM]: Successfully requested clear of persistent data.\r\n"); } } else { DM_ERR("[DM]: Failed to register with storage module, reason 0x%08X.\r\n", err_code); } DM_MUTEX_UNLOCK(); DM_TRC("[DM]: << dm_init.\r\n"); return err_code; }
执行:pstorage_load()即读出绑定信息
else
pstorage_clear()擦出
p_init_param->clear_persistent_data 这个即是:p_erase_bonds 的值
有网友遇到:事件到了100的时候,就不会增加了。就是假如收到了100条信息 可以显示内容,到了101条就不显示了。(原因不详知道的告诉下,谢谢)
6.当light连上ancs并配对后,长时间不通信会自动断开
抛出的错误类型为:#define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A /**< Different Transaction Collision. */
解决办法:每隔一段时间发送一个 无效数据 给手机。。。
7.当连接的时候跳出配对框
当点击取消的时候,系统会复位,因为在于,系统抛出了
#define BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED 0x81 /**< Passkey entry failed (user cancelled or other). */
看如下代码:
static uint32_t device_manager_evt_handler(dm_handle_t const * p_handle, dm_event_t const * p_evt, ret_code_t event_result) { uint32_t err_code; APP_ERROR_CHECK(event_result); //检查event ble_ancs_c_on_device_manager_evt(&m_ancs_c, p_handle, p_evt); switch (p_evt->event_id) { case DM_EVT_CONNECTION: m_peer_handle = (*p_handle); err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); APP_ERROR_CHECK(err_code); break; case DM_EVT_LINK_SECURED: err_code = ble_db_discovery_start(&m_ble_db_discovery, p_evt->event_param.p_gap_param->conn_handle); APP_ERROR_CHECK(err_code); break; default: break; } return NRF_SUCCESS; }APP_ERROR_CHECK(event_result); 会导致复位。这点要注意。可以把这个给屏蔽掉。。