m365/session/
mi_session.rs

1pub use super::payload::Payload;
2use super::commands::ScooterCommand;
3use crate::protocol::MiProtocol;
4use crate::mi_crypto::{encrypt_uart, decrypt_uart, LoginKeychain};
5use crate::consts::Registers;
6
7use anyhow::Result;
8use btleplug::platform::Peripheral;
9
10pub struct MiSession {
11  protocol: MiProtocol,
12  keys: LoginKeychain,
13}
14
15impl MiSession {
16  pub async fn new(device: &Peripheral, keys: &LoginKeychain) -> Result<Self> {
17    let protocol = MiProtocol::new(device).await?;
18    let keys = keys.clone();
19
20    Ok(Self { protocol, keys })
21  }
22
23  /**
24   * Serialize, encrypt and send command to scooter
25   */
26  pub async fn send(&mut self, cmd: &ScooterCommand) -> Result<bool> {
27    let bytes = encrypt_uart(&self.keys.app, &cmd.as_bytes(), 0, None); // encrypt bytes
28    self.protocol.write_nb_parcel(&Registers::TX, &bytes).await?;
29    Ok(true)
30  }
31
32  /**
33   * Wait for response from scooter. You can specify number of frames that you expect to receive
34   */
35  pub async fn read(&mut self, frames: u8) -> Result<Payload> {
36    let data = self.protocol.read_nb_parcel(frames).await?;
37    let response = decrypt_uart(&self.keys.dev, &data)?;
38    let payload = Payload::from(response);
39    Ok(payload)
40  }
41}