1use super::util::modbus_message;
14use zerocopy::{IntoBytes, big_endian};
15use zerocopy_derive::*;
16
17modbus_message! {
18 WriteHolding {
20 function_code: 0x06,
21 register: big_endian::U16,
22 value: big_endian::U16,
23 }
24}
25
26impl WriteHolding {
27 pub fn new(addr: u8, register: u16, value: u16) -> Self {
29 Self::new_inner(addr, register.into(), value.into())
30 }
31}
32
33modbus_message! {
34 ReadHoldings {
36 function_code: 0x03,
37 starting_register: big_endian::U16,
38 n_registers: big_endian::U16,
39 }
40}
41
42impl ReadHoldings {
43 pub fn new(addr: u8, starting_register: u16, n_registers: u16) -> Self {
45 Self::new_inner(addr, starting_register.into(), n_registers.into())
46 }
47}
48
49modbus_message! {
50 WriteHoldings<const N: usize> {
52 function_code: 0x10,
53 starting_register: big_endian::U16,
54 n_registers: big_endian::U16,
55 data_bytes: u8,
56 data: [big_endian::U16; N],
57 }
58}
59
60impl<const N: usize> WriteHoldings<N> {
61 pub fn new(addr: u8, starting_register: u16, data: [u16; N]) -> Self {
63 assert!(
64 N <= 127,
65 "cannot write more than 127 registers in a single request"
66 );
67
68 Self::new_inner(
69 addr,
70 starting_register.into(),
71 big_endian::U16::new(N as u16),
72 (N as u8) * 2,
73 data.map(big_endian::U16::new),
74 )
75 }
76}
77
78modbus_message! {
79 ReadInputs {
81 function_code: 0x04,
82 starting_register: big_endian::U16,
83 n_registers: big_endian::U16,
84 }
85}
86
87impl ReadInputs {
88 pub fn new(addr: u8, starting_register: u16, n_registers: u16) -> Self {
90 Self::new_inner(addr, starting_register.into(), n_registers.into())
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use hex_literal::hex;
97 use zerocopy::IntoBytes;
98
99 use super::*;
100
101 #[test]
102 fn test_write_holding_register() {
103 let msg = WriteHolding::new(0x01, 0x1001, 0x03E8);
104 assert_eq!(msg.as_bytes(), hex!("01 06 10 01 03 E8 DC 74"),);
105 }
106
107 #[test]
108 fn test_read_holding_registers() {
109 let msg = ReadHoldings::new(0x01, 0x1001, 1000);
110 assert_eq!(msg.as_bytes(), hex!("01 03 10 01 03 E8 10 74"),);
111 }
112
113 #[test]
114 #[should_panic(expected = "cannot write more than 127 registers in a single request")]
115 fn too_much_data() {
116 WriteHoldings::<128>::new(0x01, 0x1001, [0u16; 128]);
117 }
118}