1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
mod adapter;
mod advertisement;
mod common;
mod connection;
mod constants;
mod error;
mod gatt;

use futures::{future, prelude::*};
use std::sync::{Arc, Mutex};
use tokio::runtime::current_thread::Runtime;
use uuid::Uuid;

use self::{adapter::Adapter, advertisement::Advertisement, connection::Connection, gatt::Gatt};
use crate::{gatt::service::Service, Error};

pub struct Peripheral {
    adapter: Adapter,
    gatt: Gatt,
    advertisement: Advertisement,
}

impl Peripheral {
    #[allow(clippy::new_ret_no_self)]
    pub fn new(runtime: &Arc<Mutex<Runtime>>) -> Box<impl Future<Item = Self, Error = Error>> {
        let connection = match Connection::new(Arc::clone(&runtime)) {
            Ok(connection) => Arc::new(connection),
            Err(err) => return Box::new(future::Either::A(future::err(err))),
        };

        let peripheral = Adapter::new(connection.clone())
            .and_then(|adapter| {
                let adapter1 = adapter.clone();
                adapter.powered(true).and_then(move |_| Ok(adapter1))
            })
            .and_then(move |adapter| {
                let gatt = Gatt::new(connection.clone(), adapter.object_path.clone());
                let advertisement =
                    Advertisement::new(connection.clone(), adapter.object_path.clone());

                Ok(Peripheral {
                    adapter,
                    gatt,
                    advertisement,
                })
            });

        Box::new(future::Either::B(peripheral))
    }

    pub fn is_powered(self: &Self) -> Box<impl Future<Item = bool, Error = Error>> {
        self.adapter.is_powered()
    }

    pub fn start_advertising(
        self: &Self,
        name: &str,
        uuids: &[Uuid],
    ) -> Box<impl Future<Item = Box<impl Stream<Item = (), Error = Error>>, Error = Error>> {
        self.advertisement.add_name(name);
        self.advertisement.add_uuids(
            uuids
                .to_vec()
                .iter()
                .map(|uuid| uuid.to_string())
                .collect::<Vec<String>>(),
        );

        let advertisement = self.advertisement.register();
        let gatt = self.gatt.register();
        let registration = gatt.join(advertisement).map(|(stream, ..)| stream);

        Box::new(registration)
    }

    pub fn stop_advertising(self: &Self) -> Box<impl Future<Item = (), Error = Error>> {
        let advertisement = self.advertisement.unregister();
        let gatt = self.gatt.unregister();
        Box::new(advertisement.join(gatt).map(|_| ()))
    }

    pub fn is_advertising(self: &Self) -> Box<impl Future<Item = bool, Error = Error>> {
        Box::new(future::ok(self.advertisement.is_advertising()))
    }

    pub fn add_service(self: &Self, service: &Service) -> Result<(), Error> {
        self.gatt.add_service(service)
    }
}