Start midea discover function
This commit is contained in:
parent
0ce0e61f03
commit
50476b3acc
8 changed files with 146 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
Cargo.lock
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"workbench.colorCustomizations": {
|
||||||
|
"activityBar.background": "#1C3310",
|
||||||
|
"titleBar.activeBackground": "#274816",
|
||||||
|
"titleBar.activeForeground": "#F6FBF4"
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,3 +6,5 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = { version = "1.0.75", features = ["backtrace"] }
|
||||||
|
if-addrs = "0.10.1"
|
Binary file not shown.
|
@ -64,6 +64,11 @@ def discover(discover_type=None, ip_address=None):
|
||||||
data = data[8:-16]
|
data = data[8:-16]
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
print(data[20:26])
|
||||||
|
print(data[20:26].hex())
|
||||||
|
print(bytearray.fromhex(data[20:26].hex()))
|
||||||
|
|
||||||
device_id = int.from_bytes(bytearray.fromhex(data[20:26].hex()), "little")
|
device_id = int.from_bytes(bytearray.fromhex(data[20:26].hex()), "little")
|
||||||
if device_id in found_devices:
|
if device_id in found_devices:
|
||||||
continue
|
continue
|
||||||
|
|
130
src/discover.rs
Normal file
130
src/discover.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
|
||||||
|
num::ParseIntError,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
pub struct Startup {}
|
||||||
|
|
||||||
|
impl Startup {
|
||||||
|
const BROADCAST_MSG: &'static [u8] = &[
|
||||||
|
0x5a, 0x5a, 0x01, 0x11, 0x48, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x75, 0xbd, 0x6b, 0x3e,
|
||||||
|
0x4f, 0x8b, 0x76, 0x2e, 0x84, 0x9c, 0x6e, 0x57, 0x8d, 0x65, 0x90, 0x03, 0x6e, 0x9d, 0x43,
|
||||||
|
0x42, 0xa5, 0x0f, 0x1f, 0x56, 0x9e, 0xb8, 0xec, 0x91, 0x8e, 0x92, 0xe5,
|
||||||
|
];
|
||||||
|
|
||||||
|
const DEVICE_INFO_MSG: &'static [u8] = &[
|
||||||
|
0x5a, 0x5a, 0x15, 0x00, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0x33,
|
||||||
|
0x05, 0x13, 0x06, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x8d, 0x9b, 0xf9, 0xa0,
|
||||||
|
0x30, 0x1a, 0xe3, 0xb7, 0xe4, 0x2d, 0x53, 0x49, 0x47, 0x62, 0xbe,
|
||||||
|
];
|
||||||
|
|
||||||
|
const NUM_RETRIES: u8 = 5;
|
||||||
|
|
||||||
|
pub fn discover() -> Result<Self> {
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
||||||
|
socket.set_broadcast(true)?;
|
||||||
|
socket.set_read_timeout(Some(Duration::from_secs(2)))?;
|
||||||
|
|
||||||
|
let mut devices = HashMap::new();
|
||||||
|
|
||||||
|
for addr in Self::broadcast_addresses() {
|
||||||
|
for _ in 0..Self::NUM_RETRIES {
|
||||||
|
socket.send_to(Self::BROADCAST_MSG, (addr, 6445))?;
|
||||||
|
socket.send_to(Self::BROADCAST_MSG, (addr, 20086))?;
|
||||||
|
|
||||||
|
let mut buffer = [0; 1024];
|
||||||
|
if let Ok((bytes_read, addr)) = socket.recv_from(&mut buffer) {
|
||||||
|
let mut bytes = buffer[0..bytes_read].to_vec();
|
||||||
|
|
||||||
|
let protocol = if bytes[..2] == Self::hex("5a5a")? {
|
||||||
|
2
|
||||||
|
} else if bytes[..2] == Self::hex("8370")? {
|
||||||
|
if bytes[8..10] == Self::hex("5a5a")? {
|
||||||
|
bytes = bytes[8..(bytes.len() - 16)].to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
3
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut tmp: Vec<u8> = bytes[20..26].to_vec();
|
||||||
|
tmp.push(0);
|
||||||
|
tmp.push(0);
|
||||||
|
|
||||||
|
let device_id = u64::from_le_bytes(tmp.try_into().unwrap());
|
||||||
|
|
||||||
|
if !devices.contains_key(&device_id) {
|
||||||
|
devices.insert(device_id, (addr, bytes.to_vec(), protocol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{devices:#?}");
|
||||||
|
|
||||||
|
Ok(Self {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Startup {
|
||||||
|
fn broadcast_addresses() -> Vec<IpAddr> {
|
||||||
|
use if_addrs::*;
|
||||||
|
|
||||||
|
let mut addresses = Vec::new();
|
||||||
|
|
||||||
|
if let Some(interfaces) = get_if_addrs().ok() {
|
||||||
|
for interface in interfaces {
|
||||||
|
match interface.addr {
|
||||||
|
IfAddr::V4(v4) => {
|
||||||
|
let ip = v4.ip;
|
||||||
|
let octets = ip.octets();
|
||||||
|
|
||||||
|
if ip.is_private() {
|
||||||
|
addresses.push(IpAddr::V4(Ipv4Addr::new(
|
||||||
|
octets[0],
|
||||||
|
octets[1],
|
||||||
|
octets[2],
|
||||||
|
u8::MAX,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IfAddr::V6(_v6) => {
|
||||||
|
// TODO
|
||||||
|
// addresses.push(IpAddr::V6(v6.ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
|
||||||
|
(0..s.len())
|
||||||
|
.step_by(2)
|
||||||
|
.map(|i| u8::from_str_radix(&s[i..i + 2], 16))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use super::Startup;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn discover() -> Result<()> {
|
||||||
|
Startup::discover()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod discover;
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
Loading…
Reference in a new issue