easy_bluez/
api.rs

1use basic_scheduler::{BasicEvent, Duration, Scheduler};
2use std::sync::mpsc::{channel, Receiver, Sender};
3use BtMacAddress;
4use std::collections::{HashMap, HashSet};
5use errors::*;
6use std::str::FromStr;
7use uuid::Uuid;
8use std::thread;
9
10use bt_manager::SomethingItem;
11use bt_manager::discovery::{discovery_task, DiscoveryData};
12use bt_manager::connection::{connect_task, ConnectionDb};
13use bt_manager::endpoints::{endpoints_task, EndpointsDb};
14use bt_manager::data_poll::{data_poll_task, DataDb};
15use bt_manager::data_write::{data_write_task, DataWDb};
16
17pub struct EasyBluez {
18    scan_interval: Duration,
19    scan_duration: Duration,
20    connect_interval: Duration,
21    endpoint_interval: Duration,
22    poll_interval: Duration,
23    write_interval: Duration,
24}
25
26pub struct EasyBluezHandle {
27    mac_sender: Sender<BtMacAddress>,
28    poll_sender: Sender<(SomethingItem, Sender<Box<[u8]>>)>,
29    write_sender: Sender<(SomethingItem, Receiver<Box<[u8]>>)>,
30    _scheduler: thread::JoinHandle<()>,
31    _data_scheduler: thread::JoinHandle<()>,
32
33    _rx: Receiver<(String, bool)>,
34}
35
36impl EasyBluezHandle {
37    pub fn writeable(
38        &self,
39        mac_s: &str,
40        svc_s: &str,
41        chrc_s: &str,
42    ) -> Result<Sender<Box<[u8]>>> {
43        let (tx, rx) = channel();
44
45        let mac = BtMacAddress::from_str(mac_s)?;
46        let svc = Uuid::from_str(svc_s).chain_err(|| "not a UUID!")?;
47        let chrc = Uuid::from_str(chrc_s).chain_err(|| "not a UUID!")?;
48
49        self.mac_sender.send(mac.clone()).chain_err(|| "")?;
50
51        let si = SomethingItem {
52            mac: mac,
53            svc: svc,
54            chrc: chrc,
55        };
56
57        self.write_sender.send((si, rx)).chain_err(|| "")?;
58
59        Ok(tx)
60    }
61
62    pub fn poll(
63        &self,
64        mac_s: &str,
65        svc_s: &str,
66        chrc_s: &str,
67    ) -> Result<Receiver<Box<[u8]>>> {
68        let (tx, rx) = channel();
69
70        let mac = BtMacAddress::from_str(mac_s)?;
71        let svc = Uuid::from_str(svc_s).chain_err(|| "not a UUID!")?;
72        let chrc = Uuid::from_str(chrc_s).chain_err(|| "not a UUID!")?;
73
74        self.mac_sender.send(mac.clone()).chain_err(|| "")?;
75
76        let si = SomethingItem {
77            mac: mac,
78            svc: svc,
79            chrc: chrc,
80        };
81
82        self.poll_sender.send((si, tx)).chain_err(|| "")?;
83
84        Ok(rx)
85    }
86}
87
88impl EasyBluez {
89    pub fn new() -> Self {
90        EasyBluez {
91            scan_interval: Duration::seconds(10),
92            scan_duration: Duration::milliseconds(1000),
93            connect_interval: Duration::seconds(3),
94            endpoint_interval: Duration::seconds(3),
95            poll_interval: Duration::milliseconds(1000),
96            write_interval: Duration::milliseconds(100),
97        }
98    }
99
100    ///////////////////////////////////////////////////////
101    // Builder options
102    ///////////////////////////////////////////////////////
103
104    /// How often to scan for new BLE devices
105    pub fn scan_interval(mut self, interval: Duration) -> Self {
106        self.scan_interval = interval;
107        self
108    }
109
110    /// How long to scan for new BLE devices
111    pub fn scan_duration(mut self, duration: Duration) -> Self {
112        self.scan_duration = duration;
113        self
114    }
115
116    /// How often to attempt to connect to discovered devices
117    pub fn connect_interval(mut self, interval: Duration) -> Self {
118        self.connect_interval = interval;
119        self
120    }
121
122    /// How often to find services/characteristics for connected devices
123    pub fn endpoint_interval(mut self, interval: Duration) -> Self {
124        self.endpoint_interval = interval;
125        self
126    }
127
128    /// How often to poll readable endpoints
129    pub fn poll_interval(mut self, interval: Duration) -> Self {
130        self.poll_interval = interval;
131        self
132    }
133
134    ///////////////////////////////////////////////////////
135    // Run time
136    ///////////////////////////////////////////////////////
137    pub fn run(&mut self) -> EasyBluezHandle {
138        self.spawn_events()
139    }
140
141    fn spawn_events(&mut self) -> EasyBluezHandle {
142        let (tx_macs, rx_macs) = channel();
143        let (tx_devs, rx_devs) = channel();
144        let (tx_conn_evs, _rx_conn_evs) = channel();
145        let (tx_poll, rx_poll) = channel();
146        let (tx_write, rx_write) = channel();
147        let (tx_poll_characs, rx_poll_characs) = channel();
148        let (tx_write_characs, rx_write_characs) = channel();
149        let (tx_edpts, rx_edpts) = channel();
150
151        let discover_event = BasicEvent {
152            task: |s: &mut DiscoveryData| discovery_task(s),
153            state: DiscoveryData {
154                db: HashSet::new(),
155                wl: HashSet::new(),
156                receiver: rx_macs,
157                sender_connect: tx_devs,
158                sender_endpoints: tx_edpts,
159                scan_interval: self.scan_interval.clone(),
160                scan_duration: self.scan_duration.clone(),
161            },
162        };
163
164        let connection_event = BasicEvent {
165            task: |s: &mut ConnectionDb| connect_task(s),
166            state: ConnectionDb {
167                connect_interval: self.connect_interval,
168                db: vec![],
169                incoming: rx_devs,
170                outgoing: tx_conn_evs,
171            },
172        };
173
174        let endpoints_event = BasicEvent {
175            task: |s: &mut EndpointsDb| endpoints_task(s),
176            state: EndpointsDb {
177                endpoint_interval: self.endpoint_interval,
178
179                rx_polls: rx_poll,
180                rx_writes: rx_write,
181
182                pending_poll: Vec::new(),
183                pending_write: Vec::new(),
184
185                tx_poll_characs: tx_poll_characs,
186                tx_write_characs: tx_write_characs,
187
188                rx_devs: rx_edpts,
189                devices: HashMap::new(),
190            },
191        };
192
193        let poll_event = BasicEvent {
194            task: |s: &mut DataDb| data_poll_task(s),
195            state: DataDb {
196                poll_interval: self.poll_interval,
197                polls: Vec::new(),
198                poll_rx: rx_poll_characs,
199            },
200        };
201
202        let write_event = BasicEvent {
203            task: |s: &mut DataWDb| data_write_task(s),
204            state: DataWDb {
205                write_interval: self.write_interval,
206                writes: Vec::new(),
207                write_rx: rx_write_characs,
208            },
209        };
210
211        let mut scheduler = Scheduler::new();
212        let hdl = scheduler.add_handle();
213        hdl.send(Box::new(discover_event)).unwrap();
214        hdl.send(Box::new(connection_event)).unwrap();
215        hdl.send(Box::new(endpoints_event)).unwrap();
216
217        let mut data_scheduler = Scheduler::new();
218        let d_hdl = data_scheduler.add_handle();
219
220        d_hdl.send(Box::new(poll_event)).unwrap();
221        d_hdl.send(Box::new(write_event)).unwrap();
222
223        EasyBluezHandle {
224            _scheduler: thread::spawn(move || {
225                scheduler.run();
226            }),
227            _data_scheduler: thread::spawn(move || {
228                data_scheduler.run();
229            }),
230            mac_sender: tx_macs,
231            poll_sender: tx_poll,
232            write_sender: tx_write,
233            _rx: _rx_conn_evs,
234        }
235    }
236}