battery_service.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include "battery_service.h"
  2. #include "app_common.h"
  3. #include <ble/ble.h>
  4. #include <furi.h>
  5. #include <furi_hal_power.h>
  6. #define TAG "BtBatterySvc"
  7. typedef struct {
  8. uint16_t svc_handle;
  9. uint16_t battery_level_char_handle;
  10. uint16_t power_state_char_handle;
  11. } BatterySvc;
  12. enum {
  13. // Common states
  14. BatterySvcPowerStateUnknown = 0b00,
  15. BatterySvcPowerStateUnsupported = 0b01,
  16. // Level states
  17. BatterySvcPowerStateGoodLevel = 0b10,
  18. BatterySvcPowerStateCriticallyLowLevel = 0b11,
  19. // Charging states
  20. BatterySvcPowerStateNotCharging = 0b10,
  21. BatterySvcPowerStateCharging = 0b11,
  22. // Discharging states
  23. BatterySvcPowerStateNotDischarging = 0b10,
  24. BatterySvcPowerStateDischarging = 0b11,
  25. // Battery states
  26. BatterySvcPowerStateBatteryNotPresent = 0b10,
  27. BatterySvcPowerStateBatteryPresent = 0b11,
  28. };
  29. typedef struct {
  30. uint8_t present : 2;
  31. uint8_t discharging : 2;
  32. uint8_t charging : 2;
  33. uint8_t level : 2;
  34. } BattrySvcPowerState;
  35. _Static_assert(sizeof(BattrySvcPowerState) == 1, "Incorrect structure size");
  36. static BatterySvc* battery_svc = NULL;
  37. #define BATTERY_POWER_STATE (0x2A1A)
  38. static const uint16_t service_uuid = BATTERY_SERVICE_UUID;
  39. static const uint16_t battery_level_char_uuid = BATTERY_LEVEL_CHAR_UUID;
  40. static const uint16_t power_state_char_uuid = BATTERY_POWER_STATE;
  41. void battery_svc_start() {
  42. battery_svc = malloc(sizeof(BatterySvc));
  43. tBleStatus status;
  44. // Add Battery service
  45. status = aci_gatt_add_service(
  46. UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 8, &battery_svc->svc_handle);
  47. if(status) {
  48. FURI_LOG_E(TAG, "Failed to add Battery service: %d", status);
  49. }
  50. // Add Battery level characteristic
  51. status = aci_gatt_add_char(
  52. battery_svc->svc_handle,
  53. UUID_TYPE_16,
  54. (Char_UUID_t*)&battery_level_char_uuid,
  55. 1,
  56. CHAR_PROP_READ | CHAR_PROP_NOTIFY,
  57. ATTR_PERMISSION_AUTHEN_READ,
  58. GATT_DONT_NOTIFY_EVENTS,
  59. 10,
  60. CHAR_VALUE_LEN_CONSTANT,
  61. &battery_svc->battery_level_char_handle);
  62. if(status) {
  63. FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status);
  64. }
  65. // Add Power state characteristic
  66. status = aci_gatt_add_char(
  67. battery_svc->svc_handle,
  68. UUID_TYPE_16,
  69. (Char_UUID_t*)&power_state_char_uuid,
  70. 1,
  71. CHAR_PROP_READ | CHAR_PROP_NOTIFY,
  72. ATTR_PERMISSION_AUTHEN_READ,
  73. GATT_DONT_NOTIFY_EVENTS,
  74. 10,
  75. CHAR_VALUE_LEN_CONSTANT,
  76. &battery_svc->power_state_char_handle);
  77. if(status) {
  78. FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status);
  79. }
  80. // Update power state charachteristic
  81. battery_svc_update_power_state();
  82. }
  83. void battery_svc_stop() {
  84. tBleStatus status;
  85. if(battery_svc) {
  86. // Delete Battery level characteristic
  87. status =
  88. aci_gatt_del_char(battery_svc->svc_handle, battery_svc->battery_level_char_handle);
  89. if(status) {
  90. FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status);
  91. }
  92. // Delete Power state characteristic
  93. status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->power_state_char_handle);
  94. if(status) {
  95. FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status);
  96. }
  97. // Delete Battery service
  98. status = aci_gatt_del_service(battery_svc->svc_handle);
  99. if(status) {
  100. FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status);
  101. }
  102. free(battery_svc);
  103. battery_svc = NULL;
  104. }
  105. }
  106. bool battery_svc_is_started() {
  107. return battery_svc != NULL;
  108. }
  109. bool battery_svc_update_level(uint8_t battery_charge) {
  110. // Check if service was started
  111. if(battery_svc == NULL) {
  112. return false;
  113. }
  114. // Update battery level characteristic
  115. FURI_LOG_D(TAG, "Updating battery level characteristic");
  116. tBleStatus result = aci_gatt_update_char_value(
  117. battery_svc->svc_handle, battery_svc->battery_level_char_handle, 0, 1, &battery_charge);
  118. if(result) {
  119. FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result);
  120. }
  121. return result != BLE_STATUS_SUCCESS;
  122. }
  123. bool battery_svc_update_power_state() {
  124. // Check if service was started
  125. if(battery_svc == NULL) {
  126. return false;
  127. }
  128. // Update power state characteristic
  129. BattrySvcPowerState power_state = {
  130. .level = BatterySvcPowerStateUnsupported,
  131. .present = BatterySvcPowerStateBatteryPresent,
  132. };
  133. if(furi_hal_power_is_charging()) {
  134. power_state.charging = BatterySvcPowerStateCharging;
  135. power_state.discharging = BatterySvcPowerStateNotDischarging;
  136. } else {
  137. power_state.charging = BatterySvcPowerStateNotCharging;
  138. power_state.discharging = BatterySvcPowerStateDischarging;
  139. }
  140. FURI_LOG_D(TAG, "Updating power state characteristic");
  141. tBleStatus result = aci_gatt_update_char_value(
  142. battery_svc->svc_handle,
  143. battery_svc->power_state_char_handle,
  144. 0,
  145. 1,
  146. (uint8_t*)&power_state);
  147. if(result) {
  148. FURI_LOG_E(TAG, "Failed updating Power state characteristic: %d", result);
  149. }
  150. return result != BLE_STATUS_SUCCESS;
  151. }