1use super::box_handle;
8pub use crate::wire::{BleCharacteristic, BleDevice, BleDeviceInfo, BleService};
9
10pub(crate) mod ops {
11 use std::time::Duration;
12
13 use serde_json::json;
14
15 use crate::error::Result;
16 use crate::wire::{
17 box_command, unit, value_as, value_list_field, BleDevice, BleDeviceInfo, CommandResponse,
18 Op, Timeout,
19 };
20
21 const PATH: &str = "/ble/command";
22
23 const CONNECT_TIMEOUT_S: f64 = 10.0;
25
26 fn parse_devices(resp: CommandResponse) -> Result<Vec<BleDevice>> {
27 value_list_field(resp, "devices")
28 }
29
30 fn budget(box_side: f64) -> Timeout {
34 Timeout::After(Duration::from_secs_f64(box_side + 30.0))
35 }
36
37 pub(crate) fn scan(timeout: f64) -> Op<Vec<BleDevice>> {
38 Op {
39 req: box_command(PATH, "scan", json!({ "timeout": timeout }), budget(timeout)),
40 parse: parse_devices,
41 }
42 }
43
44 pub(crate) fn scan_named(timeout: f64, name_contains: &str) -> Op<Vec<BleDevice>> {
45 Op {
46 req: box_command(
47 PATH,
48 "scan",
49 json!({ "timeout": timeout, "name_contains": name_contains }),
50 budget(timeout),
51 ),
52 parse: parse_devices,
53 }
54 }
55
56 pub(crate) fn info(address: &str) -> Op<BleDeviceInfo> {
57 Op {
58 req: box_command(
59 PATH,
60 "info",
61 json!({ "address": address, "timeout": CONNECT_TIMEOUT_S }),
62 budget(CONNECT_TIMEOUT_S),
63 ),
64 parse: value_as::<BleDeviceInfo>,
65 }
66 }
67
68 pub(crate) fn connect(address: &str) -> Op<BleDeviceInfo> {
69 Op {
70 req: box_command(
71 PATH,
72 "connect",
73 json!({ "address": address, "timeout": CONNECT_TIMEOUT_S }),
74 budget(CONNECT_TIMEOUT_S),
75 ),
76 parse: value_as::<BleDeviceInfo>,
77 }
78 }
79
80 pub(crate) fn disconnect(address: &str) -> Op<()> {
81 Op {
82 req: box_command(
83 PATH,
84 "disconnect",
85 json!({ "address": address }),
86 budget(CONNECT_TIMEOUT_S),
87 ),
88 parse: unit,
89 }
90 }
91}
92
93box_handle! {
94 sync: Ble,
96 async: AsyncBle,
97 methods: {
98 fn scan(timeout: f64) -> Vec<BleDevice> = ops::scan;
101 fn scan_named(timeout: f64, name_contains: &str) -> Vec<BleDevice> = ops::scan_named;
104 fn info(address: &str) -> BleDeviceInfo = ops::info;
106 fn connect(address: &str) -> BleDeviceInfo = ops::connect;
108 fn disconnect(address: &str) -> () = ops::disconnect;
110 }
111}