1 /* 2 * Copyright (C) 2024 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 /** 39 * @title Battery Service Server v1.1 40 * 41 */ 42 43 #ifndef BATTERY_SERVICE_V1_SERVER_H 44 #define BATTERY_SERVICE_V1_SERVER_H 45 46 #include <stdint.h> 47 48 #if defined __cplusplus 49 extern "C" { 50 #endif 51 52 /** 53 * @text The Battery Service allows to query your device's battery level in a standardized way. 54 * 55 * To use with your application, add `#import <battery_service.gatt>` to your .gatt file. 56 * After adding it to your .gatt file, you call *battery_service_server_init(value)* with the 57 * current value of your battery. The valid range for the battery level is 0-100. 58 * 59 * If the battery level changes, you can call *battery_service_server_set_battery_value(value)*. 60 * The service supports sending Notifications if the client enables them. 61 */ 62 63 typedef enum { 64 BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL = 0, 65 BAS_CHARACTERISTIC_INDEX_BATTERY_LEVEL_STATUS, 66 BAS_CHARACTERISTIC_INDEX_ESTIMATED_SERVICE_DATE, 67 BAS_CHARACTERISTIC_INDEX_BATTERY_CRITCAL_STATUS, 68 BAS_CHARACTERISTIC_INDEX_BATTERY_ENERGY_STATUS, 69 BAS_CHARACTERISTIC_INDEX_BATTERY_TIME_STATUS, 70 BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_STATUS, 71 BAS_CHARACTERISTIC_INDEX_BATTERY_HEALTH_INFORMATION, 72 BAS_CHARACTERISTIC_INDEX_BATTERY_INFORMATION, 73 BAS_CHARACTERISTIC_INDEX_MANUFACTURER_NAME_STRING, 74 BAS_CHARACTERISTIC_INDEX_MODEL_NUMBER_STRING, 75 BAS_CHARACTERISTIC_INDEX_SERIAL_NUMBER_STRING, 76 BAS_CHARACTERISTIC_INDEX_NUM 77 } bas_characteristic_index_t; 78 79 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_ENERGY_STATUS flags: 80 #define BATTERY_ENERGY_STATUS_BITMASK_EXTERNAL_SOURCE_POWER_PRESENT 0x01 81 #define BATTERY_ENERGY_STATUS_BITMASK_PRESENT_VOLTAGE_PRESENT 0x02 82 #define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_PRESENT 0x04 83 #define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_BATTERY_CAPACITY_PRESENT 0x08 84 #define BATTERY_ENERGY_STATUS_BITMASK_CHARGE_RATE_PRESENT 0x10 85 #define BATTERY_ENERGY_STATUS_BITMASK_AVAILABLE_ENERGY_AT_LAST_CHARGE_PRESENT 0x20 86 #define BATTERY_ENERGY_STATUS_BITMASK_RFU 0xC0 87 88 #define BATTERY_LEVEL_STATUS_BITMASK_IDENTIFIER_PRESENT 0x01 89 #define BATTERY_LEVEL_STATUS_BITMASK_BATTERY_LEVEL_PRESENT 0x02 90 #define BATTERY_LEVEL_STATUS_BITMASK_ADDITIONAL_STATUS_PRESENT 0x04 91 #define BATTERY_LEVEL_STATUS_BITMASK_RFU 0xF8 92 93 #define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_SERVICE_REQUIRED 0x01 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU 94 #define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_BATTERY_FAULT 0x02 // 0 = No or Unknown, 1 = Yes 95 #define BATTERY_LEVEL_ADDITIONAL_STATUS_BITMASK_RFU 0xFC 96 97 #define BATTERY_LEVEL_POWER_STATE_BITMASK_EXTERNAL_BATTERY_PRESENT 0x0001 // 0 = No, 1 = Yes 98 #define BATTERY_LEVEL_POWER_STATE_BITMASK_WIRED_EXTERNAL_POWER_SOURCE_CONNECTED 0x0004 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU 99 #define BATTERY_LEVEL_POWER_STATE_BITMASK_WIRELESS_EXTERNAL_POWER_SOURCE_CONNECTED 0x0010 // 0 = No, 1 = Yes, 2 = Unknown, 3 = RFU 100 #define BATTERY_LEVEL_POWER_STATE_BITMASK_BATTERY_CHARGE_STATE 0x0040 // 0 = Unknown, 1 = Charging, 2 = Discharging: Active 3 = Discharging: Inactive 101 #define BATTERY_LEVEL_POWER_STATE_BITMASK_BATTERY_CHARGE_LEVEL 0x0100 // 0 = Unknown, 1 = Good, 2 = Low, 3 = Critical 102 #define BATTERY_LEVEL_POWER_STATE_BITMASK_CHARGING_TYPE 0x0400 // 0 = Unknown or Not Charging 1 = Constant Current, 2 = Constant Voltage, 3 = Trickle, 4 = Float, 5–7 = RFU 103 #define BATTERY_LEVEL_POWER_STATE_BITMASK_CHARGING_FAULT_REASON 0x2000 // Bit 12: Battery, Bit 13: External Power source, Bit 14: Other 104 #define BATTERY_LEVEL_POWER_STATE_BITMASK_RFU 0xC000 105 106 #define BATTERY_CRITCAL_STATUS_BITMASK_CRITICAL_POWER_STATE 0x01 107 #define BATTERY_CRITCAL_STATUS_BITMASK_IMMEDIATE_SERVICE_REQUIRED 0x02 108 #define BATTERY_CRITCAL_STATUS_BITMASK_RFU 0xFC 109 110 #define BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_DISCHARGED_ON_STANDBY_PRESENT 0x01 111 #define BATTERY_TIME_STATUS_BITMASK_TIME_UNTIL_RECHARGED_PRESENT 0x02 112 #define BATTERY_TIME_STATUS_BITMASK_RFU 0xFC 113 114 #define BATTERY_HEALTH_STATUS_BITMASK_HEALTH_SUMMARY_PRESENT 0x01 115 #define BATTERY_HEALTH_STATUS_BITMASK_CYCLE_COUNT_PRESENT 0x02 116 #define BATTERY_HEALTH_STATUS_BITMASK_CURRENT_TEMPERATURE_PRESENT 0x04 117 #define BATTERY_HEALTH_STATUS_BITMASK_DEEP_DISCHARGE_COUNT_PRESENT 0x08 118 #define BATTERY_HEALTH_STATUS_BITMASK_RFU 0xF0 119 120 #define BATTERY_HEALTH_INFORMATION_BITMASK_CYCLE_COUNT_DESIGNED_LIFETIME_PRESENT 0x01 121 #define BATTERY_HEALTH_INFORMATION_BITMASK_DESIGNED_OPERATING_TEMPERATURE_PRESENT 0x02 122 #define BATTERY_HEALTH_INFORMATION_BITMASK_RFU 0xFC 123 124 #define BATTERY_INFORMATION_BITMASK_MANUFACTURE_DATE_PRESENT 0x0001 125 #define BATTERY_INFORMATION_BITMASK_EXPIRATION_DATE_PRESENT 0x0002 126 #define BATTERY_INFORMATION_BITMASK_DESIGNED_CAPACITY_PRESENT 0x0004 127 #define BATTERY_INFORMATION_BITMASK_LOW_ENERGY_PRESENT 0x0008 128 #define BATTERY_INFORMATION_BITMASK_CRITICAL_ENERGY_PRESENT 0x0010 129 #define BATTERY_INFORMATION_BITMASK_CHEMISTRY_PRESENT 0x0020 130 #define BATTERY_INFORMATION_BITMASK_NOMINAL_VOLTAGE_PRESENT 0x0040 131 #define BATTERY_INFORMATION_BITMASK_AGGREGATION_GROUP_PRESENT 0x0080 132 #define BATTERY_INFORMATION_BITMASK_RFU 0xFF00 133 134 #define BATTERY_INFROMATION_FEATURE_BITMASK_REPLACEABLE 0x01 135 #define BATTERY_INFROMATION_FEATURE_BITMASK_RECHARGEABLE 0x02 136 #define BATTERY_INFROMATION_FEATURE_BITMASK_RFU 0xFC 137 138 struct battery_service_v1; 139 140 typedef struct { 141 hci_con_handle_t con_handle; 142 143 btstack_context_callback_registration_t scheduled_tasks_callback; 144 uint16_t scheduled_tasks; 145 uint16_t configurations[BAS_CHARACTERISTIC_INDEX_NUM]; 146 147 struct battery_service_v1 * service; 148 } battery_service_v1_server_connection_t; 149 150 typedef struct { 151 uint16_t value_handle; 152 uint16_t client_configuration_handle; 153 } bas_characteristic_t; 154 155 typedef struct { 156 uint8_t flags; 157 uint16_t power_state_flags; 158 159 uint16_t identifier; 160 uint8_t battery_level; 161 uint8_t additional_status_flags; 162 } battery_level_status_t; 163 164 typedef struct { 165 uint8_t flags; 166 uint16_t external_source_power_medfloat16; 167 uint16_t present_voltage_medfloat16; 168 uint16_t available_energy_medfloat16; 169 uint16_t available_battery_capacity_medfloat16; 170 uint16_t charge_rate_medfloat16; 171 uint16_t available_energy_at_last_charge_medfloat16; 172 } battery_energy_status_t; 173 174 typedef struct { 175 uint8_t flags; 176 177 // A value of 0xFFFFFF represents: Unknown 178 // A value of 0xFFFFFE represents: Greater than 0xFFFFFD 179 uint32_t time_until_discharged_minutes; 180 uint32_t time_until_discharged_on_standby_minutes; 181 uint32_t time_until_recharged_minutes; 182 } battery_time_status_t; 183 184 typedef struct { 185 uint8_t flags; 186 187 uint8_t summary; // Allowed range is 0 to 100. 188 uint16_t cycle_count; 189 int8_t current_temperature_degree_celsius; 190 uint16_t deep_discharge_count; 191 } battery_health_status_t; 192 193 typedef struct { 194 uint8_t flags; 195 uint16_t cycle_count_designed_lifetime; 196 197 // A raw value of 0x7F represents: Greater than 126. 198 // A raw value of 0x80 represents: Less than -127. 199 int8_t min_designed_operating_temperature_degree_celsius; 200 int8_t max_designed_operating_temperature_degree_celsius; 201 } battery_health_information_t; 202 203 typedef enum { 204 BATTERY_CHEMISTRY_UNKNOWN = 0, 205 BATTERY_CHEMISTRY_ALKALINE, // (ZINC–MANGANESE DIOXIDE) 206 BATTERY_CHEMISTRY_LEAD_ACID, 207 BATTERY_CHEMISTRY_LITHIUM_LIFES2, // (LITHIUM-IRON DISULFIDE) 208 BATTERY_CHEMISTRY_LITHIUM_LIMNO2, // (LITHIUM-MANGANESE DIOXIDE) 209 BATTERY_CHEMISTRY_LITHIUM_ION_LI, 210 BATTERY_CHEMISTRY_LITHIUM_POLYMER, 211 BATTERY_CHEMISTRY_NICKEL_OXYHYDROXIDE_NIOX, // (ZINC-MANGANESE DIOXIDE/OXY NICKEL HYDROXIDE) 212 BATTERY_CHEMISTRY_NICKEL_CADMIUM_NICD, 213 BATTERY_CHEMISTRY_NICKEL_METAL_HYDRIDE_NIMH, 214 BATTERY_CHEMISTRY_SILVER_OXIDE_AGZN, // (SILVER-ZINC) 215 BATTERY_CHEMISTRY_ZINC_CHLORIDE, 216 BATTERY_CHEMISTRY_ZINC_AIR, 217 BATTERY_CHEMISTRY_ZINC_CARBON, 218 BATTERY_CHEMISTRY_RFU_START = 14, 219 BATTERY_CHEMISTRY_RFU_END = 254, 220 BATTERY_CHEMISTRY_OTHER = 255 221 } battery_chemistry_t; 222 223 typedef struct { 224 uint16_t flags; 225 uint8_t features; 226 227 uint32_t manufacture_date_days; 228 uint32_t expiration_date_days; 229 230 uint16_t designed_capacity_kWh_medfloat16; 231 uint16_t low_energy_kWh_medfloat16; 232 uint16_t critical_energy_kWh_medfloat16; 233 battery_chemistry_t chemistry; 234 uint16_t nominal_voltage_medfloat16; 235 uint8_t aggregation_group; // 0: not in group, 255: RFU 236 } battery_information_t; 237 238 typedef struct battery_service_v1 { 239 btstack_linked_item_t item; 240 241 // service 242 uint16_t start_handle; 243 uint16_t end_handle; 244 uint8_t index; 245 246 att_service_handler_t service_handler; 247 248 bas_characteristic_t characteristics[BAS_CHARACTERISTIC_INDEX_NUM]; 249 250 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL 251 uint8_t battery_level; 252 253 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL_STATUS 254 const battery_level_status_t * level_status; 255 256 // ORG_BLUETOOTH_CHARACTERISTIC_ESTIMATED_SERVICE_DATE 257 uint32_t estimated_service_date_days; 258 259 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_CRITCAL_STATUS 260 uint8_t critcal_status_flags; 261 262 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_ENERGY_STATUS 263 const battery_energy_status_t * energy_status; 264 265 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_TIME_STATUS 266 const battery_time_status_t * time_status; 267 268 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_STATUS 269 const battery_health_status_t * health_status; 270 271 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_HEALTH_INFORMATION 272 const battery_health_information_t * health_information; 273 274 // ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_INFORMATION 275 const battery_information_t * information; 276 277 // ORG_BLUETOOTH_CHARACTERISTIC_MANUFACTURER_NAME_STRING 278 const char * manufacturer_name; 279 280 // ORG_BLUETOOTH_CHARACTERISTIC_MODEL_NUMBER_STRING 281 const char * model_number; 282 283 // ORG_BLUETOOTH_CHARACTERISTIC_SERIAL_NUMBER_STRING 284 const char * serial_number; 285 286 uint8_t connections_max_num; 287 battery_service_v1_server_connection_t * connections; 288 } battery_service_v1_t; 289 290 /* API_START */ 291 292 /** 293 * @brief Init Battery Service Server with ATT DB 294 */ 295 void battery_service_v1_server_init(void); 296 297 void battery_service_v1_server_register(battery_service_v1_t * service, battery_service_v1_server_connection_t * connections, uint8_t connection_max_num); 298 299 void battery_service_v1_server_deregister(battery_service_v1_t * service); 300 301 /** 302 * @brief Update battery level 303 * @note Triggers notification if subscribed 304 * @param service 305 * @param battery_level in range 0-100 306 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 307 */ 308 uint8_t battery_service_v1_server_set_battery_level(battery_service_v1_t * service,uint8_t battery_level); 309 310 /** 311 * @brief Update battery level status 312 * @note Triggers notification or indication if subscribed 313 * @param service 314 * @param battery_level_status in range 0-100 315 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 316 */ 317 uint8_t battery_service_v1_server_set_battery_level_status(battery_service_v1_t * service, const battery_level_status_t * battery_level_status); 318 319 /** 320 * @brief Update battery estimated service date as days elapsed since the Epoch (Jan 1, 1970) 321 * @note Triggers notification or indication if subscribed 322 * @param service 323 * @param estimated_service_date_days 324 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 325 */ 326 uint8_t battery_service_v1_server_set_estimated_service_date_days(battery_service_v1_t * service, uint32_t estimated_service_date_days); 327 328 /** 329 * @brief Update battery critcal status flags 330 * @note Triggers indication if subscribed 331 * @param service 332 * @param critcal_status_flags 333 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 334 */ 335 uint8_t battery_service_v1_server_set_critcal_status_flags(battery_service_v1_t * service, uint8_t critcal_status_flags); 336 337 /** 338 * @brief Update battery energy status 339 * @note Triggers notification or indication if subscribed 340 * @param service 341 * @param energy_status 342 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 343 */ 344 uint8_t battery_service_v1_server_set_energy_status(battery_service_v1_t * service, const battery_energy_status_t * energy_status); 345 346 /** 347 * @brief Update battery time status 348 * @note Triggers notification or indication if subscribed 349 * @param service 350 * @param time_status 351 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 352 */ 353 uint8_t battery_service_v1_server_set_time_status(battery_service_v1_t * service, const battery_time_status_t * time_status); 354 355 /** 356 * @brief Update battery health status 357 * @note Triggers notification or indication if subscribed 358 * @param service 359 * @param health_status 360 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 361 */ 362 uint8_t battery_service_v1_server_set_health_status(battery_service_v1_t * service, const battery_health_status_t * health_status); 363 364 /** 365 * @brief Update battery health information 366 * @note Triggers indication if subscribed 367 * @param service 368 * @param health_information 369 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 370 */ 371 uint8_t battery_service_v1_server_set_health_information(battery_service_v1_t * service, const battery_health_information_t * health_information); 372 373 /** 374 * @brief Update battery information 375 * @note Triggers indication if subscribed 376 * @param service 377 * @param information 378 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 379 */ 380 uint8_t battery_service_v1_server_set_information(battery_service_v1_t * service, const battery_information_t * information); 381 382 /** 383 * @brief Update manufacturer name 384 * @note Triggers indication if subscribed 385 * @param service 386 * @param manufacturer_name 387 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 388 */ 389 uint8_t battery_service_v1_server_set_manufacturer_name(battery_service_v1_t * service, const char * manufacturer_name); 390 391 /** 392 * @brief Update model_number 393 * @note Triggers indication if subscribed 394 * @param service 395 * @param model number 396 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 397 */ 398 uint8_t battery_service_v1_server_set_model_number(battery_service_v1_t * service, const char * model_number); 399 400 /** 401 * @brief Update serial_number 402 * @note Triggers indication if subscribed 403 * @param service 404 * @param serial number 405 * @return ERROR_CODE_SUCCESS if value is valid, otherwise ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 406 */ 407 uint8_t battery_service_v1_server_set_serial_number(battery_service_v1_t * service, const char * serial_number); 408 409 void battery_service_v1_server_deinit(void); 410 411 /* API_END */ 412 413 #if defined __cplusplus 414 } 415 #endif 416 417 #endif 418 419