[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); | ||||
| 
 | ||||
|     Bt* bt = context; | ||||
|     BtMessage message = {}; | ||||
|     const PowerEvent* event = _event; | ||||
|     if(event->type == PowerEventTypeBatteryLevelChanged) { | ||||
|         BtMessage message = { | ||||
|             .type = BtMessageTypeUpdateBatteryLevel, | ||||
|             .data.battery_level = event->data.battery_level}; | ||||
|         message.type = BtMessageTypeUpdateBatteryLevel; | ||||
|         message.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); | ||||
|     } | ||||
| } | ||||
| @ -378,6 +383,8 @@ int32_t bt_srv() { | ||||
|         } else if(message.type == BtMessageTypeUpdateBatteryLevel) { | ||||
|             // Update 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) { | ||||
|             // Display PIN code
 | ||||
|             bt_pin_code_show(bt, message.data.pin_code); | ||||
|  | ||||
| @ -21,6 +21,7 @@ | ||||
| typedef enum { | ||||
|     BtMessageTypeUpdateStatus, | ||||
|     BtMessageTypeUpdateBatteryLevel, | ||||
|     BtMessageTypeUpdatePowerState, | ||||
|     BtMessageTypePinCodeShow, | ||||
|     BtMessageTypeKeysStorageUpdated, | ||||
|     BtMessageTypeSetProfile, | ||||
|  | ||||
| @ -127,7 +127,7 @@ | ||||
|  * Maximum number of simultaneous connections that the device will support. | ||||
|  * 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. | ||||
|  | ||||
| @ -3,18 +3,50 @@ | ||||
| #include "ble.h" | ||||
| 
 | ||||
| #include <furi.h> | ||||
| #include <furi_hal_power.h> | ||||
| 
 | ||||
| #define TAG "BtBatterySvc" | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint16_t svc_handle; | ||||
|     uint16_t char_level_handle; | ||||
|     uint16_t battery_level_char_handle; | ||||
|     uint16_t power_state_char_handle; | ||||
| } 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; | ||||
| 
 | ||||
| #define BATTERY_POWER_STATE (0x2A1A) | ||||
| 
 | ||||
| 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() { | ||||
|     battery_svc = malloc(sizeof(BatterySvc)); | ||||
| @ -22,7 +54,7 @@ void battery_svc_start() { | ||||
| 
 | ||||
|     // Add Battery 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) { | ||||
|         FURI_LOG_E(TAG, "Failed to add Battery service: %d", status); | ||||
|     } | ||||
| @ -30,24 +62,47 @@ void battery_svc_start() { | ||||
|     status = aci_gatt_add_char( | ||||
|         battery_svc->svc_handle, | ||||
|         UUID_TYPE_16, | ||||
|         (Char_UUID_t*)&char_battery_level_uuid, | ||||
|         (Char_UUID_t*)&battery_level_char_uuid, | ||||
|         1, | ||||
|         CHAR_PROP_READ | CHAR_PROP_NOTIFY, | ||||
|         ATTR_PERMISSION_AUTHEN_READ, | ||||
|         GATT_DONT_NOTIFY_EVENTS, | ||||
|         10, | ||||
|         CHAR_VALUE_LEN_CONSTANT, | ||||
|         &battery_svc->char_level_handle); | ||||
|         &battery_svc->battery_level_char_handle); | ||||
|     if(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() { | ||||
|     tBleStatus status; | ||||
|     if(battery_svc) { | ||||
|         // 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) { | ||||
|             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
 | ||||
|     FURI_LOG_D(TAG, "Updating battery level characteristic"); | ||||
|     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) { | ||||
|         FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); | ||||
|     } | ||||
|     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_power_state(); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #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) { | ||||
|     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); | ||||
| 
 | ||||
| /** Update battery power state */ | ||||
| void furi_hal_bt_update_power_state(); | ||||
| 
 | ||||
| /** Checks if BLE state is active
 | ||||
|  * | ||||
|  * @return          true if device is connected or advertising, false otherwise | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich