Skip to content

Commit 2017baa

Browse files
authored
[FL-2441] BLE add Power state, fix double connection (#1238)
* battery service: add power state charachteristic * bt: update power state on charging / discharging events * ble config: support only one connection * bt: always update flow control characteristic * bt: fix power state update * bt: simplify updating power state * bt: don't update flow control charachteristic
1 parent f90c932 commit 2017baa

File tree

7 files changed

+115
-11
lines changed

7 files changed

+115
-11
lines changed

applications/bt/bt_service/bt.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,16 @@ static void bt_battery_level_changed_callback(const void* _event, void* context)
9191
furi_assert(context);
9292

9393
Bt* bt = context;
94+
BtMessage message = {};
9495
const PowerEvent* event = _event;
9596
if(event->type == PowerEventTypeBatteryLevelChanged) {
96-
BtMessage message = {
97-
.type = BtMessageTypeUpdateBatteryLevel,
98-
.data.battery_level = event->data.battery_level};
97+
message.type = BtMessageTypeUpdateBatteryLevel;
98+
message.data.battery_level = event->data.battery_level;
99+
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
100+
} else if(
101+
event->type == PowerEventTypeStartCharging || event->type == PowerEventTypeFullyCharged ||
102+
event->type == PowerEventTypeStopCharging) {
103+
message.type = BtMessageTypeUpdatePowerState;
99104
furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK);
100105
}
101106
}
@@ -378,6 +383,8 @@ int32_t bt_srv() {
378383
} else if(message.type == BtMessageTypeUpdateBatteryLevel) {
379384
// Update battery level
380385
furi_hal_bt_update_battery_level(message.data.battery_level);
386+
} else if(message.type == BtMessageTypeUpdatePowerState) {
387+
furi_hal_bt_update_power_state();
381388
} else if(message.type == BtMessageTypePinCodeShow) {
382389
// Display PIN code
383390
bt_pin_code_show(bt, message.data.pin_code);

applications/bt/bt_service/bt_i.h

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
typedef enum {
2222
BtMessageTypeUpdateStatus,
2323
BtMessageTypeUpdateBatteryLevel,
24+
BtMessageTypeUpdatePowerState,
2425
BtMessageTypePinCodeShow,
2526
BtMessageTypeKeysStorageUpdated,
2627
BtMessageTypeSetProfile,

firmware/targets/f7/ble_glue/app_conf.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
* Maximum number of simultaneous connections that the device will support.
128128
* Valid values are from 1 to 8
129129
*/
130-
#define CFG_BLE_NUM_LINK 2
130+
#define CFG_BLE_NUM_LINK 1
131131

132132
/**
133133
* Maximum number of Services that can be stored in the GATT database.

firmware/targets/f7/ble_glue/battery_service.c

+92-7
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,106 @@
33
#include "ble.h"
44

55
#include <furi.h>
6+
#include <furi_hal_power.h>
67

78
#define TAG "BtBatterySvc"
89

910
typedef struct {
1011
uint16_t svc_handle;
11-
uint16_t char_level_handle;
12+
uint16_t battery_level_char_handle;
13+
uint16_t power_state_char_handle;
1214
} BatterySvc;
1315

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+
1443
static BatterySvc* battery_svc = NULL;
1544

45+
#define BATTERY_POWER_STATE (0x2A1A)
46+
1647
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;
1850

1951
void battery_svc_start() {
2052
battery_svc = malloc(sizeof(BatterySvc));
2153
tBleStatus status;
2254

2355
// Add Battery service
2456
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);
2658
if(status) {
2759
FURI_LOG_E(TAG, "Failed to add Battery service: %d", status);
2860
}
2961
// Add Battery level characteristic
3062
status = aci_gatt_add_char(
3163
battery_svc->svc_handle,
3264
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,
3481
1,
3582
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
3683
ATTR_PERMISSION_AUTHEN_READ,
3784
GATT_DONT_NOTIFY_EVENTS,
3885
10,
3986
CHAR_VALUE_LEN_CONSTANT,
40-
&battery_svc->char_level_handle);
87+
&battery_svc->power_state_char_handle);
4188
if(status) {
4289
FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status);
4390
}
91+
// Update power state charachteristic
92+
battery_svc_update_power_state();
4493
}
4594

4695
void battery_svc_stop() {
4796
tBleStatus status;
4897
if(battery_svc) {
4998
// 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);
51106
if(status) {
52107
FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status);
53108
}
@@ -73,9 +128,39 @@ bool battery_svc_update_level(uint8_t battery_charge) {
73128
// Update battery level characteristic
74129
FURI_LOG_D(TAG, "Updating battery level characteristic");
75130
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);
77132
if(result) {
78133
FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result);
79134
}
80135
return result != BLE_STATUS_SUCCESS;
81136
}
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+
}

firmware/targets/f7/ble_glue/battery_service.h

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ bool battery_svc_is_started();
1515

1616
bool battery_svc_update_level(uint8_t battery_level);
1717

18+
bool battery_svc_update_power_state();
19+
1820
#ifdef __cplusplus
1921
}
2022
#endif

firmware/targets/f7/furi_hal/furi_hal_bt.c

+6
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,12 @@ void furi_hal_bt_update_battery_level(uint8_t battery_level) {
284284
}
285285
}
286286

287+
void furi_hal_bt_update_power_state() {
288+
if(battery_svc_is_started()) {
289+
battery_svc_update_power_state();
290+
}
291+
}
292+
287293
void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) {
288294
ble_app_get_key_storage_buff(key_buff_addr, key_buff_size);
289295
}

firmware/targets/furi_hal_include/furi_hal_bt.h

+3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb,
9191
*/
9292
void furi_hal_bt_update_battery_level(uint8_t battery_level);
9393

94+
/** Update battery power state */
95+
void furi_hal_bt_update_power_state();
96+
9497
/** Checks if BLE state is active
9598
*
9699
* @return true if device is connected or advertising, false otherwise

0 commit comments

Comments
 (0)