use std::{
collections::BTreeMap,
time::{Duration, SystemTime},
};
use deimos_shared::{
OperatingMetrics,
peripherals::{
PeripheralId,
analog_i_rev_3::operating_roundtrip::{OperatingRoundtripInput, OperatingRoundtripOutput},
model_numbers::EXPERIMENTAL_MODEL_NUMBER,
},
states::{ByteStruct, ByteStructLen},
};
use serde::{Deserialize, Serialize};
use deimos::{
calc::Calc,
controller::context::{ControllerCtx, Termination},
dispatcher::{DataFrameDispatcher, Overflow},
peripheral::{HootlTransport, Peripheral, PluginMap},
socket::unix::UnixSocket,
*,
};
use tracing::info;
fn main() {
let _ = std::fs::remove_dir_all("./sock");
let mut ctx = ControllerCtx::default();
ctx.op_name = "ipc_example".to_string();
let rate_hz = 50.0;
ctx.dt_ns = (1e9_f64 / rate_hz).ceil() as u32;
ctx.termination_criteria = Some(Termination::Timeout(Duration::from_millis(500)));
let mut controller = Controller::new(ctx);
controller.clear_sockets();
controller.add_socket("ipc_ex", Box::new(UnixSocket::new("ipc_ex")));
let (df_dispatcher, df_handle) = DataFrameDispatcher::new(1, Overflow::Wrap, None);
controller.add_dispatcher("df", df_dispatcher);
let mut pmap: PluginMap = BTreeMap::new();
pmap.insert(EXPERIMENTAL_MODEL_NUMBER, &|b| {
Box::new(IpcMockup {
serial_number: b.peripheral_id.serial_number,
})
});
let plugins = Some(pmap);
let p = IpcMockup { serial_number: 0 };
controller.add_peripheral("mockup", Box::new(p));
let end = Some(SystemTime::now() + Duration::from_millis(1000));
let mut mockup_handle = controller
.attach_hootl_driver("mockup", HootlTransport::unix_socket("mockup"), end)
.expect("Failed to start mockup driver");
let scan_result = controller
.scan(100, &plugins)
.expect("Failed to scan for peripherals");
info!("Scan found:\n{:?}", scan_result.values());
{
let serialized_controller = serde_json::to_string_pretty(&controller).unwrap();
let _: Controller = serde_json::from_str(&serialized_controller).unwrap();
}
let exit_status = controller.run(&plugins, None);
info!("Controller exit status: {exit_status:?}");
mockup_handle.join().unwrap();
let df = df_handle.try_read().unwrap();
info!("Collected data");
info!("{:?}", df.headers());
info!("{:?}", df.rows().first().unwrap());
info!("...");
info!("{:?}", df.rows().last().unwrap());
let _ = std::fs::remove_dir_all("./sock");
}
#[derive(Serialize, Deserialize, Default, Debug)]
pub struct IpcMockup {
pub serial_number: u64,
}
#[typetag::serde]
impl Peripheral for IpcMockup {
fn id(&self) -> PeripheralId {
PeripheralId {
model_number: EXPERIMENTAL_MODEL_NUMBER,
serial_number: self.serial_number,
}
}
fn input_names(&self) -> Vec<String> {
let mut names = Vec::new();
for i in 0..4 {
names.push(format!("pwm{i}_duty").to_owned())
}
for i in 0..4 {
names.push(format!("pwm{i}_freq").to_owned())
}
names
}
fn output_names(&self) -> Vec<String> {
let mut names = Vec::new();
for i in 0..20 {
names.push(format!("ain{i}").to_owned())
}
names.push("encoder".to_owned());
names.push("counter".to_owned());
names.push("freq0".to_owned());
names.push("freq1".to_owned());
names
}
fn operating_roundtrip_input_size(&self) -> usize {
OperatingRoundtripInput::BYTE_LEN
}
fn operating_roundtrip_output_size(&self) -> usize {
OperatingRoundtripOutput::BYTE_LEN
}
fn emit_operating_roundtrip(
&self,
id: u64,
_period_delta_ns: i64,
_phase_delta_ns: i64,
_inputs: &[f64],
bytes: &mut [u8],
) {
let msg = OperatingRoundtripInput {
id,
..Default::default()
};
msg.write_bytes(bytes);
}
fn parse_operating_roundtrip(&self, bytes: &[u8], _outputs: &mut [f64]) -> OperatingMetrics {
let n = self.operating_roundtrip_output_size();
let out = OperatingRoundtripOutput::read_bytes(&bytes[..n]);
out.metrics
}
fn standard_calcs(&self, _name: String) -> BTreeMap<String, Box<dyn Calc>> {
BTreeMap::new()
}
}