验目的:自定义Service私有服务并传输温湿度传感器数据。本实验基于SDK17.02中ble_app_uart示例代码基于ble_bls.h进行更改。
背景
1.1GAP初始化,要完成三个工作:
a.GAP初始化安全模式配置,安全模式指连接时是否需要身份验证。
b.蓝牙设备名称设置,即设置蓝牙广播的名字,注意名称长度有限制,最好不要超过十八个字节
c.连接参数设置,连接参数设置,主要是设置:最小连接间隔、最大连接间隔、从机设备潜伏周期、连接超时时间。这些值代表了外围设备针对连接的期望参数。
1.2GATT称为通用属性规范(Generic Attribute profile,GATT),GATT层是传输真正数据所在的 层。包括一个数据传输和存储框架以及其基本操作。其大部分自定义函数在.C写的,在主函数中只需要初始化和配置函数间的关系。
GATT使用了 ATT(Attribute Protocol)协议,ATT 协议把 Service,Characteristic 对应的数据保存在一个查找表中,查找表使用 16bit ID 作为每一项的索引。GATT定义的多层数据结构简要概括起来就是 服务(Service) 可以包含多个 特征(Characteristic),每个特征包含 属性(Properties) 和 值(Value),还可以包含多个 描述(Descriptor)。
main.c函数
1.宏定义
APP_TIMER_DEF(m_battery_timer_id); //实例化定时器id
BLE_LBS_mpu6050_DEF(m_mpu6050);//观察者模式,将上述声明进行定义(实例化),即在RAM中分配内存空间
2.定时器m_battery_timer_id
err_code = app_timer_create(&timer_name_temp_measure_id,
APP_TIMER_MODE_REPEATED,
measure_timer_handler);
回调函数measure_timer_handlert—>>>ble_bas_battery_level_update
TIME_TEMP为模拟值
ble_bas_battery_level_update(&m_mpu6050, TIME_TEMP, BLE_CONN_HANDLE_ALL);
3.services_init
主要是初始化ble_lbs.c里的ble_lbs_init
ble_lbs_init_t bas_init_obj;
memset(&bas_init_obj, 0, sizeof(bas_init_obj));
err_code = ble_lbs_init(&m_mpu6050, &bas_init_obj);
ble_lbs.c函数
battery_level为模拟电量的value
1#define:ble_lbs.h观察者模式
**(ble_lbs.h)**NRF_SDH_BLE_OBSERVER—>>>ble_lbs_on_ble_evt—>>> lbs_c_evt_handler()
1.1ble_lbs_on_ble_evt:
case BLE_GATTS_EVT_WRITE: //LED特征被写入数据时,产生了GATT写事件,就会调用on_write函数。
lbs_c_evt_handler(p_lbs, p_ble_evt);
1.2lbs_c_evt_handler():
p_lbs->led_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_lbs, p_evt_write->data[0]);
ble_srv_is_notification_enabled(p_evt_write->data)
// CCCD written, call application event handler.
p_lbs->evt_handler(p_lbs, &evt);
2主机客户端初始化ble_lbs_init()
// Initialize service structure
p_lbs->evt_handler = p_lbs_init->evt_handler;
p_lbs->is_notification_supported = p_lbs_init->support_notification;
p_lbs->battery_level_last = INVALID_BATTERY_LEVEL;
// Add service
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BATTERY_SERVICE);
// Add battery level characteristic
err_code = battery_level_char_add(p_lbs, p_lbs_init);
3特征添加函数battery_level_char_add()
memset(&cccd_md, 0, sizeof(cccd_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
memset(&char_md, 0, sizeof(char_md));
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BATTERY_LEVEL_CHAR);
memset(&attr_md, 0, sizeof(attr_md));
initial_battery_level = p_bas_init->initial_batt_level;
memset(&attr_char_value, 0, sizeof(attr_char_value));
err_code = sd_ble_gatts_characteristic_add(p_bas->service_handle, &char_md,
&attr_char_value,
&p_bas->battery_level_handles);
4.主机客户端温度数据处理函数
4.1main.c定时器调用ble_bas_battery_level_update
ret_code_t ble_bas_battery_level_update(ble_bas_t * p_bas,
uint8_t battery_level,
uint16_t conn_handle)
ble_gatts_value_t gatts_value; //ble_gatts.h
// Initialize value struct.
memset(&gatts_value, 0, sizeof(gatts_value));
// Update database.
err_code = sd_ble_gatts_value_set(BLE_CONN_HANDLE_INVALID,
p_bas->battery_level_handles.value_handle,
&gatts_value);
// Save new battery value.
p_bas->battery_level_last = battery_level;
// Send value if connected and notifying.
if (p_bas->is_notification_supported)
{
ble_gatts_hvx_params_t hvx_params;
memset(&hvx_params, 0, sizeof(hvx_params));
err_code = battery_notification_send(&hvx_params,
conn_handles.conn_handles[i]);
4.2battery_notification_send
ret_code_t err_code = sd_ble_gatts_hvx(conn_handle, p_hvx_params);
if (err_code == NRF_SUCCESS)
{
NRF_LOG_INFO("Battery notification has been sent using conn_handle: 0x%04X", conn_handle)
官方提供的流程
(S132 v6.0.0 API Reference - Message Sequence Charts - GATTS ATT Table Population部分)