添加服务

大神们,你们好,我自己实现了一个服务和特征值,发现这个特征值能正常接收到ble助手这种通用的APP发的数据,当接收别的APP发的数据时gatt_write_cmd_ind_handler这个函数一点反应没有,不知道是什么问题?

别的APP指的是什么?这个APP是不是能够发现你所建立的服务并且对对应的特征值进行操作?

安安 发表于 2015-5-13 15:49
别的APP指的是什么?这个APP是不是能够发现你所建立的服务并且对对应的特征值进行操作?

做的应用APP,可以发现服务和特征值,并且会返回写成功,就是固件这边没反应,但app没问题,因为我用TI的板子可以正常接收

如果对于LightBlue等等调试用的app都可以正常读写的话,我觉得可能更大的是出现在你们自己做的app上。

安安 发表于 2015-5-13 16:07
如果对于LightBlue等等调试用的app都可以正常读写的话,我觉得可能更大的是出现在你们自己做的app上。

这个APP对应的TI版本的固件已经做好了,测试正常的,不知道是不是添加的服务和特征值有问题

用LightBlue调试,如果用LightBlue写特征值,gatt_write_cmd_ind_handler函数得不到调用,应该考虑你的固件问题;检查程序。
建议下位机调试阶段都用LightBlue 读写。

楼主我现在参照防丢器程序在自己的工程中添加了自定义的服务,可是用lightblue搜索不到自定义服务,你能帮我分析下可能的原因吗?万分感谢

ydz 发表于 2015-5-27 11:45
楼主我现在参照防丢器程序在自己的工程中添加了自定义的服务,可是用lightblue搜索不到自定义服务,你能帮 …

添加的过程是怎样的,都加了那些代码,结果哪里与你想的结果不符,为什么与你想的不符,描述一下吧,亲,只有描述得够详细,才有得分析。

本帖最后由 ydz 于 2015-5-27 16:09 编辑

FireBLE_blue 发表于 2015-5-27 14:28
添加的过程是怎样的,都加了那些代码,结果哪里与你想的结果不符,为什么与你想的不符,描述一下吧,亲, …

我基于 simple_periheral 工程
在attm.h 中添加
USER_SERVICE =        0xfff1,
USER_CHARACTERISTIC,

在profile 里面添加了 test.h  test.c   test_task.h   test_task.c
test.h 文件里面的部分内容
enum
{
TEST_IDX_SVC,

TEST_IDX_CHAR,
TEST_IDX_DATA_VAL,

TEST_IDX_NB,
};

struct test_env_tag
{
struct prf_con_info con_info;
uint16_t shdl;
};

//user Database Description
extern const struct atts_desc test_att_db[TEST_IDX_NB];

extern const atts_svc_desc_t test_svc;

extern const struct atts_char_desc test_char;

extern struct test_env_tag test_env;
test.c

const struct atts_desc test_att_db[TEST_IDX_NB] =
{
//User TEST Service Declaration
[TEST_IDX_SVC] = {USER_SERVICE, PERM(RD, ENABLE), sizeof(test_svc),
sizeof(test_svc), (uint8_t *)&test_svc},

//test Characteristic Declaratoin
[TEST_IDX_CHAR] = {ATT_DECL_CHARACTERISTIC, PERM(RD, ENABLE), sizeof(test_char),
sizeof(test_char), (uint8_t *)&test_char},

// test Characteristic Value
[TEST_IDX_DATA_VAL] = {USER_CHARACTERISTIC, PERM(RD, ENABLE) | PERM(WR, ENABLE), sizeof(uint8_t),
0, NULL},
};

const atts_svc_desc_t test_svc = USER_SERVICE;

//User Service test data
const struct atts_char_desc test_char = ATTS_CHAR(ATT_CHAR_PROP_RD | ATT_CHAR_PROP_WR,
0,
USER_CHARACTERISTIC);

struct test_env_tag test_env;

void test_init(void)
{
// Reset Environment
memset(&test_env, 0, sizeof(test_env));

// Register USER TEST task into kernel
task_test_desc_register();

ke_state_set(TASK_USER, TEST_DISABLED);
}

void test_disable(void)
{
// Disable testin database
attsdb_svc_set_permission(test_env.shdl, PERM_RIGHT_DISABLE);

struct test_disable_ind *ind = KE_MSG_ALLOC(TEST_DISABLE_IND,
TASK_APP,
TASK_USER,//test_env.con_info.appid, TASK_USER,
test_disable_ind);

//Fill in data
ind->conhdl = TASK_APP;
//Send the message
ke_msg_send(ind);

//Go to idle state
ke_state_set(TASK_USER, TEST_IDLE);
}

test_task.h

// Maximum number of Proximity Reporter task instances
#define TEST_IDX_MAX (1)

// Possible states of the test task
enum
{
// Disabled State
TEST_DISABLED,

// Idle State
TEST_IDLE,
// Connected State

TEST_CONNECTED,

// Number of define State
TEST_STATE_MAX
};

// Messages for Characteristic Reporter
enum
{
// Start the Characteristic reporter
TEST_ENABLE_REQ = KE_FIRST_MSG(TASK_USER),

//Disable confirm
TEST_DISABLE_IND,

// Add Characteristic into the database
TEST_CREATE_DB_REQ,

// Inform APP of database creation status
TEST_CREATE_DB_CFM,

// Error Indicaton
TEST_ERROR_IND
};

// Parameters of the CREATE_DB_REQ message
struct test_create_db_req
{
// Indicate
uint8_t features;
};

// Parameters of the ENABLE_REQ message
struct test_enable_req
{
// Connection Handle
uint16_t conhdl;
// Security level
uint8_t sec_lvl;
// Saved user data to set in ATT DB
uint8_t data;
};

// Parameters of the CREATE_DB_CFM message
struct test_create_db_cfm
{
// States
uint8_t status;
};

// Parameters of the DISABLE_IND message
struct test_disable_ind
{
// Connection Hanle
uint16_t conhdl;
//user data
uint8_t data;
};

extern const struct ke_state_handler test_state_handler[TEST_STATE_MAX];
extern const struct ke_state_handler test_default_handler;
extern ke_state_t test_state[TEST_IDX_MAX];

extern void task_test_desc_register(void);

test_task.c
static int test_create_db_req_handler(ke_msg_id_t const msgid,
struct test_create_db_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
// Databsae Creation Status
uint8_t status;

// Save Profile ID
test_env.con_info.prf_id = TASK_USER;

/*---------------------------------------------------*
* User Characteristic Creation
*---------------------------------------------------*/

// Add Service Into Database
status = atts_svc_create_db(&test_env.shdl, NULL, TEST_IDX_NB, NULL,
dest_id, &test_att_db[0]);

if(status == ATT_ERR_NO_ERROR)
{
attsdb_svc_set_permission(test_env.shdl, PERM(SVC, DISABLE));
//If we are here, database has been fulfilled with success, go to idle state
ke_state_set(TASK_USER, TEST_IDLE);
}

//Send CFM to application
struct test_create_db_cfm * cfm = KE_MSG_ALLOC(TEST_CREATE_DB_CFM, src_id,
TASK_USER, test_create_db_cfm );
cfm->status = status;
ke_msg_send(cfm);

return (KE_MSG_CONSUMED);
}

static int test_enable_req_handler(ke_msg_id_t const msgid,
struct test_enable_req const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{

// Keep source of message, to respond to it furture on
test_env.con_info.appid = src_id;
// Strore the connection handle for which this profile is enable
test_env.con_info.conhdl = param->conhdl;

// Check if the provided connection exist
if(gap_get_rec_idx(param->conhdl) == GAP_INVALID_CONIDX)
{
// The connection doesn't exist, request disallowed
prf_server_error_ind_send((prf_env_struct *)&test_env, PRF_ERR_REQ_DISALLOWED,
TEST_ERROR_IND, TEST_ENABLE_REQ);
}
else
{

//Enable Characteristic + Set Security Level
attsdb_svc_set_permission(test_env.shdl, param->sec_lvl);

//Set Characteristic specified value
attsdb_att_set_value(test_env.shdl + TEST_IDX_DATA_VAL,
sizeof(uint8_t), (uint8_t *)¶m->data);

// Go to Connected state
ke_state_set(TASK_USER, TEST_CONNECTED);
}

return (KE_MSG_CONSUMED);
}

static int gatt_write_cmd_ind_handler(ke_msg_id_t const msgid,
struct gatt_write_cmd_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{

if(param->conhdl == test_env.con_info.conhdl)
{
if(param->handle == test_env.shdl + TEST_IDX_DATA_VAL)
{
attsdb_att_set_value(param->handle, sizeof(uint8_t), (uint8_t *)¶m->value[0]);
}
}

return (KE_MSG_CONSUMED);
}

static int gap_discon_cmp_evt_handler(ke_msg_id_t const msgid,
struct gap_discon_cmp_evt const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{

// Check Connection Handle
if(param->conhdl == test_env.con_info.conhdl)
{
// Abnormal reason - APP must alert to the level specified in the Alert Level Char.
//        if ((param->reason != CO_ERROR_REMOTE_USER_TERM_CON) &&
//        (param->reason != CO_ERROR_CON_TERM_BY_LOCAL_HOST))
//        {

//        }
test_disable();
}

return (KE_MSG_CONSUMED);
}

// Disable State handler definetion
const struct ke_msg_handler test_disabled[] =
{
{TEST_CREATE_DB_REQ, (ke_msg_func_t)test_create_db_req_handler},
};

// Idle State handler definetion
const struct ke_msg_handler test_idle[] =
{
{TEST_ENABLE_REQ, (ke_msg_func_t)test_enable_req_handler},
};

// Connected State handler definition
const struct ke_msg_handler test_connected[] =
{
{GATT_WRITE_CMD_IND, (ke_msg_func_t)gatt_write_cmd_ind_handler},
};

// Default State handlers definition
const struct ke_msg_handler test_default_state[] =
{
{GAP_DISCON_CMP_EVT, (ke_msg_func_t)gap_discon_cmp_evt_handler},
};

// Specifies the mssage handler structure for every input state
const struct ke_state_handler test_state_handler[TEST_STATE_MAX] =
{
[TEST_DISABLED] = KE_STATE_HANDLER(test_disabled),
[TEST_IDLE]        = KE_STATE_HANDLER_NONE,//KE_STATE_HANDLER(test_idle),
[TEST_CONNECTED]        = KE_STATE_HANDLER(test_connected),
};

// Specifies the message handlers that are common to all states
const struct ke_state_handler test_default_handler = KE_STATE_HANDLER(test_default_state);

// Defines the place holder for the states of all the task instances
ke_state_t test_state[TEST_IDX_MAX];

// Register test task into kernel
void task_test_desc_register(void)
{
struct ke_task_desc task_test_desc;

task_test_desc.state_handler = test_state_handler;
task_test_desc.default_handler = &test_default_handler;
task_test_desc.state = test_state;
task_test_desc.state_max = TEST_STATE_MAX;
task_test_desc.idx_max = TEST_IDX_MAX;

task_desc_register(TASK_USER, task_test_desc);
}

app 里面添加 app_test.h app_test.c  app_test_task.h app_test_task.c
app_test.c
void app_test_create_db(uint8_t features)
{
struct test_create_db_req *msg = KE_MSG_ALLOC(TEST_CREATE_DB_REQ, TASK_USER, TASK_APP,
test_create_db_req);
msg->features = features;
ke_msg_send(msg);
}

void app_test_enable_req(uint16_t conhdl, uint8_t sec_lvl, uint8_t data)
{
struct test_enable_req *msg = KE_MSG_ALLOC(TEST_ENABLE_REQ, TASK_USER, TASK_APP,
test_enable_req);
msg->conhdl = conhdl;
msg->sec_lvl = sec_lvl;
msg->data = data;
ke_msg_send(msg);
}

app_test_task.c
struct app_test_env_tag *app_test_env = &app_env.test_ev;

int app_test_create_db_cfm_handler(ke_msg_id_t const msgid,
struct test_create_db_cfm *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
if(param->status == ATT_ERR_NO_ERROR)
{
app_clear_local_service_flag(BLE_QPPS_SERVER_BIT);
}

return (KE_MSG_CONSUMED);
}

int app_test_disable_ind_handler(ke_msg_id_t const msgid,
struct test_disable_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
app_test_env->conhdl = 0xFFFF;
app_test_env->enabled = false;

return (KE_MSG_CONSUMED);
}

本帖最后由 ydz 于 2015-5-27 16:14 编辑

FireBLE_blue 发表于 2015-5-27 14:28
添加的过程是怎样的,都加了那些代码,结果哪里与你想的结果不符,为什么与你想的不符,描述一下吧,亲, …

app_until.c  app_get_local_service_flag 函数添加
srv_flag |= BLE_QPPS_SERVER_BIT;

app_env.c 修改
    //app_set_scan_rsp_data(0);
   app_set_scan_rsp_data(BLE_QPPS_SERVER_BIT);

函数 app_init(void)  添加
app_test_init();

static void app_test_init(void)
{
        app_test_env->conhdl = 0xFFFF;
}

prf_utils.c  prf_init() 函数添加
test_init();

app_task.c   const struct ke_msg_handler app_default_state[] =  里面添加
    {TEST_DISABLE_IND,                     (ke_msg_func_t) app_test_disable_ind_handler},
    {TEST_CREATE_DB_CFM,                   (ke_msg_func_t) app_test_create_db_cfm_handler},

我现在是不知道问题出在那里?

:cry: 你还是把整个工程打包上来吧,看着蛋疼

FireBLE_blue 发表于 2015-5-27 18:10
你还是把整个工程打包上来吧,看着蛋疼

大哥,文档传不上来,我放网盘了 BLE TEST , 麻烦你帮忙看下。话说2540添加真心比这个方便,也容易理解…

期待解决这个问题。

本帖最后由 FireBLE_blue 于 2015-5-28 11:54 编辑

ydz 发表于 2015-5-28 09:33
大哥,文档传不上来,我放网盘了 BLE TEST , 麻烦你帮忙看下。话说2540添加真心比这个方便,也容易理解 …

看了,我尝试改了好几处,还是没有成功,小改一下就挂了

FireBLE_blue 发表于 2015-5-28 11:51
看了,我尝试改了好几处,还是没有成功,小改一下就挂了

到现在还没有清楚添加流程,资料太少了! 并且改动的地方比较多。 大家一起研究各!

本帖最后由 ydz 于 2015-5-28 14:58 编辑

ydz 发表于 2015-5-28 12:16
到现在还没有清楚添加流程,资料太少了! 并且改动的地方比较多。 大家一起研究各!

问题找到了! 还是自己对协议栈不熟引起的, 做如下修改就可以了。

/// Full LLS Database Description - Used to add attributes into the database
const struct atts_desc proxr_lls_att_db[LLS_IDX_NB] =
{
// Link Loss Service Declaration
[LLS_IDX_SVC] = {ATT_DECL_PRIMARY_SERVICE, PERM(RD, ENABLE), sizeof(proxr_lls_svc)
sizeof(proxr_lls_svc), (uint8_t *)&proxr_lls_svc

// Alert Level Characteristic Declaration
[LLS_IDX_ALERT_LVL_CHAR]        =   {ATT_DECL_CHARACTERISTIC, PERM(RD, ENABLE), sizeof(proxr_lls_alert_lvl_char),
                                     sizeof(proxr_lls_alert_lvl_char), (uint8_t *)&proxr_lls_alert_lvl_char},
// Alert Level Characteristic Value
[LLS_IDX_ALERT_LVL_VAL]         =   {ATT_CHAR_ALERT_LEVEL, PERM(RD, ENABLE) | PERM(WR, ENABLE), sizeof(uint8_t),
                                     0, NULL},

};

:victory:

ydz 发表于 2015-5-28 14:48
问题找到了! 还是自己对协议栈不熟引起的, 做如下修改就可以了。

/// Full LLS Database Descrip …

楼主是贴出的上面的代码是怎么解决问题的,能详细说明一下吗?

connycommy 发表于 2015-5-29 10:08
楼主是贴出的上面的代码是怎么解决问题的,能详细说明一下吗?

这个说明在 BLE标准Core_v4.0 的 P1907.