#include #include #include #include #define MODULE ble_battery #include #include "battery_status_event.h" #include LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF); static bool notify_enabled; static uint8_t battery_level = 100U; static void bas_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) { ARG_UNUSED(attr); notify_enabled = (value == BT_GATT_CCC_NOTIFY); } static ssize_t read_battery_level(struct bt_conn *conn, const struct bt_gatt_attr *attr, void *buf, uint16_t len, uint16_t offset) { const uint8_t *value = attr->user_data; return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value)); } BT_GATT_SERVICE_DEFINE(ble_battery_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_BAS), BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_LEVEL, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, read_battery_level, NULL, &battery_level), BT_GATT_CCC(bas_ccc_cfg_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT), ); static bool handle_battery_status_event(const struct battery_status_event *event) { battery_level = battery_status_event_get_soc(event); if (!notify_enabled) { return false; } int err = bt_gatt_notify(NULL, &ble_battery_svc.attrs[1], &battery_level, sizeof(battery_level)); if (err == -ENOTCONN) { LOG_WRN("BAS notify skipped: peer disconnecting"); } else if (err) { LOG_ERR("BAS notify failed: %d", err); } return false; } static bool handle_module_state_event(const struct module_state_event *event) { if (!check_state(event, MODULE_ID(ble_state), MODULE_STATE_READY)) { return false; } module_set_state(MODULE_STATE_READY); return false; } static bool app_event_handler(const struct app_event_header *aeh) { if (is_battery_status_event(aeh)) { return handle_battery_status_event(cast_battery_status_event(aeh)); } if (is_module_state_event(aeh)) { return handle_module_state_event(cast_module_state_event(aeh)); } __ASSERT_NO_MSG(false); return false; } APP_EVENT_LISTENER(MODULE, app_event_handler); APP_EVENT_SUBSCRIBE(MODULE, battery_status_event); APP_EVENT_SUBSCRIBE(MODULE, module_state_event);