Skip to content

xiejay97/njs-modbus

Repository files navigation

njs-modbus

A pure JavaScript implementation of MODBUS for NodeJS.

npm download npm latest package npm bundle size

Introduction

njs-modbus is designed as a layered architecture, including the physical layer and the application layer:

  • Physical layer implements Serial Port, TCP/IP and UDP/IP.
  • Application layer implements RTU, ASCII and TCP.

njs-modbus provide both client and server.

Features

  • Full modbus standard protocol implementation
  • Support for custom function codes
  • Support broadcasting
  • Very lightweight project
  • Full typescript

Supported function codes

Code
01 Read Coils
02 Read Discrete Inputs
03 Read Holding Registers
04 Read Input Register
05 Write Single Coil
06 Write Single Register
15 Write Multiple Coils
16 Write Multiple Registers
17 Report Server ID
22 Mask Write Register
23 Read/Write Multiple Registers
43/14 Read device Identification

Supported protocols

  • Modbus RTU
  • Modbus ASCII
  • Modbus TCP/IP
  • Modbus UDP/IP
  • Modbus RTU/ASCII Over TCP/IP
  • Modbus RTU/ASCII Over UDP/IP

Installation

npm install njs-modbus

Examples

Modbus RTU Master

import { SerialPhysicalLayer, RtuApplicationLayer, ModbusMaster } from 'njs-modbus';

const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
const applicationLayer = new RtuApplicationLayer(physicalLayer, { baudRate: 9600 });

const modbusMaster = new ModbusMaster(applicationLayer, physicalLayer);

modbusMaster
  .open()
  .then(() => {
    console.log('opened');
    modbusMaster.readHoldingRegisters(1, 0, 10).then((res) => {
      console.log(res);
    });
  })
  .catch((error) => {
    console.log(error);
  });

Modbus RTU Slave

import { SerialPhysicalLayer, RtuApplicationLayer, ModbusSlave } from 'njs-modbus';

const MB_SERVER = {
  discreteInputs: new Map<number, boolean>(),
  coils: new Map<number, boolean>(),
  inputRegisters: new Map<number, number>(),
  holdingRegisters: new Map<number, number>(),
};

const physicalLayer = new SerialPhysicalLayer({ path: 'COM1', baudRate: 9600, dataBits: 8, parity: 'none', stopBits: 1 });
const applicationLayer = new RtuApplicationLayer(physicalLayer, { baudRate: 9600 });

const modbusSlave = new ModbusSlave(
  {
    readDiscreteInputs: (address, length) => {
      return Array.from({ length }).map((_, i) => {
        const discreteInput = MB_SERVER.discreteInputs.get(address + i);
        if (typeof discreteInput === 'undefined') {
          return false;
        }
        return discreteInput;
      });
    },

    readCoils: (address, length) => {
      return Array.from({ length }).map((_, i) => {
        const coil = MB_SERVER.coils.get(address + i);
        if (typeof coil === 'undefined') {
          return false;
        }
        return coil;
      });
    },
    writeSingleCoil: (address, value) => {
      MB_SERVER.coils.set(address, value);
    },

    readInputRegisters: (address, length) => {
      return Array.from({ length }).map((_, i) => {
        const inputRegister = MB_SERVER.inputRegisters.get(address + i);
        if (typeof inputRegister === 'undefined') {
          return 0;
        }
        return inputRegister;
      });
    },

    readHoldingRegisters: (address, length) => {
      return Array.from({ length }).map((_, i) => {
        const holdingRegister = MB_SERVER.holdingRegisters.get(address + i);
        if (typeof holdingRegister === 'undefined') {
          return 0;
        }
        return holdingRegister;
      });
    },
    writeSingleRegister: (address, value) => {
      MB_SERVER.holdingRegisters.set(address, value);
    },

    reportServerId: () => ({ additionalData: [1, 2, 3] }),

    readDeviceIdentification: () => ({
      0x00: 'Basic:VendorName',
      0x01: 'Basic:ProductCode',
      0x02: 'Basic:MajorMinorRevision',
      0x03: 'Regular:VendorUrl',
      0x04: 'Regular:ProductName',
      0x05: 'Regular:ModelName',
      0x06: 'Regular:UserApplicationName',
      0x80: 'Extended:Extended',
      0xff: 'Extended:Extended',
    }),
  },
  applicationLayer,
  physicalLayer,
);

modbusSlave
  .open()
  .then(() => {
    console.log('opened');
  })
  .catch((error) => {
    console.log(error);
  });

For more advanced examples, check out examples included in the repository. If you have created any utilities that meet a specific need, feel free to submit them so others can benefit.

Contributing

Please read our contributing guide first.

License

gitHub license

About

A pure JavaScript implementation of MODBUS for NodeJS.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published