Skip to content

Commit

Permalink
Use typed address
Browse files Browse the repository at this point in the history
  • Loading branch information
flosse committed Mar 19, 2024
1 parent 3d2df15 commit 6acac13
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 69 deletions.
114 changes: 69 additions & 45 deletions src/codec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl<'r> TryFrom<&'r [u8]> for Request<'r> {
| F::ReadInputRegisters
| F::ReadHoldingRegisters
| F::WriteSingleRegister => {
let addr = BigEndian::read_u16(&bytes[1..3]);
let addr = Address::new(BigEndian::read_u16(&bytes[1..3]));
let quantity = BigEndian::read_u16(&bytes[3..5]);

match FnCode::from(fn_code) {
Expand All @@ -98,11 +98,11 @@ impl<'r> TryFrom<&'r [u8]> for Request<'r> {
}
}
F::WriteSingleCoil => Self::WriteSingleCoil(
BigEndian::read_u16(&bytes[1..3]),
Address::new(BigEndian::read_u16(&bytes[1..3])),
u16_coil_to_bool(BigEndian::read_u16(&bytes[3..5]))?,
),
F::WriteMultipleCoils => {
let address = BigEndian::read_u16(&bytes[1..3]);
let address = Address::new(BigEndian::read_u16(&bytes[1..3]));
let quantity = BigEndian::read_u16(&bytes[3..5]) as usize;
let byte_count = bytes[5];
if bytes.len() < (6 + byte_count as usize) {
Expand All @@ -113,7 +113,7 @@ impl<'r> TryFrom<&'r [u8]> for Request<'r> {
Self::WriteMultipleCoils(address, coils)
}
F::WriteMultipleRegisters => {
let address = BigEndian::read_u16(&bytes[1..3]);
let address = Address::new(BigEndian::read_u16(&bytes[1..3]));
let quantity = BigEndian::read_u16(&bytes[3..5]) as usize;
let byte_count = bytes[5];
if bytes.len() < (6 + byte_count as usize) {
Expand All @@ -126,9 +126,9 @@ impl<'r> TryFrom<&'r [u8]> for Request<'r> {
Self::WriteMultipleRegisters(address, data)
}
F::ReadWriteMultipleRegisters => {
let read_address = BigEndian::read_u16(&bytes[1..3]);
let read_address = Address::new(BigEndian::read_u16(&bytes[1..3]));
let read_quantity = BigEndian::read_u16(&bytes[3..5]);
let write_address = BigEndian::read_u16(&bytes[5..7]);
let write_address = Address::new(BigEndian::read_u16(&bytes[5..7]));
let write_quantity = BigEndian::read_u16(&bytes[7..9]) as usize;
let write_count = bytes[9];
if bytes.len() < (10 + write_count as usize) {
Expand Down Expand Up @@ -178,10 +178,12 @@ impl<'r> TryFrom<&'r [u8]> for Response<'r> {
_ => unreachable!(),
}
}
F::WriteSingleCoil => Self::WriteSingleCoil(BigEndian::read_u16(&bytes[1..])),
F::WriteSingleCoil => {
Self::WriteSingleCoil(Address::new(BigEndian::read_u16(&bytes[1..])))
}

F::WriteMultipleCoils | F::WriteSingleRegister | F::WriteMultipleRegisters => {
let addr = BigEndian::read_u16(&bytes[1..]);
let addr = Address::new(BigEndian::read_u16(&bytes[1..]));
let payload = BigEndian::read_u16(&bytes[3..]);
match FnCode::from(fn_code) {
F::WriteMultipleCoils => Self::WriteMultipleCoils(addr, payload),
Expand Down Expand Up @@ -229,22 +231,22 @@ impl<'r> Encode for Request<'r> {
| Self::ReadInputRegisters(address, payload)
| Self::ReadHoldingRegisters(address, payload)
| Self::WriteSingleRegister(address, payload) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
BigEndian::write_u16(&mut buf[3..], *payload);
}
Self::WriteSingleCoil(address, state) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
BigEndian::write_u16(&mut buf[3..], bool_to_u16_coil(*state));
}
Self::WriteMultipleCoils(address, coils) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
let len = coils.len();
BigEndian::write_u16(&mut buf[3..], len as u16);
buf[5] = coils.packed_len() as u8;
coils.copy_to(&mut buf[6..]);
}
Self::WriteMultipleRegisters(address, words) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
let len = words.len();
BigEndian::write_u16(&mut buf[3..], len as u16);
buf[5] = len as u8 * 2;
Expand All @@ -253,9 +255,9 @@ impl<'r> Encode for Request<'r> {
}
}
Self::ReadWriteMultipleRegisters(read_address, quantity, write_address, words) => {
BigEndian::write_u16(&mut buf[1..], *read_address);
BigEndian::write_u16(&mut buf[1..], read_address.to_u16());
BigEndian::write_u16(&mut buf[3..], *quantity);
BigEndian::write_u16(&mut buf[5..], *write_address);
BigEndian::write_u16(&mut buf[5..], write_address.to_u16());
let n = words.len();
BigEndian::write_u16(&mut buf[7..], n as u16);
buf[9] = n as u8 * 2;
Expand Down Expand Up @@ -294,12 +296,12 @@ impl<'r> Encode for Response<'r> {
registers.copy_to(&mut buf[2..]);
}
Self::WriteSingleCoil(address) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
}
Self::WriteMultipleCoils(address, payload)
| Self::WriteMultipleRegisters(address, payload)
| Self::WriteSingleRegister(address, payload) => {
BigEndian::write_u16(&mut buf[1..], *address);
BigEndian::write_u16(&mut buf[1..], address.to_u16());
BigEndian::write_u16(&mut buf[3..], *payload);
}
Self::Custom(_, custom_data) => {
Expand Down Expand Up @@ -437,9 +439,13 @@ mod tests {
#[test]
fn read_coils() {
let bytes = &mut [0; 4];
assert!(Request::ReadCoils(0x12, 4).encode(bytes).is_err());
assert!(Request::ReadCoils(Address::new(0x12), 4)
.encode(bytes)
.is_err());
let bytes = &mut [0; 5];
Request::ReadCoils(0x12, 4).encode(bytes).unwrap();
Request::ReadCoils(Address::new(0x12), 4)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 1);
assert_eq!(bytes[1], 0x00);
assert_eq!(bytes[2], 0x12);
Expand All @@ -450,7 +456,9 @@ mod tests {
#[test]
fn read_discrete_inputs() {
let bytes = &mut [0; 5];
Request::ReadDiscreteInputs(0x03, 19).encode(bytes).unwrap();
Request::ReadDiscreteInputs(Address::new(0x03), 19)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 2);
assert_eq!(bytes[1], 0x00);
assert_eq!(bytes[2], 0x03);
Expand All @@ -461,7 +469,7 @@ mod tests {
#[test]
fn write_single_coil() {
let bytes = &mut [0; 5];
Request::WriteSingleCoil(0x1234, true)
Request::WriteSingleCoil(Address::new(0x1234), true)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 5);
Expand All @@ -476,9 +484,12 @@ mod tests {
let states = &[true, false, true, true];
let buf = &mut [0];
let bytes = &mut [0; 7];
Request::WriteMultipleCoils(0x3311, Coils::from_bools(states, buf).unwrap())
.encode(bytes)
.unwrap();
Request::WriteMultipleCoils(
Address::new(0x3311),
Coils::from_bools(states, buf).unwrap(),
)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 0x0F);
assert_eq!(bytes[1], 0x33);
assert_eq!(bytes[2], 0x11);
Expand All @@ -491,7 +502,9 @@ mod tests {
#[test]
fn read_input_registers() {
let bytes = &mut [0; 5];
Request::ReadInputRegisters(0x09, 77).encode(bytes).unwrap();
Request::ReadInputRegisters(Address::new(0x09), 77)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 4);
assert_eq!(bytes[1], 0x00);
assert_eq!(bytes[2], 0x09);
Expand All @@ -502,7 +515,7 @@ mod tests {
#[test]
fn read_holding_registers() {
let bytes = &mut [0; 5];
Request::ReadHoldingRegisters(0x09, 77)
Request::ReadHoldingRegisters(Address::new(0x09), 77)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 3);
Expand All @@ -515,7 +528,7 @@ mod tests {
#[test]
fn write_single_register() {
let bytes = &mut [0; 5];
Request::WriteSingleRegister(0x07, 0xABCD)
Request::WriteSingleRegister(Address::new(0x07), 0xABCD)
.encode(bytes)
.unwrap();
assert_eq!(bytes[0], 6);
Expand All @@ -531,7 +544,7 @@ mod tests {
let bytes = &mut [0; 10];

Request::WriteMultipleRegisters(
0x06,
Address::new(0x06),
Data::from_words(&[0xABCD, 0xEF12], buf).unwrap(),
)
.encode(bytes)
Expand Down Expand Up @@ -563,7 +576,7 @@ mod tests {
let buf = &mut [0; 4];
let bytes = &mut [0; 14];
let data = Data::from_words(&[0xABCD, 0xEF12], buf).unwrap();
Request::ReadWriteMultipleRegisters(0x05, 51, 0x03, data)
Request::ReadWriteMultipleRegisters(Address::new(0x05), 51, Address::new(0x03), data)
.encode(bytes)
.unwrap();

Expand Down Expand Up @@ -628,21 +641,21 @@ mod tests {

let data: &[u8] = &[0x01, 0x00, 0x12, 0x0, 0x4];
let req = Request::try_from(data).unwrap();
assert_eq!(req, Request::ReadCoils(0x12, 4));
assert_eq!(req, Request::ReadCoils(Address::new(0x12), 4));
}

#[test]
fn read_discrete_inputs() {
let data: &[u8] = &[2, 0x00, 0x03, 0x00, 19];
let req = Request::try_from(data).unwrap();
assert_eq!(req, Request::ReadDiscreteInputs(0x03, 19));
assert_eq!(req, Request::ReadDiscreteInputs(Address::new(0x03), 19));
}

#[test]
fn write_single_coil() {
let bytes: &[u8] = &[5, 0x12, 0x34, 0xFF, 0x00];
let req = Request::try_from(bytes).unwrap();
assert_eq!(req, Request::WriteSingleCoil(0x1234, true));
assert_eq!(req, Request::WriteSingleCoil(Address::new(0x1234), true));
}

#[test]
Expand All @@ -660,7 +673,7 @@ mod tests {
assert_eq!(
req,
Request::WriteMultipleCoils(
0x3311,
Address::new(0x3311),
Coils {
quantity: 4,
data: &[0b1101]
Expand All @@ -673,21 +686,24 @@ mod tests {
fn read_input_registers() {
let bytes: &[u8] = &[4, 0x00, 0x09, 0x00, 0x4D];
let req = Request::try_from(bytes).unwrap();
assert_eq!(req, Request::ReadInputRegisters(0x09, 77));
assert_eq!(req, Request::ReadInputRegisters(Address::new(0x09), 77));
}

#[test]
fn read_holding_registers() {
let bytes: &[u8] = &[3, 0x00, 0x09, 0x00, 0x4D];
let req = Request::try_from(bytes).unwrap();
assert_eq!(req, Request::ReadHoldingRegisters(0x09, 77));
assert_eq!(req, Request::ReadHoldingRegisters(Address::new(0x09), 77));
}

#[test]
fn write_single_register() {
let bytes: &[u8] = &[6, 0x00, 0x07, 0xAB, 0xCD];
let req = Request::try_from(bytes).unwrap();
assert_eq!(req, Request::WriteSingleRegister(0x07, 0xABCD));
assert_eq!(
req,
Request::WriteSingleRegister(Address::new(0x07), 0xABCD)
);
}

#[test]
Expand All @@ -700,7 +716,7 @@ mod tests {
assert_eq!(
req,
Request::WriteMultipleRegisters(
0x06,
Address::new(0x06),
Data {
quantity: 2,
data: &[0xAB, 0xCD, 0xEF, 0x12]
Expand Down Expand Up @@ -731,7 +747,12 @@ mod tests {
};
assert_eq!(
req,
Request::ReadWriteMultipleRegisters(0x05, 51, 0x03, data)
Request::ReadWriteMultipleRegisters(
Address::new(0x05),
51,
Address::new(0x03),
data
)
);
if let Request::ReadWriteMultipleRegisters(_, _, _, data) = req {
assert_eq!(data.get(0), Some(0xABCD));
Expand Down Expand Up @@ -785,7 +806,7 @@ mod tests {

#[test]
fn write_single_coil() {
let res = Response::WriteSingleCoil(0x33);
let res = Response::WriteSingleCoil(Address::new(0x33));
let bytes = &mut [0, 0, 0];
res.encode(bytes).unwrap();
assert_eq!(bytes[0], 5);
Expand All @@ -795,7 +816,7 @@ mod tests {

#[test]
fn write_multiple_coils() {
let res = Response::WriteMultipleCoils(0x3311, 5);
let res = Response::WriteMultipleCoils(Address::new(0x3311), 5);
let bytes = &mut [0; 5];
res.encode(bytes).unwrap();
assert_eq!(bytes[0], 0x0F);
Expand Down Expand Up @@ -840,7 +861,7 @@ mod tests {

#[test]
fn write_single_register() {
let res = Response::WriteSingleRegister(0x07, 0xABCD);
let res = Response::WriteSingleRegister(Address::new(0x07), 0xABCD);
let bytes = &mut [0; 5];
res.encode(bytes).unwrap();
assert_eq!(bytes[0], 6);
Expand All @@ -852,7 +873,7 @@ mod tests {

#[test]
fn write_multiple_registers() {
let res = Response::WriteMultipleRegisters(0x06, 2);
let res = Response::WriteMultipleRegisters(Address::new(0x06), 2);
let bytes = &mut [0; 5];
res.encode(bytes).unwrap();
assert_eq!(bytes[0], 0x10);
Expand Down Expand Up @@ -940,7 +961,7 @@ mod tests {
fn write_single_coil() {
let bytes: &[u8] = &[5, 0x00, 0x33];
let rsp = Response::try_from(bytes).unwrap();
assert_eq!(rsp, Response::WriteSingleCoil(0x33));
assert_eq!(rsp, Response::WriteSingleCoil(Address::new(0x33)));

let broken_bytes: &[u8] = &[5, 0x00];
assert!(Response::try_from(broken_bytes).is_err());
Expand All @@ -950,7 +971,7 @@ mod tests {
fn write_multiple_coils() {
let bytes: &[u8] = &[0x0F, 0x33, 0x11, 0x00, 0x05];
let rsp = Response::try_from(bytes).unwrap();
assert_eq!(rsp, Response::WriteMultipleCoils(0x3311, 5));
assert_eq!(rsp, Response::WriteMultipleCoils(Address::new(0x3311), 5));
let broken_bytes: &[u8] = &[0x0F, 0x33, 0x11, 0x00];
assert!(Response::try_from(broken_bytes).is_err());
}
Expand Down Expand Up @@ -985,7 +1006,10 @@ mod tests {
fn write_single_register() {
let bytes: &[u8] = &[6, 0x00, 0x07, 0xAB, 0xCD];
let rsp = Response::try_from(bytes).unwrap();
assert_eq!(rsp, Response::WriteSingleRegister(0x07, 0xABCD));
assert_eq!(
rsp,
Response::WriteSingleRegister(Address::new(0x07), 0xABCD)
);
let broken_bytes: &[u8] = &[6, 0x00, 0x07, 0xAB];
assert!(Response::try_from(broken_bytes).is_err());
}
Expand All @@ -994,7 +1018,7 @@ mod tests {
fn write_multiple_registers() {
let bytes: &[u8] = &[0x10, 0x00, 0x06, 0x00, 0x02];
let rsp = Response::try_from(bytes).unwrap();
assert_eq!(rsp, Response::WriteMultipleRegisters(0x06, 2));
assert_eq!(rsp, Response::WriteMultipleRegisters(Address::new(0x06), 2));
let broken_bytes: &[u8] = &[0x10, 0x00, 0x06, 0x00];
assert!(Response::try_from(broken_bytes).is_err());
}
Expand Down
5 changes: 4 additions & 1 deletion src/codec/rtu/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ mod tests {
fn encode_write_single_register_response() {
let adu = ResponseAdu {
hdr: Header { slave: 0x12 },
pdu: ResponsePdu(Ok(Response::WriteSingleRegister(0x2222, 0xABCD))),
pdu: ResponsePdu(Ok(Response::WriteSingleRegister(
Address::new(0x2222),
0xABCD,
))),
};
let buf = &mut [0; 100];
let len = encode_response(adu, buf).unwrap();
Expand Down
Loading

0 comments on commit 6acac13

Please sign in to comment.