[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
This commit is contained in:
		
							parent
							
								
									f90c9320d9
								
							
						
					
					
						commit
						2017baac48
					
				| @ -91,11 +91,16 @@ static void bt_battery_level_changed_callback(const void* _event, void* context) | |||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
| 
 | 
 | ||||||
|     Bt* bt = context; |     Bt* bt = context; | ||||||
|  |     BtMessage message = {}; | ||||||
|     const PowerEvent* event = _event; |     const PowerEvent* event = _event; | ||||||
|     if(event->type == PowerEventTypeBatteryLevelChanged) { |     if(event->type == PowerEventTypeBatteryLevelChanged) { | ||||||
|         BtMessage message = { |         message.type = BtMessageTypeUpdateBatteryLevel; | ||||||
|             .type = BtMessageTypeUpdateBatteryLevel, |         message.data.battery_level = event->data.battery_level; | ||||||
|             .data.battery_level = event->data.battery_level}; |         furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); | ||||||
|  |     } else if( | ||||||
|  |         event->type == PowerEventTypeStartCharging || event->type == PowerEventTypeFullyCharged || | ||||||
|  |         event->type == PowerEventTypeStopCharging) { | ||||||
|  |         message.type = BtMessageTypeUpdatePowerState; | ||||||
|         furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); |         furi_check(osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -378,6 +383,8 @@ int32_t bt_srv() { | |||||||
|         } else if(message.type == BtMessageTypeUpdateBatteryLevel) { |         } else if(message.type == BtMessageTypeUpdateBatteryLevel) { | ||||||
|             // Update battery level
 |             // Update battery level
 | ||||||
|             furi_hal_bt_update_battery_level(message.data.battery_level); |             furi_hal_bt_update_battery_level(message.data.battery_level); | ||||||
|  |         } else if(message.type == BtMessageTypeUpdatePowerState) { | ||||||
|  |             furi_hal_bt_update_power_state(); | ||||||
|         } else if(message.type == BtMessageTypePinCodeShow) { |         } else if(message.type == BtMessageTypePinCodeShow) { | ||||||
|             // Display PIN code
 |             // Display PIN code
 | ||||||
|             bt_pin_code_show(bt, message.data.pin_code); |             bt_pin_code_show(bt, message.data.pin_code); | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ | |||||||
| typedef enum { | typedef enum { | ||||||
|     BtMessageTypeUpdateStatus, |     BtMessageTypeUpdateStatus, | ||||||
|     BtMessageTypeUpdateBatteryLevel, |     BtMessageTypeUpdateBatteryLevel, | ||||||
|  |     BtMessageTypeUpdatePowerState, | ||||||
|     BtMessageTypePinCodeShow, |     BtMessageTypePinCodeShow, | ||||||
|     BtMessageTypeKeysStorageUpdated, |     BtMessageTypeKeysStorageUpdated, | ||||||
|     BtMessageTypeSetProfile, |     BtMessageTypeSetProfile, | ||||||
|  | |||||||
| @ -127,7 +127,7 @@ | |||||||
|  * Maximum number of simultaneous connections that the device will support. |  * Maximum number of simultaneous connections that the device will support. | ||||||
|  * Valid values are from 1 to 8 |  * Valid values are from 1 to 8 | ||||||
|  */ |  */ | ||||||
| #define CFG_BLE_NUM_LINK 2 | #define CFG_BLE_NUM_LINK 1 | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Maximum number of Services that can be stored in the GATT database. |  * Maximum number of Services that can be stored in the GATT database. | ||||||
|  | |||||||
| @ -3,18 +3,50 @@ | |||||||
| #include "ble.h" | #include "ble.h" | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
|  | #include <furi_hal_power.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "BtBatterySvc" | #define TAG "BtBatterySvc" | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint16_t svc_handle; |     uint16_t svc_handle; | ||||||
|     uint16_t char_level_handle; |     uint16_t battery_level_char_handle; | ||||||
|  |     uint16_t power_state_char_handle; | ||||||
| } BatterySvc; | } BatterySvc; | ||||||
| 
 | 
 | ||||||
|  | enum { | ||||||
|  |     // Common states
 | ||||||
|  |     BatterySvcPowerStateUnknown = 0b00, | ||||||
|  |     BatterySvcPowerStateUnsupported = 0b01, | ||||||
|  |     // Level states
 | ||||||
|  |     BatterySvcPowerStateGoodLevel = 0b10, | ||||||
|  |     BatterySvcPowerStateCriticallyLowLevel = 0b11, | ||||||
|  |     // Charging states
 | ||||||
|  |     BatterySvcPowerStateNotCharging = 0b10, | ||||||
|  |     BatterySvcPowerStateCharging = 0b11, | ||||||
|  |     // Discharging states
 | ||||||
|  |     BatterySvcPowerStateNotDischarging = 0b10, | ||||||
|  |     BatterySvcPowerStateDischarging = 0b11, | ||||||
|  |     // Battery states
 | ||||||
|  |     BatterySvcPowerStateBatteryNotPresent = 0b10, | ||||||
|  |     BatterySvcPowerStateBatteryPresent = 0b11, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uint8_t present : 2; | ||||||
|  |     uint8_t discharging : 2; | ||||||
|  |     uint8_t charging : 2; | ||||||
|  |     uint8_t level : 2; | ||||||
|  | } BattrySvcPowerState; | ||||||
|  | 
 | ||||||
|  | _Static_assert(sizeof(BattrySvcPowerState) == 1, "Incorrect structure size"); | ||||||
|  | 
 | ||||||
| static BatterySvc* battery_svc = NULL; | static BatterySvc* battery_svc = NULL; | ||||||
| 
 | 
 | ||||||
|  | #define BATTERY_POWER_STATE (0x2A1A) | ||||||
|  | 
 | ||||||
| static const uint16_t service_uuid = BATTERY_SERVICE_UUID; | static const uint16_t service_uuid = BATTERY_SERVICE_UUID; | ||||||
| static const uint16_t char_battery_level_uuid = BATTERY_LEVEL_CHAR_UUID; | static const uint16_t battery_level_char_uuid = BATTERY_LEVEL_CHAR_UUID; | ||||||
|  | static const uint16_t power_state_char_uuid = BATTERY_POWER_STATE; | ||||||
| 
 | 
 | ||||||
| void battery_svc_start() { | void battery_svc_start() { | ||||||
|     battery_svc = malloc(sizeof(BatterySvc)); |     battery_svc = malloc(sizeof(BatterySvc)); | ||||||
| @ -22,7 +54,7 @@ void battery_svc_start() { | |||||||
| 
 | 
 | ||||||
|     // Add Battery service
 |     // Add Battery service
 | ||||||
|     status = aci_gatt_add_service( |     status = aci_gatt_add_service( | ||||||
|         UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc->svc_handle); |         UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 8, &battery_svc->svc_handle); | ||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); |         FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); | ||||||
|     } |     } | ||||||
| @ -30,24 +62,47 @@ void battery_svc_start() { | |||||||
|     status = aci_gatt_add_char( |     status = aci_gatt_add_char( | ||||||
|         battery_svc->svc_handle, |         battery_svc->svc_handle, | ||||||
|         UUID_TYPE_16, |         UUID_TYPE_16, | ||||||
|         (Char_UUID_t*)&char_battery_level_uuid, |         (Char_UUID_t*)&battery_level_char_uuid, | ||||||
|         1, |         1, | ||||||
|         CHAR_PROP_READ | CHAR_PROP_NOTIFY, |         CHAR_PROP_READ | CHAR_PROP_NOTIFY, | ||||||
|         ATTR_PERMISSION_AUTHEN_READ, |         ATTR_PERMISSION_AUTHEN_READ, | ||||||
|         GATT_DONT_NOTIFY_EVENTS, |         GATT_DONT_NOTIFY_EVENTS, | ||||||
|         10, |         10, | ||||||
|         CHAR_VALUE_LEN_CONSTANT, |         CHAR_VALUE_LEN_CONSTANT, | ||||||
|         &battery_svc->char_level_handle); |         &battery_svc->battery_level_char_handle); | ||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); |         FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); | ||||||
|     } |     } | ||||||
|  |     // Add Power state characteristic
 | ||||||
|  |     status = aci_gatt_add_char( | ||||||
|  |         battery_svc->svc_handle, | ||||||
|  |         UUID_TYPE_16, | ||||||
|  |         (Char_UUID_t*)&power_state_char_uuid, | ||||||
|  |         1, | ||||||
|  |         CHAR_PROP_READ | CHAR_PROP_NOTIFY, | ||||||
|  |         ATTR_PERMISSION_AUTHEN_READ, | ||||||
|  |         GATT_DONT_NOTIFY_EVENTS, | ||||||
|  |         10, | ||||||
|  |         CHAR_VALUE_LEN_CONSTANT, | ||||||
|  |         &battery_svc->power_state_char_handle); | ||||||
|  |     if(status) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); | ||||||
|  |     } | ||||||
|  |     // Update power state charachteristic
 | ||||||
|  |     battery_svc_update_power_state(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void battery_svc_stop() { | void battery_svc_stop() { | ||||||
|     tBleStatus status; |     tBleStatus status; | ||||||
|     if(battery_svc) { |     if(battery_svc) { | ||||||
|         // Delete Battery level characteristic
 |         // Delete Battery level characteristic
 | ||||||
|         status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->char_level_handle); |         status = | ||||||
|  |             aci_gatt_del_char(battery_svc->svc_handle, battery_svc->battery_level_char_handle); | ||||||
|  |         if(status) { | ||||||
|  |             FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); | ||||||
|  |         } | ||||||
|  |         // Delete Power state characteristic
 | ||||||
|  |         status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->power_state_char_handle); | ||||||
|         if(status) { |         if(status) { | ||||||
|             FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); |             FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); | ||||||
|         } |         } | ||||||
| @ -73,9 +128,39 @@ bool battery_svc_update_level(uint8_t battery_charge) { | |||||||
|     // Update battery level characteristic
 |     // Update battery level characteristic
 | ||||||
|     FURI_LOG_D(TAG, "Updating battery level characteristic"); |     FURI_LOG_D(TAG, "Updating battery level characteristic"); | ||||||
|     tBleStatus result = aci_gatt_update_char_value( |     tBleStatus result = aci_gatt_update_char_value( | ||||||
|         battery_svc->svc_handle, battery_svc->char_level_handle, 0, 1, &battery_charge); |         battery_svc->svc_handle, battery_svc->battery_level_char_handle, 0, 1, &battery_charge); | ||||||
|     if(result) { |     if(result) { | ||||||
|         FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); |         FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); | ||||||
|     } |     } | ||||||
|     return result != BLE_STATUS_SUCCESS; |     return result != BLE_STATUS_SUCCESS; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool battery_svc_update_power_state() { | ||||||
|  |     // Check if service was started
 | ||||||
|  |     if(battery_svc == NULL) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |     // Update power state characteristic
 | ||||||
|  |     BattrySvcPowerState power_state = { | ||||||
|  |         .level = BatterySvcPowerStateUnsupported, | ||||||
|  |         .present = BatterySvcPowerStateBatteryPresent, | ||||||
|  |     }; | ||||||
|  |     if(furi_hal_power_is_charging()) { | ||||||
|  |         power_state.charging = BatterySvcPowerStateCharging; | ||||||
|  |         power_state.discharging = BatterySvcPowerStateNotDischarging; | ||||||
|  |     } else { | ||||||
|  |         power_state.charging = BatterySvcPowerStateNotCharging; | ||||||
|  |         power_state.discharging = BatterySvcPowerStateDischarging; | ||||||
|  |     } | ||||||
|  |     FURI_LOG_D(TAG, "Updating power state characteristic"); | ||||||
|  |     tBleStatus result = aci_gatt_update_char_value( | ||||||
|  |         battery_svc->svc_handle, | ||||||
|  |         battery_svc->power_state_char_handle, | ||||||
|  |         0, | ||||||
|  |         1, | ||||||
|  |         (uint8_t*)&power_state); | ||||||
|  |     if(result) { | ||||||
|  |         FURI_LOG_E(TAG, "Failed updating Power state characteristic: %d", result); | ||||||
|  |     } | ||||||
|  |     return result != BLE_STATUS_SUCCESS; | ||||||
|  | } | ||||||
|  | |||||||
| @ -15,6 +15,8 @@ bool battery_svc_is_started(); | |||||||
| 
 | 
 | ||||||
| bool battery_svc_update_level(uint8_t battery_level); | bool battery_svc_update_level(uint8_t battery_level); | ||||||
| 
 | 
 | ||||||
|  | bool battery_svc_update_power_state(); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -284,6 +284,12 @@ void furi_hal_bt_update_battery_level(uint8_t battery_level) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_hal_bt_update_power_state() { | ||||||
|  |     if(battery_svc_is_started()) { | ||||||
|  |         battery_svc_update_power_state(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { | void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { | ||||||
|     ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); |     ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); | ||||||
| } | } | ||||||
|  | |||||||
| @ -91,6 +91,9 @@ bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, | |||||||
|  */ |  */ | ||||||
| void furi_hal_bt_update_battery_level(uint8_t battery_level); | void furi_hal_bt_update_battery_level(uint8_t battery_level); | ||||||
| 
 | 
 | ||||||
|  | /** Update battery power state */ | ||||||
|  | void furi_hal_bt_update_power_state(); | ||||||
|  | 
 | ||||||
| /** Checks if BLE state is active
 | /** Checks if BLE state is active
 | ||||||
|  * |  * | ||||||
|  * @return          true if device is connected or advertising, false otherwise |  * @return          true if device is connected or advertising, false otherwise | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich