This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC2640:启用 Notify 的请求将发送到..._ValueChangeHandler、原因是什么?

Guru**** 2553360 points
Other Parts Discussed in Thread: CC2640

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/575733/cc2640-requests-to-enable-notify-are-going-to-_valuechangehandler-why

器件型号:CC2640

我有一个以 SimpleLink Academy ProjectZero 开头的项目。

我添加了对外部闪存的访问、并禁用了 OSAL 和 UART 日志记录、以便有空间在 CC2640 128MB 上运行程序。

我删除了 LED 和数据特性、并为按钮特性添加了写入功能、该特性已重命名为 HALO。

当我向 HALO 特征添加了写入功能时、我可能做得不正确、因为 Notify 似乎有时仅起作用、并且当我的 IOS 应用程序请求将 Notify 更改为 Yes 时、 我在 USER_HaloService_ValueChangeHandler 中看到请求,IOS 请求失败,并出现“资源不足”错误。

在 USER_HaloService_ValueChangeHandler 中、将通知更改为是请求显示为"01:00"或0x30 0x31 0x3A 0x00 0x00。  

为什么请求甚至会出现在我的 USER_HaloService_ValueChangeHandler 中、因为它应该被 BLE 2.2.1堆栈截取、不应该出现?

这是我可能犯了错误的 halo_service.c、有人能看到它吗?

/*********
*包括
*/
#include 
#include 

//#define XDC_runtime_Log_disable_all 1 //添加以禁用此文件中的日志
#include 
#include 

#include "bcomdef.h"
#include "OSAL.h"
#include "linkdb.h"
#include "att。h"
#include "gatt_uuid.h"

#include "gattservapp.h"
#include "gapbondmgr.h"


/*********
*宏
*/

*********
*常量
*/


* typedef
*/

/*********
*全局变量
*/

// Halo 服务 UUID
const uint8_t HaloServiceUUID[ATT_UUUUID_SIZE]=
{
HALO_SERVICE_SERV_UID_BASSE128 (HALO_SERVICE_SERV_UUID)
};

// offset
const uint8_OFFSET_UUID_OUTAUID[AM_OUT_TOUCC_UUID]











= OUT_TOOUNT_UID_UTI_AUUID_UTI_AUUTR_AUUID[_UTI_OUT_TR_OUTAUUID]




}*
*局部变量
*/

static HaloServiceCBs_t * pAppCBs = NULL;
static uint8_t bs_iCall_rs_task_id = inval_task_ID;

/*********
*配置文件属性-变量
*//

服务声明
静态 const gattAttrType_t TVoServiceDecl ={ATT_UUUUUART_SIZE、HaloServiceUUID};

//特征"偏移"属性(用于声明)
静态 uint8_t HS_OFFSETProps = GATT_PROP_NOTIFY | GATT_PROP_READ | GATT_OFFSET


=静态 uint8;static_OFFSET_TOP_ENT_PROP_ENTRY_OFFSET ={PROP_TOP_TOP_ENT}/TOP_ENT_PROPHS_W0_OFFSET =静态 uPROP_TOP_ENT = STAT_ENT + TOP_TOP_ENT = OT_OFFSET = TO

//特性"offset"值变量中的数据长度,初始化为最小大小。
静态 uint16_t HS_OFFSETVALLEEN = HS_OFFSET_LEN_MIN;

//特性"偏移"客户端特性配置描述符
静态 gattCharCfg_t * HS_OFFSETConfig;

//特性"偏移"值变量中的数据长度、初始化为最小大小。 //dale5
静态 uint16_t hs_OFFSETVallen = HS_OFFSET_LEN_MIN;//dale5




//特征"ONOFFREC"属性(用于声明)
静态 uint8_t HS_ONOFFSETProps = GATT_PROP_RECODED | GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROOFFREC




= TOP_REC = TOP_REC 0 = INT_PROONOFFREC = TOP_REC 0;已初始化的静态值/ INT_PROONOFFREC = TO_PROT_REC = TOOT_PROT_REC 0 = TOP_REC 0 = TOOTGALL_REC 0 = TOOT_PROONOFFREC = TOOT_PROT_REC 0 = TOOTGAL_RET = TOOT
静态 uint16_t HS_ONOFFRECVALLEEN = HS_ONOFFREC_LEN_MIN;

//特性"ONOFFREC"客户端特性配置描述符
静态 gattCharCfg_t * HS_ONOFFRECConfig;

//特性"ONOFFREC"值变量中的数据长度,初始化为最小大小。 //dale5
静态 uint16_t hs_ONOFFRECVALLEEN = HS_ONOFFREC_LEN_MIN;//dale5


//特征"TOTALTIME"属性(用于声明)
静态 uint8_t HS_TOTALTIMEProps = GATT_PROP_NOTIFY | GATT_PROTIME"特性"TOTACT_PROTIME"值(用于声明);已




将 TOTALT_PROTIMER 值添加到"TOTACT_PROTIME_TOPRECT_PRECT_PRECT_PRECT_PRECT_PRECT_PRECT_PRECT_PRECT_PRECT_RELE/TOTALYEST_PRECT_PRECT_PRECT_PRECT_PRIMEND 中";
静态 uint16_t HS_TOTALTIMEValLen = HS_TOTALTIME_LEN_MIN;

//特性"TOTALTIME"客户端特性配置描述符
静态 gattCharCfg_t * HS_TOTALTIMEConfig;

//特性"TOTALTIME"值变量中的数据长度,初始化为最小大小。 //dle5
静态 uint16_t hs_TOTALTIMEVallen = HS_TOTALTIM_LEN_min;//dle5

/*********
*配置文件属性-表
*/

静态 gattAttribute_t HALO_ServiceAttrTbl[]=
{
// Halo 服务声明
{
{ATT_BT_UUID_SIZE、primServiceUUID}、
GATT_permit_read、
0、
(uint8_t *)&HaloServiceDecl
}、

//偏移特征声明
{
{ATT_BT_UUUART_SIZE、characterUUID}、
GATT_permit_read、
0、
HS_OFFSETProps
}、
//偏移特性值
{
{ATT_UUUID_SIZE、HS_OFFSETUUID}、
GATT_permit_read | GATT_permit_write、//Dale add | GATT_permit_write
0、
HS_OFFSETVal
}、
//偏移 CCCD
{
{ATT_BT_UUID_SIZE、clientCharCfgUUID}、
GATT_permit_read | GATT_permit_write、
0、
(uint8_t *)&hs_OFFSETConfig
}、

// ONOFFREC Characteristic Declaration
{
{ATT_BT_UUUART_SIZE、characterUUID}、
GATT_permit_read、
0、
&HS_ONOFFRECProps
}、
// ONOFFREC 特性值
{
{ ATT_UUUUUUUI_SIZE、HS_ONOFFRECUUID }、
GATT_permit_read | GATT_permit_write、//Dale add | GATT_permit_write
0、
HS_ONOFFRECVal
}、
// ONOFFREC CCCD
{
{ATT_BT_UUID_SIZE、clientCharCfgUUID}、
GATT_permit_read | GATT_permit_write、
0、
(uint8_t *)&HS_ONOFFRECConfig
}、

// TOTALTIME 特征声明
{
{ATT_BT_UUUART_SIZE、characterUUID}、
GATT_permit_read、
0、
&HS_TOTALTIMEProps
}、
// TOTALTIME 特性值
{
{ATT_UUUID_SIZE、HS_TOTALTIMEUUID}、
GATT_permit_read | GATT_permit_write、//Dale add | GATT_permit_write
0、
HS_TOTALTIMEVAL
}、
// ONOFFREC CCCD
{
{ATT_BT_UUID_SIZE、clientCharCfgUUID}、
GATT_permit_read | GATT_permit_write、
0、
(uint8_t *)&HS_TOTALTIMEConfig
}、

};

/*********
*本地函数
*/
static bStatus_t Halo_Service_ReadAttrCB (uint16_t connHandle、gattAttribute_t *pAttr、
uint8_t * pValue、uint16_t * PLEN、uint16_t offset、
uint16_t maxLen,uint8_t 方法);
static bStatus_t Halo_Service_WriteAttrCB (uint16_t connHandle,gattAttribute_t *pAttr,
uint8_t *pValue、uint16_t len、uint16_t offset、
uint8_t 方法);

/
*配置文件回调
*//
简单配置文件服务回调
const gattServiceCBs_t HALO_ServiceCBs =
{
HALO_Service_ReadAttrCB、//读取回调函数指针
HALO_Service_WriteAttrCB、//写入回调函数指针
NULL //授权回调函数指针
};

/*********
*公共函数
*/

/*
HaloService_AddService -通过注册
*初始化 HaloService 服务 GATT 属性与 GATT 服务器。
*
* rspTaskId -应接收指示响应的 ICall 任务 ID。
//
extern bStatus_t HaloService_AddService (uint8_t rspTaskId)
{
uint8_t status;

//分配客户端特征配置表
HS_OFFSETConfig =(gattCharCfg_t *) iCall_malloc (sizeof (gattCharCnL_t)* linkDBNumConns);
if =
(nL_FFHs)
return (bleMemAllocError);
}
//初始化客户端特征配置属性
GATTServApp_InitCharCfg (invalid_CONNNANDLE、HS_OFFSETConfig);




//分配客户端特征配置表
HS_ONOFFRECConfig =(gattCharCfg_t *) iCall_malloc (sizeof (g_OFFSETConfig
);
//分配客户端特征配置表 HS_ONCONFFRECConfig =(g_NULT_N))=(nLONNULL_NULT_N));(如果为 NULT_NFFCONN),则为 NFF
return (bleMemAllocError);
}
//初始化客户端特征配置属性
GATTServApp_InitCharCfg (invalid_CONNNANDLE、HS_ONOFFRECConfig);




//分配客户端特征配置表
HS_TOTALTIMEConfig =(GattCharCfg_t *)iCall_malloc (sizeof (
NULL)=(TOTALTECONN)=);{_TALCONN = NOT_TAMNULT_TAGNOT_NON_NOTECONTOCONNECT_NULESHOLD=(*)

return (bleMemAllocError);
}
//初始化客户端特征配置属性
GATTServApp_InitCharCfg (INVALID_CONNANDLE、HS_TOTALTIMEConfig);




//使用 GATT 服务器应用
程序状态注册 GATT 属性列表和 CBS = GATTServApp_RegisterService (Halo_ServiceAttrTbl、
GATT_NUM_ATTRS (HALO_ServiceAttrTbl),
GATT_MAX_encrypt_key_size、
&HALO_ServiceCBs );
Log_Info1 (“注册的服务,%d 属性”,(IARg) GATT_NUM_ATTRS (Halo_ServiceAttrTbl);
BS_iCall_rs_task_id = rspTaskId;

返回(状态);
}//*


HaloService_RegisterAppCBs -注册应用程序回调函数。
* 只调用此函数一次。
*
* appCallback -指向应用程序回调的指针。
//
bStatus_t HaloService_RegisterAppCBs (HaloServiceCBs_t *appCallback)
{
if (appCallback)
{
pAppCBs = appCallback;
log_info1 ("注册回调到应用程序。 struct %p"、(IArg) appCallbacks);
返回(成功);
}
否则
{
log_warning0 ("为应用程序回调指定的空指针。");
返回(失败);
}
//*


HaloService_SetParameter -设置 HaloService 参数。
*
* param -配置文件参数 ID
* len -要写入的数据长度
* value -要写入的数据的指针。 这取决于
* 参数 ID 和可被转换为相应
的* 数据类型(例如:uint16_t 的数据类型将转换为
* uint16_t 指针)。
//
bStatus_t HaloService_SetParameter (uint8_t param、uint16_t len、void *值)
{
bStatus_t ret = Success;
uint8_t * pAttrVal;
uint16_t * pValLen;
uint16_t valMinLen;
uint16_t MaxvalLen;
uint8_t sendNotiInd = false;
gattCharCfg_t * attrConfig;
uint8_t needAuth;

switch (param)
{
案例 HS_OFFSET_ID:
pAttrVal = HS_OFFSETVal;
pValLen =&HS_OFFSETValLen;
valMinLen = HS_OFFSET_LEN_MIN;
valMaxLen = HS_OFFSET_LEN;
sendNotitiInd = true;
attrConfig = HS_OFFSETConfig;
needAuth = false;//如果发送需要经过身份验证的链接,则更改。
log_info2 ("SetParameter:%s len:%d"、(IArg)"offset"、(IArg) len);
中断;

案例 HS_ONOFFREC_ID:
pAttrVal = HS_ONOFFRECVal;
pValLen =&HS_ONOFFRECValLen;
valMinLen = HS_ONOFFREC_LEN_MIN;
valMaxLen = HS_ONOFFREC_LEN;
sendNotitiInd = true;
attrConfig = HS_ONOFFRECConfig;
needAuth = false;//如果发送需要经过身份验证的链接,则更改。
log_info2 ("SetParameter:%s len:%d"、(IArg)"ONOFFREC"、(IArg) len);
中断;

案例 HS_TOTALTIME_ID:
pAttrVal = HS_TOTALTIMEVAL;
pValLen =&HS_TOTALTIMEValLen;
valMinLen = HS_TOTALTIME_LEN_MIN;
valMaxLen = HS_TOTALTIME_LEN;
sendNotitiInd = true;
attrConfig = HS_TOTALTIMEConfig;
needAuth = false;//如果发送需要经过身份验证的链接,则更改。
log_info2 ("SetParameter:%s len:%d"、(IArg)"TOTALTIME"、(IArg) len);
中断;

默认值:
log_error1 ("SetParameter:参数#%d 无效。"、(IArg)param);
返回 INVALIDPARAMETER;
}

//检查边界、更新值并发送通知或指示(如果可能)。
如果( len <= valMaxLen && len >= valMinLen ){

memcpy (pAttrVal、value、len);
*pVallen = len;//更新读取和获取的长度。

IF (sendNotitiInd)
{
log_info2 ("正在尝试发送通知/提示:connHandle %x、%s"、
(IArg) attrConfig[0]。connHandle、
(IARg)((attrConfig[0].value==0)?"\x1b[33mNoti/ind disabled \x1b[0m":
(attrConfig[0].value==1)?"通知已启用":
"指示已启用");
//尝试发送通知。
GATTServApp_ProcessCharCfg (atConfig、pAttrVal、needAuth、
HALO_ServiceAttrTbl、GATT_NUM_ATTRS (Halo_ServiceAttrTbl)、
BS_iCall_rs_task_id、HALO_Service_ReadAttrCB);
}
}
否则
{
log_error3 ("边界外的长度:len:%d minlen:%d maxLen:%d."、(IArg) len、(IArg) valMinLen、(IArg) valMaxLen;
RET = bleInvalidRange;
}

return;
}


//
* HaloService_GetParameter -获取 HaloService 参数。
*
* param -配置文件参数 ID
* len -指向包含可写入*值的最大长度的变量的指针。
调用后、该值将包含实际返回的长度。
* value -指向要写入的数据的指针。 这取决于
* 参数 ID 和可被转换为相应
的* 数据类型(例如:uint16_t 的数据类型将转换为
* uint16_t 指针)。
//
bStatus_t HaloService_GetParameter (uint8_t param、uint16_t * len、void * value)
{
bStatus_t ret = Success;
switch (param)
{
默认值:
log_error1 ("GetParameter:参数#%d 无效。"、(IArg)param);
RET = INVALIDPARAMETER;
中断;
}
返回;
}

/*********
*@内部
*@fn HALO_Service_findCharParamId
*
*@简介 在服务的 attr 表中查找属性的逻辑参数 ID。
*
* 仅适用于特征值属性和
* 客户端特征配置描述符属性。
*
*@param pAttr -指向属性
*
*@return 的指针 uint8_t paramID (参考 HALO_SERVICE.h)或0xFF (如果未找到)。
*/
static uint8_t HALO_Service_findCharParamId (gattAttribute_t *pAttr)
{
//这是一个客户端特征配置描述符吗?
if (ATT_BT_UUID_SIZE = pAttr->type.len & GATT_CLIENT_CHAR_CFG_UUID =*(uint16_t *) pAttr->type.uuid)
返回 HALL_Service_findCharParamId (pAttr - 1);//假设 value 属性在 CCCD 和递归之前

//此属性是否在"offset"中?
如果(ATT _ UUID_SIZE =pAttr->type.len &&!memcmp (pAttr->type.uuid、HS_OFFSETUUID、pAttr->type.len))则为其他值
返回 HS_OFFSET_ID;

//此属性是否位于"ONOFFREC"中?
如果(ATT _ UUID_size =pAttr->type.len &&!memcmp (pAttr->type.uuid、HS_ONOFFRECUUID、pAttr->type.len))则为其他值
返回 HS_ONOFFREC_ID;

//此属性是否在"TOTALTIME 中?
如果(ATT _ UUID_SIZE =pAttr->type.len &&!memcmp (pAttr->type.uuid、HS_TOTALTIMEUUID、pAttr->type.len))则为其他值
返回 HS_TOTALTIME_ID;

否则
返回0xFF;//未找到。 返回无效。
}


/*********
*@fn HALO_Service_ReadAttrCB
*
*@简介 读取属性。
*
*@param connHandle -在
*@param 上接收到连接消息 pAttr -指向属性
*@param 的指针 pValue -指向要读取的数据的指针
*@param PLEN -要读取的数据长度
*@param offset -要读取的第一个八位位组的偏移
*@param maxLen -要读取的数据的最大长度
*@param 方法-读取消息的类型
*
*@return 成功、blePending 或失败
*/
static bStatus_t Halo_Service_ReadAttrCB (uint16_t connHandle、gattAttribute_t *pAttr、
uint8_t * pValue、uint16_t * PLEN、uint16_t offset、
uint16_t maxLen、uint8_t method)
{
bStatus_t status = Success;
uint16_t valueLen;
uint8_t paramID = 0xFF;

//查找要读取的特征的设置。
paramID = HALO_Service_findCharParamId( pAttr );
switch ( paramID )
{
案例 HS_OFFSET_ID:
valueLen = HS_OFFSETValLen;

log_info4 ("ReadAttrCB:%s connHandle:%d offset:%d method:0x%02x"、
(IArg)"偏移"、
(IArg) connHandle、
(IArg)偏移、
(IArg)方法);
/*可以在此处插入有关偏移的其他注意事项*/
中断;

案例 HS_ONOFFREC_ID:
valueLen = HS_ONOFFRECValLen;

log_info4 ("ReadAttrCB:%s connHandle:%d offset:%d method:0x%02x"、
(IARg)"ONOFFREC"、
(IArg) connHandle、
(IArg)偏移、
(IArg)方法);
//此处可插入有关 ONOFFREC 的其他注意事项*/
中断;

案例 HS_TOTALTIME_ID:
valueLen = HS_TOTALTIMEValLen;

log_info4 ("ReadAttrCB:%s connHandle:%d offset:%d method:0x%02x"、
(IArg)"TOTALTIME (TOTALTIME)"、
(IArg) connHandle、
(IArg)偏移、
(IArg)方法);
//此处可插入 TOTALTIME 的其他注意事项*/
中断;

默认值:
log_error0 ("未找到属性。");
返回 ATT_ERR_ATTR_NOT FOUND;
}
//检查边界并返回值
,如果(offset > valueLen)//防止恶意的 ATT ReadBlob 偏移。
{
log_error0 ("请求的偏移无效。");
状态= ATT_ERR_INVALID_OFFSET;
}
否则
{
* PLEN = min (maxLen、valueLen - offset);//尽可能发送
memcpy (pValue、pAttr->pValue + offset、* PLEN);
}

返回状态;
}




/*********
*@fn HALO_Service_WriteAttrCB
*
@简要在写入操作之前验证属性数据
*
*@param connHandle -在
*@param pAttr 上接收到连接消息-指向属性的指针
*@param pValue -指向要写入的数据的指针
*@param len -数据长度
*@param offset - 要写入的第一个八位位组的偏移
*@param 方法-写入消息类型
*
*@返回成功、blePending 或失败
*/
static bStatus_t Halo_Service_WriteAttrCB (uint16_t connHandle、gattAttribute_t *pAttr、
uint8_t *pValue、uint16_t len、uint16_t offset、
uint8_t 方法)
{



bStatus_t status =成功;
uint8_t paramID = 0xFF;
uint8_t changeParamID = 0xFF;
uint16_t writeLenMin;
uint16_t writeLenMax;
uint16_t *pValueLenVar;

//查看请求是否与客户机特性配置有关//dle5 ????? 不是
if (ATT_BT_UUID_SIZE = pAttr->type.len & GATT_CLIENT_CHAR_CFG_UUID =*(uint16_t *) pAttr->type.uuid)
{
log_info3 ("WriteAttrCB (CCCD):参数:%d connHandle:%d %s"、
(IArg) HALO_Service_findCharParamId (pAttr)、
(IArg) connHandle、
(IArg)(方法= GATT_LOCAL_WRITE?"-恢复绑定状态":"- OTA 写入");

//允许通知和指示,但不要检查每个 CCCD 是否真正允许。
状态= GATTServApp_ProcessCCCWriteReq (connHandle、pAttr、pValue、len、
偏移量、GATT_CLIENT_CFG_NOTIFY |
GATT_CLIENT_CFG_Indicate);
if (成功=status && pAppCBs && pAppCBs->pfnCfgChangeCb)
pAppCBs->pfnCfgChangeCb (connHandle、HALO_SERVICE_SERV_UUID、
HALO_Service_findCharParamId (pAttr)、pValue、len);
//return status;//Dale removed
}

//dle5 start:添加了写入部分
//查找要写入的特征的设置。
paramID = HALO_Service_findCharParamId( pAttr );
switch ( paramID )
{
案例 HS_OFFSET_ID:
writeLenMin = HS_OFFSET_LEN_MIN;
writeLenMax = HS_OFFSET_LEN;
pValueLenVar =&hs_OFFSETValLen;

log_info5 ("WriteAttrCB:%s connHandle (%d) len (%d) offset (%d) method (0x%02x)"、
(IArg)"偏移"、
(IArg) connHandle、
(Iarg) len,
(IArg)偏移、
(IArg)方法);
/*可以在此处插入有关偏移的其他注意事项*/
中断;

案例 HS_ONOFFREC_ID:
writeLenMin = HS_ONOFFREC_LEN_MIN;
writeLenMax = HS_ONOFFREC_LEN;
pValueLenVar =&hs_ONOFFRECValLen;

log_info5 ("WriteAttrCB:%s connHandle (%d) len (%d) offset (%d) method (0x%02x)"、
(IARg)"ONOFFREC"、
(IArg) connHandle、
(Iarg) len,
(IArg)偏移、
(IArg)方法);
//此处可插入有关 ONOFFREC 的其他注意事项*/
中断;

案例 HS_TOTALTIME_ID:
writeLenMin = HS_TOTALTIME_LEN_MIN;
writeLenMax = HS_TOTALTIME_LEN;
pValueLenVar =&hs_TOTALTIMEValLen;

log_info5 ("WriteAttrCB:%s connHandle (%d) len (%d) offset (%d) method (0x%02x)"、
(IArg)"TOTALTIME (TOTALTIME)"、
(IArg) connHandle、
(Iarg) len,
(IArg)偏移、
(IArg)方法);
//此处可插入 TOTALTIME 的其他注意事项*/
中断;

默认值:
log_error0 ("未找到属性。");
返回 ATT_ERR_ATTR_NOT _ FOUND;
}
//检查长度是否在界限内。
if (offset >= writeLenMax)
{
log_error0 ("请求的偏移无效。");
状态= ATT_ERR_INVALID_OFFSET;
}
否则(offset + len > writeLenMax)
{
log_error0 ("接收到无效的值长度。");
状态= ATT_ERR_INVALID_VALUE SIZE;
}
否则(offset + len < writeLenMin &&(method = ATT_execute _WRITE_REQ || method = ATT_WRITE_REQ))
{
//拒绝低于最小值的写入。
//注:无法确定是否完成了可靠的写入(写入多个字符),因此这些字符将会完成
// 仅当此属性是队列中的最后一个属性时才被拒绝(方法为执行)。
// 否则、将接受可靠的写入并以零敲碎打的方式进行解析。
log_error0 ("接收到无效的值长度。");
状态= ATT_ERR_INVALID_VALUE SIZE;
}
其他
{
//将 pValue 复制到我们从属性表指向的变量中。
memcpy (pAttr->pValue + offset、pValue、len);

//仅在写入足够的数据时通知应用程序并更新长度。
//
//注意:如果使用可靠的写入(这意味着使用 ATT PrepareWrite 写入多个属性),
// 应用程序将为每次写入获得回调、偏移量+ len 大于_LEN_min。
//注意:对于长写入(ATT PREPARE + Execute 只针对一个属性),只会发出一个回调,
// 因为写入片段在发送到这里之前会连接在一起。
if (offset + len >= writeLenMin)
{
changeParamID = paramID;
*pValueLenVar =偏移+ len;//更新数据长度
。}
}

//使用让应用程序知道发生了哪些变化(如果发生了变化)
//将其回调到先前注册的位置(如果是)。
if (参数 ID!= 0xFF)
if (pAppCBs && pAppCBs->pfnChangeCb)
pAppCBs->pfnChangeCb( connHandle, HALO_SERVICE_SERV_UUID,paramID,pValue,len+offset ); //从堆栈任务上下文调用应用程序函数。

退货状态;
//Dale End:添加了写入部分
}

在这里、您可以看到、将"通知"设置为"是"(从主器件写入操作码0x12)的请求由从器件的"资源不足"响应:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    成功、因此在 HALO_Service_WriteAttrCB 中、我在不应该具有时删除了"返回状态"。

    如果没有"返回状态;"、我认为通知更改确认被确认也作为书面数据发出的事实所影响。

    因此、将"返回状态"重新放置在这里似乎可以修复它、但我认为"如果"可能更好:

    if (ATT_BT_UUID_SIZE = pAttr->type.len & GATT_CLIENT_CHAR_CFG_UUID =*(uint16_t *) pAttr->type.uuid)
    {
    log_info3 ("WriteAttrCB (CCCD):参数:%d connHandle:%d %s"、
    (IArg) HALO_Service_findCharParamId (pAttr)、
    (IArg) connHandle、
    (IArg)(方法= GATT_LOCAL_WRITE?"-恢复绑定状态":"- OTA 写入");
    
    //允许通知和指示,但不要检查每个 CCCD 是否真正允许。
    状态= GATTServApp_ProcessCCCWriteReq (connHandle、pAttr、pValue、len、
    偏移量、GATT_CLIENT_CFG_NOTIFY |
    GATT_CLIENT_CFG_Indicate);
    if (成功=status && pAppCBs && pAppCBs->pfnCfgChangeCb)
    pAppCBs->pfnCfgChangeCb (connHandle、HALO_SERVICE_SERV_UUID、
    HALO_Service_findCharParamId (pAttr)、pValue、len);
    返回状态;//Dale 将此状态留在工作中!!
    }
    

    如果有更好的方法可以将通知和写操作组合在一起、请告诉我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很高兴您解决了这个问题!