发现多个特征值
参考瓜哥的文档,我这里搬运一下:
七、实验步骤 1、增加多个特征值状态的宏(sImpleBLECentral.c 中) // Discovery states enum { BLE_DISC_STATE_IDLE, // Idle BLE_DISC_STATE_SVC, // Service discovery BLE_DISC_STATE_CHAR1, // Characteristic discovery 1 BLE_DISC_STATE_CHAR2, // Characteristic discovery 2 BLE_DISC_STATE_CHAR3, // Characteristic discovery 3 BLE_DISC_STATE_CHAR4, // Characteristic discovery 4 BLE_DISC_STATE_CHAR5, // Characteristic discovery 5 BLE_DISC_STATE_CHAR6 // Characteristic discovery 6 }; 默认的特征值状态的宏只有 BLE_DISC_STATE_CHAR,因此在这里修改为 6 个。(具体要看从 机有几个可读特征值) 2、定义一个自己存放特征句柄的数组(sImpleBLECentral.c 中) // Discovered characteristic handle static uint16 simpleBLECharHdl = 0; static uint16 GUA_charHdl[6] = {0}; //6 个特征值句柄保存位置 当 然 也 可以 直 接修 改 为 simpleBLECharHdl[6],但 这 样需 要 修改 代 码中 其 他用 到 simpleBLECharHdl 的地方。 为了省事,很懒的我自己定义一个 GUA_charHdl[6]。 简单粗暴学蓝牙 4.0(CC2541 篇) 3、修改发现事件的处理函数 simpleBLEGATTDiscoveryEvent(sImpleBLECentral.c 中) /********************************************************************* * @fn simpleBLEGATTDiscoveryEvent * * @brief Process GATT discovery event * * @return none */ static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg ) { attReadByTypeReq_t req; if ( simpleBLEDiscState == BLE_DISC_STATE_SVC ) { // Service found, store handles if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->msg.findByTypeValueRsp.numInfo > 0 ) { simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle; simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle; } // If procedure complete if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->hdr.status == bleProcedureComplete ) || ( pMsg->method == ATT_ERROR_RSP ) ) { if ( simpleBLESvcStartHdl != 0 ) { // Discover characteristic simpleBLEDiscState = BLE_DISC_STATE_CHAR1; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } } 第 249 页 简单粗暴学蓝牙 4.0(CC2541 篇) else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR1 ) //发现 char1 { //读出 char1 的 handle 并保存到 GUA_charHdl if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[0] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); simpleBLEProcedureInProgress = TRUE; //此时仍在进程中 } //发送命令读取下一个特征值的句柄 else{ //注意这里一定要 else,当 numPairs=0 时才能再读下一个,下同 simpleBLEDiscState = BLE_DISC_STATE_CHAR2; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR2_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR2_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR2 ) //发现 char2 { //读出 char2 的 handle 并保存到 GUA_charHdl if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[1] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); simpleBLEProcedureInProgress = TRUE; //此时仍在进程中 } 第 250 页 简单粗暴学蓝牙 4.0(CC2541 篇) //发送命令读取下一个特征值的句柄 else{ simpleBLEDiscState = BLE_DISC_STATE_CHAR4; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR4_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR4_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } /* else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR3 ) //发现 char3 { //读出 char3 的 handle 并保存到 GUA_charHdl if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[2] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); simpleBLEProcedureInProgress = TRUE; //此时仍在进程中 } //发送命令读取下一个特征值的句柄 else{ simpleBLEDiscState = BLE_DISC_STATE_CHAR4; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR4_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR4_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } */ 第 251 页 简单粗暴学蓝牙 4.0(CC2541 篇) else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR4 ) //发现 char4 { //读出 char3 的 handle 并保存到 GUA_charHdl if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[3] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); simpleBLEProcedureInProgress = TRUE; //此时仍在进程中 } //发送命令读取下一个特征值的句柄 else{ simpleBLEDiscState = BLE_DISC_STATE_CHAR6; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR6_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR6_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } /* else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR5 ) //发现 char5 { //读出 char3 的 handle 并保存到 GUA_charHdl if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[4] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); simpleBLEProcedureInProgress = TRUE; //此时仍在进程中 } //发送命令读取下一个特征值的句柄 else{ 第 252 页 简单粗暴学蓝牙 4.0(CC2541 篇) 第 253 页 simpleBLEDiscState = BLE_DISC_STATE_CHAR6; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR6_UUID); req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR6_UUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } */ else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR6 ) //发现 char6 { // Characteristic found, store handle if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { GUA_charHdl[5] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); LCD_WRITE_STRING( "Char5 Found", HAL_LCD_LINE_6 ); simpleBLEProcedureInProgress = FALSE; //注意最后一个特征值时需要赋 值 } simpleBLEDiscState = BLE_DISC_STATE_IDLE; //读完最后的 char6,就可以返 回闲置模式了 } } 注意: 1)主机端只能获得“特征值属性为读、通知,并且属性表中为可读”的特征值句柄。 说的通俗一点,就是特征值的属性要为 GATT_PROP_READ 或 GATT_PROP_NOTIFY,且属性表中 对应的值的属性要为 GATT_PERMIT_READ,主机端才能获取到它的特征值句柄。 例子一: SimpleBLEPeripheral 工程的 char1 的属性是可读可写(满足条件) // Simple Profile Characteristic 1 Properties static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE; 简单粗暴学蓝牙 4.0(CC2541 篇) 属性表中的属性是 GATT_PERMIT_READ(满足条件) // Characteristic Value 1 { { ATT_BT_UUID_SIZE, simpleProfilechar1UUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, &simpleProfileChar1 }, 因此,主机端可获取到同时满足两个条件的 char1 的特征值句柄。 例子二: SimpleBLEPeripheral 工程的 char3 的属性是可写,不可读(不满足条件) // Simple Profile Characteristic 3 Properties static uint8 simpleProfileChar3Props = GATT_PROP_WRITE; 并且属性表中的属性也是 GATT_PERMIT_WRITE(不满足条件) // Characteristic Value 3 { { ATT_BT_UUID_SIZE, simpleProfilechar3UUID }, GATT_PERMIT_WRITE, 0, &simpleProfileChar3 }, 因此,主机端不能获取 char3 的特征值句柄。(如果想获取,需要 char3 修改为 GATT_PROP_READ 和 GATT_PERMIT_READ) 例子三: SimpleBLEPeripheral 工程的 char4 的属性是通知(满足条件) // Simple Profile Characteristic 4 Properties static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY; 但是属性表中的属性是 0,即不可读不可写(不满足条件) // Characteristic Value 4 { { ATT_BT_UUID_SIZE, simpleProfilechar4UUID }, 0, 0, &simpleProfileChar4 }, 因此,主机端不能获取 char4 的特征值句柄。(如果想获取,需要 char4 的属性表修改为 GATT_PERMIT_READ) 2)连续读取特征值句柄时,如果中间某个特征值句柄读取失败,则会导致后续的特征值也 读取不到。 3)char5 的属性表的值的属性是 GATT_PERMIT_AUTHEN_READ,是加密的,需要主机端输入密 第 254 页 简单粗暴学蓝牙 4.0(CC2541 篇) 第 255 页 码后方可读取。

浙公网安备 33010602011771号