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