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 Self::new_inner(
64 addr,
65 starting_register.into(),
66 big_endian::U16::new(N as u16),
67 (N as u8) * 2,
68 data.map(big_endian::U16::new),
69 )
70 }
71}
72
73modbus_message! {
74 ReadInputs {
76 function_code: 0x04,
77 starting_register: big_endian::U16,
78 n_registers: big_endian::U16,
79 }
80}
81
82impl ReadInputs {
83 pub fn new(addr: u8, starting_register: u16, n_registers: u16) -> Self {
85 Self::new_inner(addr, starting_register.into(), n_registers.into())
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use hex_literal::hex;
92 use zerocopy::IntoBytes;
93
94 use super::*;
95
96 #[test]
97 fn test_write_holding_register() {
98 let msg = WriteHolding::new(0x01, 0x1001, 0x03E8);
99 assert_eq!(msg.as_bytes(), hex!("01 06 10 01 03 E8 DC 74"),);
100 }
101
102 #[test]
103 fn test_read_holding_registers() {
104 let msg = ReadHoldings::new(0x01, 0x1001, 1000);
105 assert_eq!(msg.as_bytes(), hex!("01 03 10 01 03 E8 10 74"),);
106 }
107}