use std::collections::BTreeMap;
use crate::peripheral::Peripheral;
use deimos_shared::peripherals::PeripheralId;
use crate::socket::SocketAddr;
use super::context::ControllerCtx;
use super::peripheral_state::*;
#[derive(Default)]
pub(crate) struct ControllerOperatingMetrics {
pub cycle_time_margin_ns: f64,
}
impl ControllerOperatingMetrics {
pub fn names_to_write(&self) -> Vec<String> {
const OUT: [&str; 1] = ["ctrl.cycle_time_margin_ns"];
const {
assert!(OUT.len() == Self::num_to_write());
}
Vec::<String>::from_iter(OUT.iter().map(|&x| x.to_owned()))
}
pub const fn num_to_write() -> usize {
1
}
pub fn write_metric_values(&self, out: &mut [f64]) {
out[0] = self.cycle_time_margin_ns;
}
}
#[derive(Default)]
pub(crate) struct ControllerState {
pub peripheral_state: BTreeMap<SocketAddr, PeripheralState>,
names_to_write: Vec<String>,
vals_to_write: Vec<f64>,
num_to_write: usize,
pub controller_metrics: ControllerOperatingMetrics,
}
impl ControllerState {
pub fn new(
peripherals: &BTreeMap<String, Box<dyn Peripheral>>,
scan_result: &BTreeMap<SocketAddr, Box<dyn Peripheral>>,
ctx: &ControllerCtx,
) -> Self {
let mut state = Self::default();
let bound_pids = scan_result
.keys()
.map(|(_sid, pid)| *pid)
.collect::<Vec<PeripheralId>>();
let pid_name_map = BTreeMap::from_iter(peripherals.iter().map(|(name, p)| (p.id(), name)));
for p in peripherals.values() {
let id = p.id();
assert!(
bound_pids.contains(&id),
"Peripheral `{}` not found in bind result",
pid_name_map[&id]
);
}
for (addr, p) in scan_result.iter() {
let expected_this_peripheral = pid_name_map.contains_key(&p.id());
if !expected_this_peripheral {
continue;
}
let (_sid, pid) = addr;
let name = pid_name_map[pid];
let ps = PeripheralState::new(name, *addr, p, ctx);
state.peripheral_state.insert(*addr, ps);
}
state.names_to_write = state.build_names_to_write();
state.vals_to_write = vec![0.0_f64; state.names_to_write.len()];
let mut n = 0;
for state in state.peripheral_state.values() {
n += state.metric_full_names.len();
}
n += state.controller_metrics.names_to_write().len();
state.num_to_write = n;
state
}
fn build_names_to_write(&self) -> Vec<String> {
let mut names = Vec::new();
for state in self.peripheral_state.values() {
for chname in state.metric_full_names.iter() {
names.push(chname.clone());
}
}
names.extend_from_slice(&self.controller_metrics.names_to_write()[..]);
names
}
pub fn get_names_to_write(&self) -> Vec<String> {
self.names_to_write.clone()
}
pub fn write_vals(&self, dst: &mut [f64]) {
let mut i = 0;
for state in self.peripheral_state.values() {
let nmetrics = state.metric_full_names.len();
state.write_metric_values(&mut dst[i..i + nmetrics]);
i += nmetrics;
}
let nmetrics = ControllerOperatingMetrics::num_to_write();
self.controller_metrics
.write_metric_values(&mut dst[i..i + nmetrics]);
}
}