Skip to content

Commit 6fbfdcd

Browse files
Abestanisflosse
authored andcommitted
Add the value to the WriteSingleCoil response
1 parent 541c25a commit 6fbfdcd

3 files changed

Lines changed: 36 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
- Merged `modbus_core::rtu::FrameLocation` and `modbus_core::tcp::FrameLocation` and moved it to `modbus_core::FrameLocation`
1010
- Return a `FrameLocation` in addition to the parsed frame in `rtu::server::decode_response`,
1111
`rtu::client::decode_response`, `tcp::server::decode_response` and `tcp::client::decode_request`
12-
- Added `FrameLocation::end` helper.
12+
- Added `FrameLocation::end` helper
13+
- Fix `WriteSingleCoil` responses not including the output value
1314

1415
## v0.2.0 (2025-09-30)
1516

src/codec/mod.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ impl<'r> TryFrom<&'r [u8]> for Response<'r> {
189189
_ => unreachable!(),
190190
}
191191
}
192-
F::WriteSingleCoil => Self::WriteSingleCoil(BigEndian::read_u16(&bytes[1..])),
192+
F::WriteSingleCoil => Self::WriteSingleCoil(
193+
BigEndian::read_u16(&bytes[1..3]),
194+
u16_coil_to_bool(BigEndian::read_u16(&bytes[3..5]))?,
195+
),
193196

194197
F::WriteMultipleCoils | F::WriteSingleRegister | F::WriteMultipleRegisters => {
195198
let addr = BigEndian::read_u16(&bytes[1..]);
@@ -304,8 +307,9 @@ impl Encode for Response<'_> {
304307
buf[1] = (registers.len() * 2) as u8;
305308
registers.copy_to(&mut buf[2..]);
306309
}
307-
Self::WriteSingleCoil(address) => {
310+
Self::WriteSingleCoil(address, value) => {
308311
BigEndian::write_u16(&mut buf[1..], *address);
312+
BigEndian::write_u16(&mut buf[3..], bool_to_u16_coil(*value));
309313
}
310314
Self::WriteMultipleCoils(address, payload)
311315
| Self::WriteMultipleRegisters(address, payload)
@@ -385,8 +389,10 @@ const fn min_response_pdu_len(fn_code: FunctionCode) -> usize {
385389
| F::ReadInputRegisters
386390
| F::ReadHoldingRegisters
387391
| F::ReadWriteMultipleRegisters => 2,
388-
F::WriteSingleCoil => 3,
389-
F::WriteMultipleCoils | F::WriteSingleRegister | F::WriteMultipleRegisters => 5,
392+
F::WriteSingleCoil
393+
| F::WriteMultipleCoils
394+
| F::WriteSingleRegister
395+
| F::WriteMultipleRegisters => 5,
390396
_ => 1,
391397
}
392398
}
@@ -444,7 +450,7 @@ mod tests {
444450
assert_eq!(min_response_pdu_len(ReadCoils), 2);
445451
assert_eq!(min_response_pdu_len(ReadDiscreteInputs), 2);
446452
assert_eq!(min_response_pdu_len(ReadInputRegisters), 2);
447-
assert_eq!(min_response_pdu_len(WriteSingleCoil), 3);
453+
assert_eq!(min_response_pdu_len(WriteSingleCoil), 5);
448454
assert_eq!(min_response_pdu_len(ReadHoldingRegisters), 2);
449455
assert_eq!(min_response_pdu_len(WriteSingleRegister), 5);
450456
assert_eq!(min_response_pdu_len(WriteMultipleCoils), 5);
@@ -806,12 +812,23 @@ mod tests {
806812

807813
#[test]
808814
fn write_single_coil() {
809-
let res = Response::WriteSingleCoil(0x33);
810-
let bytes = &mut [0, 0, 0];
815+
let res = Response::WriteSingleCoil(0x33, true);
816+
let bytes = &mut [0, 0, 0, 0, 0];
817+
res.encode(bytes).unwrap();
818+
assert_eq!(bytes[0], 5);
819+
assert_eq!(bytes[1], 0x00);
820+
assert_eq!(bytes[2], 0x33);
821+
assert_eq!(bytes[3], 0xFF);
822+
assert_eq!(bytes[4], 0x00);
823+
824+
let res = Response::WriteSingleCoil(0x33, false);
825+
let bytes = &mut [0, 0, 0, 0, 0];
811826
res.encode(bytes).unwrap();
812827
assert_eq!(bytes[0], 5);
813828
assert_eq!(bytes[1], 0x00);
814829
assert_eq!(bytes[2], 0x33);
830+
assert_eq!(bytes[3], 0x00);
831+
assert_eq!(bytes[4], 0x00);
815832
}
816833

817834
#[test]
@@ -959,9 +976,13 @@ mod tests {
959976

960977
#[test]
961978
fn write_single_coil() {
962-
let bytes: &[u8] = &[5, 0x00, 0x33];
979+
let bytes: &[u8] = &[5, 0x00, 0x33, 0xFF, 0x00];
980+
let rsp = Response::try_from(bytes).unwrap();
981+
assert_eq!(rsp, Response::WriteSingleCoil(0x33, true));
982+
983+
let bytes: &[u8] = &[5, 0x00, 0x33, 0x00, 0x00];
963984
let rsp = Response::try_from(bytes).unwrap();
964-
assert_eq!(rsp, Response::WriteSingleCoil(0x33));
985+
assert_eq!(rsp, Response::WriteSingleCoil(0x33, false));
965986

966987
let broken_bytes: &[u8] = &[5, 0x00];
967988
assert!(Response::try_from(broken_bytes).is_err());

src/frame/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ type MessageCount = u16;
244244
pub enum Response<'r> {
245245
ReadCoils(Coils<'r>),
246246
ReadDiscreteInputs(Coils<'r>),
247-
WriteSingleCoil(Address),
247+
WriteSingleCoil(Address, Coil),
248248
WriteMultipleCoils(Address, Quantity),
249249
ReadInputRegisters(Data<'r>),
250250
ReadHoldingRegisters(Data<'r>),
@@ -309,7 +309,7 @@ impl<'r> From<Response<'r>> for FunctionCode {
309309
match r {
310310
R::ReadCoils(_) => Self::ReadCoils,
311311
R::ReadDiscreteInputs(_) => Self::ReadDiscreteInputs,
312-
R::WriteSingleCoil(_) => Self::WriteSingleCoil,
312+
R::WriteSingleCoil(_, _) => Self::WriteSingleCoil,
313313
R::WriteMultipleCoils(_, _) => Self::WriteMultipleCoils,
314314
R::ReadInputRegisters(_) => Self::ReadInputRegisters,
315315
R::ReadHoldingRegisters(_) => Self::ReadHoldingRegisters,
@@ -402,7 +402,7 @@ impl Response<'_> {
402402
pub const fn pdu_len(&self) -> usize {
403403
match *self {
404404
Self::ReadCoils(coils) | Self::ReadDiscreteInputs(coils) => 2 + coils.packed_len(),
405-
Self::WriteSingleCoil(_) => 3,
405+
Self::WriteSingleCoil(_, _) => 5,
406406
Self::WriteMultipleCoils(_, _)
407407
| Self::WriteMultipleRegisters(_, _)
408408
| Self::WriteSingleRegister(_, _) => 5,
@@ -505,7 +505,7 @@ mod tests {
505505
}),
506506
2,
507507
),
508-
(WriteSingleCoil(0x0), 5),
508+
(WriteSingleCoil(0x0, false), 5),
509509
(WriteMultipleCoils(0x0, 0x0), 0x0F),
510510
(
511511
ReadInputRegisters(Data {

0 commit comments

Comments
 (0)