fundamentum_sdk_mqtt/
message.rs

1//! Command module
2//!
3
4use std::collections::HashMap;
5
6use rumqttc::v5::mqttbytes::v5::Packet;
7
8use crate::error;
9use crate::models::{ActionRequest, Command};
10
11/// Message definition
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum Message {
14    /// Port forward message, string represent version
15    PortForward {
16        /// header of portforwarding
17        headers: HashMap<String, String>,
18        /// Payload of portforwarding
19        payload: Vec<u8>,
20    },
21
22    /// Action message
23    Action(ActionRequest),
24
25    /// Message type command
26    Commands(Vec<Command>),
27
28    /// Cloud configuration message
29    Config(serde_json::Value),
30
31    /// Unparsed messages
32    Other(Packet),
33}
34
35impl Message {
36    /// Attempts to create a `Message` instance from a given packet.
37    ///
38    /// # Returns
39    ///
40    /// An instance of `Message` if successful.
41    ///
42    /// # Errors
43    ///
44    /// Returns an `error::Error` if an error occurs while parsing the packet.
45    ///
46    pub fn try_from_packet(packet: Packet) -> Result<Self, error::Error> {
47        let message = match packet {
48            Packet::Publish(p) if p.topic.ends_with(b"/actions") => {
49                let action = p.payload.try_into()?;
50                Self::Action(action)
51            }
52            Packet::Publish(p) if p.topic.ends_with(b"/commands") => {
53                let commands = serde_json::from_slice::<Vec<Command>>(&p.payload)?;
54                Self::Commands(commands)
55            }
56            Packet::Publish(p) if p.topic.ends_with(b"/pfwd/tx") => {
57                let headers = p
58                    .properties
59                    .ok_or(error::Error::FailedToFindProperties)?
60                    .user_properties
61                    .into_iter()
62                    .collect::<HashMap<String, String>>();
63
64                Self::PortForward {
65                    headers,
66                    payload: p.payload.to_vec(),
67                }
68            }
69            Packet::Publish(p) if p.topic.ends_with(b"/config") => {
70                let config = serde_json::from_slice::<serde_json::Value>(&p.payload)?;
71                Self::Config(config)
72            }
73            Packet::Publish(p) => Self::Other(Packet::Publish(p)),
74            packet => Self::Other(packet),
75        };
76
77        Ok(message)
78    }
79}