modbus_codec 0.1.0 copy "modbus_codec: ^0.1.0" to clipboard
modbus_codec: ^0.1.0 copied to clipboard

Transport-agnostic Modbus RTU codec for Dart. Encode request frames and decode raw response bytes into typed values over BLE, serial, or TCP.

modbus_codec #

A pure Dart library for encoding and decoding Modbus RTU frames. It is a transport-agnostic translation layer that sits between your application and the raw bytes of a Modbus device — use it over BLE, serial, or TCP, anywhere you can send and receive List<int>.

  • 🔄 Two directions — encode high-level intent into request frames; decode raw response bytes into clean, typed values.
  • 🧱 Zero dependencies — no Flutter, no native code, pure Dart.
  • CRC-16/MODBUS built in (generate + validate).
  • 🧰 Conversion helpers for signed integers, 32-bit register pairs, fixed-point scaling, and packed ASCII.
  • 🚫 Unopinionated — it never assumes what a register means; your device's register map stays in your code.

Why "codec", not a device driver? #

Modbus is an application-layer protocol; it has nothing to do with the transport. A water-quality controller might speak Modbus over BLE, while a PLC speaks the same Modbus over RS-485 or TCP. This package handles only the part that is identical everywhere — the frame format — and leaves the transport and the register meanings to you.

your intent ──> ModbusEncoder ──> bytes ──> [ your transport ] ──> device
device ──> [ your transport ] ──> bytes ──> ModbusDecoder ──> typed data

Install #

dependencies:
  modbus_codec: ^0.1.0

Receive path — bytes in, usable data out #

import 'package:modbus_codec/modbus_codec.dart';

// `rawBytes` came from your transport (e.g. a BLE characteristic notification).
final response = ModbusDecoder.decode(rawBytes);

if (response is ReadRegistersResponse) {
  final regs = response.registers;            // raw List<int> of uint16 values

  // Apply YOUR device's register map:
  final ph        = ModbusConvert.scale(regs[14], factor: 100);   // 670 -> 6.70
  final offset    = ModbusConvert.toSigned16(regs[41]);           // signed
  final timestamp = ModbusConvert.combine32At(regs, 48);          // 32-bit pair
  final serial    = ModbusConvert.asciiFromRegisters(regs.sublist(50, 58));
}

Send path — intent in, bytes out #

// Read 55 holding registers starting at address 0.
final read = ModbusEncoder.readHoldingRegisters(
  slaveId: 1, startAddress: 0, quantity: 55,
);

// Write pH setpoint 6.70 -> stored as 670 in register 40.
final write = ModbusEncoder.writeSingleRegister(
  slaveId: 1, address: 40, value: (6.70 * 100).round(),
);

// Write a name to a fixed-width string field.
final name = ModbusEncoder.writeMultipleRegisters(
  slaveId: 1,
  startAddress: 1100,
  values: ModbusConvert.asciiToRegisters('MyPool', padToRegisters: 16),
);

await transport.send(read); // your BLE / serial / TCP write

Errors #

ModbusDecoder.decode throws:

Exception Meaning
ModbusDeviceException The device returned an exception response (e.g. illegal address). Inspect .exceptionCode / .description.
ModbusFrameException The bytes are malformed or failed the CRC check.
try {
  final response = ModbusDecoder.decode(rawBytes);
} on ModbusDeviceException catch (e) {
  print('Device rejected: ${e.description}');
} on ModbusFrameException catch (e) {
  print('Bad frame: ${e.message}');
}

Supported function codes #

FC Operation Encoder Decoder result
01 Read Coils readCoils ReadBitsResponse
02 Read Discrete Inputs readDiscreteInputs ReadBitsResponse
03 Read Holding Registers readHoldingRegisters ReadRegistersResponse
04 Read Input Registers readInputRegisters ReadRegistersResponse
05 Write Single Coil writeSingleCoil WriteSingleResponse
06 Write Single Register writeSingleRegister WriteSingleResponse
15 Write Multiple Coils writeMultipleCoils WriteMultipleResponse
16 Write Multiple Registers writeMultipleRegisters WriteMultipleResponse

Conversion helpers (ModbusConvert) #

Helper Purpose
toSigned16 / toSigned32 Two's-complement interpretation
combine32 / combine32At Merge two registers into a 32-bit value (word order selectable)
scale Fixed-point division (e.g. 670 / 100 = 6.70)
asciiFromRegisters / asciiToRegisters Packed-ASCII decode / encode
bit Read a single bit from a value

A note on CRC and Modbus TCP #

The trailing CRC is for Modbus RTU. If you carry RTU frames over a transport that already guarantees integrity (or you are handling Modbus TCP payloads), pass validateCrc: false to ModbusDecoder.decode.

Example #

See example/modbus_codec_example.dart for a full encode → decode → convert walkthrough.

License #

MIT

3
likes
0
points
209
downloads

Publisher

verified publisheranwinkp.online

Weekly Downloads

Transport-agnostic Modbus RTU codec for Dart. Encode request frames and decode raw response bytes into typed values over BLE, serial, or TCP.

Repository (GitHub)
View/report issues

Topics

#modbus #rtu #protocol #serial #ble

License

unknown (license)

More

Packages that depend on modbus_codec