Skip to content

feat(modbus): implement COM port sharing and robust connection management (#211)#2200

Open
lookmydog wants to merge 1 commit intofrangoteam:masterfrom
lookmydog:fix/issue-211
Open

feat(modbus): implement COM port sharing and robust connection management (#211)#2200
lookmydog wants to merge 1 commit intofrangoteam:masterfrom
lookmydog:fix/issue-211

Conversation

@lookmydog
Copy link

Description

This PR refactors the Modbus communication layer to support multiple slave devices sharing a single COM port. It introduces a centralized management system to ensure stability and efficiency in industrial environments.

Key Mechanisms Implemented:

  1. ConnectionManager: A centralized controller to manage port states and lifecycle.
  2. Reference Counting: Tracks the number of active devices per port to safely manage opening/closing.
  3. Queue System: Serializes concurrent requests to prevent data collisions on the physical layer.
  4. Skip Mechanism: Automatically skips unreachable or faulty devices to maintain overall system performance.
  5. Timeout Handling: Improved detection and recovery for unresponsive communication sessions.
  6. Concurrency Control: Robust logic to handle simultaneous connection attempts across multiple slaves.

Impact

  • Allows more flexible hardware configurations (RS-485 daisy-chaining).
  • Reduces resource overhead by reusing port instances.
  • Increases communication reliability under high load.

Related Issue

Fixes #211

…tion logic (frangoteam#211)

Refactored the communication layer to allow a single COM port to be shared across multiple slave devices. Key enhancements: ConnectionManager, Reference Counting, Skip Mechanism, Queue System, Timeout Management, and Concurrency Control. Fixes frangoteam#211
@rvbatista
Copy link
Contributor

Wow, great job, TCP could also need queue in case that serial devices are using a shared gateway.

@lookmydog
Copy link
Author

Wow, great job, TCP could also need queue in case that serial devices are using a shared gateway.

Regarding the TCP 'reuseserial' mode, I've implemented a handling mechanism identical to RTU, as the device-side hardware is RTU-based. This has been included in the current Pull Request. However, I must apologize for refactoring the mutex implementation you used into a queue-based mechanism.

@rvbatista
Copy link
Contributor

Don't need apologies, I just copied the strategy from the SocketReuse of the ModbusTcp.

@unocelli
Copy link
Member

@lookmydog Thanks a lot for this work, the overall direction is great and the refactor is a strong step forward for Modbus connection robustness and shared COM/TCP handling.

I did a brief review with Codex support and found a couple of small improvements before merge.

I also want to be transparent: I could not test COM sharing deeply, because I don’t currently use RTU hardware in my setup.
Thanks again for the effort.

@alext-extracellular
Copy link

I've tested this on my modbus RTU hardware and it is working quite well, it has prevented the crashing I was experiencing when using a slider to send lots of commands very quickly. However I still see lots of CRC errors and data length errors, which I am getting on the latest fuxa release too.

'/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_BG01Q2N7-if00-port0_57600_Even_Slave1' retry after skip period (state: fault, count reset to 0)
Error: Data length error, expected 9 got 4
    at ModbusRTU._onReceive (/usr/src/app/FUXA/server/node_modules/modbus-serial/index.js:450:14)
    at SerialPort.emit (node:events:517:28)
    at addChunk (node:internal/streams/readable:368:12)
    at readableAddChunk (node:internal/streams/readable:341:9)
    at Readable.push (node:internal/streams/readable:278:10)
    at /usr/src/app/FUXA/server/node_modules/@serialport/stream/dist/index.js:208:18
2026-03-02T18:42:53.404Z [ERR] 	'ebyte' _readMemory error at 0-100000! Data length error, expected 9 got 4
2026-03-02T18:42:53.420Z [ERR] 	'ebyte' _readMemory error at 0-100000! CRC error
'/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_BG01Q2N7-if00-port0_57600_Even_Slave1' recovered from error state.
Error: CRC error
    at ModbusRTU._onReceive (/usr/src/app/FUXA/server/node_modules/modbus-serial/index.js:460:14)
    at SerialPort.emit (node:events:517:28)
    at addChunk (node:internal/streams/readable:368:12)
    at readableAddChunk (node:internal/streams/readable:341:9)
    at Readable.push (node:internal/streams/readable:278:10)
    at /usr/src/app/FUXA/server/node_modules/@serialport/stream/dist/index.js:208:18
2026-03-02T18:43:04.409Z [ERR] 	'ebyte' _readMemory error at 0-100000! CRC error
2026-03-02T18:43:04.425Z [ERR] 	'ebyte' _readMemory error at 0-100000! CRC error
'/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_BG01Q2N7-if00-port0_57600_Even_Slave1' recovered from error state.

I don't know if this is just my device or hardware setup, but I don't see these errors when I use QModbus for example.

@lookmydog
Copy link
Author

lookmydog commented Mar 3, 2026

@alext-extracellular

Thanks for the feedback! It is interesting that QModbus works fine; this suggests the hardware itself can handle the communication, but the timing logic in FUXA might need further tuning.

These errors could be caused by serial packet fragmentation (sticky packets) or improper frame segmentation. To help us analyze and reproduce the issue, could you please provide the following information?

  1. Your FUXA Modbus configuration (a screenshot of the settings page).
  2. Details of the polled data for each device (e.g., the number of Coils, Discrete Inputs, Holding Registers, Input Registers, etc.). The more detailed, the better!
  3. Your system architecture (e.g., the number of devices, Slave IDs, and the physical wiring/connection method).

This will help us determine if the issue is related to Node.js event loop latency or the way the serial buffer is being parsed. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Modbus RTU multiple devices per serial port.

4 participants