关于simpleGATTprofile的Characteristic
simpleGATTprofile中有5个Characteristic,第4个需要启用通知才能收到,在simpleBLECentral工程中,当启用通知后,是在哪里收到数据?
求各位大神指教。
Hi x,
如果你看simpleBLECentral.c 这个文件, 里面有个函数:simpleBLECentralProcessGATTMsg()
这个函数就是处理各种从peripheral过来的数据.
但是在示例代码中并没有加入通知, 就是notification的接收, 所以你得自己添加代码.
很简单, 类似 if ( ( pMsg->method == ATT_READ_RSP ) || ........), 你添加 else if ( ( pMsg->method == ATT_HANDLE_VALUE_NOTI ) ||......)
使能通知是向handle为0x002f写入0x0001
gattPrepareWriteReq_t req;
req.handle = 0x002f;
req.len = 2;
req.pValue[0] = 0x00;
req.pValue[1] = 0x01;
req.offset = 0;
GATT_WriteLongCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
但还是无法收到?
Hi x,
首先请确定你找的handle是正确的. 这个handle应该是相应的characteristic value的handle的后面一个, 就是characteristic valude的handle加 1 .
另外, 你的 req.pValue 填错了, 上下两个请反一下.
最后, 这里不要用write long, 用一般的写就行, 就两个字节的内容.
下面是个例子:
attWriteReq_t writeReq;
writeReq.handle = 0x002f;
writeReq.len = 2;
writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x01
writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x00
writeReq.sig = 0;
writeReq.cmd = 0;
GATT_WriteCharValue( simpleBLEConnHandle, &writeReq, simpleBLETaskId );
Hi Yan,
notification发送和接收都是在第四通道channel 4吗?
在simpleBLEcenter例子程序里有个按键触发读写的代码:
// Do a read or write as long as no other read or write is in progress
if ( simpleBLEDoWrite )
{
// Do a write
attWriteReq_t req;
req.handle = simpleBLECharHdl;
req.len = 1;
req.value[0] = simpleBLECharVal;
req.sig = 0;
req.cmd = 0;
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
simpleBLECharHdl 应该是第一通道 channel 1的句柄吧。
req.value[0] = simpleBLECharVal应该是要发送的值。
跟踪发现句柄获得,其中句柄simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
那我该如何获得第四通道数据的句柄?
还有你上面notification的例子怎么是
writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x01
writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x00
notification的要发送的值写在哪里呢?比如我要发送一个数值0xFF,我该怎么用notification发送?
谢谢!
Hi xie,
你说的channel是什么? 第四个channel说的是第四个characteristic?
simpleBLECharHdl这里必须是你对应的characteristic的CCC的那个句柄. CCC指的是Client Characteristic Configuration 的这个descriptor.
CCC句柄一般是在characteristic value的句柄后面.
句柄的顺序是characteristic declaration, characteristic value, 然后是 CCC.
你这个0xFF的value就填写在simpleBLECharVal里面啊.
Hi Yan,
我还是不懂,我说的channel是指
// Profile Parameters
#define SIMPLEPROFILE_CHAR1 0 // RW uint8 - Profile Characteristic 1 value
#define SIMPLEPROFILE_CHAR2 1 // RW uint8 - Profile Characteristic 2 value
#define SIMPLEPROFILE_CHAR3 2 // RW uint8 - Profile Characteristic 3 value
#define SIMPLEPROFILE_CHAR4 3 // RW uint8 - Profile Characteristic 4 value
#define SIMPLEPROFILE_CHAR5 4 // RW uint8 - Profile Characteristic 4 value
第四个SIMPLEPROFILE_CHAR4 是GATT profile的第四个值,他是一个可以通过通知发送给GATT客户端设备。
在simpleBLEcenter例子程序中有一段按键读写第一个SIMPLEPROFILE_CHAR1的值的代码,如下:
// Do a read or write as long as no other read or write is in progress
if ( simpleBLEDoWrite )
{
// Do a write
attWriteReq_t req;
req.handle = simpleBLECharHdl;
req.len = 1;
req.value[0] = simpleBLECharVal;
req.sig = 0;
req.cmd = 0;
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
else
{
// Do a read
attReadReq_t req;
req.handle = simpleBLECharHdl;
status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
这段代码很好理解,SIMPLEPROFILE_CHAR1的句柄和value值都在代码中体现了。
但是notification的代码我就很难理解,句柄和value值还有0x01和0x00(
writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x01
writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x00
)
不明白什么意思。
writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x01
writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY); 这里是 0x00
我之前解释可能有误, 没给你讲清楚.
这两个值目的是打开Notification功能. CCC的参数有两个, 一个Notification, 一个indication. value[0]就是打开关闭notification, value[1]是打开关闭indication.
至于接下来notification发的值是什么, 其实就是对应的characteristic value.
你有空最好去看一下协议栈对spec的定义, 我这样告诉你也只是很少的比较片面的协议栈定义里面的一些内容, 如果你要更好地理解, 最好去看一下spec.
你也可以看上面的教学视频, 也可以看上面的深度培训文档,
最好是可以去blueooth sig 官网上下载spec:
https://www.bluetooth.org/en-us/specification/adopted-specifications
其中第三章 volume 3 Core System Package 里面的 part G: GENERIC ATTRIBUTE PROFILE (GATT) 里面的第三章 3 SERVICE INTEROPERABILITY REQUIREMENTS, 这里面有很详细的介绍 service, characteristic 定义的内容.
里面的 3.3.3.3, 就是Client Characteristic Configuration
好的,非常感谢!
我还想问一下,simpleBLEcenter例子程序中,有个simpleBLECharHdl 句柄的获得,这个句柄应该是SIMPLEPROFILE_CHAR1的句柄吧
simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
这段什么意思呢?dataList[0],dataList[1]代表什么?假如我想获得其他SIMPLEPROFILE_CHAR的句柄该如何获得呢?比如SIMPLEPROFILE_CHAR2、SIMPLEPROFILE_CHAR3等。
谢谢!
是的.
如果你仔细看代码, 就应该不难看出, 这里有个状态机.
前面的状态里面的代码:
req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId );
就是用来查找SIMPLEPROFILE_CHAR1的句柄的.
你贴的代码就是状态机进入到找到这个句柄后的状态.
dagaList, 你如果也仔细看代码的话, 这个就是peripheral那边回复过来的具体数据, 这里就是句柄.
如果你要查找SIMPLEPROFILE_CHAR2,或者SIMPLEPROFILE_CHAR3, 你可以简单替换掉前面状态机里面(就是我上面贴的代码)的查找参数.
更好的方法是你在原先的状态机里面多添加几个状态, 在查找玩CHAR1之后添加查找CHAR2, CHAR3, 等等. 也很方便, 不难.
在收到CHAR1的handle后立刻查找其他特征值的handle,会找不到
else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )
{
。。。
//simpleBLEDiscState = BLE_DISC_STATE_IDLE;
接着查找
if ( simpleBLESvcStartHdl != 0 )
{
// Discover characteristic 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 );
LCD_WRITE_STRING( "Finding", HAL_LCD_LINE_1 );
}
}
else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR6 )
{
// Characteristic found, store handle
if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 )
{
simpleBLECharHd6 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
LCD_WRITE_STRING( "CHAR6 Found", HAL_LCD_LINE_1 );
}
simpleBLEDiscState = BLE_DISC_STATE_IDLE;
}
如果不马上查找就可以,请问是哪里有问题?
在没有收到上一个查找请求的回复之前, 再次发送查找命令, 协议栈规定不予理睬.
这是个顺序执行的过程.
Hi Yan,
你的意思是查找多个句柄的时候,应该收到上一个查找请求的回复之后才能再次发送查找命令吗?在例程中,查找请求回复是在哪个地方?能不能给我讲解一下查找多个句柄时的完整流程是怎么样的?
谢谢!
Hi lv,
你说:“在收到CHAR1的handle后立刻查找其他特征值的handle,会找不到;如果不马上查找就可以”。当我发现CHAR1的句柄之后再查找其他特征值,该如何做?接下来该怎么样再次发送查找句柄命令(函数)?
谢谢!
Hi Yan,
我尝试了几次,然后用这种方法再次查找,终于发现了CHAR4的句柄,如下红色部分:
static void simpleBLECentralProcessGATTMsg( gattMsgEvent_t *pMsg )
{
……
else if ( simpleBLEDiscState != BLE_DISC_STATE_IDLE )
{
simpleBLEGATTDiscoveryEvent( pMsg );
/*=====================================================*/
simpleBLEGATTDiscoveryEvent( pMsg ); //再次执行
/*=====================================================*/
}
}
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_CHAR;
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 );
}
}
}
else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )
{
// Characteristic found, store handle
if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0 )
{
simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 );
//simpleBLEProcedureInProgress = FALSE;
}
// simpleBLEDiscState = BLE_DISC_STATE_IDLE;
//}
/*================================================================================*/
if ( simpleBLESvcStartHdl != 0 )
{
// Discover characteristic
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_CHAR4 )
{
// Characteristic found, store handle
if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0 )
{
simpleBLECharHd4 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 );
simpleBLEProcedureInProgress = FALSE;
}
simpleBLEDiscState = BLE_DISC_STATE_IDLE;
}
/*================================================================================*/
}
在线调试可以看到CHAR4的句柄:simpleBLECharHd4 =0x0025;
但是我感觉这样写的程序比较纠结、不顺眼,如下:
else if ( simpleBLEDiscState != BLE_DISC_STATE_IDLE )
{
simpleBLEGATTDiscoveryEvent( pMsg );
/*=====================================================*/
simpleBLEGATTDiscoveryEvent( pMsg ); //再次执行
/*=====================================================*/
}
执行一次,再执行一次一样的函数,感觉非常的2,还有没有更好的方法?
谢谢!
Hi Yan:
请问在Central程序中,第四个Characteristic是在哪里启动的呢?我GATT_notification()==success;成立的是不是代表底层通讯已经成功了?需要做的就是主机端的数据读取。
兄弟,你太厉害了。我都调了好长时间都没找到CHAR4的句柄。
你确定你或的这个句柄对吗?我感觉获得的这个句柄还是CHAR1的句柄吧
好像还真是,晕。不知道怎么弄,你调出来了吗?
我是哪里出了问题呢?明明用的是CHAR4的UUID。怎么变成CHAR1的句柄呢?
没有,我以为你调出来了呢,然后我也试了以下,发现得到的不是CHAR4的句柄,还是CHAR1的句柄。
我看不懂TI工程师说的那个状态机。
我也是看的一头雾水。我猜我那代码应该是接着发现特征值时,函数调用出问题了,调用早了,里面存的还是CHAR1的句柄,没等发现CHAR4的句柄。
其实咱俩的问题是同一个问题。就是能不能同时获得Peripheral提供的5个CHAR的句柄。只有的得到这些句柄,Central和Peripheral才能更方便地相互传递数据。
Hi Yan,
关于CHAR4句柄获得问题,我将例程中static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )函数中的SIMPLEPROFILE_CHAR1_UUID替换为SIMPLEPROFILE_CHAR4_UUID,但是下载到开发板上,设备根本无法发现服务,无法获得CHAR4的UUID. 问题出在哪呢?代码如下,红色部分是被我修改的地方。
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_CHAR;
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);
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_CHAR )
{
// Characteristic found, store handle
if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0 )
{
/*simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );*/
simpleBLECharHd4 = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],
pMsg->msg.readByTypeRsp.dataList[1] );
LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 );
simpleBLEProcedureInProgress = FALSE;
}
simpleBLEDiscState = BLE_DISC_STATE_IDLE;
}
}
经过实验:
SIMPLEPROFILE_CHAR3_UUID,
SIMPLEPROFILE_CHAR4_UUID,
SIMPLEPROFILE_CHAR5_UUID.
这三个UUID的句柄都无法被单独发现。只有SIMPLEPROFILE_CHAR1_UUID和SIMPLEPROFILE_CHAR2_UUID可以。
Hi xie,
不好意思, 要读这几个char 还有几个地方要改.
GATT_ReadUsingCharUUID() 需要read 属性支持. 加上read
// Simple Profile Characteristic 3 Properties
static uint8 simpleProfileChar3Props = GATT_PROP_WRITE; //只有write, 没有read
// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY; //只有notiry, 没有read
char 5 则是因为被定义为 需要鉴权参能读它
// Characteristic Value 5
{
{ ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
GATT_PERMIT_AUTHEN_READ,
0,
simpleProfileChar5
},
Hi Yan,
我这几天想了一下,也猜到是这个原因。但是我想问:像notification的句柄该如何去发现呢,因为当我们要使能notification的时候必须先知道它的句柄啊。
Hi xie,
每个service 都有个表格, 以simpleBLEPripheral 为例, 有 simpleProfileAttrTbl[], 是个数组.
以其中的char4 为例, 你可以用类似 simpleProfileAttrTbl[ char4_val_idx ]. handle 来得到hanle 的值. char4_val_idx 你可以在表格里面数一下, 就是attribute 在表格中的位置.
Hi Yan,
我发现这个simpleProfileAttrTbl[]数组只在simpleBLEPeripheral例程中有定义。那么当我们在simpleBLEcenter里要用到CHAR4的句柄时,我们是不是只能间接获得CHAR4的句柄?比如在线调试simpleBLEPeripheral程序在IAR里面通过 simpleProfileAttrTbl[ char4_val_idx ]. handle 来得到hanle 的值,或者通过BTool获得CHAR4的句柄,然后再用到simpleBLEcenter程序中使能notification吗?
Hi,
我如何才能找到正确的handle,本人刚接触BLE不久。
请问各种消息响应从peripheral传过来后就直接调用simpleBLECentralProcessGATTMsg()函数么?还是要在Central中写入请求
HI ,前面的大神, 请问你们有调通notification吗?
我当前是在central端的simpleBLECentralProcessGATTMsg函数中写了关于notification的处理,但是从消息获取的method是response error
请大神们指点下
感觉怪怪的,怎么你的char4 的句柄跟char1 的一样啊
我的char4一直没找到,按照你的方法找出来的是
0x0025
但我一执行一次查找Char 1 和char 2
Char1 Handler 0x0025
Char2 Handler 0x0028
哦哦,没看后面的,感谢了,对上面哪位兄弟说声抱歉了,我没看后面的帖子。不好意思了
Hi Yan
恕我愚笨,我在simpleBLEGATTDiscoveryEvent用以下程序获得Char4的Handler(实际上没反应)
static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg ) { attReadByTypeReq_t req; uint16 IWantSerchUUID=0; /* Serch_CharNum 7 6-0 EnableSerch SercherNum */ switch(Serch_CharNum&0x7f) { case 0 :IWantSerchUUID=SIMPLEPROFILE_CHAR1_UUID; break; case 1 :IWantSerchUUID=SIMPLEPROFILE_CHAR3_UUID; break; default: simpleBLEProcedureInProgress = FALSE; break; } if ( simpleBLEDiscState == BLE_DISC_STATE_SVC ) { if(!(Serch_CharNum&0x80)) { // 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 ) { Serch_CharNum|=0x80; } } if((Serch_CharNum&0x80)) { // Discover characteristic simpleBLEDiscState = BLE_DISC_STATE_CHAR; req.startHandle = simpleBLESvcStartHdl; req.endHandle = simpleBLESvcEndHdl; req.type.len = ATT_BT_UUID_SIZE; req.type.uuid[0] = LO_UINT16(IWantSerchUUID); req.type.uuid[1] = HI_UINT16(IWantSerchUUID); GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId ); } } else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR ) { // Characteristic found, store handle if ( pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0 ) { simpleBLECharHdl[(Serch_CharNum&0x7f)] = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0], pMsg->msg.readByTypeRsp.dataList[1] ); //simpleBLEProcedureInProgress = TRUE; Serch_CharNum++; simpleBLEDiscState=BLE_DISC_STATE_SVC; }else if((pMsg->method == ATT_ERROR_RSP)) { SerialPrintString("Not Find The Handle"); SerialPrintValue("Read Error", pMsg->msg.errorRsp.errCode, 10);SerialPrintString("\r\n"); simpleBLEDiscState = BLE_DISC_STATE_IDLE; } } if(simpleBLEProcedureInProgress == FALSE ) { SerialPrintValue("simpleBLECharHdl[0]:",simpleBLECharHdl[0],16); SerialPrintString("\r\n"); SerialPrintValue("simpleBLECharHdl[1]:",simpleBLECharHdl[1],16); SerialPrintString("\r\n"); SerialPrintString("Simple Svc Found\r\n"); } }
但现在还是读不到Handle啊
读 Char2的还是找得到
相应的characteristic value的handle,这个handle怎样确定?
哥们,你已经可以读连续两个handle了?
没有,我刚接触,不是很了解,为什么要读取handle?为了主从机之间的通信?
那你可以先看下TI官网的资料,https://www.bluetooth.org/en-us/specification/adopted-specifications
里面对profile的定义啊 挺详细的
对,我的目的就是读两个handler,方便对比,但现在差不多解决了
首先是从机里面就先定义好了读写的规范,
然后如果能读写,读写的服务程序也必不可少,
我之前吧这些属性该了,但没发现自己读写的程序中没读的服务程序
所以才一直没读出来的
工程师,你好!
我按照你的方法, 把 Characteristic 4 添加了读的权限,但是客户端还是读不到句柄,
GATT_PROP_READ 以及GATT_PERMIT_AUTHEN_READ
// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_READ | GATT_PROP_NOTIFY;
你有测试过吗?帮忙指点一下,谢谢
原来我漏掉了一个权限,把这个加上就可以读出CHAR 4的特征值的地址了。
// Characteristic Value 4
{
{ ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE, //本来是0的,自己加上读写权限
0,
&simpleProfileChar4
},
要想读出CHAR 4需要设置两个地方的权限:
1、
// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_READ | GATT_PROP_NOTIFY; //增加GATT_PROP_READ
2、属性表中
// Characteristic Value 4
{
{ ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE, //本来是0的,自己加上读写权限
0,
&simpleProfileChar4
},
论坛给我了指导,也希望能够帮助大家
hi sizao
大神,你是一次性同时获取多个handle吗?在主机里面是调用simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg )这个函数发现handle吗?
你有测试过GATT_DiscCharsByUUID( uint16 connHandle, attReadByTypeReq_t *pReq, uint8 taskId );这个函数吗?
Hi Yan
GATT_WriteCharValue()参数中有个simpleBLEConnHandle,这个参数是simpleBLECentral.c文件中的本文件全局变量,我一直都是不太明白这个参数的含义。谢谢关注。CQ_JIMI
嗨 Yan,首先我是自己建立另外一个特征值char8,长度15;我按着你这个例程对特征值通知开通了,主机中开通通知代码如下
if( keys & HAL_KEY_SW_1 ) { //使能char8通知 attWriteReq_t attReq; uint8 pValue[2]; attReq.handle = 0x0040; //这里我用的是btool软件Read/Write功能发现特征值功能,发现char8的句柄是0x003f,然后handle+1 =0x0040 attReq.len = 2; attReq.sig = 0; attReq.cmd = 0; pValue[0] = LO_UINT16( GATT_CLIENT_CFG_NOTIFY ); //0X01 pValue[1] = HI_UINT16( GATT_CLIENT_CFG_NOTIFY ); //0X00 osal_memcpy( attReq.value, pValue, 2 ); GATT_WriteCharValue( simpleBLEConnHandle, &attReq, simpleBLETaskId ); NPI_WriteTransport( "Notification enabled", osal_strlen("Notification enabled") ); }
但是我并不知道从机是否相应的给我开通了通知;然后我从peripheral串口助手发送一串字符,在串口回调函数中对从串口接收到的数据更新特征值8的值,
从机中串口代码如下
static void NpiSerialCallback(uint8 port ,uint8 events ) { (void)port; uint8 numBytes=0; uint8 buf[128]; if(events & HAL_UART_RX_TIMEOUT) //串口有数据, { numBytes=NPI_RxBufLen(); //读出串口有多少数据 if(numBytes) { if(numBytes >= SIMPLEPROFILE_CHAR8_LEN ) buf[0] = SIMPLEPROFILE_CHAR8_LEN -1; else buf[0] = numBytes; //从串口缓冲区读出nuBytes个字节数据 NPI_ReadTransport( &buf[1], buf[0] ); SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR8, SIMPLEPROFILE_CHAR8_LEN, buf); //把接收到的数据在打印出来 //NPI_WriteTransport(buf,numBytes); } } }
现在的问题是,我从串口发送一串字符过去,主机那边不能进入这个simpleBLECentralProcessGATTMsg消息处理函数中。
其中我对通知的处理代码如下:
else if( pMsg->method == ATT_HANDLE_VALUE_NOTI ) { //串口打印char8通知,由从机通知过来char8的值 if(pMsg->msg.handleValueNoti.handle == 0x003F ) { if( pMsg->msg.handleValueNoti.value[0] >= 15 ) { NPI_WriteTransport( &pMsg->msg.handleValueNoti.value[1], 14 ); NPI_WriteTransport("....\n", 5); } else { NPI_WriteTransport( &pMsg->msg.handleValueNoti.value[1], pMsg->msg.handleValueNoti.value[0] ); } } }
谢谢Yan的关注,我叫CQ_JIMI
你为什么不用attHandleValueNoti_t?
CQ_JIMI
你的问题解决了么? 我现在和你一模一样卡在了这里,无法获得从机的特征值句柄,我跟踪了一下,在CCCD位写入使能01 00 后返回一个0x16的数值,我查了一下,这个数值是 waiting的意思,应该是没有读取到 所以我就不确定自己写入的01 00 是否真的到达了从机。困扰一个星期了,希望你能帮我一下
我是直接从表里读的:pReport.handle = simpleProfileAttrTbl[11].handle;//读取notification对应的handle
你好:
我用GATT_ReadUsingCharUUID获取的conhandle为0x25,是char1的句柄,然后用GATT_ReadCharValue获取特征值,返回值为0x16,让我等待,是不是蓝牙协议的一些流程我不熟悉导致的?
你好:
请问你问题解决了吗?我遇到了