Files
new_kbd/src/modules/ble_battery_module.c

92 lines
2.2 KiB
C
Raw Normal View History

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/gatt.h>
#include <app_event_manager.h>
#define MODULE ble_battery
#include <caf/events/module_state_event.h>
#include "battery_status_event.h"
#include <zephyr/logging/log.h>
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 = event->soc;
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);