Improve write test
All checks were successful
Midea Merge / Serial Reader (pull_request) Successful in 13m59s
All checks were successful
Midea Merge / Serial Reader (pull_request) Successful in 13m59s
This commit is contained in:
parent
2cf725b5aa
commit
56fe4beb2a
3 changed files with 84 additions and 26 deletions
|
@ -2,6 +2,9 @@ use super::{body::Body, header::Header, Command, MessageType};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub trait RequestSerializer {
|
pub trait RequestSerializer {
|
||||||
|
fn message_type(&self) -> MessageType;
|
||||||
|
fn body_type(&self) -> u8;
|
||||||
|
|
||||||
fn serialize(&self) -> Vec<u8>;
|
fn serialize(&self) -> Vec<u8>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +68,14 @@ impl RequestSerializer for CommandRequest {
|
||||||
|
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn message_type(&self) -> MessageType {
|
||||||
|
self.header().message_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body_type(&self) -> u8 {
|
||||||
|
self.body().body_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandQuerySubtype {
|
pub struct CommandQuerySubtype {
|
||||||
|
@ -102,6 +113,14 @@ impl RequestSerializer for CommandQuerySubtype {
|
||||||
fn serialize(&self) -> Vec<u8> {
|
fn serialize(&self) -> Vec<u8> {
|
||||||
self.command.serialize()
|
self.command.serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn message_type(&self) -> MessageType {
|
||||||
|
self.header().message_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body_type(&self) -> u8 {
|
||||||
|
self.body().body_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandQueryCustom {
|
pub struct CommandQueryCustom {
|
||||||
|
@ -140,6 +159,14 @@ impl RequestSerializer for CommandQueryCustom {
|
||||||
fn serialize(&self) -> Vec<u8> {
|
fn serialize(&self) -> Vec<u8> {
|
||||||
self.command.serialize()
|
self.command.serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn message_type(&self) -> MessageType {
|
||||||
|
self.header().message_type()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body_type(&self) -> u8 {
|
||||||
|
self.body().body_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandHeartbeat;
|
pub struct CommandHeartbeat;
|
||||||
|
@ -148,4 +175,12 @@ impl RequestSerializer for CommandHeartbeat {
|
||||||
fn serialize(&self) -> Vec<u8> {
|
fn serialize(&self) -> Vec<u8> {
|
||||||
vec![0x00]
|
vec![0x00]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn message_type(&self) -> MessageType {
|
||||||
|
MessageType::None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn body_type(&self) -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,6 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
for cmd in cmds {
|
for cmd in cmds {
|
||||||
'sending: loop {
|
|
||||||
self.build_send(cmd.clone())?;
|
self.build_send(cmd.clone())?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -139,12 +138,11 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.parse_message(&buf[..bytes_read])? {
|
match self.parse_message(&buf[..bytes_read])? {
|
||||||
ParseMessage::Success => break 'sending,
|
ParseMessage::Success => break,
|
||||||
ParseMessage::Padding => continue,
|
ParseMessage::Padding => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -226,7 +224,11 @@ impl Device {
|
||||||
fn send_message(&self, msg: &[u8]) -> Result<()> {
|
fn send_message(&self, msg: &[u8]) -> Result<()> {
|
||||||
let data = self.security.encode_8370(msg, MsgType::ENCRYPTED_REQUEST)?;
|
let data = self.security.encode_8370(msg, MsgType::ENCRYPTED_REQUEST)?;
|
||||||
|
|
||||||
self.socket.lock().unwrap().write(&data)?;
|
self.socket
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.write(&data)
|
||||||
|
.context(format!("{msg:?}"))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -237,15 +239,26 @@ impl Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_send(&self, cmd: impl RequestSerializer) -> Result<()> {
|
fn build_send(&self, cmd: impl RequestSerializer) -> Result<()> {
|
||||||
|
let message_type = cmd.message_type();
|
||||||
|
let body_type = cmd.body_type();
|
||||||
|
|
||||||
let data = PacketBuilder::builder(self.info.id, cmd).finalize(1);
|
let data = PacketBuilder::builder(self.info.id, cmd).finalize(1);
|
||||||
|
|
||||||
self.send_message(&data)
|
Ok(self.send_message(&data).context(format!(
|
||||||
|
"message_type: {message_type:?}, body_type: {body_type}"
|
||||||
|
))?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::net::{Ipv4Addr, SocketAddr};
|
use std::{
|
||||||
|
net::{Ipv4Addr, SocketAddr},
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use futures::future::try_join;
|
use futures::future::try_join;
|
||||||
|
@ -342,19 +355,29 @@ mod test {
|
||||||
addr: SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::new(192, 168, 178, 94)), 6444),
|
addr: SocketAddr::new(std::net::IpAddr::V4(Ipv4Addr::new(192, 168, 178, 94)), 6444),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut device = Device::connect(device_info, token, key)
|
let power: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
let device = Device::connect(device_info, token, key)
|
||||||
.await?
|
.await?
|
||||||
.register_update(|attributes| {
|
.register_update({
|
||||||
|
let power = power.clone();
|
||||||
|
|
||||||
|
move |attributes| {
|
||||||
println!("{attributes:?}");
|
println!("{attributes:?}");
|
||||||
|
|
||||||
|
power.store(attributes["power"].bool(), Ordering::SeqCst);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
device
|
device
|
||||||
.set_attribute("attribute", AttributeValue::Bool(false))
|
.set_attribute("power", AttributeValue::Bool(true))
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
device.refresh_status().await?;
|
device
|
||||||
|
.set_attribute("power", AttributeValue::Bool(false))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl DeviceBackend for E1 {
|
||||||
cmd.request()
|
cmd.request()
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => todo!(),
|
_ => todo!("attribute: {attribute}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue