設置 | 登錄 | 註冊

目前共有19篇帖子。

【ble_remote工程】给蓝牙设备添加Manufacturer Name String(0x2A29)属性

12樓 巨大八爪鱼 2026-1-9 18:03

如果想在收到master的Read Request/Read Blob Request后修改即将回复的Read Response/Read Blob Response的内容,就可以注册对应的回调函数r,在回调函数里修改pAttrValue指针所指RAM的内容,并且return的值只能是0。

只能修改内容pAttrValue,无法修改长度attrLen。

这两个变量都是在static const attribute_t my_Attributes[]数组里面定义的,跟回调函数的参数p无关。


读函数的固定格式:

int my_ReadCallback(void *p)
{
  // 参数p没有用
  pAttrValue[0] = xxx;
  pAttrValue[1] = xxx;
  ...
  pAttrValue[attrLen - 1] = xxx;
  return 0; // 返回值必须是0
}
13樓 巨大八爪鱼 2026-1-9 19:25
自定义service:
[stack/ble/service/uuid.h]
#define HELLO_SERVICE                       0x22,0x19,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00

[vendor/ble_remote/app_att.h]
在typedef enum的OTA_CMD_OUT_DESC_H下方加上
    // hello_service
    hello_PS_H,
    hello_str_CD_H,
    hello_str_DP_H,

[vendor/ble_remote/app_att.c]
static const u8 my_HelloServiceUUID[16] = WRAPPING_BRACES(HELLO_SERVICE);
static const u8 my_HelloServiceManufacturerNameStringVal[5] = {
    CHAR_PROP_READ,
    U16_LO(hello_str_DP_H), U16_HI(hello_str_DP_H),
    U16_LO(CHARACTERISTIC_UUID_MANU_NAME_STRING), U16_HI(CHARACTERISTIC_UUID_MANU_NAME_STRING)
};

在static const attribute_t my_Attributes[] = {的
{0,ATT_PERMISSIONS_READ, 2,sizeof (my_OtaName),(u8*)(&userdesc_UUID), (u8*)(my_OtaName), 0, 0},
#endif
的下方加上
    // hello service
    {3,ATT_PERMISSIONS_READ,2,16,(u8*)&my_primaryServiceUUID, (u8*)my_HelloServiceUUID, 0, 0},
    {0,ATT_PERMISSIONS_READ,2,sizeof(my_HelloServiceManufacturerNameStringVal),(u8*)&my_characterUUID, (u8*)my_HelloServiceManufacturerNameStringVal, 0, 0},

    {0,ATT_PERMISSIONS_READ,2,23,(u8*)&my_HelloServiceManufacturerNameStringVal[3],(u8*)"Hello Hello Hello World",0,0},


14樓 巨大八爪鱼 2026-1-12 12:08
自定义服务(Unknown Service)的Manufacturer Name String的Value显示为N/A的解决方案:

点一下右边的下箭头按钮,再点一下右上角的Disconnect,然后再重新Connect,Value的值Hello Hello Hello World就出来了。

15樓 巨大八爪鱼 2026-1-12 18:09
关于GATT中的特征声明(Characteristic Declaration)‌:https://zh.purasbar.com/post.php?t=35099
16樓 巨大八爪鱼 2026-1-12 18:19
把特征值改成可读可写:
(1)把my_Attributes里面的特征值的操作权限由ATT_PERMISSIONS_READ改成ATT_PERMISSIONS_RDWR。
(2)给特征声明my_HelloServiceManufacturerNameStringVal的操作权限加上CHAR_PROP_WRITE。
(3)【可选操作】可以实现写函数write_my_HelloServiceManufacturerNameString,写数据时在控制台打印要写的内容。

static const attribute_t my_Attributes[] = {
    ...
    // hello service
// 服务声明
    {3,ATT_PERMISSIONS_READ,2,16,(u8*)&my_primaryServiceUUID, (u8*)my_HelloServiceUUID, 0, 0},
// 特征声明
    {0,ATT_PERMISSIONS_READ,2,sizeof(my_HelloServiceManufacturerNameStringVal),(u8*)&my_characterUUID, (u8*)my_HelloServiceManufacturerNameStringVal, 0, 0},
// 特征值
    {0,ATT_PERMISSIONS_RDWR,2,sizeof(my_HelloServiceManufacturerNameString),(u8*)&my_HelloServiceManufacturerNameStringVal[3],my_HelloServiceManufacturerNameString,write_my_HelloServiceManufacturerNameString,0},
    ...
};

// 服务UUID
static const u8 my_HelloServiceUUID[16] = WRAPPING_BRACES(HELLO_SERVICE);
// 特征声明
static const u8 my_HelloServiceManufacturerNameStringVal[5] = {
    CHAR_PROP_READ | CHAR_PROP_WRITE,
    U16_LO(hello_str_DP_H), U16_HI(hello_str_DP_H),
    U16_LO(CHARACTERISTIC_UUID_MANU_NAME_STRING), U16_HI(CHARACTERISTIC_UUID_MANU_NAME_STRING)
};
// 特征值
static u8 my_HelloServiceManufacturerNameString[] = "https://zh.purasbar.com/post.php?t=34981";
// 特征值的写函数
static int write_my_HelloServiceManufacturerNameString(void *p)
{
    rf_packet_att_data_t *pw = (rf_packet_att_data_t *)p;
    int len = pw->l2cap - 3;

    printf("len=%d\n", len);
    if (len > sizeof(my_HelloServiceManufacturerNameString) - 1)
        len = sizeof(my_HelloServiceManufacturerNameString) - 1;
    memcpy(my_HelloServiceManufacturerNameString, pw->dat, len);
    my_HelloServiceManufacturerNameString[len] = '\0';
    printf("my_HelloServiceManufacturerNameString=%s\n", my_HelloServiceManufacturerNameString);
    return 1;
}
17樓 巨大八爪鱼 2026-1-12 18:26

点一下最右边的上箭头按钮,就可以写值(UTF8字符串值),写完后值会出现在Value Sent上,而Value值保持不变。同时在开发板的串口中可以看到写入的值。

巨大八爪鱼一个汉字占3字节,一个emoji表情占4字节。三个汉字加一个表情,加起来就是13字节。
18樓 巨大八爪鱼 2026-1-12 18:48
在同一个服务中再声明一个特征值2:
[app_att.h]
typedef enum
{
    ...
    // hello_service
    hello_PS_H,
    hello_str_CD_H,
    hello_str_DP_H,
    hello_str2_CD_H,
    hello_str2_DP_H,
    ...
};

[app_att.c]
// 特征声明2
static const u8 my_HelloServiceManufacturerNameString2Val[5] = {
    CHAR_PROP_READ, // 特征值2的操作权限
    U16_LO(hello_str2_DP_H), U16_HI(hello_str2_DP_H), // 特征值2的数组下标
    U16_LO(CHARACTERISTIC_UUID_MODEL_NUM_STRING), U16_HI(CHARACTERISTIC_UUID_MODEL_NUM_STRING) // 特征值2的UUID
};
static const attribute_t my_Attributes[] = {
    ...
    // hello service
    // 服务声明
    {5,ATT_PERMISSIONS_READ,2,16,(u8*)&my_primaryServiceUUID, (u8*)my_HelloServiceUUID, 0, 0},
    // 特征声明1
    {0,ATT_PERMISSIONS_READ,2,sizeof(my_HelloServiceManufacturerNameStringVal),(u8*)&my_characterUUID, (u8*)my_HelloServiceManufacturerNameStringVal, 0, 0},
    // 特征值1
    {0,ATT_PERMISSIONS_RDWR,2,sizeof(my_HelloServiceManufacturerNameString),(u8*)&my_HelloServiceManufacturerNameStringVal[3],my_HelloServiceManufacturerNameString,write_my_HelloServiceManufacturerNameString,0},
    // 特征声明2
    {0,ATT_PERMISSIONS_READ,2,sizeof(my_HelloServiceManufacturerNameString2Val),(u8*)&my_characterUUID, (u8*)my_HelloServiceManufacturerNameString2Val, 0, 0},
    // 特征值2
    {0,ATT_PERMISSIONS_READ,2,19,(u8*)&my_HelloServiceManufacturerNameString2Val[3],(u8*)"@啊啊是谁都对",0,0},
    ...
};

注意同一个服务的两个特征值UUID不能相同,否则会出错。
特征值1的UUID是CHARACTERISTIC_UUID_MANU_NAME_STRING=0x2a29。
特征值2换了个UUID:CHARACTERISTIC_UUID_MODEL_NUM_STRING=0x2a24。
19樓 巨大八爪鱼 2026-1-12 18:49

程序运行结果:

可以看到一个自定义服务中同时拥有两个不同的特征值。

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張