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
use std::{
collections::HashMap,
net::{SocketAddr, UdpSocket},
time::Duration,
};
use crate::{datatypes::DeviceData, error::Result, protocol};
const QUERY: &str = r#"{
"system": {"get_sysinfo": null},
"emeter": {"get_realtime": null},
"smartlife.iot.dimmer": {"get_dimmer_parameters": null},
"smartlife.iot.common.emeter": {"get_realtime": null},
"smartlife.iot.smartbulb.lightingservice": {"get_light_state": null}
}"#;
pub fn with_timeout(timeout: Option<Duration>) -> Result<Vec<(SocketAddr, DeviceData)>> {
let socket = UdpSocket::bind("0.0.0.0:0")?;
socket.set_broadcast(true)?;
socket.set_read_timeout(timeout)?;
let req = protocol::encrypt(QUERY)?;
for _ in 0..3 {
socket.send_to(&req[4..req.len()], "255.255.255.255:9999")?;
}
let mut buf = [0_u8; 4096];
let mut devices = HashMap::new();
while let Ok((size, addr)) = socket.recv_from(&mut buf) {
let data = protocol::decrypt(&mut buf[0..size]);
if let Ok(device_data) = serde_json::from_str::<DeviceData>(&data) {
devices.insert(addr, device_data);
}
}
Ok(devices.into_iter().collect())
}
pub fn discover() -> Result<Vec<(SocketAddr, DeviceData)>> {
with_timeout(Some(Duration::from_secs(3)))
}