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