blec/
ble.rs

1use crate::setup::{self, RUNTIME};
2use crate::{block_on, spawn, BleAddress, BleDevice};
3use crate::{handler::BleHandler, BleError};
4use futures::{Future, StreamExt};
5use once_cell::sync::OnceCell;
6use tokio::sync::{mpsc, Mutex};
7use uuid::Uuid;
8
9static HANDLER: OnceCell<Mutex<BleHandler>> = OnceCell::new();
10
11/// The init() function must be called before anything else.
12/// At the moment the developer has to make sure it is only called once.
13pub fn init() -> Result<(), BleError> {
14    // crate the runtime include architecture specific differences
15    setup::create_runtime()?;
16    let rt = RUNTIME.get().ok_or(BleError::RuntimeNotInitialized)?;
17    HANDLER
18        .set(Mutex::new(rt.block_on(BleHandler::new())?))
19        .map_err(|_| BleError::HandlerAlreadyInitialized)?;
20    // start a loop running in the background for handling ble events
21    rt.spawn(event_loop());
22    Ok(())
23}
24
25async fn event_loop() -> Result<(), BleError> {
26    let handler = get_handler();
27    let mut events = handler.lock().await.get_event_stream().await?;
28    while let Some(event) = events.next().await {
29        handler.lock().await.handle_event(event).await?;
30    }
31    Ok(())
32}
33
34fn get_handler() -> &'static Mutex<BleHandler> {
35    let handler = HANDLER
36        .get()
37        .ok_or(BleError::HandlerNotInitialized)
38        .unwrap();
39    handler
40}
41
42async fn run_on_runtime<F, O>(f: F) -> Result<O, BleError>
43where
44    F: Future<Output = Result<O, BleError>> + Send + 'static,
45    O: Send + 'static,
46{
47    let rt = RUNTIME.get().ok_or(BleError::RuntimeNotInitialized)?;
48    rt.spawn(f).await.map_err(|e| BleError::JoinError(e))?
49}
50
51pub async fn connect(
52    addr: BleAddress,
53    service: Uuid,
54    characs: Vec<Uuid>,
55    on_disconnect: Option<impl Fn() + Send + 'static>,
56) -> Result<(), BleError> {
57    run_on_runtime(async move {
58        let mut handler = get_handler().lock().await;
59        handler.connect(addr, service, characs, on_disconnect).await
60    })
61    .await
62}
63
64pub async fn disconnect() -> Result<(), BleError> {
65    run_on_runtime(async move {
66        let mut handler = get_handler().lock().await;
67        handler.disconnect().await
68    })
69    .await
70}
71
72pub fn discover(sink: mpsc::Sender<Vec<BleDevice>>, timeout: u64) -> Result<(), BleError> {
73    spawn(async move {
74        let mut handler = get_handler().lock().await;
75        handler.discover(Some(sink), timeout).await
76    })
77}
78
79pub async fn discover_async(timeout: u64) -> Result<Vec<BleDevice>, BleError> {
80    let discovered = run_on_runtime(async move {
81        let mut handler = get_handler().lock().await;
82        handler.discover(None, timeout).await
83    })
84    .await?;
85    Ok(discovered)
86}
87
88pub fn discover_blocking(timeout: u64) -> Result<Vec<BleDevice>, BleError> {
89    let discovered = block_on(async move {
90        let mut handler = get_handler().lock().await;
91        handler.discover(None, timeout).await
92    })??;
93    Ok(discovered)
94}
95
96pub async fn send_data(charac: Uuid, data: Vec<u8>) -> Result<(), BleError> {
97    run_on_runtime(async move {
98        let mut handler = get_handler().lock().await;
99        handler.send_data(charac, &data).await
100    })
101    .await
102}
103
104pub async fn recv_data(charac: Uuid) -> Result<Vec<u8>, BleError> {
105    run_on_runtime(async move {
106        let mut handler = get_handler().lock().await;
107        handler.recv_data(charac).await
108    })
109    .await
110}
111
112pub async fn is_connected() -> Result<bool, BleError> {
113    run_on_runtime(async move {
114        let handler = get_handler().lock().await;
115        handler.check_connected().await
116    })
117    .await
118}
119
120pub async fn connected_device() -> Result<BleDevice, BleError> {
121    run_on_runtime(async move {
122        let handler = get_handler().lock().await;
123        handler.connected_device().await
124    })
125    .await
126}
127
128pub async fn subscribe(
129    charac: Uuid,
130    callback: impl Fn(&[u8]) + Send + Sync + 'static,
131) -> Result<(), BleError> {
132    run_on_runtime(async move {
133        let mut handler = get_handler().lock().await;
134        handler.subscribe(charac, callback).await
135    })
136    .await
137}