rsiot/components/cmp_plc/plc/
function_block_base.rs1use std::time::Duration;
4
5use serde::{Deserialize, Serialize};
6
7#[cfg(not(target_arch = "wasm32"))]
8use std::time::SystemTime;
9#[cfg(target_arch = "wasm32")]
10use web_time::SystemTime;
11
12#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
14pub struct FunctionBlockBase<I, Q, S>
15where
16 I: Clone + Default + Serialize,
17 Q: Clone + Default + Serialize,
18 S: Clone + Default + Serialize,
19 Self: IFunctionBlock<I, Q, S>,
20{
21 pub i: I,
23 pub q: Q,
25 pub s: S,
27
28 calc_period_errors: usize,
29
30 pub last_call_time: SystemTime,
35
36 pub first_call: bool,
38}
39
40impl<I, Q, S> Default for FunctionBlockBase<I, Q, S>
41where
42 I: Clone + Default + Serialize,
43 Q: Clone + Default + Serialize,
44 S: Clone + Default + Serialize,
45 Self: IFunctionBlock<I, Q, S>,
46{
47 fn default() -> Self {
48 Self {
49 i: I::default(),
50 q: Q::default(),
51 s: S::default(),
52 calc_period_errors: 0,
53 last_call_time: SystemTime::now(),
54 first_call: true,
55 }
56 }
57}
58
59impl<I, Q, S> FunctionBlockBase<I, Q, S>
60where
61 I: Clone + Default + Serialize,
62 Q: Clone + Default + Serialize,
63 S: Clone + Default + Serialize,
64 Self: IFunctionBlock<I, Q, S>,
65{
66 pub fn new() -> Self {
68 Self::default()
69 }
70
71 pub(crate) fn new_with_restore_stat(self, stat: S) -> Self {
73 Self {
74 s: stat,
75 ..Default::default()
76 }
77 }
78
79 pub fn call(&mut self, input: &mut I) -> Q {
81 let now = SystemTime::now();
82
83 let period = now.duration_since(self.last_call_time);
84 self.last_call_time = now;
85
86 let period = match period {
87 Ok(v) => {
88 if v >= Duration::from_millis(5000) {
89 Duration::from_millis(5000)
90 } else {
91 v
92 }
93 }
94 Err(_) => {
95 self.calc_period_errors += 1;
96 Duration::from_millis(0)
97 }
98 };
99
100 let fb_system_data = FbSystemData {
101 first_call: self.first_call,
102 period,
103 };
104 self.q = FunctionBlockBase::logic(input, &mut self.s, &fb_system_data);
107 self.i = input.clone();
108 self.first_call = false;
109 self.q.clone()
110 }
111}
112
113pub trait IFunctionBlock<I, Q, S> {
115 fn logic(input: &mut I, stat: &mut S, fb_system_data: &FbSystemData) -> Q;
120}
121
122#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
124pub struct FbSystemData {
125 pub first_call: bool,
127
128 pub period: Duration,
130}
131
132impl Default for FbSystemData {
133 fn default() -> Self {
134 Self {
135 first_call: true,
136 period: Duration::from_millis(100),
137 }
138 }
139}