Start E1 device

This commit is contained in:
hodasemi 2023-09-26 08:30:16 +02:00
parent d3fb193e8d
commit 6f1106ee28
10 changed files with 233 additions and 37 deletions

View file

@ -3,5 +3,9 @@
"activityBar.background": "#1C3310",
"titleBar.activeBackground": "#274816",
"titleBar.activeForeground": "#F6FBF4"
}
},
"rust-analyzer.linkedProjects": [
"./Cargo.toml"
],
"rust-analyzer.showUnlinkedFileNotification": false
}

View file

@ -127,9 +127,6 @@ class MideaCloud:
data.update({
"udpid": udp_id
})
print(data)
response = await self._api_request(
endpoint="/v1/iot/secure/getToken",
data=data

View file

@ -73,9 +73,6 @@ class MiedaDevice(threading.Thread):
self._heartbeat_interval = 10
self._default_refresh_interval = 30
print(token)
print(self._token)
k = 0
@property
@ -151,24 +148,10 @@ class MiedaDevice(threading.Thread):
request = self._security.encode_8370(
self._token, MSGTYPE_HANDSHAKE_REQUEST)
_LOGGER.debug(f"[{self._device_id}] Handshaking")
print("REQUEST")
print(request)
req = bytearray([131, 112, 0, 64, 32, 0, 0, 0, 112, 43, 157, 252, 58, 198, 200, 41, 121, 152, 110, 227, 160, 83, 167, 111, 117, 249, 233, 199, 99, 206, 92, 37, 175, 92, 44, 201, 130, 247, 151, 169, 64, 154, 223, 243, 116, 94, 35, 254, 227, 164, 100, 215, 69, 224, 5, 200, 57, 239, 176, 184, 64, 130, 172, 201, 98, 229, 154, 184, 104, 62, 2, 153])
if (req == request):
print("both requests are the same")
self._socket.send(req)
response = self._socket.recv(512)
print(response)
self._socket.send(request)
response = self._socket.recv(512)
print(response)
if len(response) < 20:
raise AuthException()
response = response[8: 72]

View file

@ -65,7 +65,7 @@ async def test():
attributes={}
)
if dev.connect(False):
if dev.connect(True):
return dev
dev = asyncio.run(test())

View file

@ -59,8 +59,6 @@ class CloudSecurity:
@staticmethod
def get_udp_id(appliance_id, method=0):
print()
if method == 0:
bytes_id = bytes(reversed(appliance_id.to_bytes(8, "big")))
elif method == 1:
@ -70,21 +68,12 @@ class CloudSecurity:
else:
return None
print(bytes_id)
data = bytearray(sha256(bytes_id).digest())
print(data)
for i in range(0, 16):
data[i] ^= data[i + 16]
hex = data[0: 16].hex()
print(hex)
print()
return hex
return data[0: 16].hex()
def set_aes_keys(self, key, iv):
if isinstance(key, str):

View file

@ -8,6 +8,7 @@ use std::{
use anyhow::{bail, Context, Error, Result};
use crate::{
devices::{e1::E1, DeviceBackend},
hex,
security::{MsgType, Security},
DeviceInfo,
@ -19,6 +20,8 @@ pub struct Device {
socket: TcpStream,
security: Security,
device_backend: Box<dyn DeviceBackend>,
token: [u8; 64],
key: [u8; 32],
}
@ -42,6 +45,12 @@ impl Device {
socket.set_read_timeout(Some(Duration::from_secs(10)))?;
let mut me = Self {
device_backend: Box::new(match info.device_type {
0xE1 => E1::new()?,
_ => bail!("unsupported device type: {:02X}", info.device_type),
}),
info,
socket,
security: Security::default(),
@ -82,8 +91,6 @@ impl Device {
}
pub fn refresh_status(&self) -> Result<()> {
//
Ok(())
}
}

209
src/devices/e1.rs Normal file
View file

@ -0,0 +1,209 @@
use std::collections::HashMap;
use anyhow::Result;
use super::DeviceBackend;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum DeviceAttributes {
Power,
Status,
Mode,
Additional,
Door,
RinseAid,
Salt,
ChildLock,
UV,
Dry,
DryStatus,
Storage,
StorageStatus,
TimeRemaining,
Progress,
StorageRemaining,
Temperature,
Humidity,
Waterswitch,
WaterLack,
ErrorCode,
Softwater,
WrongOperation,
Bright,
}
impl DeviceAttributes {
fn as_str(&self) -> &str {
match self {
DeviceAttributes::Power => "power",
DeviceAttributes::Status => "status",
DeviceAttributes::Mode => "mode",
DeviceAttributes::Additional => "additional",
DeviceAttributes::Door => "door",
DeviceAttributes::RinseAid => "rinse_aid",
DeviceAttributes::Salt => "salt",
DeviceAttributes::ChildLock => "child_lock",
DeviceAttributes::UV => "uv",
DeviceAttributes::Dry => "dry",
DeviceAttributes::DryStatus => "dry_status",
DeviceAttributes::Storage => "storage",
DeviceAttributes::StorageStatus => "storage_status",
DeviceAttributes::TimeRemaining => "time_remaining",
DeviceAttributes::Progress => "progress",
DeviceAttributes::StorageRemaining => "storage_remaining",
DeviceAttributes::Temperature => "temperature",
DeviceAttributes::Humidity => "humidity",
DeviceAttributes::Waterswitch => "waterswitch",
DeviceAttributes::WaterLack => "water_lack",
DeviceAttributes::ErrorCode => "error_code",
DeviceAttributes::Softwater => "softwater",
DeviceAttributes::WrongOperation => "wrong_operation",
DeviceAttributes::Bright => "bright",
}
}
fn from_str(s: &str) -> Self {
match s {
"power" => Self::Power,
"status" => Self::Status,
"mode" => Self::Mode,
"additional" => Self::Additional,
"door" => Self::Door,
"rinse_aid" => Self::RinseAid,
"salt" => Self::Salt,
"child_lock" => Self::ChildLock,
"uv" => Self::UV,
"dry" => Self::Dry,
"dry_status" => Self::DryStatus,
"storage" => Self::Storage,
"storage_status" => Self::StorageStatus,
"time_remaining" => Self::TimeRemaining,
"progress" => Self::Progress,
"storage_remaining" => Self::StorageRemaining,
"temperature" => Self::Temperature,
"humidity" => Self::Humidity,
"waterswitch" => Self::Waterswitch,
"water_lack" => Self::WaterLack,
"error_code" => Self::ErrorCode,
"softwater" => Self::Softwater,
"wrong_operation" => Self::WrongOperation,
"bright" => Self::Bright,
_ => panic!(),
}
}
}
enum AttributeValue {
String(Option<String>),
Bool(bool),
Int(i32),
}
pub struct E1 {
modes: HashMap<u32, String>,
attributes: HashMap<DeviceAttributes, AttributeValue>,
status: [&'static str; 5],
progress: [&'static str; 6],
}
impl E1 {
pub fn new() -> Result<Self> {
let modes = [
(0x0, "Neutral Gear"),
(0x1, "Auto"),
(0x2, "Heavy"),
(0x3, "Normal"),
(0x4, "Energy Saving"),
(0x5, "Delicate"),
(0x6, "Hour"),
(0x7, "Quick"),
(0x8, "Rinse"),
(0x9, "90min"),
(0xA, "Self Clean"),
(0xB, "Fruit Wash"),
(0xC, "Self Define"),
(0xD, "Germ"),
(0xE, "Bowl Wash"),
(0xF, "Kill Germ"),
(0x10, "Sea Food Wash"),
(0x12, "Hot Pot Wash"),
(0x13, "Quiet"),
(0x14, "Less Wash"),
(0x16, "Oil Net Wash"),
(0x19, "Cloud Wash"),
]
.into_iter()
.map(|(i, s)| (i, s.to_string()))
.collect();
let attributes = [
(DeviceAttributes::Power, AttributeValue::Bool(false)),
(DeviceAttributes::Status, AttributeValue::String(None)),
(DeviceAttributes::Mode, AttributeValue::Int(0)),
(DeviceAttributes::Additional, AttributeValue::Int(0)),
(DeviceAttributes::UV, AttributeValue::Bool(false)),
(DeviceAttributes::Dry, AttributeValue::Bool(false)),
(DeviceAttributes::DryStatus, AttributeValue::Bool(false)),
(DeviceAttributes::Door, AttributeValue::Bool(false)),
(DeviceAttributes::RinseAid, AttributeValue::Bool(false)),
(DeviceAttributes::Salt, AttributeValue::Bool(false)),
(DeviceAttributes::ChildLock, AttributeValue::Bool(false)),
(DeviceAttributes::Storage, AttributeValue::Bool(false)),
(DeviceAttributes::StorageStatus, AttributeValue::Bool(false)),
(
DeviceAttributes::TimeRemaining,
AttributeValue::String(None),
),
(DeviceAttributes::Progress, AttributeValue::String(None)),
(
DeviceAttributes::StorageRemaining,
AttributeValue::String(None),
),
(DeviceAttributes::Temperature, AttributeValue::String(None)),
(DeviceAttributes::Humidity, AttributeValue::String(None)),
(DeviceAttributes::Waterswitch, AttributeValue::Bool(false)),
(DeviceAttributes::WaterLack, AttributeValue::Bool(false)),
(DeviceAttributes::ErrorCode, AttributeValue::String(None)),
(DeviceAttributes::Softwater, AttributeValue::Int(0)),
(
DeviceAttributes::WrongOperation,
AttributeValue::String(None),
),
(DeviceAttributes::Bright, AttributeValue::Int(0)),
]
.into_iter()
.collect();
let status = ["Off", "Idle", "Delay", "Running", "Error"];
let progress = ["Idle", "Pre-wash", "Wash", "Rinse", "Dry", "Complete"];
Ok(Self {
modes,
attributes,
status,
progress,
})
}
}
impl DeviceBackend for E1 {
fn build_query(&self) -> () {
todo!()
}
fn process_message(&self, msg: &str) -> () {
todo!()
}
fn set_attribute(&self, attribute: &str, value: &str) -> () {
match DeviceAttributes::from_str(attribute) {
DeviceAttributes::Power => (),
DeviceAttributes::ChildLock => (),
DeviceAttributes::Storage => (),
_ => (),
}
}
}

7
src/devices/mod.rs Normal file
View file

@ -0,0 +1,7 @@
pub mod e1;
pub trait DeviceBackend {
fn build_query(&self) -> ();
fn process_message(&self, msg: &str) -> ();
fn set_attribute(&self, attribute: &str, value: &str) -> ();
}

View file

@ -3,6 +3,7 @@ use std::num::ParseIntError;
mod cloud;
mod cloud_security;
mod device;
mod devices;
mod discover;
mod security;

View file

@ -16,7 +16,6 @@ use crate::hex;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum MsgType {
HANDSHAKE_REQUEST = 0x0,
HANDSHAKE_RESPONSE = 0x1,
ENCRYPTED_RESPONSE = 0x3,
ENCRYPTED_REQUEST = 0x6,
}