Skip to main content

rsiot/components/cmp_plc/
config.rs

1use std::time::Duration;
2
3use serde::Serialize;
4
5use crate::message::{Message, MsgDataBound};
6
7use super::plc::{FunctionBlockBase, IFunctionBlock};
8
9type TFnExport<TMsg, I, Q, S> = fn(&I, &Q, &S) -> Option<Vec<Message<TMsg>>>;
10
11// ANCHOR: Config
12
13/// Конфигурация компонента ПЛК
14#[derive(Clone)]
15pub struct Config<TMsg, I, Q, S>
16where
17    TMsg: MsgDataBound,
18    I: Clone + Default + Serialize,
19    Q: Clone + Default + Serialize,
20    S: Clone + Default + Serialize,
21    FunctionBlockBase<I, Q, S>: IFunctionBlock<I, Q, S>,
22{
23    /// Функция инициализации входной структуры в начале цикла ПЛК
24    ///
25    /// **Примеры**
26    ///
27    /// ```rust
28    /// fn_cycle_init: |_input: &mut fb_main::I| {}
29    /// ```
30    pub fn_cycle_init: fn(&mut I) -> (),
31
32    /// Функция преобразования входящих сообщений во входную структуру ПЛК.
33    pub fn_input: fn(&mut I, &TMsg) -> (),
34
35    /// Функция преобразования выходной структуры ПЛК в исходящие сообщения.
36    ///
37    /// **Примеры**
38    ///
39    /// ```rust
40    /// fn_output: |output: &fb_main::Q| vec![]
41    /// ```
42    pub fn_output: fn(&Q) -> Vec<TMsg>,
43
44    /// Главный функциональный блок ПЛК
45    ///
46    /// **Примеры**
47    ///
48    /// ```rust
49    /// fb_main: fb_main::FB::new()
50    /// ```
51    pub fb_main: FunctionBlockBase<I, Q, S>,
52
53    /// Периодичность выполнения логики ПЛК
54    ///
55    /// **Примеры**
56    ///
57    /// ```rust
58    /// period: Duration::from_millis(100)
59    /// ```
60    pub period: Duration,
61
62    /// Настройки сохранения состояния и восстановления при запуске
63    pub retention: Option<ConfigRetention<TMsg, I, Q, S>>,
64}
65// ANCHOR: Config
66
67impl<TMsg, I, Q, S> Default for Config<TMsg, I, Q, S>
68where
69    TMsg: MsgDataBound,
70    I: Clone + Default + Serialize,
71    Q: Clone + Default + Serialize,
72    S: Clone + Default + Serialize,
73    FunctionBlockBase<I, Q, S>: IFunctionBlock<I, Q, S>,
74{
75    fn default() -> Self {
76        Self {
77            fn_cycle_init: |_| (),
78            fn_input: |_, _| (),
79            fn_output: |_| vec![],
80            fb_main: FunctionBlockBase::new(),
81            period: Duration::default(),
82            retention: None,
83        }
84    }
85}
86
87// ANCHOR: ConfigRetention
88/// Настройка сохранения и восстановления области Static
89#[derive(Clone)]
90pub struct ConfigRetention<TMsg, I, Q, S>
91where
92    TMsg: MsgDataBound,
93    I: Clone + Default + Serialize,
94    Q: Clone + Default + Serialize,
95    S: Clone + Default + Serialize,
96{
97    /// Периодичность сохранения текущего состояния
98    pub save_period: Duration,
99
100    /// Функция преобразования состояния ПЛК в исходящие сообщения
101    /// TODO - отвязать экспорт состояния от структуры восстановления
102    pub fn_export: TFnExport<TMsg, I, Q, S>,
103
104    /// Функция восстановления состояния из входящих сообщений
105    pub fn_import_static: fn(&Message<TMsg>) -> anyhow::Result<Option<S>>,
106
107    /// Таймаут восстановления
108    ///
109    /// Если в течение заданного времени не будет получено сообщение с данными для восстановления,
110    /// считаем что восттановление не удалось и запускаем ПЛК с дефолтным состоянием
111    pub restore_timeout: Duration,
112}
113// ANCHOR: ConfigRetention
114
115pub enum ConfigRetentionRestoreResult<S>
116where
117    S: Clone + Default + Serialize,
118{
119    NoRestoreData,
120    RestoreDeserializationError,
121    RestoreData(S),
122}