fundamentum_sdk_mqtt/models/
states.rs

1//! `States` module
2//!
3use std::hash::{Hash, Hasher};
4
5use serde::{Deserialize, Serialize};
6
7use crate::{Device, Error, PublishOptions, Publishable};
8
9/// `SubDevice` is an external system.
10/// If your device acts as a gateway, it might be useful to report sub-devices states.
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
12pub struct SubDevice {
13    /// Sub-device's serial number
14    #[serde(rename = "identification")]
15    serial_number: String,
16    /// Sub-device's states
17    #[serde(skip_serializing_if = "serde_json::Value::is_null")]
18    states: serde_json::Value,
19}
20
21impl SubDevice {
22    /// Create a new `SubDevice`
23    #[must_use]
24    pub fn new(serial_number: &str, states: serde_json::Value) -> Self {
25        Self {
26            serial_number: serial_number.to_owned(),
27            states,
28        }
29    }
30}
31
32impl Hash for SubDevice {
33    fn hash<H: Hasher>(&self, state: &mut H) {
34        self.serial_number.hash(state);
35        self.states.to_string().hash(state);
36    }
37}
38
39/// States definition
40#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
41pub struct StatesEvent {
42    /// Device's timestamp
43    timestamp: u64,
44    /// Device's sub-devices
45    #[serde(rename = "beacons")]
46    sub_devices: Vec<SubDevice>,
47    /// Device's state
48    #[serde(skip_serializing_if = "serde_json::Value::is_null")]
49    states: serde_json::Value,
50}
51
52impl StatesEvent {
53    /// Create a new `StatesEvent`
54    #[must_use]
55    pub const fn new(
56        states: serde_json::Value,
57        timestamp: u64,
58        sub_devices: Vec<SubDevice>,
59    ) -> Self {
60        Self {
61            timestamp,
62            sub_devices,
63            states,
64        }
65    }
66
67    /// Create a new `StatesEvent` with default timestamp and no sub-devices.
68    #[must_use]
69    pub const fn from_states(states: serde_json::Value) -> Self {
70        let timestamp = 0u64;
71        Self {
72            states,
73            timestamp,
74            sub_devices: vec![],
75        }
76    }
77
78    /// Create a new `StatesEvent` with custom timestamp and no sub-devices.
79    #[must_use]
80    pub const fn from_states_timestamp(states: serde_json::Value, timestamp: u64) -> Self {
81        Self {
82            states,
83            timestamp,
84            sub_devices: vec![],
85        }
86    }
87}
88
89impl Publishable for StatesEvent {
90    type Error = Error;
91
92    fn topic(&self, device: &Device) -> impl Into<String> + Send {
93        format!(
94            "registries/{}/devices/{}/states",
95            device.registry_id(),
96            device.serial()
97        )
98    }
99
100    fn payload(&self) -> Result<impl Into<bytes::Bytes> + Send, Error> {
101        Ok(serde_json::to_vec(self)?)
102    }
103
104    fn publish_overrides(&self) -> PublishOptions {
105        PublishOptions::default()
106    }
107}
108
109impl Hash for StatesEvent {
110    fn hash<H: Hasher>(&self, state: &mut H) {
111        self.timestamp.hash(state);
112        self.sub_devices.hash(state);
113        self.states.to_string().hash(state);
114    }
115}