1 use crate::battery_manager::{Batteries, BatterySet}; 2 use crate::callbacks::Callbacks; 3 use crate::{Message, RPCProxy}; 4 use std::collections::HashMap; 5 use tokio::sync::mpsc::Sender; 6 7 /// Callback for BatteryProvider implementers. 8 pub trait IBatteryProviderCallback: RPCProxy { 9 /// Requests that the BatteryProvider send updated battery information. refresh_battery_info(&mut self)10 fn refresh_battery_info(&mut self); 11 } 12 13 /// Interface for managing BatteryProvider instances. 14 pub trait IBatteryProviderManager { 15 /// Registers a BatteryProvider and generates a unique batttery provider ID for future calls. register_battery_provider( &mut self, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u3216 fn register_battery_provider( 17 &mut self, 18 battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, 19 ) -> u32; 20 21 /// Unregisters a BatteryProvider, potentially removes battery information for the remote device 22 /// if there are no other providers. unregister_battery_provider(&mut self, battery_provider_id: u32)23 fn unregister_battery_provider(&mut self, battery_provider_id: u32); 24 25 /// Updates the battery information for the battery associated with battery_id. set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet)26 fn set_battery_info(&mut self, battery_provider_id: u32, battery_set: BatterySet); 27 } 28 29 /// Represents the BatteryProviderManager, a central point for collecting battery information from 30 /// numerous sources. 31 pub struct BatteryProviderManager { 32 /// Sender for callback communication with the main thread. 33 tx: Sender<Message>, 34 battery_provider_callbacks: Callbacks<dyn IBatteryProviderCallback + Send>, 35 /// Stored information merged from all battery providers. 36 battery_info: HashMap<String, Batteries>, 37 } 38 39 impl BatteryProviderManager { 40 /// Constructs a new BatteryProviderManager with callbacks communicating on tx. new(tx: Sender<Message>) -> BatteryProviderManager41 pub fn new(tx: Sender<Message>) -> BatteryProviderManager { 42 let battery_provider_callbacks = 43 Callbacks::new(tx.clone(), Message::BatteryProviderManagerCallbackDisconnected); 44 let battery_info = HashMap::new(); 45 BatteryProviderManager { tx, battery_provider_callbacks, battery_info } 46 } 47 48 /// Request battery info refresh from all battery providers. refresh_battery_info(&mut self)49 pub fn refresh_battery_info(&mut self) { 50 self.battery_provider_callbacks 51 .for_all_callbacks(|callback| callback.refresh_battery_info()); 52 } 53 54 /// Get the best battery info available for a given device. get_battery_info(&self, remote_address: String) -> Option<BatterySet>55 pub fn get_battery_info(&self, remote_address: String) -> Option<BatterySet> { 56 self.battery_info.get(&remote_address)?.pick_best() 57 } 58 59 /// Removes a battery provider callback. remove_battery_provider_callback(&mut self, battery_provider_id: u32)60 pub fn remove_battery_provider_callback(&mut self, battery_provider_id: u32) { 61 self.battery_provider_callbacks.remove_callback(battery_provider_id); 62 } 63 } 64 65 impl IBatteryProviderManager for BatteryProviderManager { register_battery_provider( &mut self, battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, ) -> u3266 fn register_battery_provider( 67 &mut self, 68 battery_provider_callback: Box<dyn IBatteryProviderCallback + Send>, 69 ) -> u32 { 70 self.battery_provider_callbacks.add_callback(battery_provider_callback) 71 } 72 unregister_battery_provider(&mut self, battery_provider_id: u32)73 fn unregister_battery_provider(&mut self, battery_provider_id: u32) { 74 self.remove_battery_provider_callback(battery_provider_id); 75 } 76 set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet)77 fn set_battery_info(&mut self, _battery_provider_id: u32, battery_set: BatterySet) { 78 let batteries = self 79 .battery_info 80 .entry(battery_set.address.clone()) 81 .or_insert_with(|| Batteries::new()); 82 batteries.add_or_update_battery_set(battery_set); 83 if let Some(best_battery_set) = batteries.pick_best() { 84 let tx = self.tx.clone(); 85 tokio::spawn(async move { 86 let _ = tx 87 .send(Message::BatteryProviderManagerBatteryUpdated( 88 best_battery_set.address.clone(), 89 best_battery_set, 90 )) 91 .await; 92 }); 93 } 94 } 95 } 96