gatt-service/bas_server: implement read callback

This commit is contained in:
Milanka Ringwald 2024-09-24 18:12:28 +02:00 committed by Matthias Ringwald
parent f572617f5b
commit e5ae30da29
2 changed files with 381 additions and 20 deletions

View File

@ -49,11 +49,26 @@
#include "bluetooth_gatt.h"
#include "btstack_debug.h"
#define BS_CONNECTIONS_MAX_NUM 10
#include "ble/gatt-service/battery_service_v1_server.h"
#define BATTERY_SERVICE_TASK_BATTERY_VALUE_CHANGED 0x0001
// list of uuids
static const uint16_t bas_uuid16s[BAS_CHARACTERISTIC_INDEX_NUM] = {
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATUS,
ORG_BLUETOOTH_CHARACTERISTIC_ESTIMATED_SERVICE_DATE,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_CRITCAL_STATUS,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_ENERGY_STATUS,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_TIME_STATUS,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_STATUS,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_INFORMATION,
ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_INFORMATION,
ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING,
ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING,
ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING,
};
static btstack_linked_list_t battery_services;
@ -133,11 +148,173 @@ static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint1
}
}
if (attribute_handle == service->battery_value_handle){
return att_read_callback_handle_byte(service->battery_value, offset, buffer, buffer_size);
uint8_t index;
uint8_t event[18];
uint8_t pos = 0;
for (index = 0; index < (uint8_t) BAS_CHARACTERISTIC_INDEX_NUM; index++){
if (attribute_handle != service->characteristics[index].value_handle){
continue;
}
if (attribute_handle == service->battery_value_client_configuration_handle){
return att_read_callback_handle_little_endian_16(connection->battery_value_client_configuration, offset, buffer, buffer_size);
switch ((bas_characteristic_index_t) index){
case BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL:
return att_read_callback_handle_byte(service->battery_value, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL_STATUS:
event[pos++] = service->battery_level.flags;
little_endian_store_16(event, pos, service->battery_level.power_state_flags);
pos += 2;
if ((service->battery_level.flags & BATTERY_LEVEL_STATUS_BITMASK_IDENTIFIER_PRESENT) > 0u){
little_endian_store_16(event, pos, service->battery_level.identifier);
pos += 2;
}
if ((service->battery_level.flags & BATTERY_LEVEL_STATUS_BITMASK_BATTERY_LEVEL_PRESENT) > 0u){
event[pos++] = service->battery_level.battery_level;
}
if ((service->battery_level.flags & BATTERY_LEVEL_STATUS_BITMASK_ADDITIONAL_STATUS_PRESENT) > 0u){
event[pos++] = service->battery_level.additional_status_flags;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_ESTIMATED_SERVICE_DATE:
little_endian_store_24(event, pos, service->estimated_service_date_days);
pos += 3;
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_CRITCAL_STATUS:
return att_read_callback_handle_byte(service->battery_critcal_status_flags, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_ENERGY_STATUS:
event[pos++] = service->energy_status.flags;
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_EXTERNAL_SOURCE_POWER_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.external_source_power_medfloat16);
pos += 2;
}
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_PRESENT_VOLTAGE_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.present_voltage_medfloat16);
pos += 2;
}
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.available_energy_medfloat16);
pos += 2;
}
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_BATTERY_CAPACITY_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.available_battery_capacity_medfloat16);
pos += 2;
}
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_CHARGE_RATE_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.charge_rate_medfloat16);
pos += 2;
}
if ((service->energy_status.flags & BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_AT_LAST_CHARGE_PRESENT) > 0u){
little_endian_store_16(event, pos, service->energy_status.available_energy_at_last_charge_medfloat16);
pos += 2;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_TIME_STATUS:
event[pos++] = service->time_status.flags;
little_endian_store_24(event, pos, service->time_status.time_until_discharged_minutes);
pos += 3;
if ((service->time_status.flags & BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_DISCHARGED_ON_STANDBY_PRESENT) > 0u){
little_endian_store_24(event, pos, service->time_status.time_until_discharged_on_standby_minutes);
pos += 3;
}
if ((service->time_status.flags & BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_RECHARGED_PRESENT) > 0u){
little_endian_store_24(event, pos, service->time_status.time_until_recharged_minutes);
pos += 3;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_STATUS:
event[pos++] = service->health_status.flags;
if ((service->health_status.flags & BATTERY_HEALTH_STATUS_BITMASK_HEALTH_SUMMARY_PRESENT) > 0u){
event[pos++] = service->health_status.summary;
}
if ((service->health_status.flags & BATTERY_HEALTH_STATUS_BITMASK_CYCLE_COUNT_PRESENT) > 0u){
little_endian_store_16(event, pos, service->health_status.cycle_count);
pos += 2;
}
if ((service->health_status.flags & BATTERY_HEALTH_STATUS_BITMASK_CURRENT_TEMPERATURE_PRESENT) > 0u){
event[pos++] = service->health_status.current_temperature_degree_celsius;
}
if ((service->health_status.flags & BATTERY_HEALTH_STATUS_BITMASK_DEEP_DISCHARGE_COUNT_PRESENT) > 0u){
little_endian_store_16(event, pos, service->health_status.deep_discharge_count);
pos += 2;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_INFORMATION:
event[pos++] = service->health_information.flags;
if ((service->health_information.flags & BATTERY_HEALTH_INFORMATION_BITMASK_CYCLE_COUNT_DESIGNED_LIFETIME_PRESENT) > 0u){
little_endian_store_16(event, pos, service->health_information.cycle_count_designed_lifetime);
pos += 2;
}
if ((service->health_information.flags & BATTERY_HEALTH_INFORMATION_BITMASK_DESIGNED_OPERATING_TEMPERATURE_PRESENT) > 0u){
event[pos++] = service->health_information.min_designed_operating_temperature_degree_celsius;
}
if ((service->health_information.flags & BATTERY_HEALTH_INFORMATION_BITMASK_DESIGNED_OPERATING_TEMPERATURE_PRESENT) > 0u){
event[pos++] = service->health_information.max_designed_operating_temperature_degree_celsius;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_BATTERY_INFORMATION:
little_endian_store_16(event, pos, service->information.flags);
pos += 2;
event[pos++] = service->information.features;
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_MANUFACTURE_DATE_PRESENT) > 0u){
little_endian_store_24(event, pos, service->information.manufacture_date_days);
pos += 3;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_EXPIRATION_DATE_PRESENT) > 0u){
little_endian_store_24(event, pos, service->information.expiration_date_days);
pos += 3;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_DESIGNED_CAPACITY_PRESENT) > 0u){
little_endian_store_16(event, pos, service->information.designed_capacity_kWh_medfloat16);
pos += 2;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_LOW_ENERGY_PRESENT) > 0u){
little_endian_store_16(event, pos, service->information.low_energy_kWh_medfloat16);
pos += 2;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_CRITICAL_ENERGY_PRESENT) > 0u){
little_endian_store_16(event, pos, service->information.critical_energy_kWh_medfloat16);
pos += 2;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_CHEMISTRY_PRESENT) > 0u){
event[pos++] = service->information.chemistry;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_NOMINAL_VOLTAGE_PRESENT) > 0u){
little_endian_store_16(event, pos, service->information.nominal_voltage_medfloat16);
pos += 2;
}
if ((service->information.flags & BATTERY_INFORMATION_BITMASK_AGGREGATION_GROUP_PRESENT) > 0u){
event[pos++] = service->information.aggregation_group;
}
return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_MANUFACTURER_NAME_STRING:
return att_read_callback_handle_blob(service->manufacturer_name, service->manufacturer_name_len, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_MODEL_NUMBER_STRING:
return att_read_callback_handle_blob(service->model_number, service->model_number_len, offset, buffer, buffer_size);
case BAS_CHARACTERISTIC_INDEX_SERIAL_NUMBER_STRING:
return att_read_callback_handle_blob(service->serial_number, service->serial_number_len, offset, buffer, buffer_size);
default:
return 0;
}
}
for (index = 0; index < (uint8_t) BAS_CHARACTERISTIC_INDEX_NUM; index++){
if (attribute_handle != service->characteristics[index].client_configuration_handle){
continue;
}
return att_read_callback_handle_little_endian_16(connection->configurations[index], offset, buffer, buffer_size);
}
return 0;
}
@ -163,8 +340,12 @@ static int battery_service_write_callback(hci_con_handle_t con_handle, uint16_t
}
}
if (attribute_handle == service->battery_value_client_configuration_handle){
connection->battery_value_client_configuration = little_endian_read_16(buffer, 0);
uint8_t index;
for (index = 0; index < (uint8_t) BAS_CHARACTERISTIC_INDEX_NUM; index++){
if (attribute_handle != service->characteristics[index].client_configuration_handle){
continue;
}
connection->configurations[index] = little_endian_read_16(buffer, 0);
}
return 0;
}
@ -181,7 +362,7 @@ static void battery_service_can_send_now(void * context){
if ( (connection->scheduled_tasks & BATTERY_SERVICE_TASK_BATTERY_VALUE_CHANGED) > 0u){
connection->scheduled_tasks &= ~BATTERY_SERVICE_TASK_BATTERY_VALUE_CHANGED;
att_server_notify(connection->con_handle, service->battery_value_handle, &service->battery_value, 1);
att_server_notify(connection->con_handle, service->characteristics[BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL].value_handle, &service->battery_value, 1);
}
if (connection->scheduled_tasks > 0u){
@ -218,19 +399,20 @@ void battery_service_v1_server_register(battery_service_v1_t *service, battery_s
service->start_handle = start_handle;
service->end_handle = end_handle;
uint8_t i;
for (i = 0; i < (uint8_t) BAS_CHARACTERISTIC_INDEX_NUM; i++){
// get characteristic value handle and client configuration handle
service->battery_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
service->battery_value_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
service->characteristics[i].value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, bas_uuid16s[i]);
service->characteristics[i].client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, bas_uuid16s[i]);
}
memset(connections, 0, sizeof(battery_service_v1_server_connection_t) * connection_max_num);
uint8_t i;
for (i = 0; i < connection_max_num; i++){
connections[i].con_handle = HCI_CON_HANDLE_INVALID;
}
service->connections_max_num = connection_max_num;
service->connections = connections;
service->service_handler.read_callback = &battery_service_read_callback;
service->service_handler.write_callback = &battery_service_write_callback;
att_server_register_service_handler(&service->service_handler);
@ -268,14 +450,14 @@ void battery_service_v1_server_set_battery_value(battery_service_v1_t * service,
uint8_t i;
for (i = 0; i < service->connections_max_num; i++){
battery_service_v1_server_connection_t * connection = &service->connections[i];
if (connection->battery_value_client_configuration != 0){
if (connection->configurations[BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL] != 0){
battery_service_set_callback(connection, BATTERY_SERVICE_TASK_BATTERY_VALUE_CHANGED);
}
}
}
void battery_service_v1_server_deregister(battery_service_v1_t *service){
btstack_linked_list_iterator_remove((btstack_linked_item_t * )service);
btstack_linked_list_remove(&battery_services, (btstack_linked_item_t * )service);
// TODO cansel can send now
}

View File

@ -59,19 +59,112 @@ extern "C" {
* If the battery level changes, you can call *battery_service_server_set_battery_value(value)*.
* The service supports sending Notifications if the client enables them.
*/
#define BATTERY_SERVICE_MAX_STRING_LEN 32
typedef enum {
BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL = 0,
BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL_STATUS,
BAS_CHARACTERISTIC_INDEX_ESTIMATED_SERVICE_DATE,
BAS_CHARACTERISTIC_INDEX_BATTERY_CRITCAL_STATUS,
BAS_CHARACTERISTIC_INDEX_BATTERY_ENERGY_STATUS,
BAS_CHARACTERISTIC_INDEX_BATTERY_TIME_STATUS,
BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_STATUS,
BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_INFORMATION,
BAS_CHARACTERISTIC_INDEX_BATTERY_INFORMATION,
BAS_CHARACTERISTIC_INDEX_MANUFACTURER_NAME_STRING,
BAS_CHARACTERISTIC_INDEX_MODEL_NUMBER_STRING,
BAS_CHARACTERISTIC_INDEX_SERIAL_NUMBER_STRING,
BAS_CHARACTERISTIC_INDEX_NUM
} bas_characteristic_index_t;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_ENERGY_STATUS flags:
#define BATTERY_ENERGY_STATUS_BITMASK_EXTERNAL_SOURCE_POWER_PRESENT 0x01
#define BATTERY_ENERGY_STATUS_BITMASK_PRESENT_VOLTAGE_PRESENT 0x02
#define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_PRESENT 0x04
#define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_BATTERY_CAPACITY_PRESENT 0x08
#define BATTERY_ENERGY_STATUS_BITMASK_CHARGE_RATE_PRESENT 0x10
#define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_AT_LAST_CHARGE_PRESENT 0x20
#define BATTERY_ENERGY_STATUS_BITMASK_RFU 0x40
#define BATTERY_LEVEL_STATUS_BITMASK_IDENTIFIER_PRESENT 0x01
#define BATTERY_LEVEL_STATUS_BITMASK_BATTERY_LEVEL_PRESENT 0x02
#define BATTERY_LEVEL_STATUS_BITMASK_ADDITIONAL_STATUS_PRESENT 0x04
#define BATTERY_LEVEL_STATUS_BITMASK_RFU 0x08
#define BATTERY_LEVEL_POWER_STATE_BITMASK_EXTERNAL_BATTERY_PRESENT 0x0001 // 0 = No, 1 = Yes
#define BATTERY_LEVEL_POWER_STATE_BITMASK_WIRED_EXTERNAL_POWER_SOURCE_CONNECTED 0x0004 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU
#define BATTERY_LEVEL_POWER_STATE_BITMASK_WIRELESS_EXTERNAL_POWER_SOURCE_CONNECTED 0x0010 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU
#define BATTERY_LEVEL_POWER_STATE_BITMASK_BATTERY_CHARGE_STATE 0x0040 // 0 = Unknown, 1 = Charging, 2 = Discharging: Active 3 = Discharging: Inactive
#define BATTERY_LEVEL_POWER_STATE_BITMASK_BATTERY_CHARGE_LEVEL 0x0100 // 0 = Unknown, 1 = Good, 2 = Low, 3 = Critical
#define BATTERY_LEVEL_POWER_STATE_BITMASK_CHARGING_TYPE 0x0400 // 0 = Unknown or Not Charging 1 = Constant Current, 2 = Constant Voltage, 3 = Trickle, 4 = Float, 57 = RFU
#define BATTERY_LEVEL_POWER_STATE_BITMASK_CHARGING_FAULT_REASON 0x2000 // Bit 12: Battery, Bit 13: External Power source, Bit 14: Other
#define BATTERY_LEVEL_POWER_STATE_BITMASK_RFU 0x4000
#define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_SERVICE_REQUIRED 0x01 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU
#define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_BATTERY_FAULT 0x02 // 0 = No or Unknown, 1 = Yes
#define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_RFU 0x04
#define BATTERY_CRITCAL_STATUS_BITMASK_CRITICAL_POWER_STATE 0x01
#define BATTERY_CRITCAL_STATUS_BITMASK_IMMEDIATE_SERVICE_REQUIRED 0x02
#define BATTERY_CRITCAL_STATUS_BITMASK_RFU 0x04
#define BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_DISCHARGED_ON_STANDBY_PRESENT 0x01
#define BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_RECHARGED_PRESENT 0x02
#define BATTERY_TIME_STATUS_BITMASK_RFU 0x04
#define BATTERY_HEALTH_STATUS_BITMASK_HEALTH_SUMMARY_PRESENT 0x01
#define BATTERY_HEALTH_STATUS_BITMASK_CYCLE_COUNT_PRESENT 0x02
#define BATTERY_HEALTH_STATUS_BITMASK_CURRENT_TEMPERATURE_PRESENT 0x04
#define BATTERY_HEALTH_STATUS_BITMASK_DEEP_DISCHARGE_COUNT_PRESENT 0x08
#define BATTERY_HEALTH_STATUS_BITMASK_RFU 0x10
#define BATTERY_HEALTH_INFORMATION_BITMASK_CYCLE_COUNT_DESIGNED_LIFETIME_PRESENT 0x01
#define BATTERY_HEALTH_INFORMATION_BITMASK_DESIGNED_OPERATING_TEMPERATURE_PRESENT 0x02
#define BATTERY_HEALTH_INFORMATION_BITMASK_RFU 0x04
#define BATTERY_INFORMATION_BITMASK_MANUFACTURE_DATE_PRESENT 0x0001
#define BATTERY_INFORMATION_BITMASK_EXPIRATION_DATE_PRESENT 0x0002
#define BATTERY_INFORMATION_BITMASK_DESIGNED_CAPACITY_PRESENT 0x0004
#define BATTERY_INFORMATION_BITMASK_LOW_ENERGY_PRESENT 0x0008
#define BATTERY_INFORMATION_BITMASK_CRITICAL_ENERGY_PRESENT 0x0010
#define BATTERY_INFORMATION_BITMASK_CHEMISTRY_PRESENT 0x0020
#define BATTERY_INFORMATION_BITMASK_NOMINAL_VOLTAGE_PRESENT 0x0040
#define BATTERY_INFORMATION_BITMASK_AGGREGATION_GROUP_PRESENT 0x0080
#define BATTERY_INFORMATION_BITMASK_RFU 0x0100
#define BATTERY_INFROMATION_FEATURE_BITMASK_REPLACEABLE 0x01
#define BATTERY_INFROMATION_FEATURE_BITMASK_RECHARGEABLE 0x02
#define BATTERY_INFROMATION_FEATURE_BITMASK_RFU 0x04
struct battery_service_v1;
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
} btstack_utc_date_t;
typedef struct {
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
} btstack_utc_time_t;
typedef struct {
hci_con_handle_t con_handle;
btstack_context_callback_registration_t scheduled_tasks_callback;
uint8_t scheduled_tasks;
uint16_t configurations[BAS_CHARACTERISTIC_INDEX_NUM];
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL
uint16_t battery_value_client_configuration;
struct battery_service_v1 * service;
} battery_service_v1_server_connection_t;
typedef struct {
uint16_t value_handle;
uint16_t client_configuration_handle;
} bas_characteristic_t;
typedef struct battery_service_v1 {
btstack_linked_item_t item;
@ -83,11 +176,97 @@ typedef struct battery_service_v1 {
att_service_handler_t service_handler;
bas_characteristic_t characteristics[BAS_CHARACTERISTIC_INDEX_NUM];
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL
uint16_t battery_value_handle;
uint16_t battery_value_client_configuration_handle;
uint8_t battery_value;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATUS
struct {
uint8_t flags;
uint16_t power_state_flags;
uint16_t identifier;
uint8_t battery_level;
uint8_t additional_status_flags;
} battery_level;
// ORG_BLUETOOTH_CHARACTERISTIC_ESTIMATED_SERVICE_DATE
uint32_t estimated_service_date_days;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_CRITCAL_STATUS
uint8_t battery_critcal_status_flags;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_ENERGY_STATUS
struct {
uint8_t flags;
uint16_t external_source_power_medfloat16;
uint16_t present_voltage_medfloat16;
uint16_t available_energy_medfloat16;
uint16_t available_battery_capacity_medfloat16;
uint16_t charge_rate_medfloat16;
uint16_t available_energy_at_last_charge_medfloat16;
} energy_status;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_TIME_STATUS
struct {
uint8_t flags;
// A value of 0xFFFFFF represents: Unknown
// A value of 0xFFFFFE represents: Greater than 0xFFFFFD
uint32_t time_until_discharged_minutes;
uint32_t time_until_discharged_on_standby_minutes;
uint32_t time_until_recharged_minutes;
} time_status;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_STATUS
struct {
uint8_t flags;
uint8_t summary; // Allowed range is 0 to 100.
uint16_t cycle_count;
int8_t current_temperature_degree_celsius;
uint16_t deep_discharge_count;
} health_status;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_INFORMATION
struct {
uint8_t flags;
uint16_t cycle_count_designed_lifetime;
// A raw value of 0x7F represents: Greater than 126.
// A raw value of 0x80 represents: Less than -127.
int8_t min_designed_operating_temperature_degree_celsius;
int8_t max_designed_operating_temperature_degree_celsius;
} health_information;
// ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_INFORMATION
struct {
uint16_t flags;
uint8_t features;
uint32_t manufacture_date_days;
uint32_t expiration_date_days;
uint16_t designed_capacity_kWh_medfloat16;
uint16_t low_energy_kWh_medfloat16;
uint16_t critical_energy_kWh_medfloat16;
uint8_t chemistry;
uint16_t nominal_voltage_medfloat16;
uint8_t aggregation_group; // 0: not in group, 255: RFU
} information;
// ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING
uint8_t manufacturer_name[BATTERY_SERVICE_MAX_STRING_LEN];
uint8_t manufacturer_name_len;
// ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING
uint8_t model_number[BATTERY_SERVICE_MAX_STRING_LEN];
uint8_t model_number_len;
// ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING
uint8_t serial_number[BATTERY_SERVICE_MAX_STRING_LEN];
uint8_t serial_number_len;
uint8_t connections_max_num;
battery_service_v1_server_connection_t * connections;
} battery_service_v1_t;