B4A Library Modbus Master TCP/IP Library

Hello everyone,
Here is a Modbus library that I just wrapped to test something out, so I thought that I would share it with the community. Using this library, you can connect your B4A apps directly to industrial devices (PLCs) over TCP to read and write Modbus data. Your app should (in theory) connect to any Modbud slave device running over Ethernet or WiFi. I've fully tested this library and it should work as advertised. I'll be releasing V1.01 in the next few days with the extra functions highlighted red in the table below).

B4A library tab (XUI Views is just for the test app)
1764089951808.png


Important:
There are 4 separate files in the attached library zip file, place all 4 files in your B4A additional libraries folder.

B4A Modbus Master test app screenshot:
Screenshot_20251125-164453.png


SS_ModbusMaster

Author:
Peter Simpson
Version: 1.0
  • ModbusMaster
    • Events:
      • CoilRead (Success As Boolean, Data() As Boolean, Message As String)
      • ConnectionCheckDone (IsLive As Boolean, Message As String)
      • DiscreteInputRead (Success As Boolean, Data() As Boolean, Message As String)
      • HoldingRegisterRead (Success As Boolean, Data() As Short, Message As String)
      • InitResult (Success As Boolean, Message As String)
      • InputRegisterRead (Success As Boolean, Data() As Short, Message As String)
      • WriteResult (Success As Boolean, Message As String)
    • Functions:
      • Disconnect
        Disconnects and closes the underlying Modbus TCP connection.
        This should be called when the application exits or the Modbus communication is no longer required.
        After calling this, the connection must be re-initialized using Initialize() before further requests can be made.
      • Initialize (EventName As String, Host As String, Port As Int, Encapsulated As Boolean, KeepAlive As Boolean, Timeout As Int, Retries As Int)
        Initializes the Modbus TCP connection parameters and attempts to connect to the PLC/slave device.
        This function is asynchronous and raises the InitResult event upon completion.
        EventName: The prefix used for the callback events (e.g., "MB" will raise MB_InitResult).
        Host: The IP address or hostname of the Modbus TCP slave device.
        Port: The TCP port of the Modbus slave (usually 502).
        Encapsulated: If true, uses Modbus RTU over TCP (Encapsulated) format. Set false for standard Modbus TCP.
        KeepAlive: If true, the TCP socket connection is kept alive between requests.
        Timeout: The connection and request timeout in milliseconds.
        Retries: The number of times the library will retry a failed connection or request.
      • IsInitialized As Boolean
        Checks if the Modbus connection has been successfully initialized and is currently ready to process requests.
        This returns true only after the initial connection heartbeat is successful.
        Return type: @return:True if the connection is ready; otherwise, False.
      • ReadCoil (SlaveId As Int, Start As Int, Len As Int)
        Reads a contiguous block of Coil Statuses (Function Code 1).
        The result is returned asynchronously in the CoilRead event.
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Start: The starting address of the first coil to read (0-based).
        Len: The number of coils to read.
      • ReadDiscreteInput (SlaveId As Int, Start As Int, Len As Int)
        Reads a contiguous block of Discrete Inputs (Function Code 2).
        The result is returned asynchronously in the DiscreteInputRead event.
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Start: The starting address of the first discrete input to read (0-based).
        Len: The number of discrete inputs to read.
      • ReadHoldingRegisters (SlaveId As Int, Start As Int, Len As Int)
        Reads a contiguous block of Holding Registers (Function Code 3).
        The result is returned asynchronously in the HoldingRegisterRead event. The data is returned as an array of Short (16-bit signed integers).
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Start: The starting address of the first register to read (0-based).
        Len: The number of registers to read.
      • ReadInputRegisters (SlaveId As Int, Start As Int, Len As Int)
        Reads a contiguous block of Input Registers (Function Code 4).
        The result is returned asynchronously in the InputRegisterRead event. The data is returned as an array of Short (16-bit signed integers).
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Start: The starting address of the first register to read (0-based).
        Len: The number of registers to read.
      • WriteCoil (SlaveId As Int, Offset As Int, Value As Boolean)
        Writes a single Coil value (Function Code 5).
        The result is returned asynchronously in the WriteResult event.
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Offset: The address of the coil to write to (0-based).
        Value: The boolean value (True/False) to write to the coil.
      • WriteRegister (SlaveId As Int, Offset As Int, Value As Int)
        Writes a single Holding Register value (Function Code 6).
        The result is returned asynchronously in the WriteResult event.
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Offset: The address of the register to write to (0-based).
        Value: The 16-bit integer value (Short in B4A) to write to the register.
      • WriteRegisters (SlaveId As Int, Start As Int, Values As Short())
        Writes multiple Holding Register values (Function Code 16).
        The result is returned asynchronously in the WriteResult event.
        SlaveId: The unique slave address (unit identifier) of the Modbus device.
        Start: The starting address of the first register to write (0-based).
        Values: An array of 16-bit integer values (Shorts in B4A) to write sequentially starting from the Start address.
    • Properties:
      • HostAddress As String [read only]
        Returns the IP address or hostname of the Modbus TCP slave device
        that was set during the last call to Initialize().

B4A Modbus Master quick reference (FC → Method)

FC (Hex)FC (Dec)DescriptionData TypeR/W OperationMethod NameEvent Raised
0x01FC1Read CoilsCoil (Discrete Output)Read (R)ReadCoil(SlaveId, Start, Len)_coilread
0x02FC2Read Discrete InputsDiscrete InputRead (R)ReadDiscreteInput(SlaveId, Start, Len)_discreteinputread
0x03FC3Read Holding RegistersHolding RegisterRead (R)ReadHoldingRegisters(SlaveId, Start, Len)_holdingregisterread
0x04FC4Read Input RegistersInput RegisterRead (R)ReadInputRegisters(SlaveId, Start, Len)_inputregisterread
0x05FC5Write Single CoilCoil (Discrete Output)Write (W)WriteCoil(SlaveId, Offset, Value)_writeresult
0x06FC6Write Single RegisterHolding RegisterWrite (W)WriteRegister(SlaveId, Offset, Value)_writeresult
0x08FC8 Using Loopback V1.01Diagnostic (Loopback)N/ADiagnosticDiagnosticRequest(SlaveId, SubFunction, Data)_diagnosticrequest
0x0FFC15 V1.01Write Multiple CoilsCoil (Discrete Output)Write (W)WriteCoils(SlaveId, Start, Values)_writeresult
0x10FC16Write Multiple RegistersHolding RegisterWrite (W)WriteRegisters(SlaveId, Start, Values)_writeresult
0x17FC23 Using FC16 + FC3 V1.01Read/Write Multiple Registers. Implemented as Chained FC16 + FC3Holding RegisterRead/Write (R/W)ReadWriteMultipleRegisters(...)_holdingregisterread and _writeresult


Enjoy...
 

Attachments

  • ModbusMaster.zip
    24.7 KB · Views: 41
  • ModbusMasterLib.zip
    234.9 KB · Views: 39
Last edited:

SimonAndroid

Active Member
Licensed User
Longtime User
Sorry for my curiosity, but was this library converted for B4A from Python or another language? I needed this a few months ago and created some procedures in Python, where the library works very well. Best regards.
 

Peter Simpson

Expert
Licensed User
Longtime User
Hello @SimonAndroid.
but was this library converted for B4A from Python or another language?
No, not at all, it's a straightforward Java library wrap. Once I got my head around the six basic FCs, I then added the other Function Code features. It only took a few hours to wrap the original java library which I fully tested with a Windows slave simulator, extending and testing this library took another day.

Below is a link that some developers might find useful.

Modbus CRC-16 checksum function with detailed breakdown for each hex value:


Enjoy...
 
Last edited:
Top