大神们,你们好,我自己实现了一个服务和特征值,发现这个特征值能正常接收到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},
我现在是不知道问题出在那里?
你还是把整个工程打包上来吧,看着蛋疼
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.