藍牙芯片----BK3431開發筆記------RW stack中添加自定義服務教程(4)
一、實現自定義服務
在 RW 協議棧協議棧中添加一個自定義服務需要實現 6 個文件,分別為:
custom.c
custom.h
custom_task.c
custom_task.h
app_custom.c
app_custom.h
在 sdk\ble_stack\common\profiles\custom。將custom.h、custom_task.h文件放在api目錄下,custom.c、custom_task.c兩個文件放在src目錄下。將app_custom.c與app_custom.h存放在projects\ble\ble_app_gatt\app\下。
本文檔以 custom 服務為例介紹了如何添加一個服務到 RW 的詳細步驟。
1. sdk\ble_stack\common\profiles\custom 目錄如下:
2. projects\ble_app_gatt\app 目錄如下:
二、添加 service 到工程中
1. 使用 keil 5.12 打開對應工程,在工程目錄 profile 目錄下添加指定 profile 相關源文
件,本例中是 custom.c 和 custom_task.c,如下圖:
2. 在 keil C/C++選項卡下面添加對應 profile 的路徑,如下:
3. 在工程目錄 app 目錄下添加指定自定義服務在應用層文件:
4. 在 app_task.c 文件中找到 appm_msg_handler 函數,在其中自定義服務獲取 handler 的
函數,如下:
case (TASK_ID_CUSTOM):
{
// Call the custom Modules
msg_pol = appm_get_handler(&app_custom_table_handler, msgid, param, src_id);
} break;
5. 在 app.c 文件中的服務列表中添加自定義服務,如下:
/// List of service to add in the database
enum appm_svc_list
{
APPM_SVC_CUSTOM,
APPM_SVC_DIS,
APPM_SVC_BATT,
APPM_SVC_OADS,
APPM_SVC_LIST_STOP ,
};
6. 在 app.c 文件中的函數列表中增加往 db 添加自定義服務的函數,如下:
/// List of functions used to create the database
static const appm_add_svc_func_t appm_add_svc_func_list[APPM_SVC_LIST_STOP] =
{
(appm_add_svc_func_t)app_custom_add_custom,
(appm_add_svc_func_t)app_dis_add_dis,
(appm_add_svc_func_t)app_batt_add_bas,
(appm_add_svc_func_t)app_oad_add_oads,
};
7. 在 app.c 文件中找到 appm_init 函數,在其中添加 app_custom_init()函數,如下
8. 在 rwip_task.h 文件中增加自定義服務的 task_id,如下:
9. 在 prf.c 文件中添加 custom_prf_itf_get()的調用:
10. 在 prf.c 文件中添加 custom_prf_itf_get()的聲明:
11. 在 rwprf_config.h 文件中增加如下定義:
BLE_CUSTOM_SERVER 這 個 宏 定 義 在 custom.c 、 custom.h 、 custom_task.c 、 custom_task.h 中都有用到,只有當這個宏被打開后,編譯器在編譯的時候才能把 自定義的服務編譯進去。部分截圖如下
以上步驟全部完成之后,整體編譯 project,使用 lightblue 連接進行驗證是否添 加成功。
三、app_custom.c 接口說明:
度 備注
1. custom 服務實現了兩個特征,其 UUID 及相關屬性如下表所示
UUID
20bytes
20bytes
2. 數據發送 API
例如:
//send data api
void app_fff1_send_lvl(uint8_t* buf, uint8_t len)
{
if(app_fff0_env.send_status==0)
{
app_fff0_env.send_status=1;
// Allocate the message
struct fff0s_fff1_level_upd_req * req = KE_MSG_ALLOC(FFF0S_FFF1_LEVEL_UPD_REQ,
prf_get_task_from_id(TASK_ID_FFF0S),
TASK_APP,
fff0s_fff1_level_upd_req);
// Fill in the parameter structure
req->length = len;
memcpy(req->fff1_level, buf, len);
// Send the message
ke_msg_send(req);
}
}
3. 數據接收回調
例如:
//數據接收回調函數
static int fff2_writer_req_handler(ke_msg_id_t const msgid,
struct fff0s_fff2_writer_ind *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
// Drop the message
UART_PRINTF("FFF2 param->value = 0x ");
for(uint8_t i = 0;i < param->length;i++)
{
UART_PRINTF("%02x ",param->fff2_value[i]);
}
UART_PRINTF("\r\n");
return (KE_MSG_CONSUMED);
}
4. 數據發送狀態回復
static int fff1_level_upd_handler(ke_msg_id_t const msgid,
struct fff0s_fff1_level_upd_rsp const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
if(param->status == GAP_ERR_NO_ERROR)
{
//uint8_t buf[128];
//memset(buf, 0xcc, 128);
//app_fff1_send_lvl(buf, 128);
app_fff0_env.send_status=0;
}
return (KE_MSG_CONSUMED);
}
5. Notify 成功使能回調
static int fff0s_fff1_level_ntf_cfg_ind_handler(ke_msg_id_t const msgid,
struct fff0s_fff1_level_ntf_cfg_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
UART_PRINTF("param->ntf_cfg = %x\r\n",param->ntf_cfg);
if(param->ntf_cfg == PRF_CLI_STOP_NTFIND)
{
//ke_timer_clear(FFF0S_FFF1_LEVEL_PERIOD_NTF,dest_id);
}else
{
//ke_timer_set(FFF0S_FFF1_LEVEL_PERIOD_NTF,dest_id , 1);
}
return (KE_MSG_CONSUMED);
}
為了系統的穩定,應用層發送 notify 到手機端時需要在發送完成一包數據之后再 觸發下一次的發送。
移動APP
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。