use futures::StreamExt;
use tokio::sync::mpsc;
pub struct Monitor {
connection: std::sync::Arc<zbus::Connection>,
manager: std::sync::Arc<crate::ObjectManagerProxy<'static>>,
device_added_tx: mpsc::Sender<crate::cache::DeviceInfo>,
device_removed_tx: mpsc::Sender<crate::cache::DeviceInfo>,
}
impl Monitor {
pub async fn new(
connection: std::sync::Arc<zbus::Connection>,
manager: std::sync::Arc<crate::ObjectManagerProxy<'static>>,
device_added_tx: mpsc::Sender<crate::cache::DeviceInfo>,
device_removed_tx: mpsc::Sender<crate::cache::DeviceInfo>,
) -> Self {
Self {
connection,
manager,
device_added_tx,
device_removed_tx,
}
}
pub async fn monitor_device_removed(&self) {
let mut interfaces_removed = self.manager.receive_interfaces_removed().await.unwrap();
loop {
if let Some(signal) = interfaces_removed.next().await {
let args = signal.args().unwrap();
if let Some(removed_dev) = crate::remove_device(args.object_path().as_str()) {
let _ = self.device_removed_tx.send(removed_dev).await;
}
}
}
}
pub async fn monitor_device_added(&self) {
let mut interfaces_added = self.manager.receive_interfaces_added().await.unwrap();
loop {
if let Some(signal) = interfaces_added.next().await {
let args = signal.args().unwrap();
if let Some(interfaces) = args.interfaces().get("org.bluez.Device1") {
if let (Some(address), Some(als), Some(cnnctd), Some(prd)) = (
interfaces.get("Address"), interfaces.get("Alias"), interfaces
.get("Connected"), interfaces
.get("Paired")) {
let addr = address.to_string();
let alias = als.to_string();
let connected = cnnctd
.downcast_ref::<bool>()
.unwrap();
let paired = prd
.downcast_ref::<bool>()
.unwrap();
let path = args.object_path().to_string();
let new_device = crate::cache::DeviceInfo {
address: addr.to_string(),
alias,
connected,
paired,
};
crate::add_or_update_device(path, &new_device);
self.monitor_device_properties(
self.connection.clone(),
std::sync::Arc::new(args.object_path.to_string()),
)
.await
.unwrap();
let _ = self.device_added_tx.send(new_device.clone()).await;
}
}
}
}
}
async fn monitor_device_properties(
&self,
conn: std::sync::Arc<zbus::Connection>,
object_path: std::sync::Arc<String>,
) -> zbus::Result<()> {
tokio::spawn(async move {
let props = zbus::fdo::PropertiesProxy::builder(&conn)
.destination("org.bluez")
.unwrap()
.path(object_path.as_str())
.unwrap()
.build()
.await
.unwrap();
let mut props_changed = props.receive_properties_changed().await.unwrap();
while let Some(signal) = props_changed.next().await {
let args = signal.args().unwrap();
let interface_name = args.interface_name().to_string();
let changed_props = args.changed_properties();
if interface_name == "org.bluez.Device1" {
if let Some(mut device) = crate::get_device(object_path.as_str()) {
if let Some(new_value) = changed_props.get("Connected") {
let val = new_value.downcast_ref::<bool>().unwrap();
device.connected = val;
}
if let Some(new_value) = changed_props.get("Paired") {
let val = new_value.downcast_ref::<bool>().unwrap();
device.paired = val;
}
if let Some(new_value) = changed_props.get("Alias") {
let val = new_value.downcast_ref::<String>().unwrap();
device.alias = val;
}
crate::add_or_update_device(object_path.to_string(), &device);
}
}
}
});
Ok(())
}
}