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/// Конфигурация компонента ПЛК
12#[derive(Clone)]
13pub struct Config<TMsg, I, Q, S>
14where
15    TMsg: MsgDataBound,
16    I: Clone + Default + Serialize,
17    Q: Clone + Default + Serialize,
18    S: Clone + Default + Serialize,
19    FunctionBlockBase<I, Q, S>: IFunctionBlock<I, Q, S>,
20{
21    /// Функция инициализации входной структуры в начале цикла ПЛК
22    ///
23    /// **Примеры**
24    ///
25    /// ```rust
26    /// fn_cycle_init: |_input: &mut fb_main::I| {}
27    /// ```
28    pub fn_cycle_init: fn(&mut I) -> (),
29
30    /// Функция преобразования входящих сообщений во входную структуру ПЛК.
31    ///
32    /// **Примеры**
33    /// ```rust
34    #[doc = include_str!("./tests/config_fn_input.rs")]
35    /// ```
36    pub fn_input: fn(&mut I, &Message<TMsg>) -> (),
37
38    /// Функция преобразования выходной структуры ПЛК в исходящие сообщения.
39    ///
40    /// **Примеры**
41    ///
42    /// ```rust
43    /// fn_output: |output: &fb_main::Q| vec![]
44    /// ```
45    pub fn_output: fn(&Q) -> Vec<Message<TMsg>>,
46
47    /// Главный функциональный блок ПЛК
48    ///
49    /// **Примеры**
50    ///
51    /// ```rust
52    /// fb_main: fb_main::FB::new()
53    /// ```
54    pub fb_main: FunctionBlockBase<I, Q, S>,
55
56    /// Периодичность выполнения логики ПЛК
57    ///
58    /// **Примеры**
59    ///
60    /// ```rust
61    /// period: Duration::from_millis(100)
62    /// ```
63    pub period: Duration,
64
65    /// Настройки сохранения состояния и восстановления при запуске
66    pub retention: Option<ConfigRetention<TMsg, I, Q, S>>,
67}
68
69impl<TMsg, I, Q, S> Default for Config<TMsg, I, Q, S>
70where
71    TMsg: MsgDataBound,
72    I: Clone + Default + Serialize,
73    Q: Clone + Default + Serialize,
74    S: Clone + Default + Serialize,
75    FunctionBlockBase<I, Q, S>: IFunctionBlock<I, Q, S>,
76{
77    fn default() -> Self {
78        Self {
79            fn_cycle_init: |_| (),
80            fn_input: |_, _| (),
81            fn_output: |_| vec![],
82            fb_main: FunctionBlockBase::new(),
83            period: Duration::default(),
84            retention: None,
85        }
86    }
87}
88
89/// Настройка сохранения и восстановления области Static
90#[derive(Clone)]
91pub struct ConfigRetention<TMsg, I, Q, S>
92where
93    TMsg: MsgDataBound,
94    I: Clone + Default + Serialize,
95    Q: Clone + Default + Serialize,
96    S: Clone + Default + Serialize,
97{
98    /// Периодичность сохранения текущего состояния
99    pub save_period: Duration,
100
101    /// Функция преобразования состояния ПЛК в исходящие сообщения
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
114pub enum ConfigRetentionRestoreResult<S>
115where
116    S: Clone + Default + Serialize,
117{
118    NoRestoreData,
119    RestoreDeserializationError,
120    RestoreData(S),
121}