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.

[参考译文] CC2650:通知在电话上显示已启用、并且可以订阅、但在设置参数时不会发布通知。

Guru**** 2582405 points
Other Parts Discussed in Thread: CC2650MODA, CC2650, CC2640R2F

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/823400/cc2650-notifications-appear-enabled-on-phone-and-can-be-subscribed-to-but-no-notification-posted-when-parameter-set

器件型号:CC2650
主题中讨论的其他器件: 、CC2640R2F

您好!

我一直在使用 CC2650MODA、但我更改了电路板头文件、使其与 cc2650 launchpad 演示代码兼容。

我使用 BLE SDK 2.2.2.25简单外设示例作为代码的基础。

我已经能够使用 这里的发生器创建一个定制服务 、并将其集成到简单的外设示例 中、以便在 这个 资源和这个资源的非常重要的帮助下、按照针对 cc2640r2f 的另一个教程中的指南来发送 ADC 读数。 实际上、这是一项令人惊讶的工作。

现在、我已经相当成功地完成了大量的调色工作、我可以读取 ADC 值、将其存储在数组中、并使用 SetParameter 将数组的第一个单元格设置为参数。

然后、我重新生成了定制服务、还在示例服务发生器上选择 GATT_PROP_NOTIFY 选项、并相应地更新了我的代码。

现在、当我打开我的应用程序(我在 Android 上使用 LightBlue)时、我可以订阅我的服务的通知、但当我"设置"一个新参数时、它不会自动传输到我的手机。 基本上、我的手机说我已订阅通知、但它仍然只能通过手动单击"再次阅读"按钮来工作。

是否有任何关于如何解决此问题的想法? 谢谢。

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

    Michael、

    我已将您的帖子内部分配给可以提供帮助的人。  

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

    您好 Evan、

    非常感谢! 期待他们的见解。

    Mike

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

    尊敬的 Mike:

     请您分享您的自定义配置文件、我将对其进行审核。  此外、如您所知、simple_peripheral 附带了一个可通知特征(char 4)、因此您可以确认/比较您的特征 的配置方式与此特征相同。

     此致、

       David

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

    尊敬的 David:

    很抱歉、响应缓慢、

    以下分别是我的头文件和 c 文件:

    /
    *文件名: my2650Therm.h
    *
    *说明:此文件包含 my2650Therm 服务定义和
    * 原型。
    *
    *版权所有(c) 2015-2016、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *
    /
    
    
    #ifndef _MY2650THERM_H_
    #define _MY2650THERM_H_
    
    #ifdef _cplusplus
    extern "C"
    {
    #endif
    
    /*****
    *包括
    */
    #include "bcomdef.h"
    /*********
    *常量
    */
    
    
    *常量
    */
    //服务 UUID
    #define MY2650THERM_SERV_UUID 0xAA00
    
    //特征定义
    #define MY2650THERM_THERM 0
    #define MY2650THERM_THERM_UUID 0xAA01
    #define MY2650THERM_THERM_LEN 100
    
    /*********
    * typedef
    */
    
    /*********
    *宏
    */
    
    *********
    *配置文件回调
    *//
    
    特性值更改
    typedef void (* my2650ThermChange_t)(uint8 paramID)时回调;
    
    typedef 结构
    {
    my2650ThermChange_t pfnChangeCb;//特征值更改时调用
    }my2650ThermCBs_t;
    
    
    
    /*********
    * API 函数
    */
    
    
    /*
    My2650Therm_AddService -通过注册
    *初始化 My2650Therm 服务 GATT 属性与 GATT 服务器。
    *
    */
    extern bStatus_t My2650Therm_AddService (void);
    
    /*
    My2650Therm_RegisterAppCBs -注册应用程序回调函数。
    * 只调用此函数一次。
    *
    * appCallback -指向应用程序回调的指针。
    //
    extern bStatus_t My2650Therm_RegisterAppCBs (my2650ThermCBs_t * appCallback);
    
    //
    * My2650Therm_SetParameter -设置 My2650Therm 参数。
    *
    * param -配置文件参数 ID
    * len -数据向右的长度
    * value -要写入的数据的指针。 这取决于
    * 参数 ID 和将被转换为相应
    的* 数据类型(例如:uint16的数据类型将转换为
    * uint16指针)。
    //
    extern bStatus_t My2650Therm_SetParameter (uint8 param、uint8 len、void *值);
    
    //
    * My2650Therm_GetParameter -获取 My2650Therm 参数。
    *
    * param -配置文件参数 ID
    *值-指向要写入的数据的指针。 这取决于
    * 参数 ID 和将被转换为相应
    的* 数据类型(例如:uint16的数据类型将转换为
    * uint16指针)。
    //
    extern bStatus_t My2650Therm_GetParameter (uint8 param,void * value);
    
    /*********
    (三 /
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif //_MY2650THERM_H_*
    
    /
    *文件名: my2650Therm.c
    *
    说明:此文件包含服务的实现。
    *
    *版权所有(c) 2015-2016、德州仪器(TI)公司
    *保留所有权利。
    *
    *
    只要
    符合以下条件*、允许以源代码和二进制形式重新分发和使用:
    *
    *源代码的重新分发必须保留上述版权
    声明*、此条件列表和以下免责声明。
    *
    ***二进制形式的再发行必须在
    
    *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。
    *
    ***未经
    
    事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。
    *
    *本软件由版权所有者和贡献者"按原样"提供
    *、
    
    不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或
    *贡献者都不对任何直接、间接、偶然、特殊、
    *模范、 或相应的损害(包括但不限于
    *采购替代产品或服务;丧失使用、数据或利润;
    *或业务中断)、但出于任何责任理论
    、*无论是在合同中、严格责任还是由于
    使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他)
    、*即使已获悉可能会发生此类损坏。
    *
    /
    
    
    /*********
    *包括
    */
    #include 
    
    #include "bcomdef.h"
    #include "osal.h"
    #include "linkdb.h"
    #include "att。h"
    #include "gatt_uuid.h"
    
    #include "gattservapp.h"
    #include "gapbondmgr.h"
    
    #include "my2650Therm.h"
    
    /*****
    *宏
    */
    
    *********
    *常量
    */
    
    
    * typedef
    */
    
    /*********
    *全局变量
    */
    
    / my2650Therm Service UUID
    ****const uint8_t my2650ThermUUUUUID[ATT_UUUUUART_SIZE]=
    {
    TI_BASE_UUID_128 (MY2650THERM_SERV_MYUUID)
    };
    
    // therm UUID
    const uint8_t my2650therm_Thermm[MYERM_SIDU]=
    {TI_UUUTI_UUUUUUID_UUART__UTI__UTI_UTI_UTI__UTI_UTI_UTI__UTI_UTI_UTI__UUID
    
    
    
    
    *局部变量
    */
    
    静态 my2650ThermCBs_t *pAppCBs =空;
    
    /*********
    *配置文件属性-变量
    *//
    
    服务声明
    静态 const gattAttrType_t my2650ThermDecl ={ATT UUID _size、my2650Thermfg};
    
    //特征"Therm"属性(用于声明)
    静态 uint8_t my2650Therm_ThermProps =****GATT_PROP_Read | GATT_ThermP_Val =
    
    
    *静态 uint8;*更改"m_m_static_2650thratic";*更改"m_m_m_m_m_m_m_m_static_ratic";*更改"m_m_m_m_m_m_m_m_m_m_m_thratic"
    
    
    
    
    
    *配置文件属性-表
    */
    
    static gattAttribute_t my2650ThermAttrTbl[]=
    {
    // my2650Therm 服务声明
    {
    {ATT_BT_UUID_SIZE、primServiceUUID}、
    GATT_permit_read、
    0、
    (uint8_t *)&my2650ThermDecl
    }、
    // Therm Characteristic Declaration
    {
    {ATT_BT_UUUART_SIZE、characterUUID}、
    GATT_permit_read、
    0、
    &my2650Therm_ThermProps
    }、
    //热特性值
    {
    {ATT_UUUUUUAR_SIZE、my2650Therm_ThermUUID}、
    GATT_permit_read、
    0、
    my2650Therm_ThermVal
    }、
    // Therm CCCD
    {
    {ATT_BT_UUID_SIZE、clientCharCfgUUID}、
    GATT_permit_read | GATT_permit_write、
    0、
    (uint8 *)&my2650Therm_ThermConfig
    }、
    };
    
    /*********
    *本地函数
    */
    static bStatus_t my2650Therm_ReadAttrCB (uint16 connHandle、gattAttribute_t * pAttr、
    uint8 *pValue、uint16 *PLEN、uint16 offset、
    uint16 maxLen,uint8方法);
    static bStatus_t my2650Therm_WriteAttrCB (uint16 connHandle,gattAttribute_t *pAttr,
    uint8 *pValue、uint16 len、uint16 offset、
    uint8方法);
    
    /
    *配置文件回调
    *//
    简单配置文件服务回调
    const gattServiceCBs_t my2650ThermCBs =
    {
    my2650Therm_ReadAttrCB、//读取回调函数指针
    my2650Therm_WriteAttrCB、//写入回调函数指针
    NULL //授权回调函数指针
    };
    
    /*********
    *公共函数
    */
    
    /*
    My2650Therm_AddService -通过注册
    *初始化 My2650Therm 服务 GATT 属性与 GATT 服务器。
    *
    //
    bStatus_t My2650Therm_AddService (void)
    {
    uint8_t status;
    
    //分配客户端特征配置表
    my2650Therm_ThermConfig =(gattCharCfg_t *) iCall_malloc (sizeof (gattCharCfg_t)* linkDBCConns);
    if (my2650Therm=NULL)
    
    return (bleMemAllocError);
    }
    
    //初始化客户端特征配置属性
    GATTServApp_InitCharCfg (INVALID_CONNANDLE、my2650Therm_ThermConfig);
    //使用 GATT 服务器应用
    程序状态注册 GATT 属性列表和 CBS = GATTServApp_RegisterService (my2650ThermAttrTbl、
    GATT_NUM_ATTRS (my2650ThermAttrTbl),
    GATT_MAX_encrypt_key_size、
    &my2650ThermCBs );
    
    return ( status );
    }//*
    
    
    My2650Therm_RegisterAppCBs -注册应用程序回调函数。
    * 只调用此函数一次。
    *
    * appCallback -指向应用程序回调的指针。
    //
    bStatus_t My2650Therm_RegisterAppCBs (my2650ThermCBs_t *appCallback)
    {
    if (appCallback)
    {
    pAppCBs = appCallback;
    
    返回(成功);
    }
    否则
    {
    return (bleAlreadyInRequestedMode);
    }
    //*
    
    
    My2650Therm_SetParameter -设置 My2650Therm 参数。
    *
    * param -配置文件参数 ID
    * len -数据向右的长度
    * value -要写入的数据的指针。 这取决于
    * 参数 ID 和将被转换为相应
    的* 数据类型(例如:uint16的数据类型将转换为
    * uint16指针)。
    //
    bStatus_t My2650Therm_SetParameter (uint8 param、uint8 len、void * value)
    {
    bStatus_t ret = Success;
    switch (param)
    {
    案例 MY2650THERM_THERM:
    如果(len ==MY2650THERM_THERM_LEN)
    {
    memcpy (my2650Therm_ThermVal、value、len);
    
    //尝试发送通知。
    GATTServApp_ProcessCharCfg (my2650Therm_ThermConfig、(uint8_t *)和 my2650Therm_ThermVal、false、
    my2650ThermAttrTbl、GATT_NUM_ATTRS (my2650ThermAttrTbl)、
    invalid _task_ID、my2650Therm_ReadAttrCB);
    }
    其他
    {
    RET = bleInvalidRange;
    }
    中断;
    
    默认值:
    RET = INVALIDPARAMETER;
    break;
    }
    return ret;
    }
    
    
    //
    * My2650Therm_GetParameter -获取 My2650Therm 参数。
    *
    * param -配置文件参数 ID
    *值-指向要写入的数据的指针。 这取决于
    * 参数 ID 和将被转换为相应
    的* 数据类型(例如:uint16的数据类型将转换为
    * uint16指针)。
    //
    bStatus_t My2650Therm_GetParameter (uint8 param,void * value)
    {
    bStatus_t ret = Success;
    switch (param)
    {
    默认值:
    RET = INVALIDPARAMETER;
    中断;
    }
    返回;
    }
    
    
    /*********
    *@fn my2650Therm_ReadAttrCB
    *
    *@简介 读取属性。
    *
    *@param connHandle -在
    *@param 上接收到连接消息 pAttr -指向属性
    *@param 的指针 pValue -指向要读取的数据的指针
    *@param PLEN -要读取的数据长度
    *@param offset -要读取的第一个八位位组的偏移
    *@param maxLen -要读取的数据的最大长度
    *@param 方法-读取消息的类型
    *
    *@return 成功、blePending 或失败
    */
    static bStatus_t my2650Therm_ReadAttrCB (uint16 connHandle、gattAttribute_t *pAttr、
    uint8 *pValue、uint16 *PLEN、uint16 offset、
    uint16 maxLen,uint8方法)
    {
    bStatus_t status = SUCCESS;
    
    //查看请求是否与 Therm 特性值相关
    ,如果(! memcmp (pAttr->type.uuid、my2650Therm_ThermUUID、pAttr->type.len))
    {
    if (offset > MY2650THERM_THERM_LEN)//防止恶意的 ATT ReadBlob 偏移。
    {
    状态= ATT_ERR_INVALID_OFFSET;
    }
    其他
    {
    * PLEN = min (maxLen、MY2650THERM_THERM_LEN - offset);//尽可能传输
    memcpy (pValue、pAttr->pValue + offset、*PLEN);
    }
    }
    否则
    {
    //如果我们来到这里,这意味着您忘记为添加 if 子句
    //属性表中具有读取权限的 Characteristic Value 属性。
    *PLEN=0;
    状态= ATT_ERR_ATTR_LOT_FOUND;
    }
    
    返回状态;
    }
    
    
    /*********
    *@fn my2650Therm_WriteAttrCB
    *
    *@简要在写入操作之前验证属性数据
    *
    *@param connHandle -在
    *@param pAttr 上接收到连接消息-指向属性的指针
    *@param pValue -指向要写入的数据的指针
    *@param len -数据长度
    *@param offset - 要写入的第一个八位字节的偏移
    量*@param 方法-写入消息类型
    *
    *@返回成功、blePending 或失败
    */
    static bStatus_t my2650Therm_WriteAttrCB (uint16 connHandle、gattAttribute_t *pAttr、
    uint8 *pValue、uint16 len、uint16 offset、
    uint8方法)
    {
    bStatus_t status = SUCCESS;
    uint8_t paramID = 0xFF;
    
    //查看请求是否与客户机特性配置有关
    if (! memcmp (pAttr->type.uuid、clientCharCfgUUID、pAttr->type.len))
    {
    //仅允许通知。
    状态= GATTServApp_ProcessCCCWriteReq (connHandle、pAttr、pValue、len、
    offset、GATT_CLIENT_CFG_NOTIFY);
    }
    否则
    {
    //如果我们来到这里,这意味着您忘记为添加 if 子句
    //属性表中具有写入权限的 Characteristic Value 属性。
    状态= ATT_ERR_ATTR_NOT _已找到;
    }
    
    //使用
    先前注册的//回调(如果已更改)让应用程序知道发生了什么变化。
    if (paramID!= 0xFF)
    if (pAppCBs && pAppCBs->pfnChangeCb)
    pAppCBs->pfnChangeCb( paramID );//从堆栈任务上下文调用应用程序函数。
    
    返回状态;
    }