嗨对话小组,
我遵循AN-B-029文档,并成功地将新的特征(通知/读取)添加到我的服务中。但是,当我添加一个新的特征时(写/读取),我无法写入它。当我写任何东西时,每次都会显示“写入特征失败”。如果有任何文件,如AN-B-029,它将提供步骤?我陷入了困境。
但是,现在我想向现有的示例添加新服务。而我的新服务应该包含两个特征。我该如何实施它?请帮忙。
最诚挚的问候,
萨姆
设备:
嗨对话小组,
我遵循AN-B-029文档,并成功地将新的特征(通知/读取)添加到我的服务中。但是,当我添加一个新的特征时(写/读取),我无法写入它。当我写任何东西时,每次都会显示“写入特征失败”。如果有任何文件,如AN-B-029,它将提供步骤?我陷入了困境。
但是,现在我想向现有的示例添加新服务。而我的新服务应该包含两个特征。我该如何实施它?请帮忙。
最诚挚的问候,
萨姆
你好山姆,
profile will receive
GATTC_WRITE_CMD_IND信息。您需要在您的个人资料中附加此消息的处理函数,您可能已经已经完成了?你能分享你的处理函数吗?profilename_task.c?嗨Vesan,
I am trying to add a write/read characteristic to the existing sample128.
/ **
****************************************************************************************
*
* @file sample128_task.c.
*
* @brief sample128任务实施。
*
* @brief 128 uuid服务。示例代码
*
*版权所有(c)2013年对话半导体Gmb雷竞技电竞平台H及其关联公司,未发表的工作
*This computer program includes Confidential, Proprietary Information and is a Trade Secret
*对话半导雷竞技电竞平台体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 Pointer to the parameters of the message.
* @param [in]接收任务实例的dest_id ID(probably unused).
*@param[in] src_id ID of the sending task instance.
* @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 status;
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 Attribute declaration types
nb_att_32 = 0; // 0 UUID32 Attribute declaration types
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,//属性句柄
ATT_UUID_128_LEN,//数据大小= 16(ATT_UUID_128_LEN)
ATT_UUID_16_LEN, // Size of declaration type ID
(UINT8_T *)&ATT_DECL_SVC,// 0x2800用于主要服务声明
perm(rd,启用),//权限
&(sample128_env.sample128_shdl)//属性句柄
);
// Add the value of the primary service attribute (The custom UUID)
status = attmdb_att_set_value( sample128_env.sample128_shdl, // Attribute handle
ATT_UUID_128_LEN, // The value is the 128 bit UUID of the service
(uint8_t *)sample128_svc.uuid // uuid的服务
);
// Characterisitic 1: ////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3,//数据大小= 19(ATT_UUID_128_LEN + 3)
ATT_UUID_16_LEN, // Size of declaration type ID
(uint8_t*) &att_decl_char, // 0x2803 for a characteristic declaration
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//将特征值声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t),// data size = 1字节
ATT_UUID_128_LEN,//自定义声明类型= 128位的大小
(uint8_t *)&sample128_1_val.uuid,// uuid的特征值
perm(rd,启用)|perm(wr,启用),//权限
&(val_hdl)//句柄到值属性
);
//存储特性1的值句柄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 for a characteristic declaration
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//将特征值声明属性添加到数据库
status = 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,启用)|PERM(NTF, ENABLE),// Permissions
&(val_hdl) // Handle to the value attribute
);
//存储特性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, // Size of client configuration type ID
(UINT8_T *)&ATT_DECL_CFG,// 0x2902客户端配置声明类型的UUID
perm(rd,启用)|perm(wr,启用),//权限
&(val_hdl)//句柄value属性
);
// writeitisit 3 for write://///////////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3,//数据大小= 19(ATT_UUID_128_LEN + 3)
ATT_UUID_16_LEN, // Size of declaration type ID
(uint8_t*) &att_decl_char, // 0x2803 for a characteristic declaration
perm(rd,启用),//权限
&(char_hdl)//处理特征声明
);
//将特征值声明属性添加到数据库
status = 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,启用)|perm(wr,启用),//权限
&(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);
//////// //////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//禁用示例128服务
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-> status = status;
KE_MSG_SEND(CFM);
return (KE_MSG_CONSUMED);
}
/ **
****************************************************************************************
* @brief启用示例128角色,在连接后使用。
* @param [in]收到的消息的msgid ID。
*@param[in] param Pointer to the parameters of the message.
* @param [in]接收任务实例的dest_id ID
*@param[in] src_id ID of the sending task instance.
* @return如果邮件被消耗或不。
****************************************************************************************
* /
静态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);
//检查是否存在提供的连接
if(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);
}
别的
{
//示例128服务权限
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 *)¶m->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->特征;
if(!sample128_env.feature)
{
temp = 0;
}
attmdb_att_set_value(sample128_env.sample128_shdl + sample128_2_idx_cfg,
sizeof(uint16_t), (uint8_t *)&temp);
// Go to Connected state
ke_state_set(task_sample128,sample128_connection);
}
return (KE_MSG_CONSUMED);
}
/ **
****************************************************************************************
* @brief更新特性值2.如果启用了属性,请向对等体发送通知。
* @param [in]收到的消息的msgid ID。
*@param[in] param Pointer to the parameters of the message.
* @param [in]接收任务实例的dest_id ID
*@param[in] src_id ID of the sending task instance.
* @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;
//检查提供的值
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 *)和param-> val);
if((sample128_env.feature&prf_cli_start_ntf))
// Send notification through 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(status);
}
return (KE_MSG_CONSUMED);
}
/ **
****************************************************************************************
* @brief处理@ref gatt_write_cmd_ind消息的接收。
* @param [in]收到的消息的msgid ID(可能未使用)。
*@param[in] param Pointer to the parameters of the message.
* @param [in]接收任务实例的dest_id ID(probably unused).
*@param[in] src_id ID of the sending task instance.
* @return如果邮件被消耗或不。
****************************************************************************************
* /
msgid静态int gattc_write_cmd_ind_handler(ke_msg_id_t const,
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.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)
{
//Save value in DB
attmdb_att_set_value(param->句柄,sizeof(uint8_t),(uint8_t *)和param->值[0]);
if(param->last)
{
sample128_send_val(param-> value [0]);
}
status = PRF_ERR_OK;
}
否则if(char_code == sample128_2_cfg)
{
//书面价值
uint16_t ntf_cfg;
// Extract value before check
ntf_cfg = co_read16p(¶m->value[0]);
// Only update configuration if value for stop or notification enable
if((ntf_cfg == prf_cli_stop_ntfind)||(ntf_cfg == prf_cli_start_ntf))
{
//Save value in DB
attmdb_att_set_value(param->句柄,sizeof(uint16_t),(uint8_t *)和param->值[0]);
//保存环境中的信息
if(ntf_cfg == prf_cli_start_ntf)
{
// ntf cfg bit设置为1
sample128_env.feature | = prf_cli_start_ntf;
}
别的
{
// ntf cfg bit设置为0
sample128_env.feature&=〜prf_cli_start_ntf;
}
status = PRF_ERR_OK;
}
}
否则if(char_code == sample128_3_char)
{
//Save value in DB
attmdb_att_set_value(param->句柄,sizeof(uint8_t),(uint8_t *)和param->值[0]);
if(param->last)
{
sample128_send_val(param-> value [0]);
}
status = PRF_ERR_OK;
}
}
//发送写回复
ATTS_WRITE_RSP_SEND(Sample128_ENV.CON_INFO.CONIDX,PARAM->句柄,状态);
return (KE_MSG_CONSUMED);
}
/ **
****************************************************************************************
*@brief Disconnection indication to sample128.
* @param [in]收到的消息的msgid ID。
*@param[in] param Pointer to the parameters of the message.
* @param [in]接收任务实例的dest_id ID
*@param[in] src_id ID of the sending task instance.
* @return如果邮件被消耗或不。
****************************************************************************************
* /
static int gap_disconnnect_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)
{
// Check Connection Handle
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},
{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);
/// Defines the place holder for the states of all the task instances.
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}。You need to handle every service characteristics in withGATTC_WRITE_CMD_IND。您可以通过检查消息参数的句柄值来讲述每个特征之间的差异
paramin the handler function. It has the following structure///通知对等设备已请求修改数据库。
struct gattc_write_cmd_ind
{
/// Handle of the attribute that has to be written
uint16_t handle;
///数据长度写入
uint16_t长度;
///要写数据的偏移量
uint16_t偏移;
///目标任务如果为true,则应发送返回写入响应命令。
bool response;
///Informs that it's last request of a multiple prepare write request.
BOOL最后;
/// Data to be written in attribute database
UINT8_T值[__ array_empty];
};
换句话说,检查参数 - >手柄的值。例如,您可以为属性(特征值)创建交换盒比较:
交换机(param->句柄 - your_profile_env.start_handle){
案例char1:休息;
案件char2:休息;
}
Sorry, this is a bit hastily written. Didn't test but I hope you got some picture out of this
谢谢!
Hi,
我只能在服务中添加8个特征,当我添加第9个时,它不运行,有人尝试过这个?
嗨redbear,
这取决于您在您的服务中添加的特征。软件支持每次服务32个属性。
谢谢mt_dialog.
嗨mt_dialog,
nb_att_16 = 1 + 9 + 9;// 1svc,9char,9user_desc
nb_att_32 = 0;
nb_att_128 = 9;// val Att.
I roughly understand, but 28 < 32.
嗨redbear,
你是什么意思它没有运行,你可以调试应用程序,以便查看它是否通过app_adv_start()函数?
您可以在一个服务中拥有9个特征。请检查您的代码很容易用复制和粘贴造成错误。
谢谢mt_dialog.
嗨mt_dialog,
“它没有运行”意味着我看不到闪烁。
首先,我编写宏开关以添加两个字符,可能会复制和粘贴您所说的错误,
但现在我添加了两个宏开关,只添加第8个,确定。只添加第9个,确定,这意味着代码是对的。
添加两个,我看不到闪烁。
用keil?
可以使用其他方式调试?
我认为用户DESC字符串有点长,
I made it shorter, nowit is working!
但限制是多少?
嗨Antony,
I didn't get it what did you make shorter and worked ?
谢谢mt_dialog.
嗨mt_dialog,
I changed CHAR_USER_DESCRIPTION length like following:
旧的:
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 const8_t beacon_user_desc_3 [] =“minor”;
。。。
and it works.
嗨Antony42,
您正在更改数据库的特征或广告字符串?广告字符串具有固定的最大数量为29字节有效载荷。与数据库无关。
谢谢mt_dialog.
嗨mt_dialog,
数据库的特征,
ATT_DESC_CHAR_USER_DESCRIPTION,我制作了描述字符串较短,服务中的9个特征可以正常。
Hi,
I added sereral services and 28 characteristics in total, works fine,
但我添加了另外两个特征,我可以从浅蓝色看,但不能连接,
why and how many characteristics in a project at most?
嗨Antony,
Besides the limitation of 32 attributes per service i 've mentioned in a previous post, theoretically there is no other limitation in the number of characteristics. The only limit is the memory size of your database which is defined by the DB_HEAP_SIZE.
谢谢mt_dialog.
嗨mt_dialog,
我试过,仍然没有工作。
first I increased the size of DB_HEAP_SZ, even up to 1024*2,but not working, then I increased anthoner three, nothing changed.
#define db_heap_sz(1024 + 256)
#define ENV_HEAP_SZ 328
#define msg_heap_sz 1312.
#define non_ret_heap_sz 1024.
undef其中一个,一切正常,添加这三个灯泡不起作用。
CFG_BEACON_CONFIG_STRUCT
cfg_prf_spotar.
cfg_prf_anthony.
What may cause this problem?
非常感谢,
安东尼。
嗨Antony42,
当你是#undef任何#defines你已经提到你的设备是广告的,你想要的所有30个特征?
谢谢mt_dialog.
嗨mt_dialog,
when I #def the three, I can't see from light blue,
其中一个人,工作正常。
顺便问一下,你使用Skype吗?(ID:ElectronicFan)
谢谢,
安东尼
嗨Antony42,
A member from dialog's local team will contact you soon in order to support you.
谢谢mt_dialog.