Hi Dialog Team,
我遵循AN-B-029文档,并成功地将新的特征(通知/读取)添加到我的服务中。但是,当我添加一个新的特征时(写/读取),我无法写入它。当我写任何东西时,每次都会显示“写入特征失败”。如果有任何文件,如AN-B-029,它将提供步骤?我陷入了困境。
但是,现在我想向现有的示例添加新服务。而我的新服务应该包含两个特征。我该如何实施它?请帮忙。
With Best Regards,
Sam
Keywords:
设备:

你好山姆,
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"
/ *
*FUNCTION DEFINITIONS
****************************************************************************************
* /
/ **
****************************************************************************************
*@brief Handles reception of the @ref SAMPLE128_CREATE_DB_REQ message.
* @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_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 Service Creation
* -------------------------------------------- * /
//Add Service Into Database
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, ENABLE), // Permissions
&(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: ////////////////////////////////////////////////////////////////////////////////
// Add characteristic declaration attribute to database
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, ENABLE), // Permissions
&(char_hdl) // Handle to the characteristic declaration
);
//将特征值声明属性添加到数据库
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 of the characteristic value
perm(rd,启用)|perm(wr,启用),//权限
&(val_hdl)//句柄到值属性
);
//存储特性1的值句柄1
memcpy(sample128_1_char.attr_hdl,&val_hdl,sizeof(uint16_t));
// Set initial value of characteristic 1
status = attmdb_att_set_value(char_hdl,sizeof(sample128_1_char),(uint8_t *)和sample128_1_char);
//特征2://///////////////////////////////////////////////////////////////////////////////////////////
// Add characteristic declaration attribute to database
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, ENABLE),// Permissions
&(char_hdl) // Handle to the characteristic declaration
);
//将特征值声明属性添加到数据库
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 of the characteristic value
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));
// Set initial value of characteristic 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://///////////////////////////////////////////////////////////////////////////////////////
// Add characteristic declaration attribute to database
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, ENABLE), // Permissions
&(char_hdl) // Handle to the characteristic declaration
);
//将特征值声明属性添加到数据库
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 of the characteristic value
perm(rd,启用)|perm(wr,启用),//权限
&(val_hdl)//句柄到值属性
);
//存储特征3的值句柄
memcpy(sample128_3_char.attr_hdl, &val_hdl, sizeof(uint16_t));
// Set initial value of characteristic 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));
//If we are here, database has been fulfilled with success, go to idle state
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;
// Store the connection handle for which this profile is enabled
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 *)¶m->sample128_2_val);
//将特征3设置为指定值
attmdb_att_set_value(sample128_env.sample128_shdl + SAMPLE128_3_IDX_VAL,
sizeof(uint8_t), (uint8_t *)¶m->sample128_3_val);
sample128_env.feature = param->feature;
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如果邮件被消耗或不。
****************************************************************************************
* /
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.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->handle, sizeof(uint8_t), (uint8_t *)¶m->value[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))
{
//保存DB中的值
attmdb_att_set_value(param->句柄,sizeof(uint16_t),(uint8_t *)和param->值[0]);
//保存环境中的信息
if(ntf_cfg == prf_cli_start_ntf)
{
// Ntf cfg bit set to 1
sample128_env.feature | = prf_cli_start_ntf;
}
别的
{
// Ntf cfg bit set to 0
sample128_env.feature &= ~PRF_CLI_START_NTF;
}
status = PRF_ERR_OK;
}
}
否则if(char_code == sample128_3_char)
{
//保存DB中的值
attmdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)¶m->value[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)
{
// In any case, inform APP about disconnection
sample128_disable();
}
return (KE_MSG_CONSUMED);
}
/ *
*全局变量定义
****************************************************************************************
* /
/// Disabled State handler definition.
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},
};
/// Idle State handler definition.
const struct ke_msg_handler sample128_idle [] =
{
{sample128_enable_req,(ke_msg_func_t)sample128_enable_req_handler},
};
/// Connected State handler definition.
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},
};
/// Specifies the message handler structure for every input state.
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),
};
/// Specifies the message handlers that are common to all states.
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__((section("retention_mem_area0"),zero_init));
#endif // ble_sample128.
Hi 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。You can tell the difference between each characteristics by inspecting the handle value of the message parameter
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 length;
///要写数据的偏移量
uint16_t offset;
///目标任务如果为true,则应发送返回写入响应命令。
bool response;
/ / /通知的最后的请求的多个公关epare write request.
BOOL最后;
/// Data to be written in attribute database
UINT8_T值[__ array_empty];
};
In other words, inspect the value of the param->handle. Eg., you can create switch case comparison for the attribute (characteristic value):
交换机(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,
It depends on the characteristic's you are adding to your service. The software supports until 32 attributes per service.
谢谢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一个服务的特征。请耐心ase check your code its easy to make a mistake with copying and pasting.
谢谢mt_dialog.
嗨mt_dialog,
“它没有运行”意味着我看不到闪烁。
首先,我编写宏开关以添加两个字符,可能会复制和粘贴您所说的错误,
但现在我添加了两个宏开关,只添加第8个,确定。只添加第9个,确定,这意味着代码是对的。
添加两个,我看不到闪烁。
用keil?
可以使用其他方式调试?
我认为用户DESC字符串有点长,
I made it shorter, nowit is working!
but what is the limit?
嗨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.
new one:
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[] = "Minor";
。。。
and it works.
嗨Antony42,
You are changing the characteristics of the database or the advertising string ? The advertising string has a fixed maximum number of 29 bytes payload. That has nothing to do with the database.
谢谢mt_dialog.
嗨mt_dialog,
数据库的特征,
ATT_DESC_CHAR_USER_DESCRIPTION, I made the description string shorter, 9 characteristics in a service is ok.
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)
谢谢,
Anthony
嗨Antony42,
A member from dialog's local team will contact you soon in order to support you.
谢谢mt_dialog.