Modbus RTU requests and replies with CRC-16/MODBUS for RS485 field devices. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.
npm install @pamoja/modbus
This pulls in @pamoja/native, the compiled engine. npm install pamoja is the whole framework in one package.
The test that runs in CI, spliced here as it ran.
From bindings/node/guides/modbus.ts:
import { parseFrame, readHoldingRegisters, readHoldingRegistersReply } from '@pamoja/modbus'
// The device this gateway polls: a power meter at unit 17, whose manual says the three
// registers holding voltage, current and a fault word start at address 107.
const METER = 17
const FIRST_REGISTER = 107
// Ask it for those three registers. The frame is complete, checksum included, exactly as
// it goes out on the wire.
const request = readHoldingRegisters(METER, FIRST_REGISTER, 3)
console.log(`polling unit ${METER}, ${request.length} bytes out`)
// A stand-in for the meter. On a running gateway this frame arrives over RS485; here the
// library builds what a meter reporting those three values would send back.
const fromTheMeter = readHoldingRegistersReply(METER, [2301, 418, 0])
// Everything below is the gateway's own code. A reply carries its own checksum, so the
// frame is validated before any value is read out of it.
const reply = parseFrame(fromTheMeter)
const registers = reply.registers()
console.log(`voltage ${(registers[0] / 10).toFixed(1)} V`)
console.log(`current ${(registers[1] / 100).toFixed(2)} A`)
console.log(`faults ${registers[2]}`)
// One flipped bit anywhere in the frame fails the checksum, which is the whole point of
// carrying one over a long RS485 run.
const mangled = Buffer.from(fromTheMeter)
mangled[2] ^= 0xff
try {
parseFrame(mangled)
console.log('mangled frame accepted, which should never happen')
} catch (error) {
console.log(`mangled frame rejected: ${(error as Error).message}`)
}
| Language | Package | Reference |
|---|---|---|
| Rust | pamoja-modbus |
reference, docs.rs, install |
| TypeScript | @pamoja/modbus |
reference, install |
| Python | pamoja-modbus |
reference, install |
| C# | Pamoja.Modbus |
reference, install |
@pamoja/modbus reference, every class, function, and type this package exports.MIT
Ergonomic facade over the generated Modbus RTU binding.
Modbus over RS485 is what cheap industrial sensing speaks: energy meters, soil probes, water-quality transmitters, pump controllers. Each request builder here returns a complete frame with its CRC, ready to write to a port, and a reply comes back through parseFrame as an object that reads its own values.