pamoja for TypeScript - v0.1.17
    Preparing search index...

    Module @pamoja/modbus

    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.

    @pamoja/modbus

    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#.

    API reference read the guide documentation

    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

    MIT

    ModbusFrame
    crc16
    parseFrame
    raw
    readCoils
    readDiscreteInputs
    readHoldingRegisters
    readHoldingRegistersReply
    readInputRegisters
    readInputRegistersReply
    writeMultipleCoils
    writeMultipleRegisters
    writeSingleCoil
    writeSingleRegister