嗨对话小组,
我遵循了AN-B-029文档,并成功地将新特性(notify/read)添加到我的服务中。但是,当我添加一个新特性(写/读)时,我无法在其中写入。每次我写东西的时候,它都会显示“Writing to characteristic failed”。有没有像AN-B-029这样的文件提供步骤?我被困在这里面了。
但是,现在我想向现有的sample128添加新的服务。我的新服务应该包含这两个特征。我应该如何实现它?请帮助。
最诚挚的问候,
萨姆
Device:

你好,山姆,
profile will receive
GATTC_WRITE_CMD_IND信息。您需要在您的配置文件中附加此消息的处理程序函数,您可能已经这样做了?你能和我分享一下你电脑里的处理函数吗profilename_task.c?Hi VesaN,
I am trying to add a write/read characteristic to the existing sample128.
/**
****************************************************************************************
*
* @file sample128_task.c
*
*@brief Sample128任务实现。
*
*@UUID服务。样本代码
*
*版权所有(C)2013 Dialog S雷竞技电竞平台emiconductor GmbH及其附属公司,未出版作品
* This computer program includes Confidential, Proprietary Information and is a Trade Secret
*Dial雷竞技电竞平台og Semiconductor GmbH及其附属公司。所有使用、披露和/或
*未经书面授权,禁止复制。版权所有。
*
****************************************************************************************
*/
/*
*包含文件
****************************************************************************************
*/
#include "rwble_config.h"
#if (BLE_SAMPLE128)
#include "gap.h"
#包括“gapc.h”
#包括“gattc\u task.h”
#include“Atts_util.h”
#include "sample128.h"
#include“sample128_task.h”
#include "attm_cfg.h"
#包括“attm\u 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 of the receiving task instance (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,
Keu任务\u id \u t const src \u id)
{
//数据库创建状态
uint8_t status;
uint8_t nb_att_16;
uint8\ t nb\ U att\ U 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值hdl;
uint16_t char_hdl;
//Save Profile 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
注意:附件128=3;//2个UUID128属性声明类型
状态=attmdb\u add\u服务(&(sample128\u env.sample128\u shdl),
任务样本128,
nb_att_16,
注意,附件32,
nb_att_128,
78
);
if (status == ATT_ERR_NO_ERROR)
{
// Add the primary service attribute /////////////////////////////////////////////////////////////////
status = attmdb_add_attribute(sample128_env.sample128_shdl,// Attribute Handle
ATT_UUID_128_LEN, // Data size = 16 (ATT_UUID_128_LEN)
ATT_UUID_16_LEN, // Size of declaration type ID
(uint8\u t*)&att\u decl\u svc,//0x2800表示主服务声明
perm(rd,启用),//权限
&(sample128\u env.sample128\u 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 of the service
);
// Characterisitic 1: ////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3, // Data size = 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)//处理特征声明
);
// Add characteristic value declaration attribute to database
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8\u t),//数据大小=1字节
ATT_UUID_128_LEN,// Size of custom declaration type = 128bit
(uint8_t *)&sample128_1_val.uuid,// uuid的特征值
PERM(RD,ENABLE)| PERM(WR,ENABLE),//权限
&(val_hdl) // handle to the value attribute
);
//存储特征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, //Data size = 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)//处理特征声明
);
// Add characteristic value declaration attribute to database
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint8_t), //Data size = 1 Byte
ATT_UUID_128_LEN,// Size of custom declaration type ID = 128bit
(uint8_t *)&sample128_2_val.uuid,// uuid的特征值
PERM(RD, ENABLE) | 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\u att\u set\u value(char\u hdl,sizeof(sample128\u 2\u char),(uint8\u t*)&sample128\u 2\u char);
// Add client configuration declaration attribute to database ( Facilitates Notify )
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(uint16_t), // Data size 2bytes (16bit)
ATT_UUID_16_LEN, // Size of client configuration type ID
(uint8\u t*)&att\u decl\u cfg,//0x2902客户端配置声明类型的UUID
PERM(RD, ENABLE) | PERM(WR, ENABLE), // Permissions
&(val_hdl) // Handle to value attribute
);
//写的特征3:////////////////////////////////////////////////////////////////////////////////
//将特征声明属性添加到数据库
status = attmdb_add_attribute(sample128_env.sample128_shdl,
ATT_UUID_128_LEN + 3, // Data size = 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)//处理特征声明
);
// Add characteristic value declaration attribute to database
status = attmdb_add_attribute(sample128_env.sample128_shdl,
sizeof(my\u\t),//数据大小=1字节
ATT_UUID_128_LEN,// Size of custom declaration type = 128bit
(uint8_t *)&sample128_3_val.uuid,// uuid的特征值
PERM(RD,ENABLE)| PERM(WR,ENABLE),//权限
&(val_hdl) // handle to the value attribute
);
//存储特征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);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Disable sample128 service
attmdb_svc_set_permission(sample128_env.sample128_shdl, PERM(SVC, DISABLE));
//如果我们在这里,数据库已经成功完成,转到空闲状态
ke_state_set(TASK_SAMPLE128, SAMPLE128_IDLE);
}
//Send CFM to application
struct sample128_create_db_cfm * cfm = KE_MSG_ALLOC(SAMPLE128_CREATE_DB_CFM, src_id,
任务(SAMPLE128,SAMPLE128,create,db,cfm);
cfm->status=状态;
ke_msg_send(cfm);
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
*@brief启用Sample128角色,连接后使用。
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance
* @param[in] src_id ID of the sending task instance.
*@return消息是否被消耗。
****************************************************************************************
*/
静态int sample128 \u enable \u req \u handler(ke \u msg \u id \u t const msgid,
struct sample128_enable_req const *param,
ke_task_id_t const dest_id,
Keu任务\u id \u t const src \u id)
{
uint16_t temp = 1;
// Keep source of message, to respond to it further on
sample128\u env.con\u info.appid=src\u id;
//存储启用此配置文件的连接句柄
sample128_env.con_info.conidx = gapc_get_conidx(param->conhdl);
//检查提供的连接是否存在
if(sample128\u env.con\u info.conidx==GAP\u INVALID\u conidx)
{
// The connection doesn't exist, request disallowed
prf_server_error_ind_send((prf_env_struct *)&sample128_env, PRF_ERR_REQ_DISALLOWED,
SAMPLE128\u ERROR\u IND,SAMPLE128\u ENABLE\u REQ);
}
else
{
//Sample128服务权限
attmdb_svc_set_permission(sample128_env.sample128_shdl,param-> sec_lvl);
// Set characteristic 1 to specified value
attmdb_att_set_value(sample128_env.sample128_shdl + SAMPLE128_1_IDX_VAL,
sizeof(uint8_t), (uint8_t *)¶m->sample128_1_val);
// Set characteristic 2 to specified value
attmdb\ att\ set\值(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->特征;
如果(!样本128(环境特征)
{
temp = 0;
}
attmdb_att_set_value(sample128_env.sample128_shdl + SAMPLE128_2_IDX_CFG,
sizeof(uint16_t), (uint8_t *)&temp);
// Go to Connected state
keu state集(TASK\u SAMPLE128,SAMPLE128\u CONNECTED);
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Updates value of characteristic 2. Sends notification to peer if property is enabled.
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance
* @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,
Keu任务\u id \u t const src \u id)
{
uint8_t status = PRF_ERR_OK;
// Check provided values
if(param->conhdl == gapc_get_conhdl(sample128_env.con_info.conidx))
{
// Update value in database
attmdb\ att\ set\值(sample128\ env.sample128\ shdl+sample128\ 2\ IDX\ VAL,
sizeof(uint8_t), (uint8_t *)¶m->val);
if((sample128_env.feature & PRF_CLI_START_NTF))
// Send notification through GATT
prf_server_send_event((prf_env_struct *)&sample128_env, false,
sample128\u env.sample128\u shdl+sample128\u 2\u IDX\u VAL);
}
else
{
status = PRF_ERR_INVALID_PARAM;
}
if (status != PRF_ERR_OK)
{
sample128_upd_char2_cfm_send(status);
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
*@brief处理@ref GATT\u WRITE\u CMD\u IND消息的接收。
*@param[in]收到的消息的msgid Id(可能未使用)。
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (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,
结构gattc\u write\u cmd\u ind const*param,
ke_task_id_t const dest_id,
Keu任务\u id \u t const src \u id)
{
uint8\u t char\u code=SAMPLE128\u ERR\u char;
uint8\u t status=PRF\u APP\u错误;
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\u code==SAMPLE128\u 1\u char)
{
//保存值(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)
{
// Written value
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_NTFIND)| |(ntf_cfg==PRF_CLI_ntf START))
{
//保存值(DB)
attmdb_att_set_value(param->handle, sizeof(uint16_t), (uint8_t *)¶m->value[0]);
//在环境中保存信息
if (ntf_cfg == PRF_CLI_START_NTF)
{
// ntf cfg bit设置为1
sample128|env.feature |=PRF|u CLI|u START|NTF;
}
else
{
// ntf cfg bit设置为0
sample128_env.feature&=〜prf_cli_start_ntf;
}
status = PRF_ERR_OK;
}
}
else if(char\u code==SAMPLE128\u 3\u char)
{
//保存值(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->handle,status);
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Disconnection indication to sample128.
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance
* @param[in] src_id ID of the sending task instance.
*@return消息是否被消耗。
****************************************************************************************
*/
static int gap_disconnnect_ind_handler(ke_msg_id_t const msgid,
结构gapc\u disconnect\u ind const*参数,
ke_task_id_t const dest_id,
Keu任务\u id \u t const src \u id)
{
// Check Connection Handle
if(ke_idx_get(src_id)== sample128_env.con_info.conidx)
{
//在任何情况下,通知应用程序关于断开连接
sample128_disable();
}
return (KE_MSG_CONSUMED);
}
/*
* GLOBAL VARIABLE DEFINITIONS
****************************************************************************************
*/
///禁用状态处理程序定义。
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},
};
/// Default State handlers definition
const struct ke \u msg \u handler sample128 \u default \u state[]=
{
{GAPC_DISCONNECT_IND, (ke_msg_func_t) gap_disconnnect_ind_handler},
};
///指定每个输入状态的消息处理程序结构。
const struct ke\u state\u handler sample128\u state\u handler[sample128\u state\u MAX]=
{
[SAMPLE128\u DISABLED]=KE\u STATE\u HANDLER(SAMPLE128\u 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,
you can't have
{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长度;
/// offset at which the data has to be written
uint16_t偏移;
/// Destination task shall send back a write response command if true.
bool response;
/ / /通知的最后的请求的多个公关epare write request.
布尔最后;
/// Data to be written in attribute database
uint8_t value[__ARRAY_EMPTY];
};
换句话说,检查参数 - >手柄的值。例如,您可以为属性(特征值)创建交换盒比较:
switch(param->handle - your_profile_env.start_handle) {
case CHAR1: break;
case CHAR2: break;
}
Sorry, this is a bit hastily written. Didn't test but I hope you got some picture out of this
Thanks!
Hi,
我只能在一个服务中添加8个特性,当我添加第9个特性时,它没有运行,有人尝试过这个吗?
嗨,红熊,
这取决于您在您的服务中添加的特征。软件支持每次服务32个属性。
Thanks MT_dialog
Hi MT_dialog,
注意16=1+9+9;//1svc,9字符,9用户描述
nb_att_32 = 0;
注意:附件128=9;//val附件
I roughly understand, but 28 < 32.
嗨,红熊,
你说它不运行是什么意思?你能调试你的应用程序以查看它是否通过app\u adv\u start()函数吗?
您可以在一个服务中拥有9个特征。请检查您的代码很容易用复制和粘贴造成错误。
Thanks MT_dialog
Hi MT_dialog,
“它不跑”意味着我不能从浅蓝色看东西。
首先我写了一个宏开关来添加两个字符,可能是你说的复制和粘贴错误,
but now I add two macro switch, only add the 8th one, ok. only add the 9th one, ok, that means the code is right.
add both, I can not see from lightblue.
use keil?
还有别的调试方法吗?
I think the user desc string is a little long,
I made it shorter, nowit is working!
但限制是多少?
Hi antony,
I didn't get it what did you make shorter and worked ?
Thanks MT_dialog
Hi MT_dialog,
I changed CHAR_USER_DESCRIPTION length like following:
old one:
static const uint8_t beacon_user_desc_1[] = "Beacon UUID";
static const uint8 \u t beacon \u user \u desc \u 2[]=“主要标识ID”;
static const uint8_t beacon_user_desc_3[] = "Minor identity ID";
... until 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”;
...
and it works.
Hi antony42,
您正在更改数据库的特征或广告字符串?广告字符串具有固定的最大数量为29字节有效载荷。与数据库无关。
Thanks MT_dialog
Hi MT_dialog,
数据库的特点,
ATT_DESC_CHAR_USER_DESCRIPTION,我制作了描述字符串较短,服务中的9个特征可以正常。
Hi,
I added sereral services and 28 characteristics in total, works fine,
but I add another two characteristics and I can see from light blue but can not connect,
why and how many characteristics in a project at most?
Hi 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.
Thanks MT_dialog
Hi MT_dialog,
I tried, still not working.
first I increased the size of DB_HEAP_SZ, even up to 1024*2,but not working, then I increased anthoner three, nothing changed.
#定义DB\u HEAP\u SZ(1024+256)
#define ENV_HEAP_SZ 328
#定义MSG\u HEAP\u SZ 1312
#定义非\u RET \u HEAP \u SZ 1024
undef one of the following, everything is ok, add these three beacon will not work.
CFG_BEACON_CONFIG_STRUCT
CFG\ PRF\ SPOTAR公司
cfg_prf_anthony.
What may cause this problem?
Thanks a lot,
anthony.
Hi antony42,
When you are #undef any of #defines you 've mentioned your device is advertising with all 30 characteristics you want ?
Thanks MT_dialog
Hi MT_dialog,
when I #def the three, I can't see from light blue,
undef one of them, works fine.
by the way, do you use skype? (id:electronicfan)
Thanks,
安东尼
Hi antony42,
A member from dialog's local team will contact you soon in order to support you.
Thanks MT_dialog