1use eva_common::events::{
2 LocalStateEvent, RawStateEventOwned, RemoteStateEvent, ReplicationStateEvent,
3};
4use eva_common::prelude::*;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use std::fmt;
7use std::str::FromStr;
8
9#[derive(Serialize, Deserialize, Clone, Debug)]
11pub struct State {
12 #[serde(alias = "s")]
13 pub status: ItemStatus,
14 #[serde(alias = "v")]
15 pub value: Option<Value>,
16 #[serde(rename = "t")]
17 pub set_time: f64,
18}
19
20impl From<LocalStateEvent> for State {
21 #[inline]
22 fn from(ev: LocalStateEvent) -> Self {
23 Self {
24 status: ev.status,
25 value: Some(ev.value),
26 set_time: ev.t,
27 }
28 }
29}
30
31impl From<RemoteStateEvent> for State {
32 #[inline]
33 fn from(ev: RemoteStateEvent) -> Self {
34 Self {
35 status: ev.status,
36 value: Some(ev.value),
37 set_time: ev.t,
38 }
39 }
40}
41
42#[derive(Serialize, Deserialize, Clone, Debug)]
45pub struct ItemState {
46 #[serde(alias = "i")]
47 pub oid: OID,
48 #[serde(alias = "s")]
49 pub status: ItemStatus,
50 #[serde(alias = "v")]
51 pub value: Option<Value>,
52 #[serde(rename = "t")]
53 pub set_time: f64,
54}
55
56impl ItemState {
57 #[inline]
58 pub fn from_state(state: State, oid: OID) -> Self {
59 Self {
60 oid,
61 status: state.status,
62 value: state.value,
63 set_time: state.set_time,
64 }
65 }
66 #[inline]
67 pub fn into_state(self) -> (OID, State) {
68 (
69 self.oid,
70 State {
71 status: self.status,
72 value: self.value,
73 set_time: self.set_time,
74 },
75 )
76 }
77}
78
79#[derive(Serialize, Deserialize, Clone, Debug)]
82pub struct ShortItemState {
83 #[serde(alias = "i")]
84 pub oid: OID,
85 #[serde(alias = "s")]
86 pub status: ItemStatus,
87 #[serde(alias = "v")]
88 pub value: Option<Value>,
89}
90
91impl ShortItemState {
92 #[inline]
93 pub fn into_raw_state_event_owned(self) -> (OID, RawStateEventOwned) {
94 (
95 self.oid,
96 if let Some(value) = self.value {
97 RawStateEventOwned::new(self.status, value)
98 } else {
99 RawStateEventOwned::new0(self.status)
100 },
101 )
102 }
103}
104
105#[derive(Serialize, Deserialize, Clone, Debug)]
108pub struct ShortItemStateConnected {
109 #[serde(alias = "i")]
110 pub oid: OID,
111 #[serde(alias = "s")]
112 pub status: ItemStatus,
113 #[serde(alias = "v")]
114 pub value: Option<Value>,
115 pub connected: bool,
116}
117
118#[derive(Serialize, Deserialize, Clone, Debug)]
120pub struct HistoricalState {
121 #[serde(alias = "s", skip_serializing_if = "Option::is_none")]
122 pub status: Option<Value>,
123 #[serde(alias = "v", skip_serializing_if = "Option::is_none")]
124 pub value: Option<Value>,
125 #[serde(rename = "t")]
126 pub set_time: f64,
127}
128
129impl HistoricalState {
130 pub fn na(timestamp: f64, need_status: bool, need_value: bool) -> Self {
131 Self {
132 status: if need_status { Some(Value::Unit) } else { None },
133 value: if need_value { Some(Value::Unit) } else { None },
134 set_time: timestamp,
135 }
136 }
137}
138
139#[derive(Serialize, Deserialize, Clone, Debug)]
141pub struct CompactStateHistory {
142 #[serde(alias = "s", skip_serializing_if = "Option::is_none")]
143 pub status: Option<Vec<Value>>,
144 #[serde(alias = "v", skip_serializing_if = "Option::is_none")]
145 pub value: Option<Vec<Value>>,
146 #[serde(rename = "t")]
147 pub set_time: Vec<f64>,
148}
149
150impl From<CompactStateHistory> for Vec<HistoricalState> {
151 fn from(mut data: CompactStateHistory) -> Self {
152 let mut result = Vec::new();
153 for set_time in data.set_time.into_iter().rev() {
154 let status = if let Some(ref mut s) = data.status {
155 s.pop()
156 } else {
157 None
158 };
159 let value = if let Some(ref mut v) = data.value {
160 v.pop()
161 } else {
162 None
163 };
164 result.push(HistoricalState {
165 status,
166 value,
167 set_time,
168 });
169 }
170 result.reverse();
171 result
172 }
173}
174
175#[derive(Serialize, Deserialize, Clone, Debug)]
177#[serde(untagged)]
178pub enum StateHistoryData {
179 Regular(Vec<HistoricalState>),
180 Compact(CompactStateHistory),
181}
182
183impl StateHistoryData {
184 #[inline]
185 pub fn new_regular(data: Vec<HistoricalState>) -> Self {
186 Self::Regular(data)
187 }
188 pub fn new_compact(data: Vec<HistoricalState>, need_status: bool, need_value: bool) -> Self {
189 let mut status = Vec::new();
190 let mut value = Vec::new();
191 let mut set_time = Vec::new();
192 for d in data {
193 if need_status {
194 status.push(d.status.unwrap_or_default());
195 }
196 if need_value {
197 value.push(d.value.unwrap_or_default());
198 }
199 set_time.push(d.set_time);
200 }
201 Self::Compact(CompactStateHistory {
202 status: if need_status { Some(status) } else { None },
203 value: if need_value { Some(value) } else { None },
204 set_time,
205 })
206 }
207}
208
209#[derive(Debug, Copy, Clone)]
211pub enum Fill {
212 Seconds(u32),
213 Minutes(u32),
214 Hours(u32),
215 Days(u32),
216 Weeks(u32),
217}
218
219impl Fill {
220 pub fn as_secs_f64(&self) -> f64 {
221 match self {
222 Fill::Seconds(v) => f64::from(*v),
223 Fill::Minutes(v) => f64::from(*v) * 60.0,
224 Fill::Hours(v) => f64::from(*v) * 3_600.0,
225 Fill::Days(v) => f64::from(*v) * 86_400.0,
226 Fill::Weeks(v) => f64::from(*v) * 604_800.0,
227 }
228 }
229 pub fn as_secs(&self) -> u64 {
230 match self {
231 Fill::Seconds(v) => u64::from(*v),
232 Fill::Minutes(v) => u64::from(*v) * 60,
233 Fill::Hours(v) => u64::from(*v) * 3_600,
234 Fill::Days(v) => u64::from(*v) * 86_400,
235 Fill::Weeks(v) => u64::from(*v) * 604_800,
236 }
237 }
238 pub fn time_series(&self, t_start: f64, t_end: f64, limit: Option<usize>) -> Vec<f64> {
239 let mut data = Vec::new();
240 let period = self.as_secs_f64();
241 if let Some(l) = limit {
242 let x = t_end % period;
243 let mut ts = if x == 0.0 { t_end } else { t_end - x };
244 let y = t_start % period;
245 let start = if y == 0.0 { t_start } else { t_start - x };
246 while ts >= start && data.len() < l {
247 data.push(ts);
248 ts -= period;
249 }
250 data.reverse();
251 } else {
252 let x = t_start % period;
253 let mut ts = if x == 0.0 { t_start } else { t_start - x };
254 while ts <= t_end {
255 data.push(ts);
256 ts += period;
257 }
258 }
259 data
260 }
261 pub fn fill_na(
262 &self,
263 t_start: f64,
264 t_end: f64,
265 limit: Option<usize>,
266 need_status: bool,
267 need_value: bool,
268 ) -> Vec<HistoricalState> {
269 let mut data = Vec::new();
270 let period = self.as_secs_f64();
271 if let Some(l) = limit {
272 let x = t_end % period;
273 let mut ts = if x == 0.0 { t_end } else { t_end - x };
274 let y = t_start % period;
275 let start = if y == 0.0 { t_start } else { t_start - x };
276 while ts >= start && data.len() < l {
277 data.push(HistoricalState::na(ts, need_status, need_value));
278 ts -= period;
279 }
280 data.reverse();
281 } else {
282 let x = t_start % period;
283 let mut ts = if x == 0.0 { t_start } else { t_start - x };
284 while ts <= t_end {
285 data.push(HistoricalState::na(ts, need_status, need_value));
286 ts += period;
287 }
288 }
289 data
290 }
291}
292
293impl fmt::Display for Fill {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 match self {
296 Fill::Seconds(v) => write!(f, "{}S", v),
297 Fill::Minutes(v) => write!(f, "{}T", v),
298 Fill::Hours(v) => write!(f, "{}H", v),
299 Fill::Days(v) => write!(f, "{}D", v),
300 Fill::Weeks(v) => write!(f, "{}W", v),
301 }
302 }
303}
304
305impl<'de> Deserialize<'de> for Fill {
306 #[inline]
307 fn deserialize<D>(deserializer: D) -> Result<Fill, D::Error>
308 where
309 D: Deserializer<'de>,
310 {
311 let s: String = Deserialize::deserialize(deserializer)?;
312 s.parse().map_err(serde::de::Error::custom)
313 }
314}
315
316impl Serialize for Fill {
317 #[inline]
318 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
319 where
320 S: Serializer,
321 {
322 serializer.serialize_str(&self.to_string())
323 }
324}
325
326impl FromStr for Fill {
327 type Err = Error;
328 #[inline]
329 fn from_str(s: &str) -> Result<Self, Self::Err> {
330 if s.len() < 2 {
331 Err(Error::invalid_params("invalid filling"))
332 } else {
333 macro_rules! ep {
334 ($res: expr) => {{
335 let res = $res.map_err(|e| {
336 Error::invalid_params(format!("unable to parse filling: {}", e))
337 })?;
338 if res == 0 {
339 return Err(Error::invalid_params("fill numbers can not be zero"));
340 }
341 res
342 }};
343 }
344 Ok(match &s[s.len() - 1..] {
345 "S" => Fill::Seconds(ep!(s[..s.len() - 1].parse())),
346 "T" => Fill::Minutes(ep!(s[..s.len() - 1].parse())),
347 "H" => Fill::Hours(ep!(s[..s.len() - 1].parse())),
348 "D" => Fill::Days(ep!(s[..s.len() - 1].parse())),
349 "W" => Fill::Weeks(ep!(s[..s.len() - 1].parse())),
350 v => {
351 return Err(Error::invalid_params(format!(
352 "invalid filling type: {}",
353 v
354 )));
355 }
356 })
357 }
358 }
359}
360
361#[derive(Copy, Clone, Eq, PartialEq, Hash)]
363pub enum StateProp {
364 Status,
365 Value,
366}
367
368impl StateProp {
369 pub fn as_str(&self) -> &str {
370 match self {
371 StateProp::Status => "status",
372 StateProp::Value => "value",
373 }
374 }
375}
376
377impl fmt::Display for StateProp {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 write!(f, "{}", self.as_str())
380 }
381}
382
383impl<'de> Deserialize<'de> for StateProp {
384 #[inline]
385 fn deserialize<D>(deserializer: D) -> Result<StateProp, D::Error>
386 where
387 D: Deserializer<'de>,
388 {
389 let s: String = Deserialize::deserialize(deserializer)?;
390 s.parse().map_err(serde::de::Error::custom)
391 }
392}
393
394impl Serialize for StateProp {
395 #[inline]
396 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
397 where
398 S: Serializer,
399 {
400 serializer.serialize_str(self.as_str())
401 }
402}
403
404impl FromStr for StateProp {
405 type Err = Error;
406 #[inline]
407 fn from_str(s: &str) -> Result<Self, Self::Err> {
408 match s {
409 "status" | "S" => Ok(StateProp::Status),
410 "value" | "V" => Ok(StateProp::Value),
411 v => Err(Error::invalid_params(format!("invalid prop: {}", v))),
412 }
413 }
414}
415
416#[derive(Copy, Clone, Eq, PartialEq, Hash)]
418pub enum StatePropExt {
419 Status,
420 Value,
421 Act,
422}
423
424impl StatePropExt {
425 pub fn as_str(&self) -> &str {
426 match self {
427 StatePropExt::Status => "status",
428 StatePropExt::Value => "value",
429 StatePropExt::Act => "act",
430 }
431 }
432}
433
434impl<'de> Deserialize<'de> for StatePropExt {
435 #[inline]
436 fn deserialize<D>(deserializer: D) -> Result<StatePropExt, D::Error>
437 where
438 D: Deserializer<'de>,
439 {
440 let s: String = Deserialize::deserialize(deserializer)?;
441 s.parse().map_err(serde::de::Error::custom)
442 }
443}
444
445impl Serialize for StatePropExt {
446 #[inline]
447 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
448 where
449 S: Serializer,
450 {
451 serializer.serialize_str(self.as_str())
452 }
453}
454
455impl FromStr for StatePropExt {
456 type Err = Error;
457 #[inline]
458 fn from_str(s: &str) -> Result<Self, Self::Err> {
459 match s {
460 "status" | "S" => Ok(StatePropExt::Status),
461 "value" | "V" => Ok(StatePropExt::Value),
462 "act" | "A" => Ok(StatePropExt::Act),
463 v => Err(Error::invalid_params(format!("invalid prop: {}", v))),
464 }
465 }
466}
467
468#[derive(Debug, Clone, Serialize, Deserialize)]
470pub struct FullItemState {
471 #[serde(alias = "i")]
472 pub oid: OID,
473 #[serde(alias = "s")]
474 pub status: ItemStatus,
475 #[serde(alias = "v")]
476 pub value: Value,
477 #[serde(skip_serializing_if = "Option::is_none")]
478 pub act: Option<usize>,
479 pub ieid: IEID,
480 pub t: f64,
481}
482
483impl FullItemState {
484 pub fn from_local_state_event(state: LocalStateEvent, oid: OID) -> Self {
485 Self {
486 oid,
487 status: state.status,
488 value: state.value,
489 act: state.act,
490 ieid: state.ieid,
491 t: state.t,
492 }
493 }
494 pub fn from_remote_state_event(state: RemoteStateEvent, oid: OID) -> Self {
495 Self {
496 oid,
497 status: state.status,
498 value: state.value,
499 act: state.act,
500 ieid: state.ieid,
501 t: state.t,
502 }
503 }
504 pub fn into_replication_state_event(self, node_name: &str) -> ReplicationStateEvent {
505 ReplicationStateEvent {
506 status: self.status,
507 value: self.value,
508 act: self.act,
509 ieid: self.ieid,
510 t: self.t,
511 node: node_name.to_owned(),
512 force_accept: false,
513 }
514 }
515}
516
517impl From<FullItemState> for LocalStateEvent {
518 fn from(state: FullItemState) -> LocalStateEvent {
519 Self {
520 status: state.status,
521 value: state.value,
522 act: state.act,
523 ieid: state.ieid,
524 t: state.t,
525 }
526 }
527}
528
529#[derive(Debug, Clone, Serialize, Deserialize)]
531pub struct FullItemStateConnected {
532 #[serde(alias = "i")]
533 pub oid: OID,
534 #[serde(alias = "s")]
535 pub status: ItemStatus,
536 #[serde(alias = "v")]
537 pub value: Value,
538 #[serde(skip_serializing_if = "Option::is_none")]
539 pub act: Option<usize>,
540 pub ieid: IEID,
541 pub t: f64,
542 pub connected: bool,
543}
544
545impl FullItemStateConnected {
546 pub fn from_local_state_event(state: LocalStateEvent, oid: OID) -> Self {
547 Self {
548 oid,
549 status: state.status,
550 value: state.value,
551 act: state.act,
552 ieid: state.ieid,
553 t: state.t,
554 connected: true,
555 }
556 }
557 pub fn from_remote_state_event(state: RemoteStateEvent, oid: OID) -> Self {
558 Self {
559 oid,
560 status: state.status,
561 value: state.value,
562 act: state.act,
563 ieid: state.ieid,
564 t: state.t,
565 connected: state.connected,
566 }
567 }
568}
569
570#[derive(Debug, Clone, Serialize, Deserialize)]
572#[serde(deny_unknown_fields)]
573pub struct FullRemoteItemState {
574 #[serde(alias = "i")]
575 pub oid: OID,
576 #[serde(alias = "s")]
577 pub status: ItemStatus,
578 #[serde(alias = "v")]
579 pub value: Value,
580 #[serde(skip_serializing_if = "Option::is_none")]
581 pub act: Option<usize>,
582 pub ieid: IEID,
583 pub t: f64,
584 pub node: String,
585 pub connected: bool,
586}
587
588impl FullRemoteItemState {
589 pub fn from_local_state_event(state: LocalStateEvent, oid: OID, system_name: &str) -> Self {
590 Self {
591 oid,
592 status: state.status,
593 value: state.value,
594 act: state.act,
595 ieid: state.ieid,
596 t: state.t,
597 node: system_name.to_owned(),
598 connected: true,
599 }
600 }
601 pub fn from_remote_state_event(state: RemoteStateEvent, oid: OID) -> Self {
602 Self {
603 oid,
604 status: state.status,
605 value: state.value,
606 act: state.act,
607 ieid: state.ieid,
608 t: state.t,
609 node: state.node,
610 connected: state.connected,
611 }
612 }
613}