嗨,对话框的团队,
我遵循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 yabo国际娱乐Semiconductor GmbH及其附属公司,未发表的作品
*本计算机程序包括机密、专有信息,属商业机密
* Diayabo国际娱乐log Semiconductor GmbH及其附属公司。所有使用、披露和/或
*除非得到书面授权,否则不得复制。保留所有权利。
*
****************************************************************************************
*/
/*
*包含文件
****************************************************************************************
*/
#include“rwble_config.h”
#if(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消息是否被消费。
****************************************************************************************
*/
Static 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_CHARACTERISTIC;
uint16_t att_decl_cfg = ATT_DESC_CLIENT_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…4uid16属性声明类型
nb_att_32 = 0;// 0 UUID32属性声明类型
nb_att_128 = 3;// 2 UUID128属性声明类型
状态= attmdb_add_service(&(sample128_env.sample128_shdl),
TASK_SAMPLE128,
nb_att_16,
nb_att_32,
nb_att_128,
78
);
status == ATT_ERR_NO_ERROR
{
//添加主要服务属性//////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
status = attmdb_add_attribute(sample128_env.sample128_shdl,//属性句柄
ATT_UUID_128_LEN,//数据大小= 16(ATT_UUID_128_LEN)
ATT_UUID_16_LEN, //声明类型ID的大小
(uint8_t*)&att_decl_svc, // 0x2800主服务声明
PERM(RD, ENABLE), //权限
&(sample128_env.sample128_shdl) //属性句柄
);
//添加主服务属性的值(自定义UUID)
状态= attmdb_att_set_value(sample128_env. value)sample128_shdl, //属性句柄
ATT_UUID_128_LEN, //服务的128位UUID
(uint8_t *)sample128_svc.uuid // uuid的服务
);
/ /特点1 : ////////////////////////////////////////////////////////////////////////////////
//添加特征声明属性到数据库
状态= 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, ENABLE), //权限
&(char_hdl) //特征声明的句柄
);
//将特征值声明属性添加到数据库
状态= attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t), //数据大小= 1字节
ATT_UUID_128_LEN,//自定义声明类型= 128位的大小
(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 : //////////////////////////////////////////////////////////////////////////////////
//添加特征声明属性到数据库
状态= 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为特征声明
烫(RD,启用),/ /权限
&(char_hdl) //特征声明的句柄
);
//将特征值声明属性添加到数据库
状态= attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t),// data size = 1字节
ATT_UUID_128_LEN,//自定义声明类型ID = 128bit的大小
(uint8_t *) &sample128_2_val。uuid, //特征值的uuid
PERM(RD, ENABLE) | PERM(NTF, ENABLE),//权限
&(val_hdl) // value属性句柄
);
//保存特征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);
//将客户端配置声明属性添加到数据库(促进通知)
状态= attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint16_t),//数据大小2bytes(16bit)
ATT_UUID_16_LEN, //客户端配置类型ID大小
(uint8_t*) &att_decl_cfg, // 0x2902客户端配置声明类型UUID
perm(rd,启用)|perm(wr,启用),//权限
&(val_hdl)//句柄value属性
);
/ /写特点3 : ////////////////////////////////////////////////////////////////////////////////
//添加特征声明属性到数据库
状态= 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, ENABLE), //权限
&(char_hdl) //特征声明的句柄
);
//将特征值声明属性添加到数据库
状态= attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(my_newer_t), //数据大小= 1字节
ATT_UUID_128_LEN,//自定义声明类型= 128位的大小
(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的初始值
状态= attmdb_att_set_value(char_hdl, sizeof(sample128_3_char), (uint8_t *)&sample128_3_char);
//////// //////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//禁用示例128服务
attmdb_svc_set_permission (sample128_env。禁用sample128_shdl烫(SVC));
//如果我们在这里,数据库已完成与成功,转到空闲状态
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);
返回(KE_MSG_CONSUMED);
}
/**
****************************************************************************************
启用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_DISALLOWED,
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 *)参数- > sample128_1_val);
//将特征值2设置为指定值
attmdb_att_set_value (sample128_env。sample128_shdl + SAMPLE128_2_IDX_VAL,
sizeof (uint8_t), (uint8_t *)参数- > sample128_2_val);
//将特征值3设置为指定值
attmdb_att_set_value (sample128_env。sample128_shdl + SAMPLE128_3_IDX_VAL,
sizeof (uint8_t), (uint8_t *)参数- > sample128_3_val);
sample128_env。特点=参数- >功能;
如果(! sample128_env.feature)
{
temp = 0;
}
attmdb_att_set_value (sample128_env。sample128_shdl + SAMPLE128_2_IDX_CFG,
sizeof (uint16_t), (uint8_t *)临时);
//进入连接状态
ke_state_set (TASK_SAMPLE128 SAMPLE128_CONNECTED);
}
返回(KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief更新特性值2.如果启用了属性,请向对等体发送通知。
* @param [in]收到的消息的msgid ID。
* @param[in] param指向消息参数的指针。
* @param [in]接收任务实例的dest_id ID
* @param[in] src_id发送任务实例ID。
* @return消息是否被消费。
****************************************************************************************
*/
Static 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;
//检查提供的值
如果(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 *)和param-> val);
if((sample128_env.feature&prf_cli_start_ntf))
//通过GATT发送通知
prf_server_send_event((prf_env_struct *)和sample128_env,false,
sample128_env。sample128_shdl + SAMPLE128_2_IDX_VAL);
}
别的
{
status = prf_err_invalid_param;
}
if(状态!= prf_err_ok)
{
sample128_upd_char2_cfm_send(状态);
}
返回(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消息是否被消费。
****************************************************************************************
*/
Static int gattc_write_cmd_ind_handler(ke_msg_id_t const msgid,
Struct 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. conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf。sample128_shdl + SAMPLE128_1_IDX_VAL)
{
char_code = SAMPLE128_1_CHAR;
}
If (param->handle == sample128_env. conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf。sample128_shdl + SAMPLE128_2_IDX_CFG)
{
char_code = SAMPLE128_2_CFG;
}
If (param->handle == sample128_env. conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf . conf。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 *)¶m->值[0]);
如果(param - >最后)
{
sample128_send_val(param-> value [0]);
}
状态= PRF_ERR_OK;
}
else if (char_code == sample128_cfg)
{
//书面价值
uint16_t ntf_cfg;
//在检查前提取值
ntf_cfg = co_read16p (param - >值[0]);
//如果stop或notification的值为enable,则只更新配置
if ((ntsf_cfg == PRF_CLI_STOP_NTFIND) || (ntsf_cfg == PRF_CLI_START_NTF)) / / ntsf_cfg == PRF_CLI_START_NTF)
{
//在DB中保存值
attmdb_att_set_value(param->句柄,sizeof(uint16_t),(uint8_t *)和param->值[0]);
//在环境中保存信息
if(ntf_cfg == prf_cli_start_ntf)
{
// Ntf cfg位设置为1
sample128_env。功能| = PRF_CLI_START_NTF;
}
别的
{
// Ntf cfg位设置为0
sample128_env。& = ~ PRF_CLI_START_NTF特性;
}
状态= PRF_ERR_OK;
}
}
else if (char_code == SAMPLE128_3_CHAR)
{
//在DB中保存值
Attmdb_att_set_value (param->句柄,sizeof(uint8_t), (uint8_t *)¶m->值[0]);
如果(param - >最后)
{
sample128_send_val(param-> value [0]);
}
状态= PRF_ERR_OK;
}
}
//发送写响应
atts_write_rsp_send (sample128_env.con_info。conidx param - >处理、状态);
返回(KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief disconnect indication to sample128。
* @param [in]收到的消息的msgid ID。
* @param[in] param指向消息参数的指针。
* @param [in]接收任务实例的dest_id ID
* @param[in] src_id发送任务实例ID。
* @return消息是否被消费。
****************************************************************************************
*/
Static int gap_disconnect_ind_handler (ke_msg_id_t const msgid,
Struct gapc_disconnect_ind const *param,
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); / /采样
{
//在任何情况下,通知APP断开连接
sample128_disable ();
}
返回(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 [] =
{
(ke_msg_func_t) gattc_write_cmd_ind_handler}, {GATTC_WRITE_CMD_IND
(ke_msg_func_t) sample128_upd_char2_req_handler}, {SAMPLE128_UPD_CHAR2_REQ
{gattc_write_cmd_ind3,(ke_msg_func_t)gattc_write_cmd_ind_handler3},
};
///默认状态处理程序定义
Const struct ke_msg_handler sample128_default_state[] =
{
{gapc_disconnect_ind,(ke_msg_func_t)gap_disconnnect_ind_handler},
};
///指定每个输入状态的消息处理程序结构。
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__(((“retention_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];
};
换句话说,检查param->句柄的值。如。,可以为属性(特征值)创建开关大小写比较:
交换机(param->句柄 - 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个,确定,这意味着代码是对的。
添加两个,我看不到闪烁。
用keil?
还有其他调试方法吗?
我认为用户DESC字符串有点长,
我现在把它改短了这是工作!
但是极限是什么呢?
嗨Antony,
我不明白你把什么改短了又管用?
谢谢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[] = "主标识ID";
static const uint8_t beacon_user_desc_3 [] =“次要身份ID”;
...直到beaccon_user_desc_9.
新一:
static const uint8_t beacon_user_desc_1 [] =“uuid”;
static const uint8_t beaccon_user_desc_2 [] =“major”;
static const uint8_t beacon_user_desc_3[] = "次要";
...
和它的工作原理。
嗨Antony42,
您正在改变数据库或广告字符串的特征吗?广告字符串的最大有效载荷固定为29字节。这和数据库没有关系。
谢谢mt_dialog.
嗨mt_dialog,
数据库的特点,
ATT_DESC_CHAR_USER_DESCRIPTION,我把描述字符串缩短了,一个服务中有9个特征是可以的。
你好,
我一共添加了几种服务和28个特点,效果很好,
但我添加了另外两个特征,我可以从浅蓝色看,但不能连接,
为什么?一个项目中最多有多少个特征?
嗨Antony,
除了我在前一篇文章中提到的每个服务限制32个属性之外,理论上在特征的数量上没有其他限制。唯一的限制是数据库的内存大小,它是由DB_HEAP_SIZE定义的。
谢谢mt_dialog.
嗨mt_dialog,
我试过,仍然没有工作。
首先,我增加了DB_HEAP_SZ的大小,甚至达到1024*2,但不工作,然后我增加了三个,没有改变。
#定义DB_HEAP_SZ (1024 + 256)
#定义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任何#defines你已经提到你的设备是广告的,你想要的所有30个特征?
谢谢mt_dialog.
嗨mt_dialog,
当我定义三个时,我从浅蓝色看不见,
其中一个人,工作正常。
顺便问一下,你使用Skype吗?(ID:ElectronicFan)
谢谢,
安东尼
嗨Antony42,
来自dialog本地团队的成员将很快与您联系以支持您。
谢谢mt_dialog.