parseReadResponse static method

List<int> parseReadResponse(
  1. Uint8List response,
  2. int registerCount
)

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;
}