blob: 941ea7e3296c9a64fb56e458bf4672810574509e [file] [log] [blame]
use std::collections::HashMap;
use crate::uci_packets::{DeviceState, UciPacketPacket};
use crate::uwb_subsystem::*;
use anyhow::{anyhow, Result};
use tokio::sync::mpsc;
use crate::position::Position;
use super::session::{Session, MAX_SESSION};
pub const MAX_DEVICE: usize = 4;
pub struct Device {
pub mac_address: usize,
pub position: Position,
pub state: DeviceState,
pub sessions: HashMap<u32, Session>,
pub tx: mpsc::Sender<UciPacketPacket>,
pub country_code: [u8; 2],
}
impl Device {
pub fn new(device_handle: usize, tx: mpsc::Sender<UciPacketPacket>) -> Self {
Device {
mac_address: device_handle,
position: Position::default(),
state: DeviceState::DeviceStateReady,
sessions: Default::default(),
tx,
country_code: Default::default(),
}
}
pub fn add_session(&mut self, session: Session) -> Result<()> {
if self.sessions.len() > MAX_SESSION {
return Err(anyhow!("Can't add session, maximum number of session reached"));
}
self.sessions.insert(
session.id,
session
);
Ok(())
}
}
impl Pica {
// The fira norm specify to send a response, then reset, then
// send a notification once the reset is done
pub async fn device_reset(
&mut self,
device_handle: usize,
cmd: DeviceResetCmdPacket,
) -> Result<()> {
let reset_config = cmd.get_reset_config();
println!("[{}] Device Reset", device_handle);
println!(" reset_config={}", reset_config);
{
let mut device = self.get_device(device_handle);
let status = match reset_config {
ResetConfig::UwbsReset => StatusCode::UciStatusOk,
};
device.state = DeviceState::DeviceStateReady;
device
.tx
.send(DeviceResetRspBuilder { status }.build().into())
.await?;
}
self.devices.insert(
device_handle,
Device::new(device_handle, self.devices[&device_handle].tx.clone()),
);
Ok(self
.get_device(device_handle)
.tx
.send(
DeviceStatusNtfBuilder {
device_state: DeviceState::DeviceStateReady,
}
.build()
.into(),
)
.await?)
}
pub async fn get_device_info(
&mut self,
device_handle: usize,
_cmd: GetDeviceInfoCmdPacket,
) -> Result<()> {
// TODO: Implement a fancy build time state machine instead of crash at runtime
let device = self.get_device(device_handle);
assert_eq!(device.state, DeviceState::DeviceStateReady);
Ok(device
.tx
.send(
GetDeviceInfoRspBuilder {
status: StatusCode::UciStatusOk,
uci_version: 1,
mac_version: 1,
phy_version: 1,
uci_test_version: 1,
vendor_spec_info: Vec::new(),
}
.build()
.into(),
)
.await?)
}
pub async fn get_caps_info(
&mut self,
_device_handle: usize,
_cmd: GetCapsInfoCmdPacket,
) -> Result<()> {
todo!()
}
pub async fn set_config(&mut self, device_handle: usize, _cmd: SetConfigCmdPacket) -> Result<()> {
let device = self.get_device(device_handle);
assert_eq!(device.state, DeviceState::DeviceStateReady);
// TODO: Check if the config is supported
// Currently we are saying we support everything
Ok(device
.tx
.send(
SetConfigRspBuilder {
status: StatusCode::UciStatusOk,
cfg_status: Vec::new(),
}
.build()
.into(),
)
.await?)
}
pub async fn get_config(&mut self, _device_handle: usize, _cmd: GetConfigCmdPacket) -> Result<()> {
todo!()
}
}