Skip to main content

rs_matter_stack/
ble.rs

1use core::future::Future;
2
3use rs_matter::error::Error;
4use rs_matter::transport::network::btp::{AdvData, Btp};
5
6#[cfg(all(feature = "os", target_os = "linux", feature = "bluer"))]
7pub use bluer::*;
8#[cfg(feature = "zbus")]
9pub use bluez::*;
10
11/// A trait modeling a platform-specific / BLE-stack specific GATT peripheral.
12///
13/// Running the peripheral means it would advertise the Matter BTP service
14/// and then - once a peer connects - will drive the passed `Btp` instance
15/// via write requests and indications to the Matter C1 and C2 characteristics.
16pub trait GattPeripheral {
17    /// Run the Matter GATT app
18    ///
19    /// # Arguments
20    /// - `btp`: the BTP instance to drive with the GATT app
21    /// - `service_name`: the name to advertise for the BTP service
22    /// - `service_adv`: the advertisement data to use for the BTP service
23    async fn run(
24        &mut self,
25        btp: &Btp,
26        service_name: &str,
27        service_adv: &AdvData,
28    ) -> Result<(), Error>;
29}
30
31impl<T> GattPeripheral for &mut T
32where
33    T: GattPeripheral,
34{
35    fn run(
36        &mut self,
37        btp: &Btp,
38        service_name: &str,
39        service_adv: &AdvData,
40    ) -> impl Future<Output = Result<(), Error>> {
41        (*self).run(btp, service_name, service_adv)
42    }
43}
44
45#[cfg(all(feature = "os", target_os = "linux", feature = "bluer"))]
46#[allow(clippy::large_futures)]
47mod bluer {
48    use rs_matter::error::Error;
49    use rs_matter::transport::network::btp::{AdvData, Btp};
50
51    pub struct BluerGattPeripheral<'a>(Option<&'a str>);
52
53    impl<'a> BluerGattPeripheral<'a> {
54        /// Create a new `BluerGattPeripheral` that will use the Bluetooth adapter with the given name.
55        /// If `adapter_name` is `None`, the default adapter will be used.
56        pub const fn new(adapter_name: Option<&'a str>) -> Self {
57            Self(adapter_name)
58        }
59    }
60
61    impl super::GattPeripheral for BluerGattPeripheral<'_> {
62        async fn run(
63            &mut self,
64            btp: &Btp,
65            service_name: &str,
66            service_adv: &AdvData,
67        ) -> Result<(), Error> {
68            rs_matter::transport::network::btp::bluer::run_peripheral(
69                self.0,
70                service_name,
71                service_adv,
72                btp,
73            )
74            .await
75        }
76    }
77}
78
79#[cfg(feature = "zbus")]
80#[allow(clippy::large_futures)]
81mod bluez {
82    use rs_matter::error::Error;
83    use rs_matter::transport::network::btp::{AdvData, Btp};
84    use rs_matter::utils::zbus::Connection;
85
86    pub struct BluezGattPeripheral<'a> {
87        connection: &'a Connection,
88        adapter_name: Option<&'a str>,
89    }
90
91    impl<'a> BluezGattPeripheral<'a> {
92        /// Create a new `BluezGattPeripheral` that will use the Bluetooth adapter with the given name.
93        /// If `adapter_name` is `None`, the default adapter will be used.
94        pub const fn new(connection: &'a Connection, adapter_name: Option<&'a str>) -> Self {
95            Self {
96                connection,
97                adapter_name,
98            }
99        }
100    }
101
102    impl super::GattPeripheral for BluezGattPeripheral<'_> {
103        async fn run(
104            &mut self,
105            btp: &Btp,
106            service_name: &str,
107            service_adv: &AdvData,
108        ) -> Result<(), Error> {
109            rs_matter::transport::network::btp::bluez::run_peripheral(
110                self.connection,
111                self.adapter_name,
112                service_name,
113                service_adv,
114                btp,
115            )
116            .await
117        }
118    }
119}