parseReadResponse static method
Parse and validate an FC03 response.
Returns the raw register integer values (unsigned 16-bit). Throws FormatException on CRC mismatch or short response. Throws StateError on Modbus exception response.
Implementation
static List<int> parseReadResponse(Uint8List response, int registerCount) {
final expected = expectedResponseLength(registerCount);
if (response.length < expected) {
throw FormatException(
'Response too short: got ${response.length}, expected $expected bytes.',
);
}
// Exception response: FC has high bit set (0x03 | 0x80 = 0x83)
if ((response[1] & 0x80) != 0) {
final code = response[2];
final msg = switch (code) {
0x01 => 'Illegal Function',
0x02 => 'Illegal Data Address',
0x03 => 'Illegal Data Value',
0x04 => 'Slave Device Failure',
_ => '0x${code.toRadixString(16).toUpperCase()}',
};
throw StateError('Modbus exception: $msg');
}
// Validate CRC (lo byte first in frame)
final receivedCrc = response[expected - 2] | (response[expected - 1] << 8);
final calculatedCrc = calculateCrc16(response, expected - 2);
if (receivedCrc != calculatedCrc) {
throw FormatException(
'CRC mismatch: received 0x${receivedCrc.toRadixString(16)}, '
'calculated 0x${calculatedCrc.toRadixString(16)}.',
);
}
// Extract register values (big-endian, starting at byte 3)
final registers = <int>[];
for (int i = 0; i < registerCount; i++) {
final offset = 3 + i * 2;
registers.add((response[offset] << 8) | response[offset + 1]);
}
return registers;
}