嗨对话小组,
我遵循AN-B-029文件,并成功地添加了新的特性(通知/读取)到我的服务中。然而,当我添加一个新的特征(写/读),我不能写它。每次我写东西的时候都表现出“写作的特点是失败的”。有AN-B-029这样的文件可以提供步骤吗?我被困在这里了。
但是,现在我想向现有的sample128添加新服务。我的新服务应该包含这两个特点。我该如何实现它?请帮助。
最诚挚的问候,
萨姆
关键词:
设备:

你好山姆,
个人资料将收到
gattc_write_cmd_ind.消息。您需要在概要文件中附加此消息的处理程序函数,您可能已经这样做了?你能分享你的处理器函数吗profilename_task.c.?嗨VesaN,
我正在尝试向现有示例128添加写入/读取特性。
/**
****************************************************************************************
*
* @file sample128_task.c
*
* @brief Sample128任务实现。
*
* @brief 128 UUID服务。示例代码
*
*版权(C) 2013 Dialog Se雷竞技电竞平台miconductor GmbH及其子公司,未出版的作品
*此计算机程序包括机密,专有信息,是商业秘密
Dialo雷竞技电竞平台g Semiconductor GmbH及其附属公司的*。所有使用、披露和/或
*除非得到书面授权,否则禁止复制。保留所有权利。
*
****************************************************************************************
*/
/*
*包含文件
****************************************************************************************
*/
# include“rwble_config.h”
#如果(BLE_SAMPLE128)
# include“gap.h”
# include“gapc.h”
# include“gattc_task.h”
#include“Atts_util.h”
# include“sample128.h”
#include“sample128_task.h”
# include“attm_cfg.h”
# include“attm_db.h”
#include“prf_utils.h”
/*
*功能定义
****************************************************************************************
*/
/**
****************************************************************************************
* @brief处理@ref sample128_create_db_req消息的接收。
* @param[in] msgid收到的消息的Id(可能未使用)。
* @param [in] param指向消息的参数。
* @param [in]接收任务实例的dest_id ID(可能未使用)。
* @param [in]发送任务实例的src_id ID。
* @return消息是否被使用。
****************************************************************************************
*/
静态int sample128_create_db_req_handler(ke_msg_id_t const msgid,
struct sample128_create_db_req const * param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
/ /创建数据库的状态
UINT8_T状态;
uint8_t nb_att_16;
uint8_t nb_att_128;
uint8_t nb_att_32;
uint16_t att_decl_svc = ATT_DECL_PRIMARY_SERVICE;
UINT16_T ATT_DECL_CHAR = ATT_DECL_CHAROMATION;
UINT16_T ATT_DECL_CFG = ATT_DESC_CLIENT_CHAR_CHAR_CFG;
uint16_t val_hdl;
uint16_t char_hdl;
/ /保存概要文件ID
sample128_env.con_info.prf_id = task_sample128;
/*---------------------------------------------------*
* Sample128服务创建
*---------------------------------------------------*/
//将服务添加到数据库中
nb_att_16 = 5;// 6 ... 4 UUID16属性声明类型
nb_att_32 = 0;// 0 UUID32属性声明类型
nb_att_128 = 3;// 2 UUID128属性声明类型
Status = attmdb_add_service(&(sample128_env.sample128_shdl),
TASK_SAMPLE128,
nb_att_16,
nb_att_32,
nb_att_128,
78.
);
if(status == att_err_no_error)
{
/ /添加的主要服务属性 /////////////////////////////////////////////////////////////////
status = attmdb_add_attribute(sample128_env.sample128_shdl,// Attribute Handle
ATT_UUID_128_LEN, //数据大小= 16 (ATT_UUID_128_LEN)
ATT_UUID_16_LEN,//声明类型ID的大小
(uint8_t*)&att_decl_svc, // 0x2800用于主服务声明
perm(rd,启用),//权限
&(sample128_env.sample128_shdl) //属性句柄
);
//添加主服务属性的值(自定义UUID)
status = attmdb_att_set_value(sample128_env.sample128_shdl,//属性句柄
ATT_UUID_128_LEN,//该值是服务的128位UUID
(uint8_t *) sample128_svc。uuid //服务的uuid
);
//独特性1:////// //////////////////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3, //数据大小= 19 (ATT_UUID_128_LEN + 3)
ATT_UUID_16_LEN,//声明类型ID的大小
(UINT8_T *)&ATT_DECL_CHAR,// 0x2803用于特征声明
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//向数据库添加特征值声明属性
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t), //数据大小= 1字节
ATT_UUID_128_LEN,//自定义声明类型的大小= 128bit
(uint8_t *)&sample128_1_val.uuid,// uuid的特征值
PERM(RD, ENABLE) | PERM(WR, ENABLE),//权限
&(val_hdl) //处理值属性
);
//存储特征1的值句柄
memcpy (sample128_1_char。attr_hdl &val_hdl, sizeof (uint16_t));
//设置特征的初始值1
Status = attmdb_att_set_value(char_hdl, sizeof(sample128_1_char), (uint8_t *)&sample128_1_char);
/ /特征2 : //////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3, //数据大小= 19 (ATT_UUID_128_LEN + 3)
ATT_UUID_16_LEN,//声明类型ID的大小
(UINT8_T *)&ATT_DECL_CHAR,// 0x2803用于特征声明
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//向数据库添加特征值声明属性
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t), //数据大小= 1字节
ATT_UUID_128_LEN,//自定义声明类型ID = 128bit
(uint8_t *)&sample128_2_val.uuid,// uuid的特征值
perm(rd,启用)|perm(ntf,启用),//权限
&(val_hdl)//句柄到值属性
);
//存储特征2的值句柄
memcpy (sample128_2_char。attr_hdl &val_hdl, sizeof (uint16_t));
//设置特征2的初始值
Status = attmdb_att_set_value(char_hdl, sizeof(sample128_2_char), (uint8_t *)&sample128_2_char);
//添加客户端配置声明属性到数据库(方便通知)
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint16_t), //数据大小2bytes (16bit)
ATT_UUID_16_LEN,//客户端配置类型ID的大小
(uint8_t*) &att_decl_cfg, // 0x2902 client configuration declaration type的UUID
PERM(RD, ENABLE) | PERM(WR, ENABLE), //权限
&(val_hdl) //处理值属性
);
/ /写特点3 : ////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3, //数据大小= 19 (ATT_UUID_128_LEN + 3)
ATT_UUID_16_LEN,//声明类型ID的大小
(UINT8_T *)&ATT_DECL_CHAR,// 0x2803用于特征声明
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//向数据库添加特征值声明属性
status = attmdb_add_attribute(sample128_env.sample128_shdl,
my_newer_t, //数据大小= 1字节
ATT_UUID_128_LEN,//自定义声明类型的大小= 128bit
(uint8_t *)&sample128_3_val.uuid,// uuid的特征值
PERM(RD, ENABLE) | PERM(WR, ENABLE),//权限
&(val_hdl) //处理值属性
);
//存储特征3的值句柄
memcpy(sample128_3_char.attr_hdl,&val_hdl,sizeof(uint16_t));
//设置特征3的初始值
status = attmdb_att_set_value(char_hdl,sizeof(sample128_3_char),(uint8_t *)和sample128_3_char);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/ /禁用sample128服务
attmdb_svc_set_permission(sample128_env.sample128_shdl,perm(svc,disable));
//如果我们在这里,数据库已经成功完成,转到空闲状态
ke_state_set(task_sample128,sample128_idle);
}
//发送CFM到申请
struct sample128_create_db_cfm * cfm = KE_MSG_ALLOC(sample128_create_db_cfm, src_id,
TASK_SAMPLE128 sample128_create_db_cfm);
cfm - >状态=状态;
ke_msg_send (cfm);
return(ke_msg_consumed);
}
/**
****************************************************************************************
* @brief启用Sample128角色,连接后使用。
* @param[in] msgid收到的消息Id。
* @param [in] param指向消息的参数。
* @param[in] dest_id接收任务实例ID
* @param [in]发送任务实例的src_id ID。
* @return消息是否被使用。
****************************************************************************************
*/
Static int sample128_enable_req_handler(ke_msg_id_t const msgid,
Struct sample128_enable_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint16_t temp = 1;
//保持消息来源,以进一步响应它
sample128_env.con_info。appid = src_id;
//存储启用此配置文件的连接句柄
sample128_env.con_info.conidx = gapc_get_conidx(param-> conhdl);
//检查提供的连接是否存在
如果(sample128_env.con_info。conidx = = GAP_INVALID_CONIDX)
{
//连接不存在,请求不允许
prf_server_error_ind_send((prf_env_struct *)和sample128_env,prf_err_req_disally,
SAMPLE128_ERROR_IND SAMPLE128_ENABLE_REQ);
}
其他的
{
// Sample128服务权限
attmdb_svc_set_permission(sample128_env.sample128_shdl,param-> sec_lvl);
//将特征1设置为指定值
attmdb_att_set_value(sample128_env.sample128_shdl + sample128_1_idx_val,
sizeof(uint8_t),(uint8_t *)和param-> sample128_1_val);
//将特征2设置为指定值
attmdb_att_set_value (sample128_env。sample128_shdl + SAMPLE128_2_IDX_VAL,
sizeof(uint8_t),(uint8_t *)和param-> sample128_2_val);
//将特征3设置为指定值
attmdb_att_set_value(sample128_env.sample128_shdl + sample128_3_idx_val,
sizeof(uint8_t),(uint8_t *)和param-> sample128_3_val);
sample128_env.feature = param->特征;
如果(! sample128_env.feature)
{
temp = 0;
}
attmdb_att_set_value(sample128_env.sample128_shdl + sample128_2_idx_cfg,
sizeof(uint16_t),(uint8_t *)&temp);
//转到连接状态
ke_state_set (TASK_SAMPLE128 SAMPLE128_CONNECTED);
}
return(ke_msg_consumed);
}
/**
****************************************************************************************
* @brief更新特征2的值。如果属性被启用,发送通知给对等体。
* @param[in] msgid收到的消息Id。
* @param [in] param指向消息的参数。
* @param[in] dest_id接收任务实例ID
* @param [in]发送任务实例的src_id ID。
* @return消息是否被使用。
****************************************************************************************
*/
静态int sample128_upd_char2_req_handler(ke_msg_id_t const msgid,
Struct sample128_upd_char2_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t status = PRF_ERR_OK;
//检查提供的值
if(param-> conhdl == gapc_get_conhdl(sample128_env.con_info.conidx))
{
//更新数据库中的值
attmdb_att_set_value (sample128_env。sample128_shdl + SAMPLE128_2_IDX_VAL,
sizeof (uint8_t), (uint8_t *)参数- > val);
如果(sample128_env。特性和PRF_CLI_START_NTF))
//通过gatt发送通知
prf_server_send_event ((prf_env_struct *) &sample128_env假,
sample128_env。sample128_shdl + SAMPLE128_2_IDX_VAL);
}
其他的
{
状态= PRF_ERR_INVALID_PARAM;
}
if (status != PRF_ERR_OK)
{
sample128_upd_char2_cfm_send(状态);
}
return(ke_msg_consumed);
}
/**
****************************************************************************************
* @brief处理接收@ref GATT_WRITE_CMD_IND消息。
* @param[in] msgid收到的消息的Id(可能未使用)。
* @param [in] param指向消息的参数。
* @param [in]接收任务实例的dest_id ID(可能未使用)。
* @param [in]发送任务实例的src_id ID。
* @return消息是否被使用。
****************************************************************************************
*/
msgid静态int gattc_write_cmd_ind_handler(ke_msg_id_t const,
gattc_write_cmd_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t char_code = SAMPLE128_ERR_CHAR;
uint8_t status = PRF_APP_ERROR;
if(ke_idx_get(src_id)== sample128_env.con_info.conidx)
{
if(param-> handle == sample128_env.sample128_shdl + sample128_1_idx_val)
{
char_code = sample128_1_char;
}
if(param-> handle == sample128_env.sample128_shdl + sample128_2_idx_cfg)
{
char_code = sample128_2_cfg;
}
if(param-> handle == sample128_env.sample128_shdl + sample128_3_idx_val)
{
char_code = sample128_3_char;
}
if (char_code == SAMPLE128_1_CHAR)
{
//保存到DB中
attmdb_att_set_value(param->句柄,sizeof(uint8_t),(uint8_t *)和param->值[0]);
如果(param->最后)
{
sample128_send_val (param - >值[0]);
}
status = prf_err_ok;
}
否则if(char_code == sample128_2_cfg)
{
/ /写价值
uint16_t ntf_cfg;
//在检查前提取值
ntf_cfg = co_read16p(&param-> value [0]);
//仅更新配置如果停止或通知启用的值
if (ntf_cfg == PRF_CLI_STOP_NTFIND) || (ntf_cfg == PRF_CLI_START_NTF))
{
//保存到DB中
Attmdb_att_set_value (param->句柄,sizeof(uint16_t), (uint8_t *)¶m->值[0]);
//保护环境中的信息
if (ntf_cfg == PRF_CLI_START_NTF)
{
// ntf cfg bit设置为1
sample128_env。功能| = PRF_CLI_START_NTF;
}
其他的
{
// ntf cfg bit设置为0
sample128_env.feature&=〜prf_cli_start_ntf;
}
status = prf_err_ok;
}
}
else if (char_code == SAMPLE128_3_CHAR) / /编码
{
//保存到DB中
attmdb_att_set_value(param->句柄,sizeof(uint8_t),(uint8_t *)和param->值[0]);
如果(param->最后)
{
sample128_send_val (param - >值[0]);
}
status = prf_err_ok;
}
}
//发送写响应
atts_write_rsp_send (sample128_env.con_info。conidx param - >处理、状态);
return(ke_msg_consumed);
}
/**
****************************************************************************************
* @brief断开指示样本128。
* @param[in] msgid收到的消息Id。
* @param [in] param指向消息的参数。
* @param[in] dest_id接收任务实例ID
* @param [in]发送任务实例的src_id ID。
* @return消息是否被使用。
****************************************************************************************
*/
msgid静态int gap_disconnect_ind_handler(ke_msg_id_t const,
Struct gapc_disconnect_ind const *参数,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
//检查连接句柄
if(ke_idx_get(src_id)== sample128_env.con_info.conidx)
{
//在任何情况下,通知应用程序关于断开连接
sample128_disable();
}
return(ke_msg_consumed);
}
/*
*全局变量定义
****************************************************************************************
*/
///禁用状态处理程序定义。
const struct ke_msg_handler sample128_disabled [] =
{
SAMPLE128_CREATE_DB_REQ, (ke_msg_func_t) sample128_create_db_req_handler,
{SAMPLE128_CREATE_DB_REQ3, (ke_msg_func_t) sample128_create_db_req_handler},
};
///空闲状态处理程序定义。
Const struct ke_msg_handler sample128_idle[] =
{
{SAMPLE128_ENABLE_REQ, (ke_msg_func_t) sample128_enable_req_handler},
};
///连接状态处理程序定义。
Const struct ke_msg_handler sample128_connected[] =
{
{gattc_write_cmd_ind,(ke_msg_func_t)gattc_write_cmd_ind_handler},
{sample128_upd_char2_req,(ke_msg_func_t)sample128_upd_char2_req_handler},
(ke_msg_func_t) gattc_write_cmd_ind_handler3}, {GATTC_WRITE_CMD_IND3
};
///默认状态处理程序定义
Const struct ke_msg_handler sample128_default_state[] =
{
(ke_msg_func_t) gap_disconnnect_ind_handler}, {GAPC_DISCONNECT_IND
};
///指定每个输入状态的消息处理程序结构。
const struct ke_state_handler sample128_state_handler[SAMPLE128_STATE_MAX] =
{
[SAMPLE128_DISABLED] = KE_STATE_HANDLER (SAMPLE128_DISABLED),
[sample128_idle] = ke_state_handler(sample128_idle),
[SAMPLE128_CONNECTED] = KE_STATE_HANDLER (SAMPLE128_CONNECTED),
};
///指定所有状态常见的消息处理程序。
const struct ke_state_handler sample128_default_handler = ke_state_handler (sample128_default_state);
///定义所有任务实例的状态的位置持有者。
ke_state_t sample128_state [sample128_idx_max] __attribute __((部分(“保留_mem_area0”),zero_init));
# endif / / BLE_SAMPLE128
嗨Sam123,
你不能有
{gattc_write_cmd_ind3,(ke_msg_func_t)gattc_write_cmd_ind_handler3}.您需要处理每个服务特征gattc_write_cmd_ind..您可以通过检查消息参数的句柄值来讲述每个特征之间的差异
帕纳在处理函数中。它具有以下结构///通知对等设备请求修改数据库。
struct gattc_write_cmd_ind.
{
///处理必须写入的属性
UINT16_T手柄;
///要写入的数据长度
uint16_t长度;
///数据写入的偏移量
uint16_t偏移;
///如果为true,目标任务将返回一个写响应命令。
BOOL反应;
///通知它是多个准备写请求的最后一个请求。
bool去年;
///在属性数据库中写入的数据
uint8_t值(__ARRAY_EMPTY);
};
换句话说,检查参数 - >手柄的值。例如,您可以为属性(特征值)创建切换盒比较:
Switch (param->handle - your_profile_env.start_handle) {
案例CHAR1:休息;
案例CHAR2:休息;
}
对不起,这有点匆匆写。没有测试,但我希望你有一些照片
谢谢!
你好,
我只能在一个服务中添加8个特征,当我添加第9个时,它没有运行,有人试过吗?
嗨redbear,
这取决于您在您的服务中添加的特征。软件支持每次服务32个属性。
由于MT_dialog
嗨MT_dialog,
nb_att_16 = 1 + 9 + 9;/ / 1 svc, 9 char、9 user_desc
nb_att_32 = 0;
nb_att_128 = 9;/ / val丙氨酸
我大致了解,但28 <32。
嗨redbear,
你的意思是它不运行,你可以调试你的应用程序,以查看它是否通过app_adv_start()函数?
您可以在一个服务中拥有9个特征。请检查您的代码很容易用复制和粘贴造成错误。
由于MT_dialog
嗨MT_dialog,
“它不跑”的意思是我从浅蓝色看不见。
首先我写了一个宏开关来添加两个字符,可能像你说的复制粘贴错误,
但是现在我添加了两个宏开关,只添加了第8个。只加第9个,好吧,这意味着密码是正确的。
加上这两种颜色,我就看不见了。
用我们的吗?
还有其他调试方法吗?
我认为用户描述字符串有点长,
我现在缩短了这是工作!
但限制是多少?
嗨,安东尼,
我没有得到它,你缩短了什么和工作?
由于MT_dialog
嗨MT_dialog,
我更改了char_user_description长度,如下所示:
旧:
static const uint8_t beacon_user_desc_1[] = "Beacon UUID";
static const uint8_t beacon_user_desc_2[] = "Major identity ID";
static const uint8_t beacon_user_desc_3[] = "次要身份ID";
...直到beacon_user_desc_9
新的一个:
static const uint8_t beacon_user_desc_1[] = "UUID";
static const uint8_t beacon_user_desc_2[] = "Major";
static const8_t beacon_user_desc_3 [] =“minor”;
...
它有效。
嗨antony42,
您正在更改数据库的特征或广告字符串?广告字符串具有固定的最大数量为29字节有效载荷。与数据库无关。
由于MT_dialog
嗨MT_dialog,
数据库的特点,
ATT_DESC_CHAR_USER_DESCRIPTION,我制作了描述字符串较短,服务中的9个特征可以正常。
你好,
我添加了塞尔维护和28个特征,工作正常,
但我添加了另外两个特征,我可以从浅蓝色看到,但不能连接,
为什么一个最多的项目中的特点是多少?
嗨,安东尼,
除了在前一篇文章中提到的32个属性的限制,理论上,特征数量没有其他限制。唯一的限制是数据库的内存大小,由db_heap_size定义。
由于MT_dialog
嗨MT_dialog,
我试过了,还是没成功。
首先我增加了db_heap_sz的大小,甚至高达1024 * 2,但不起作用,然后我增加了三雪石三,没什么改变。
#定义DB_HEAP_SZ (1024 + 256)
#define env_heap_sz 328.
#定义MSG_HEAP_SZ 1312
#定义NON_RET_HEAP_SZ 1024
Undef如下之一,一切正常,添加这三个信标将不工作。
cfg_beacon_config_struct.
CFG_PRF_SPOTAR
cfg_prf_anthony.
什么可能导致这个问题?
非常感谢,
安东尼。
嗨antony42,
当你#undef任何#定义你提到你的设备是广告与所有30你想要的特征?
由于MT_dialog
嗨MT_dialog,
当我#def这三个时,我看不到浅蓝色,
解开其中一个,效果很好。
顺便问一下,你用skype吗?(id: electronicfan)
谢谢,
安东尼
嗨antony42,
对话框本地团队的成员将尽快与您联系,以支持您。
由于MT_dialog