sdk17.0.2附带的example中,各种类型和函数等都过度包装了,一个很简单的东西,定义了一层又一层,很容易让人看的头皮发麻。
为了降低添加Service和处理各种handler的难度,使用宏来简化添加自定义Service和attribute
typedef struct ble_bas_s ble_bas_t;
typedef struct
{
ble_bas_evt_handler_t evt_handler;
bool support_notification;
ble_srv_report_ref_t * p_report_ref;
uint8_t initial_batt_level;
ble_srv_cccd_security_mode_t battery_level_char_attr_md;
ble_gap_conn_sec_mode_t battery_level_report_read_perm;
} ble_bas_init_t;
struct ble_bas_s
{
ble_bas_evt_handler_t evt_handler; /**< Event handler to be called for handling events in the Battery Service. */
uint16_t service_handle; /**< Handle of Battery Service (as provided by the BLE stack). */
ble_gatts_char_handles_t battery_level_handles; /**< Handles related to the Battery Level characteristic. */
uint16_t report_ref_handle; /**< Handle of the Report Reference descriptor. */
uint8_t battery_level_last; /**< Last Battery Level measurement passed to the Battery Service. */
bool is_notification_supported; /**< TRUE if notification of Battery Level is supported. */
};
typedef struct
{
ble_bas_evt_type_t evt_type; /**< Type of event. */
uint16_t conn_handle; /**< Connection handle. */
} ble_bas_evt_t;
typedef enum
{
BLE_BAS_EVT_NOTIFICATION_ENABLED, /**< Battery value notification enabled event. */
BLE_BAS_EVT_NOTIFICATION_DISABLED /**< Battery value notification disabled event. */
} ble_bas_evt_type_t;
static void services_init(void)
memset(&bas_init_obj, 0, sizeof(bas_init_obj));
//BLE_BAS_DEF(m_bas); /**< Battery service instance. */
err_code = pvt_ble_bas_init(&m_bas, &bas_init_obj);
APP_ERROR_CHECK(err_code);//需要调用pvt_ble_bas_init返回值,pvt_ble_bas_init必须加入return err_code。
uint32_t pvt_ble_bas_init(ble_bas_t * p_bas, const ble_bas_init_t * p_bas_init)
ble_bas_init_t bas_init_obj;
bas_init_obj.support_notification = true;
bas_init_obj.p_report_ref = NULL;
bas_init_obj.initial_batt_level = 100;
bas_init_obj.evt_handler = on_bas_evt;//在services_init加上这行代码,不会有bas实时数据
err_code = msy_ble_bas_init(&m_bas, &bas_init_obj);
// APP_ERROR_CHECK(err_code);
return err_code;//尤为重要
ret_code_t msy_ble_bas_init(ble_bas_t * p_bas, const ble_bas_init_t * p_bas_init)
// Initialize service structure
p_bas->evt_handler = p_bas_init->evt_handler;
p_bas->is_notification_supported = p_bas_init->support_notification;
p_bas->battery_level_last = INVALID_BATTERY_LEVEL;
// Add service
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_BATTERY_SERVICE);
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&ble_uuid,
&p_bas->service_handle);
VERIFY_SUCCESS(err_code);
// Add battery level characteristic
err_code = battery_level_char_add(p_bas, p_bas_init);
return err_code;
static ret_code_t battery_level_char_add(ble_bas_t * p_bas, const ble_bas_init_t * p_bas_init)
ble_gatts_char_md_t char_md;
ble_gatts_attr_md_t cccd_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t ble_uuid;
ble_gatts_attr_md_t attr_md;
// Add Battery Level characteristic
if (p_bas->is_notification_supported)
memset(&cccd_md, 0, sizeof(cccd_md));
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);
if (p_bas_init->p_report_ref != NULL)
// Add Report Reference descriptor
BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_REPORT_REF_DESCR);
memset(&attr_md, 0, sizeof(attr_md));
init_len = ble_srv_report_ref_encode(encoded_report_ref, p_bas_init->p_report_ref);
memset(&attr_char_value, 0, sizeof(attr_char_value));
err_code = sd_ble_gatts_descriptor_add(p_bas->battery_level_handles.value_handle,
&attr_char_value,
&p_bas->report_ref_handle);