1#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10#[repr(u8)]
11pub enum FunctionCode {
12 ReadCoils = 0x01,
13 ReadDiscreteInputs = 0x02,
14 ReadHoldingRegisters = 0x03,
15 ReadInputRegisters = 0x04,
16 WriteSingleCoil = 0x05,
17 WriteSingleRegister = 0x06,
18 WriteMultipleCoils = 0x0f,
19 WriteMultipleRegisters = 0x10,
20 ReportServerId = 0x11,
21 MaskWriteRegister = 0x16,
22 ReadWriteMultipleRegisters = 0x17,
23 ReadDeviceIdentification = 0x2b,
24}
25
26impl FunctionCode {
27 pub const fn as_u8(self) -> u8 {
28 self as u8
29 }
30}
31
32pub const EXCEPTION_OFFSET: u8 = 0x80;
34
35pub const COIL_ON: u16 = 0xff00;
37pub const COIL_OFF: u16 = 0x0000;
39
40pub const MEI_READ_DEVICE_ID: u8 = 0x0e;
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45#[repr(u8)]
46pub enum ReadDeviceIdCode {
47 BasicStream = 0x01,
48 RegularStream = 0x02,
49 ExtendedStream = 0x03,
50 SpecificAccess = 0x04,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55#[repr(u8)]
56pub enum ConformityLevel {
57 Basic = 0x81,
58 Regular = 0x82,
59 Extended = 0x83,
60}
61
62pub mod limits {
64 pub const READ_COILS_MIN: u16 = 0x0001;
65 pub const READ_COILS_MAX: u16 = 0x07d0;
66 pub const READ_REGISTERS_MIN: u16 = 0x0001;
67 pub const READ_REGISTERS_MAX: u16 = 0x007d;
68 pub const WRITE_COILS_MAX: u16 = 0x07b0;
69 pub const WRITE_REGISTERS_MAX: u16 = 0x007b;
70 pub const RW_REGISTERS_WRITE_MAX: u16 = 0x0079;
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn function_code_values_match_spec() {
79 assert_eq!(FunctionCode::ReadCoils as u8, 0x01);
80 assert_eq!(FunctionCode::ReadDiscreteInputs as u8, 0x02);
81 assert_eq!(FunctionCode::ReadHoldingRegisters as u8, 0x03);
82 assert_eq!(FunctionCode::ReadInputRegisters as u8, 0x04);
83 assert_eq!(FunctionCode::WriteSingleCoil as u8, 0x05);
84 assert_eq!(FunctionCode::WriteSingleRegister as u8, 0x06);
85 assert_eq!(FunctionCode::WriteMultipleCoils as u8, 0x0f);
86 assert_eq!(FunctionCode::WriteMultipleRegisters as u8, 0x10);
87 assert_eq!(FunctionCode::ReportServerId as u8, 0x11);
88 assert_eq!(FunctionCode::MaskWriteRegister as u8, 0x16);
89 assert_eq!(FunctionCode::ReadWriteMultipleRegisters as u8, 0x17);
90 assert_eq!(FunctionCode::ReadDeviceIdentification as u8, 0x2b);
91 }
92
93 #[test]
94 fn exception_offset_is_high_bit() {
95 assert_eq!(EXCEPTION_OFFSET, 0x80);
96 }
97
98 #[test]
99 fn coil_constants_match_spec() {
100 assert_eq!(COIL_ON, 0xff00);
101 assert_eq!(COIL_OFF, 0x0000);
102 }
103
104 #[test]
105 fn limits_match_spec() {
106 assert_eq!(limits::READ_COILS_MIN, 1);
107 assert_eq!(limits::READ_COILS_MAX, 2000);
108 assert_eq!(limits::READ_REGISTERS_MIN, 1);
109 assert_eq!(limits::READ_REGISTERS_MAX, 125);
110 assert_eq!(limits::WRITE_COILS_MAX, 1968);
111 assert_eq!(limits::WRITE_REGISTERS_MAX, 123);
112 assert_eq!(limits::RW_REGISTERS_WRITE_MAX, 121);
113 }
114
115 #[test]
116 fn conformity_levels_match_spec() {
117 assert_eq!(ConformityLevel::Basic as u8, 0x81);
118 assert_eq!(ConformityLevel::Regular as u8, 0x82);
119 assert_eq!(ConformityLevel::Extended as u8, 0x83);
120 }
121
122 #[test]
123 fn mei_read_device_id_is_0x0e() {
124 assert_eq!(MEI_READ_DEVICE_ID, 0x0e);
125 }
126}