Skip to main content

mabi_core/
protocol.rs

1//! Protocol definitions.
2
3use serde::{Deserialize, Serialize};
4use strum::{Display, EnumIter, EnumString};
5
6/// Supported protocols.
7#[derive(
8    Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, EnumIter, EnumString,
9)]
10#[strum(serialize_all = "lowercase")]
11#[derive(Default)]
12pub enum Protocol {
13    /// Modbus TCP protocol.
14    #[strum(serialize = "modbus_tcp", serialize = "modbus-tcp")]
15    #[default]
16    ModbusTcp,
17
18    /// Modbus RTU protocol.
19    #[strum(serialize = "modbus_rtu", serialize = "modbus-rtu")]
20    ModbusRtu,
21
22    /// OPC UA protocol.
23    #[strum(serialize = "opcua", serialize = "opc-ua")]
24    OpcUa,
25
26    /// BACnet/IP protocol.
27    #[strum(serialize = "bacnet", serialize = "bacnet-ip")]
28    BacnetIp,
29
30    /// KNXnet/IP protocol.
31    #[strum(serialize = "knx", serialize = "knxnet-ip")]
32    KnxIp,
33}
34
35impl Protocol {
36    /// Get default port for this protocol.
37    pub fn default_port(&self) -> u16 {
38        match self {
39            Protocol::ModbusTcp => 502,
40            Protocol::ModbusRtu => 0, // Serial
41            Protocol::OpcUa => 4840,
42            Protocol::BacnetIp => 47808,
43            Protocol::KnxIp => 3671,
44        }
45    }
46
47    /// Check if protocol uses TCP.
48    pub fn is_tcp(&self) -> bool {
49        matches!(self, Protocol::ModbusTcp | Protocol::OpcUa)
50    }
51
52    /// Check if protocol uses UDP.
53    pub fn is_udp(&self) -> bool {
54        matches!(self, Protocol::BacnetIp | Protocol::KnxIp)
55    }
56
57    /// Check if protocol uses serial.
58    pub fn is_serial(&self) -> bool {
59        matches!(self, Protocol::ModbusRtu)
60    }
61
62    /// Get protocol display name.
63    pub fn display_name(&self) -> &'static str {
64        match self {
65            Protocol::ModbusTcp => "Modbus TCP",
66            Protocol::ModbusRtu => "Modbus RTU",
67            Protocol::OpcUa => "OPC UA",
68            Protocol::BacnetIp => "BACnet/IP",
69            Protocol::KnxIp => "KNXnet/IP",
70        }
71    }
72}
73
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use std::str::FromStr;
79
80    #[test]
81    fn test_protocol_from_str() {
82        assert_eq!(
83            Protocol::from_str("modbus_tcp").unwrap(),
84            Protocol::ModbusTcp
85        );
86        assert_eq!(Protocol::from_str("opcua").unwrap(), Protocol::OpcUa);
87        assert_eq!(Protocol::from_str("bacnet").unwrap(), Protocol::BacnetIp);
88        assert_eq!(Protocol::from_str("knx").unwrap(), Protocol::KnxIp);
89    }
90
91    #[test]
92    fn test_protocol_default_port() {
93        assert_eq!(Protocol::ModbusTcp.default_port(), 502);
94        assert_eq!(Protocol::OpcUa.default_port(), 4840);
95        assert_eq!(Protocol::BacnetIp.default_port(), 47808);
96        assert_eq!(Protocol::KnxIp.default_port(), 3671);
97    }
98}