Code improvements
This commit is contained in:
parent
1cf3e17faa
commit
cf88642612
8 changed files with 111 additions and 79 deletions
4
cloud.py
4
cloud.py
|
@ -90,9 +90,6 @@ class MideaCloud:
|
||||||
})
|
})
|
||||||
response:dict = {"code": -1}
|
response:dict = {"code": -1}
|
||||||
|
|
||||||
print(header)
|
|
||||||
print(dump_data)
|
|
||||||
|
|
||||||
for i in range(0, 3):
|
for i in range(0, 3):
|
||||||
try:
|
try:
|
||||||
with self._api_lock:
|
with self._api_lock:
|
||||||
|
@ -105,7 +102,6 @@ class MideaCloud:
|
||||||
pass
|
pass
|
||||||
if int(response["code"]) == 0 and "data" in response:
|
if int(response["code"]) == 0 and "data" in response:
|
||||||
return response["data"]
|
return response["data"]
|
||||||
print(response)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _get_login_id(self) -> str | None:
|
async def _get_login_id(self) -> str | None:
|
||||||
|
|
|
@ -71,6 +71,13 @@ def discover(discover_type=None, ip_address=None):
|
||||||
encrypt_data = data[40:-16]
|
encrypt_data = data[40:-16]
|
||||||
reply = security.aes_decrypt(encrypt_data)
|
reply = security.aes_decrypt(encrypt_data)
|
||||||
_LOGGER.debug(f"Declassified reply: {reply.hex()}")
|
_LOGGER.debug(f"Declassified reply: {reply.hex()}")
|
||||||
|
|
||||||
|
start = 41
|
||||||
|
end = start + reply[40]
|
||||||
|
|
||||||
|
ssid_bytes = reply[start:end]
|
||||||
|
print(ssid_bytes)
|
||||||
|
|
||||||
ssid = reply[41:41 + reply[40]].decode("utf-8")
|
ssid = reply[41:41 + reply[40]].decode("utf-8")
|
||||||
device_type = ssid.split("_")[1]
|
device_type = ssid.split("_")[1]
|
||||||
port = bytes2port(reply[4:8])
|
port = bytes2port(reply[4:8])
|
||||||
|
|
2
midea.py
2
midea.py
|
@ -13,9 +13,9 @@ async def test():
|
||||||
"Hoda.semi1"
|
"Hoda.semi1"
|
||||||
)
|
)
|
||||||
|
|
||||||
if await cl.login():
|
|
||||||
devices = discover.discover()
|
devices = discover.discover()
|
||||||
|
|
||||||
|
if await cl.login():
|
||||||
for device_id in devices:
|
for device_id in devices:
|
||||||
keys = await cl.get_keys(device_id)
|
keys = await cl.get_keys(device_id)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Error, Result};
|
use anyhow::{bail, Error, Result};
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
|
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
|
|
@ -99,8 +99,8 @@ impl CloudSecurity {
|
||||||
|
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
1 => {
|
2 => {
|
||||||
let mut v = device_id.to_be_bytes().to_vec();
|
let mut v = device_id.to_le_bytes().to_vec();
|
||||||
v.truncate(6);
|
v.truncate(6);
|
||||||
|
|
||||||
v
|
v
|
||||||
|
|
67
src/device.rs
Normal file
67
src/device.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use std::{net::UdpSocket, time::Duration};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
security::{MsgType, Security},
|
||||||
|
DeviceInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Device {
|
||||||
|
info: DeviceInfo,
|
||||||
|
|
||||||
|
socket: UdpSocket,
|
||||||
|
security: Security,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Device {
|
||||||
|
pub fn connect(info: DeviceInfo) -> Result<Self> {
|
||||||
|
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
||||||
|
socket.set_write_timeout(Some(Duration::from_secs(10)))?;
|
||||||
|
socket.set_read_timeout(Some(Duration::from_secs(10)))?;
|
||||||
|
|
||||||
|
socket.connect(info.addr)?;
|
||||||
|
|
||||||
|
let mut me = Self {
|
||||||
|
info,
|
||||||
|
socket,
|
||||||
|
security: Security::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if me.info.protocol == 3 {
|
||||||
|
me.authenticate()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
me.refresh_status()?;
|
||||||
|
|
||||||
|
Ok(me)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn authenticate(&mut self) -> Result<()> {
|
||||||
|
let request = self.security.encode_8370(MsgType::HANDSHAKE_REQUEST)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn refresh_status(&self) -> Result<()> {
|
||||||
|
//
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::{device::Device, Startup};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn connect() -> Result<()> {
|
||||||
|
for device_info in Startup::discover().await? {
|
||||||
|
Device::connect(device_info)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,62 +7,17 @@ use std::{
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{hex, security::Security};
|
||||||
hex,
|
|
||||||
security::{MsgType, Security},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DeviceInfo {
|
pub struct DeviceInfo {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
model: String,
|
pub model: String,
|
||||||
sn: String,
|
pub sn: String,
|
||||||
protocol: u8,
|
pub protocol: u8,
|
||||||
|
pub device_type: u32,
|
||||||
|
|
||||||
addr: SocketAddr,
|
pub addr: SocketAddr,
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Device {
|
|
||||||
info: DeviceInfo,
|
|
||||||
|
|
||||||
socket: UdpSocket,
|
|
||||||
security: Security,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Device {
|
|
||||||
pub fn connect(info: DeviceInfo) -> Result<Self> {
|
|
||||||
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
|
||||||
socket.set_write_timeout(Some(Duration::from_secs(10)))?;
|
|
||||||
socket.set_read_timeout(Some(Duration::from_secs(10)))?;
|
|
||||||
|
|
||||||
socket.connect(info.addr)?;
|
|
||||||
|
|
||||||
let mut me = Self {
|
|
||||||
info,
|
|
||||||
socket,
|
|
||||||
security: Security::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if me.info.protocol == 3 {
|
|
||||||
me.authenticate()?;
|
|
||||||
}
|
|
||||||
|
|
||||||
me.refresh_status()?;
|
|
||||||
|
|
||||||
Ok(me)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn authenticate(&mut self) -> Result<()> {
|
|
||||||
let request = self.security.encode_8370(MsgType::HANDSHAKE_REQUEST)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn refresh_status(&self) -> Result<()> {
|
|
||||||
//
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Startup;
|
pub struct Startup;
|
||||||
|
@ -119,12 +74,23 @@ impl Startup {
|
||||||
let len = bytes.len();
|
let len = bytes.len();
|
||||||
let encrypt_data = Security::decrypt(&mut bytes[40..(len - 16)]);
|
let encrypt_data = Security::decrypt(&mut bytes[40..(len - 16)]);
|
||||||
|
|
||||||
|
let start = 41;
|
||||||
|
let upper = start + encrypt_data[40] as usize;
|
||||||
|
let ssid = from_utf8(&encrypt_data[start..upper])?;
|
||||||
|
|
||||||
|
let device_type = u32::from_str_radix(ssid.split('_').nth(1).unwrap(), 16)?;
|
||||||
let model = from_utf8(&encrypt_data[17..25])?;
|
let model = from_utf8(&encrypt_data[17..25])?;
|
||||||
let sn = from_utf8(&encrypt_data[8..40])?;
|
let sn = from_utf8(&encrypt_data[8..40])?;
|
||||||
|
|
||||||
devices.insert(
|
devices.insert(
|
||||||
device_id,
|
device_id,
|
||||||
(addr, model.to_string(), sn.to_string(), protocol),
|
(
|
||||||
|
addr,
|
||||||
|
model.to_string(),
|
||||||
|
sn.to_string(),
|
||||||
|
protocol,
|
||||||
|
device_type,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,14 +98,17 @@ impl Startup {
|
||||||
|
|
||||||
Ok(devices
|
Ok(devices
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(id, (addr, model, sn, protocol))| DeviceInfo {
|
.map(
|
||||||
|
|(id, (addr, model, sn, protocol, device_type))| DeviceInfo {
|
||||||
id,
|
id,
|
||||||
model,
|
model,
|
||||||
sn,
|
sn,
|
||||||
protocol,
|
protocol,
|
||||||
|
device_type,
|
||||||
|
|
||||||
addr,
|
addr,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +151,7 @@ impl Startup {
|
||||||
mod test {
|
mod test {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use super::{Device, Startup};
|
use super::Startup;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn discover() -> Result<()> {
|
async fn discover() -> Result<()> {
|
||||||
|
@ -192,13 +161,4 @@ mod test {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn connect() -> Result<()> {
|
|
||||||
for device_info in Startup::discover().await? {
|
|
||||||
Device::connect(device_info)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::num::ParseIntError;
|
||||||
|
|
||||||
mod cloud;
|
mod cloud;
|
||||||
mod cloud_security;
|
mod cloud_security;
|
||||||
|
mod device;
|
||||||
mod discover;
|
mod discover;
|
||||||
mod security;
|
mod security;
|
||||||
|
|
||||||
|
@ -13,4 +14,5 @@ fn hex(s: &str) -> Result<Vec<u8>, ParseIntError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use cloud::Cloud;
|
pub use cloud::Cloud;
|
||||||
pub use discover::{Device, DeviceInfo, Startup};
|
pub use device::Device;
|
||||||
|
pub use discover::{DeviceInfo, Startup};
|
||||||
|
|
Loading…
Reference in a new issue