Skip to main content

feagi_sensorimotor/
connector_cache.rs

1use crate::caching::MotorDeviceCache;
2use crate::caching::SensorDeviceCache;
3use crate::configuration::jsonable::JSONInputOutputDefinition;
4use crate::feedbacks::{FeedBackRegistration, FeedbackRegistrar, FeedbackRegistrationTargets};
5use feagi_structures::FeagiDataError;
6use std::fmt;
7use std::sync::{Arc, Mutex, MutexGuard};
8
9// TODO this file may be redudant, we may want to clear it
10
11fn lock_recover<'a, T>(mutex: &'a Mutex<T>) -> MutexGuard<'a, T> {
12    match mutex.lock() {
13        Ok(guard) => guard,
14        Err(poisoned) => {
15            mutex.clear_poison();
16            poisoned.into_inner()
17        }
18    }
19}
20
21#[derive(Debug)]
22pub struct ConnectorCache {
23    sensor_cache: Arc<Mutex<SensorDeviceCache>>,
24    motor_cache: Arc<Mutex<MotorDeviceCache>>,
25    feedback_registrar: FeedbackRegistrar,
26}
27
28impl Default for ConnectorCache {
29    fn default() -> Self {
30        Self::new()
31    }
32}
33
34impl ConnectorCache {
35    pub fn new() -> Self {
36        ConnectorCache {
37            sensor_cache: Arc::new(Mutex::new(SensorDeviceCache::new())),
38            motor_cache: Arc::new(Mutex::new(MotorDeviceCache::new())),
39            feedback_registrar: FeedbackRegistrar::new(),
40        }
41    }
42
43    pub fn get_sensor_cache(&self) -> MutexGuard<'_, SensorDeviceCache> {
44        lock_recover(&self.sensor_cache)
45    }
46
47    pub fn get_sensor_cache_ref(&self) -> Arc<Mutex<SensorDeviceCache>> {
48        self.sensor_cache.clone()
49    }
50
51    pub fn get_motor_cache(&self) -> MutexGuard<'_, MotorDeviceCache> {
52        lock_recover(&self.motor_cache)
53    }
54
55    pub fn get_motor_cache_ref(&self) -> Arc<Mutex<MotorDeviceCache>> {
56        self.motor_cache.clone()
57    }
58
59    pub fn register_feedback(
60        &mut self,
61        feedback: FeedBackRegistration,
62        target: FeedbackRegistrationTargets,
63    ) -> Result<(), FeagiDataError> {
64        let sensors = self.get_sensor_cache_ref();
65        let motors = self.get_motor_cache_ref();
66
67        feedback.try_registering_feedback_and_save(
68            &mut self.feedback_registrar,
69            sensors,
70            motors,
71            target,
72        )?;
73        Ok(())
74    }
75
76    pub fn export_device_registrations_as_config_json(
77        &self,
78    ) -> Result<serde_json::Value, FeagiDataError> {
79        let mut output = JSONInputOutputDefinition::new();
80        self.get_sensor_cache()
81            .export_to_input_definition(&mut output)?;
82        self.get_motor_cache()
83            .export_to_output_definition(&mut output)?;
84        output.set_feedbacks(self.feedback_registrar.clone());
85        serde_json::to_value(output)
86            .map_err(|err| FeagiDataError::SerializationError(err.to_string()))
87    }
88
89    pub fn import_device_registrations_as_config_json(
90        &mut self,
91        json: serde_json::Value,
92    ) -> Result<(), FeagiDataError> {
93        // NOTE: Wipes all registered devices
94        let definition: JSONInputOutputDefinition = serde_json::from_value(json)
95            .map_err(|err| FeagiDataError::DeserializationError(err.to_string()))?;
96        self.get_motor_cache()
97            .import_from_output_definition(&definition)?;
98        self.get_sensor_cache()
99            .import_from_input_definition(&definition)?;
100        self.feedback_registrar = definition.get_feedbacks().clone();
101        // Re-activate imported feedback registrations by wiring callbacks against the newly
102        // imported motor/sensor caches.
103        self.feedback_registrar
104            .reload_all_from_self(self.get_sensor_cache_ref(), self.get_motor_cache_ref())?;
105        Ok(())
106    }
107}
108
109impl fmt::Display for ConnectorCache {
110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111        write!(f, "ConnectorAgent")
112    }
113}