npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aaqu/node-red-modbus-tcp

v0.3.2

Published

Node-RED nodes for Modbus TCP client communication with PLCs and industrial automation devices. Zero production dependencies.

Readme

@aaqu/node-red-modbus-tcp

Node-RED nodes for Modbus TCP client communication.

Disclaimer

THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. The author makes no guarantees regarding the reliability, accuracy, or suitability of this software for any particular purpose. Use at your own risk. The author shall not be liable for any damages arising from the use of this software in production environments, industrial automation, or any other application.

Features

  • Modbus TCP Client - Connect to Modbus TCP servers (PLCs, RTUs, simulators)
  • Read Operations - FC01, FC02, FC03, FC04
  • Write Operations - FC05, FC06, FC15, FC16
  • Auto-reconnect - Automatic reconnection on connection loss
  • Dynamic configuration - Override parameters via msg properties
  • External Data mode - Hide GUI fields and require parameters from msg only
  • Unit ID per node - Different Unit IDs for each operation
  • No external dependencies - Uses only native Node.js modules
  • Multi-language support - English, Polish, Chinese, Japanese

Installation

From npm

npm install @aaqu/node-red-modbus-tcp

From source

cd ~/.node-red
npm install /path/to/aaqu-modbus-tcp

After installation, restart Node-RED and refresh the browser.

Nodes

aaqu-modbus-client (Configuration Node)

Manages the TCP connection to a Modbus server. Shared by all operation nodes.

| Property | Type | Default | Description | |----------|------|---------|-------------| | Host | string | localhost | IP address or hostname of Modbus server | | Port | number | 502 | TCP port number | | Timeout | number | 5000 | Request timeout in milliseconds | | Auto Reconnect | boolean | true | Automatically reconnect on connection loss | | Reconnect Interval | number | 5000 | Time between reconnection attempts (ms) | | Log Connection Errors | boolean | true | Log connection errors to console | | TCP Keep-Alive | boolean | true | Enable TCP keep-alive probes | | Keep-Alive Delay | number | 10000 | Initial delay before first keep-alive probe (ms) | | Heartbeat | boolean | false | Send periodic Modbus requests to keep connection active | | Heartbeat Interval | number | 5000 | Interval between heartbeat requests (ms) | | Include Raw Response | boolean | false | Include raw Modbus frame buffer in msg.raw |

Connection Keep-Alive Options

The client provides multiple options to maintain stable connections:

  1. TCP Keep-Alive - System-level TCP probes. May not work with all devices.
  2. Heartbeat - Application-level Modbus requests. More reliable for devices that close idle connections.

Recommendation: If your device closes idle connections, enable Heartbeat. It sends periodic read requests (FC03) that are ignored but keep the connection active. Heartbeat is skipped when there are pending requests to avoid interference.

aaqu-modbus-read

Reads data from a Modbus server.

Properties

| Property | Type | Default | Description | |----------|------|---------|-------------| | Server | config | - | Reference to aaqu-modbus-client node | | External Data | checkbox | false | When enabled, Unit ID/Address/Quantity are hidden and must come from msg | | Unit ID | number | 1 | Modbus unit identifier (1-255) | | Function | select | FC03 | Function code (FC01-FC04) | | Address | number | 0 | Starting address (0-65535) | | Quantity | number | 1 | Number of items to read |

Supported Functions

| Function | Code | Description | Max Quantity | |----------|------|-------------|--------------| | Read Coils | FC01 | Read coil status (bits) | 2000 | | Read Discrete Inputs | FC02 | Read discrete input status (bits) | 2000 | | Read Holding Registers | FC03 | Read holding registers (16-bit) | 125 | | Read Input Registers | FC04 | Read input registers (16-bit) | 125 |

Input Message (optional overrides)

msg.unitId = 2;           // Override Unit ID
msg.functionCode = 3;     // Override function code
msg.address = 100;        // Override starting address
msg.quantity = 10;        // Override quantity

External Data Mode

When External Data checkbox is enabled, the GUI fields for Unit ID, Address, and Quantity are hidden. These values must be provided in the incoming message:

msg.unitId = 1;           // Required
msg.address = 100;        // Required
msg.quantity = 10;        // Required
msg.functionCode = 3;     // Optional (uses node config if not provided)

This mode is useful when parameters come from external sources (database, API, other nodes) and you don't want to configure them statically in the node.

Output Message

msg.payload = [100, 101, 102, ...];  // Array of read values
msg.modbus = {
    unitId: 1,
    functionCode: 3,
    address: 0,
    quantity: 10,
    byteCount: 20
};

aaqu-modbus-write

Writes a single value to a Modbus server.

Properties

| Property | Type | Default | Description | |----------|------|---------|-------------| | Server | config | - | Reference to aaqu-modbus-client node | | External Data | checkbox | false | When enabled, Unit ID/Address are hidden and must come from msg | | Unit ID | number | 1 | Modbus unit identifier (1-255) | | Function | select | FC06 | Function code (FC05 or FC06) | | Address | number | 0 | Address to write (0-65535) |

Supported Functions

| Function | Code | Description | Value Range | |----------|------|-------------|-------------| | Write Single Coil | FC05 | Write single coil | true/false | | Write Single Register | FC06 | Write single register | 0-65535 |

Input Message

msg.payload = 1234;       // Value to write (number for registers, boolean for coils)
msg.unitId = 2;           // Optional: Override Unit ID
msg.functionCode = 6;     // Optional: Override function code
msg.address = 100;        // Optional: Override address

External Data Mode

When External Data checkbox is enabled, the GUI fields for Unit ID and Address are hidden. These values must be provided in the incoming message:

msg.payload = 1234;       // Value to write
msg.unitId = 1;           // Required
msg.address = 100;        // Required
msg.functionCode = 6;     // Optional (uses node config if not provided)

Output Message

msg.payload = 1234;       // Original payload (unchanged)
msg.modbus = {
    unitId: 1,
    functionCode: 6,
    address: 100,
    value: 1234
};

aaqu-modbus-write-multiple

Writes multiple values to a Modbus server. This node operates in forced external data mode - Unit ID and Address must always be provided via the incoming message.

Properties

| Property | Type | Default | Description | |----------|------|---------|-------------| | Server | config | - | Reference to aaqu-modbus-client node | | Function | select | FC16 | Function code (FC15 or FC16) |

Note: Unit ID and Address are not configurable in the node. They must be provided in msg.unitId and msg.address.

Supported Functions

| Function | Code | Description | Max Quantity | |----------|------|-------------|--------------| | Write Multiple Coils | FC15 | Write multiple coils | 1968 | | Write Multiple Registers | FC16 | Write multiple registers | 123 |

Input Message

msg.payload = [100, 200, 300];  // Array of values to write
msg.unitId = 1;                  // Required: Modbus Unit ID (1-255)
msg.address = 100;               // Required: Starting address (0-65535)
msg.functionCode = 16;           // Optional: Override function code

Output Message

msg.payload = [100, 200, 300];  // Original payload (unchanged)
msg.requestModbus = {
    unitId: 1,
    functionCode: 16,
    address: 100,
    quantity: 3
};

Why External Data Mode?

This node is designed for dynamic, data-driven scenarios where parameters come from external sources (database, API, other nodes). This makes it ideal for:

  • Multi-device communication with varying addresses
  • Dynamic write operations based on external configuration
  • Integration with SCADA systems and databases

Examples

Read 10 Holding Registers

[inject] -> [aaqu-modbus-read] -> [debug]

Configure aaqu-modbus-read:

  • Function: FC03 - Read Holding Registers
  • Address: 0
  • Quantity: 10
  • Unit ID: 1

Write Single Register

[inject (payload: 1234)] -> [aaqu-modbus-write] -> [debug]

Configure aaqu-modbus-write:

  • Function: FC06 - Write Single Register
  • Address: 0
  • Unit ID: 1

Write Multiple Registers

[inject] -> [function] -> [aaqu-modbus-write-multiple] -> [debug]

Inject node sends payload, Function node adds required properties:

msg.payload = [100, 200, 300];
msg.unitId = 1;
msg.address = 100;
return msg;

Configure aaqu-modbus-write-multiple:

  • Function: FC16 - Write Multiple Registers

Dynamic Configuration

Use a function node to set parameters dynamically:

msg.unitId = 2;
msg.address = flow.get('startAddress') || 0;
msg.quantity = 5;
return msg;

External Data Mode

When you need all parameters to come from external sources (database, API, etc.), enable External Data checkbox. This hides the GUI fields and requires values in the message:

[inject] -> [function] -> [aaqu-modbus-read (External Data: ON)] -> [debug]

Function node:

msg.unitId = msg.payload.deviceId;
msg.address = msg.payload.registerAddress;
msg.quantity = msg.payload.count;
return msg;

This is useful for:

  • Reading device configuration from database
  • Dynamic polling based on external schedules
  • Multi-device scanning with varying parameters

Error Handling

Errors are reported through Node-RED's standard error handling:

  1. Node status - Visual indicator (red ring with error message)
  2. Catch node - Use a catch node to handle errors programmatically
  3. Debug sidebar - Errors appear in the debug sidebar

Common Errors

| Error | Description | Solution | |-------|-------------|----------| | Not connected | No connection to server | Check host/port, network connectivity | | Request timeout | Server didn't respond in time | Increase timeout, check server | | Illegal Data Address | Invalid address | Check address range | | Illegal Data Value | Invalid value | Check value range | | Illegal Function | Function not supported | Check server capabilities |

Modbus Protocol Reference

Address Space

| Type | Address Range | Description | |------|---------------|-------------| | Coils | 0-65535 | Read/Write single bits | | Discrete Inputs | 0-65535 | Read-only single bits | | Holding Registers | 0-65535 | Read/Write 16-bit values | | Input Registers | 0-65535 | Read-only 16-bit values |

Data Types

  • Coils/Discrete Inputs: Boolean (true/false)
  • Registers: 16-bit unsigned integer (0-65535)

For larger data types (32-bit, float, etc.), read multiple consecutive registers and combine them in a function node.

Unit ID

The Unit ID (also called Slave ID) identifies the target device when multiple devices share a connection (e.g., through a gateway). Valid range: 1-255.

Testing

Run the test suite:

npm test

Supported Languages

| Language | Locale | |----------|--------| | English | en-US | | Polish | pl-PL | | Chinese (Simplified) | zh-CN | | Japanese | ja-JP |

Requirements

  • Node.js >= 14.0.0
  • Node-RED >= 2.0.0
  • No external dependencies (uses native Node.js net module)

License

MIT

Author

Aaqu

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: npm test
  5. Submit a pull request

Changelog

0.3.2 (2026-02-05)

  • Fixed MaxListenersExceededWarning - Event listeners on ModbusClient (connect/disconnect/error) are now removed when config node is closed
  • Support for many operational nodes - Config node now allows unlimited listeners, preventing warnings when using 10+ read/write nodes

0.3.1 (2026-02-05)

  • Fixed memory leak - Event listeners (connected/disconnected) on config node are now properly removed when operation nodes are closed/redeployed

0.3.0 (2026-02-05)

  • Heartbeat - periodic Modbus requests to keep connections alive
    • Configurable interval (default: 5000ms)
    • Automatically skipped when there are pending requests
  • External Data mode for modbus-read and modbus-write nodes
    • When enabled, Unit ID/Address/Quantity fields are hidden and must come from msg
    • When disabled, msg.* overrides are ignored (uses only node config)
  • modbus-write-multiple now operates in forced external data mode
    • Unit ID and Address must be provided via msg.unitId and msg.address
  • Include Raw Response option in client config
    • When enabled, includes raw Modbus frame buffer in msg.raw (default: disabled)
  • Fixed checkbox state persistence in configuration dialog
  • Updated External Data hints to show parameter names (msg.unitId, msg.address, msg.quantity)
  • Improved disconnect logging with reason (error or server closed)
  • Added disclaimer to README

0.2.1

  • Fixed uncaught exception when Modbus server is unavailable (ECONNREFUSED)
  • Improved error handling to prevent Node-RED crash on connection errors
  • Added host:port info to connection error messages
  • Fixed timeout when closing Node-RED with unavailable Modbus server
  • Added option to disable connection error logging in console

0.2.0

  • Fixed node names to be unique (added aaqu- prefix)
  • Changed palette category to "Aaqu Portal"
  • Renamed locale files to match new node names

0.1.3

  • Update README

0.1.2

  • Test github actions

0.1.1

  • Added to npm registry
  • Updated README

0.1.0

  • Initial release
  • Support for FC01, FC02, FC03, FC04 (read operations)
  • Support for FC05, FC06, FC15, FC16 (write operations)
  • Auto-reconnect functionality
  • Unit ID configuration per node
  • Dynamic parameter override via message properties