|
10 | 10 |
|
11 | 11 | use super::{ |
12 | 12 | central_delegate::{CentralDelegate, CentralDelegateEvent}, |
13 | | - framework::cb::{self, CBManagerAuthorization, CBPeripheralState}, |
| 13 | + framework::cb::{self, CBManagerAuthorization, CBManagerState, CBPeripheralState}, |
14 | 14 | future::{BtlePlugFuture, BtlePlugFutureStateShared}, |
15 | 15 | utils::{ |
16 | 16 | core_bluetooth::{cbuuid_to_uuid, uuid_to_cbuuid}, |
@@ -139,6 +139,7 @@ pub enum CoreBluetoothReply { |
139 | 139 | ReadResult(Vec<u8>), |
140 | 140 | Connected(BTreeSet<Service>), |
141 | 141 | State(CBPeripheralState), |
| 142 | + ManagerState(CBManagerState), |
142 | 143 | Ok, |
143 | 144 | Err(String), |
144 | 145 | } |
@@ -399,11 +400,14 @@ pub enum CoreBluetoothMessage { |
399 | 400 | data: Vec<u8>, |
400 | 401 | future: CoreBluetoothReplyStateShared, |
401 | 402 | }, |
| 403 | + FetchManagerState { |
| 404 | + future: CoreBluetoothReplyStateShared, |
| 405 | + }, |
402 | 406 | } |
403 | 407 |
|
404 | 408 | #[derive(Debug)] |
405 | 409 | pub enum CoreBluetoothEvent { |
406 | | - AdapterConnected, |
| 410 | + DidUpdateState, |
407 | 411 | DeviceDiscovered { |
408 | 412 | uuid: Uuid, |
409 | 413 | name: Option<String>, |
@@ -789,6 +793,18 @@ impl CoreBluetoothInternal { |
789 | 793 | } |
790 | 794 | } |
791 | 795 |
|
| 796 | + fn get_manager_state(&mut self) -> CBManagerState { |
| 797 | + cb::centeralmanger_state(&*self.manager) |
| 798 | + } |
| 799 | + |
| 800 | + fn get_manager_state_async(&mut self, fut: CoreBluetoothReplyStateShared) { |
| 801 | + let state = cb::centeralmanger_state(&*self.manager); |
| 802 | + trace!("Manager state {:?} ", state); |
| 803 | + fut.lock() |
| 804 | + .unwrap() |
| 805 | + .set_reply(CoreBluetoothReply::ManagerState(state)); |
| 806 | + } |
| 807 | + |
792 | 808 | fn write_value( |
793 | 809 | &mut self, |
794 | 810 | peripheral_uuid: Uuid, |
@@ -831,6 +847,11 @@ impl CoreBluetoothInternal { |
831 | 847 | characteristic_uuid: Uuid, |
832 | 848 | fut: CoreBluetoothReplyStateShared, |
833 | 849 | ) { |
| 850 | + trace!( |
| 851 | + "Manager State {:?}", |
| 852 | + cb::centeralmanger_state(&*self.manager) |
| 853 | + ); |
| 854 | + |
834 | 855 | if let Some(peripheral) = self.peripherals.get_mut(&peripheral_uuid) { |
835 | 856 | if let Some(service) = peripheral.services.get_mut(&service_uuid) { |
836 | 857 | if let Some(characteristic) = service.characteristics.get_mut(&characteristic_uuid) |
@@ -1004,7 +1025,7 @@ impl CoreBluetoothInternal { |
1004 | 1025 | // "ready" variable in our adapter that will cause scans/etc |
1005 | 1026 | // to fail if this hasn't updated. |
1006 | 1027 | CentralDelegateEvent::DidUpdateState => { |
1007 | | - self.dispatch_event(CoreBluetoothEvent::AdapterConnected).await |
| 1028 | + self.dispatch_event(CoreBluetoothEvent::DidUpdateState).await |
1008 | 1029 | } |
1009 | 1030 | CentralDelegateEvent::DiscoveredPeripheral{cbperipheral} => { |
1010 | 1031 | self.on_discovered_peripheral(cbperipheral).await |
@@ -1103,6 +1124,9 @@ impl CoreBluetoothInternal { |
1103 | 1124 | CoreBluetoothMessage::IsConnected{peripheral_uuid, future} => { |
1104 | 1125 | self.is_connected(peripheral_uuid, future); |
1105 | 1126 | }, |
| 1127 | + CoreBluetoothMessage::FetchManagerState {future} =>{ |
| 1128 | + self.get_manager_state_async(future); |
| 1129 | + }, |
1106 | 1130 | CoreBluetoothMessage::ReadDescriptorValue{peripheral_uuid, service_uuid, characteristic_uuid, descriptor_uuid, future} => { |
1107 | 1131 | self.read_descriptor_value(peripheral_uuid, service_uuid, characteristic_uuid, descriptor_uuid, future) |
1108 | 1132 | } |
@@ -1184,6 +1208,14 @@ pub fn run_corebluetooth_thread( |
1184 | 1208 | runtime.block_on(async move { |
1185 | 1209 | let mut cbi = CoreBluetoothInternal::new(receiver, event_sender); |
1186 | 1210 | loop { |
| 1211 | + // When the IOS or MacOS device if powered off or locked |
| 1212 | + // the manager state will suddenly throw DidUpdateState event and turn off. |
| 1213 | + // If we are not exiting the main loop here the futures requested after |
| 1214 | + // power off will be stuck forever. |
| 1215 | + if cbi.get_manager_state() == CBManagerState::PoweredOff { |
| 1216 | + trace!("Breaking out of the corebluetooth loop. Manager is off."); |
| 1217 | + break; |
| 1218 | + } |
1187 | 1219 | cbi.wait_for_message().await; |
1188 | 1220 | } |
1189 | 1221 | }) |
|
0 commit comments