From db9fdd680281f095072c4fdafe372d045866923c Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Wed, 25 Sep 2024 09:04:57 +0200 Subject: [PATCH] gatt-service/bas_server: extract structs for battery characteristics --- .../gatt-service/battery_service_v1_server.c | 326 ++++++++++-------- .../gatt-service/battery_service_v1_server.h | 134 +++---- 2 files changed, 255 insertions(+), 205 deletions(-) diff --git a/src/ble/gatt-service/battery_service_v1_server.c b/src/ble/gatt-service/battery_service_v1_server.c index 44e81a7d7..909200ddd 100644 --- a/src/ble/gatt-service/battery_service_v1_server.c +++ b/src/ble/gatt-service/battery_service_v1_server.c @@ -131,6 +131,170 @@ static battery_service_v1_t * battery_service_service_for_con_handle(hci_con_han return NULL; } +static uint8_t bas_serialize_characteristic(battery_service_v1_t * service, bas_characteristic_index_t index, uint8_t * event, uint8_t event_size){ + uint8_t pos = 0; + switch ((bas_characteristic_index_t) index){ + case BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL: + event[pos++] = service->battery_value; + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL_STATUS: + if (service->level_status == NULL){ + return 0; + } + event[pos++] = service->level_status->flags; + little_endian_store_16(event, pos, service->level_status->power_state_flags); + pos += 2; + if ((service->level_status->flags & BATTERY_LEVEL_STATUS_BITMASK_IDENTIFIER_PRESENT) > 0u){ + little_endian_store_16(event, pos, service->level_status->identifier); + pos += 2; + } + if ((service->level_status->flags & BATTERY_LEVEL_STATUS_BITMASK_BATTERY_LEVEL_PRESENT) > 0u){ + event[pos++] = service->level_status->battery_level; + } + if ((service->level_status->flags & BATTERY_LEVEL_STATUS_BITMASK_ADDITIONAL_STATUS_PRESENT) > 0u){ + event[pos++] = service->level_status->additional_status_flags; + } + break; + + case BAS_CHARACTERISTIC_INDEX_ESTIMATED_SERVICE_DATE: + little_endian_store_24(event, pos, service->estimated_service_date_days); + pos += 3; + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_CRITCAL_STATUS: + event[pos++] = service->battery_critcal_status_flags; + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_ENERGY_STATUS: + if (service->energy_status == NULL){ + return 0; + } + 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; + } + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_TIME_STATUS: + if (service->time_status == NULL){ + return 0; + } + 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; + } + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_STATUS: + if (service->health_status == NULL){ + return 0; + } + 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; + } + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_INFORMATION: + if (service->health_information == NULL){ + return 0; + } + 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; + } + break; + + case BAS_CHARACTERISTIC_INDEX_BATTERY_INFORMATION: + if (service->information == NULL){ + return 0; + } + 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; + } + break; + default: + break; + } + return pos; +} static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ UNUSED(con_handle); @@ -157,155 +321,33 @@ static uint16_t battery_service_read_callback(hci_con_handle_t con_handle, uint1 continue; } - 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_MANUFACTURER_NAME_STRING: + if (service->manufacturer_name == NULL){ + return 0; + } + return att_read_callback_handle_blob((uint8_t *)service->manufacturer_name, strlen(service->manufacturer_name), 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; + case BAS_CHARACTERISTIC_INDEX_MODEL_NUMBER_STRING: + if (service->model_number == NULL){ + return 0; } - 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); + return att_read_callback_handle_blob((uint8_t *)service->model_number, strlen(service->model_number), 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; + case BAS_CHARACTERISTIC_INDEX_SERIAL_NUMBER_STRING: + if (service->serial_number == NULL){ + return 0; } - 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); + return att_read_callback_handle_blob((uint8_t *)service->serial_number, strlen(service->serial_number), offset, buffer, buffer_size); default: + pos = bas_serialize_characteristic(service, index, event, sizeof(event)); + if (pos == 1u){ + return att_read_callback_handle_byte(event[0], offset, buffer, buffer_size); + } + if (pos > 1u){ + return att_read_callback_handle_blob(event, pos, offset, buffer, buffer_size); + } return 0; } } diff --git a/src/ble/gatt-service/battery_service_v1_server.h b/src/ble/gatt-service/battery_service_v1_server.h index 4ca55d048..feb358596 100644 --- a/src/ble/gatt-service/battery_service_v1_server.h +++ b/src/ble/gatt-service/battery_service_v1_server.h @@ -59,7 +59,6 @@ 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, @@ -165,6 +164,68 @@ typedef struct { uint16_t client_configuration_handle; } bas_characteristic_t; +typedef struct { + uint8_t flags; + uint16_t power_state_flags; + + uint16_t identifier; + uint8_t battery_level; + uint8_t additional_status_flags; +} battery_level_status_t; + +typedef 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; +} battery_energy_status_t; + +typedef 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; +} battery_time_status_t; + +typedef 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; +} battery_health_status_t; + +typedef 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; +} battery_health_information_t; + +typedef 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 +} battery_information_t; typedef struct battery_service_v1 { btstack_linked_item_t item; @@ -182,14 +243,7 @@ typedef struct battery_service_v1 { 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; + const battery_level_status_t * level_status; // ORG_BLUETOOTH_CHARACTERISTIC_ESTIMATED_SERVICE_DATE uint32_t estimated_service_date_days; @@ -198,74 +252,28 @@ typedef struct battery_service_v1 { 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; + const battery_energy_status_t * 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; + const battery_time_status_t * 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; + const battery_health_status_t * 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; + const battery_health_information_t * 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; + const battery_information_t * information; // ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING - uint8_t manufacturer_name[BATTERY_SERVICE_MAX_STRING_LEN]; - uint8_t manufacturer_name_len; + const char * manufacturer_name; // ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING - uint8_t model_number[BATTERY_SERVICE_MAX_STRING_LEN]; - uint8_t model_number_len; + const char * model_number; // ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING - uint8_t serial_number[BATTERY_SERVICE_MAX_STRING_LEN]; - uint8_t serial_number_len; + const char * serial_number; uint8_t connections_max_num; battery_service_v1_server_connection_t * connections;