嗨,对话小组,
我遵循了AN-B-029文档,并成功地将新特性(notify/read)添加到我的服务中。但是,当我添加一个新特性(写/读)时,我无法在其中写入。每次我写作的时候,它都会显示“写作失败”什么都行。是吗有没有像AN-B-029这样的文件提供这些步骤?我被困在这里面了。
但是,现在我想向现有的sample128添加新的服务。我的新服务应该包含这两个特征。我应该如何实现它?请帮忙。
致以最诚挚的问候,
山姆
Device:
嗨,对话小组,
我遵循了AN-B-029文档,并成功地将新特性(notify/read)添加到我的服务中。但是,当我添加一个新特性(写/读)时,我无法在其中写入。每次我写作的时候,它都会显示“写作失败”什么都行。是吗有没有像AN-B-029这样的文件提供这些步骤?我被困在这里面了。
但是,现在我想向现有的sample128添加新的服务。我的新服务应该包含这两个特征。我应该如何实现它?请帮忙。
致以最诚挚的问候,
山姆
你好,山姆,
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”
#包括“atts\u util.h”
#include "sample128.h"
#包括“sample128\u task.h”
#include "attm_cfg.h"
#包括“attm\u db.h”
#包括“prf\u utils.h”
/*
*函数定义
****************************************************************************************
*/
/**
****************************************************************************************
*@brief处理@ref SAMPLE128\u CREATE\u DB\u 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,
ke_task_id_t const src_id)
{
//数据库创建状态
uint8_t status;
uint8_t nb_att_16;
uint8\ t nb\ U att\ U 128;
uint8\ t nb\ U附件32;
uint16_t att_decl_svc = ATT_DECL_PRIMARY_SERVICE;
uint16\u t att\u decl\u char=att\u decl\u特征;
uint16\u t att\u decl\u cfg=att\u DESC\u CLIENT\u CHAR\u 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
nb_att_128=3;//2个UUID128属性声明类型
状态=attmdb\ U add\ U service(&(示例128_环境样品128\U shdl),
任务样本128,
nb_att_16,
注意,附件32,
nb_att_128,
78
);
if (status == ATT_ERR_NO_ERROR)
{
// Add the primary service attribute /////////////////////////////////////////////////////////////////
status=attmdb\u add\u属性(示例128_环境样品128\U 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,ENABLE),//权限
&(样本128)_环境样品128\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\u add\u属性(示例128_环境样品128\U 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,ENABLE),//权限
&(char\u hdl)//特征声明的句柄
);
// Add characteristic value declaration attribute to database
status=attmdb\u add\u属性(示例128_环境样品128\U shdl,
sizeof(uint8\u t),//数据大小=1字节
ATT_UUID_128_LEN,// Size of custom declaration type = 128bit
(uint8\u t*)和样本128\u 1_增值税,//特征值的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\u add\u属性(示例128_环境样品128\U shdl,
ATT_UUID_128_LEN + 3, //Data size = 19 (ATT_UUID_128_LEN + 3)
ATT\u UUID\u 16\u LEN,//声明类型ID的大小
(uint8_t*) &att_decl_char, // 0x2803 for a characteristic declaration
PERM(RD,ENABLE),//权限
&(char\u hdl)//特征声明的句柄
);
// Add characteristic value declaration attribute to database
status=attmdb\u add\u属性(示例128_环境样品128\U shdl,
sizeof(uint8_t), //Data size = 1 Byte
ATT_UUID_128_LEN,// Size of custom declaration type ID = 128bit
(uint8\u t*)和样本128\u 2_增值税,//特征值的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\u add\u属性(示例128_环境样品128\U 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\u add\u属性(示例128_环境样品128\U 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,ENABLE),//权限
&(char\u hdl)//特征声明的句柄
);
// Add characteristic value declaration attribute to database
status=attmdb\u add\u属性(示例128_环境样品128\U shdl,
sizeof(my\u\t),//数据大小=1字节
ATT_UUID_128_LEN,// Size of custom declaration type = 128bit
(uint8\u t*)和样本128\u 3_增值税,//特征值的UUID
PERM(RD,ENABLE)| PERM(WR,ENABLE),//权限
&(val_hdl) // handle to the value attribute
);
//存储特征3的值句柄
memcpy(样本128\u 3_字符属性\u 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,
ke_task_id_t const src_id)
{
uint16_t temp = 1;
// Keep source of message, to respond to it further on
样本128_环境控制信息.appid=src\u id;
//存储启用此配置文件的连接句柄
sample128_env.con_info.conidx = gapc_get_conidx(param->conhdl);
//检查提供的连接是否存在
如果(样本128_环境控制信息.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\u svc\u set\u权限(示例128)_环境样品128\U shdl,参数->二级);
// 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);
//将特征2设置为规定值
attmdb\ att\ set\值(样本128_环境样品128\U shdl+样本128\u 2\u IDX\u VAL,
sizeof(uint8\u t),(uint8\u t*)¶m->sample128\u 2\u val);
//将特征3设置为规定值
attmdb_att_set_value(sample128_env.sample128_shdl + SAMPLE128_3_IDX_VAL,
sizeof(uint8\u t),(uint8\u t*)¶m->sample128\u 3\u val);
样本128_环境特征=参数->特征;
如果(!样本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,
ke_task_id_t const src_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\值(样本128_环境样品128\U shdl+样本128\u 2\u IDX\u 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,
样本128_环境样品128\U shdl+样本128(2×IDX×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消息是否被消耗。
****************************************************************************************
*/
静态int gattc\u write\u cmd\u ind\u handler(ke\u msg\u id\u t const msgid,
结构gattc\u write\u cmd\u ind const*param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8\u t char\u code=SAMPLE128\u ERR\u char;
uint8\u t status=PRF\u APP\u错误;
if(KE\u IDX\u GET(src\u id)=样本128_环境控制信息.conidx文件)
{
if(参数->句柄==sample128_环境样品128\U shdl+样本128\u 1\u IDX\u VAL)
{
char\u code=SAMPLE128\u 1\u char;
}
if (param->handle == sample128_env.sample128_shdl + SAMPLE128_2_IDX_CFG)
{
char_code = SAMPLE128_2_CFG;
}
if(参数->句柄==sample128_环境样品128\U shdl+样本128\u 3\u IDX\u VAL)
{
char\u code=SAMPLE128\u 3\u char;
}
if(char\u code==SAMPLE128\u 1\u 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;
}
else if(char\u code==SAMPLE128\u 2\u 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位设置为1
样本128_环境特征|=PRF\u CLI\u START\u NTF;
}
else
{
//Ntf cfg位设置为0
样本128_环境特征&=~PRF\u CLI\u START\u NTF;
}
status = PRF_ERR_OK;
}
}
else if(char\u code==SAMPLE128\u 3\u 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\ U write\ rsp\ U send(样本128_环境控制信息.conidx,参数->句柄,状态);
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,
ke_task_id_t const src_id)
{
// Check Connection Handle
if(KE\u IDX\u GET(src\u id)=样本128_环境控制信息.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\u UPD\u CHAR2\u REQ,(ke\u msg\u func\t)SAMPLE128\u UPD\u CHAR2\u REQ\u 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]uu attribute_uuuu((节(“retention_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长度;
/// offset at which the data has to be written
uint16 t偏移量;
/// Destination task shall send back a write response command if true.
bool response;
/ / /通知啦st request of a multiple prepare write request.
布尔最后;
/// Data to be written in attribute database
uint8_t value[__ARRAY_EMPTY];
};
换句话说,检查param->handle的值。例如,可以为属性(特征值)创建开关大小写比较:
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,
nb_att_16=1+9+9;//1svc,9char,9user_desc
nb_att_32 = 0;
nb_att_128=9;//值att
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 const uint8 \u t beacon \u user \u desc \u 3[]=“次要”;
...
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\安东尼
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