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().

The library has the following Function Code (FC) functions:
FC (Hex)FC (Dec)DescriptionModbus Data TypeData Access TypeR/W Operation
0x011Read CoilsCoil (Discrete Output)Read/WriteRead (R)
0x022Read Discrete InputsDiscrete InputRead-OnlyRead (R)
0x033Read Holding RegistersHolding RegisterRead/WriteRead (R)
0x044Read Input RegistersInput RegisterRead-OnlyRead (R)
0x055Write Single CoilCoil (Discrete Output)Read/WriteWrite (W)
0x066Write Single RegisterHolding RegisterRead/WriteWrite (W)
0x0F15 Next version V1.01Write Multiple CoilsCoil (Discrete Output)Read/WriteWrite (W)
0x1016Write Multiple RegistersHolding RegisterRead/WriteWrite (W)
0x1723 Using FC16 + FC3 V1.01Read/Write Multiple Registers (FC16 + FC3 chained)Holding RegisterRead/WriteRead/Write (R/W)

B4A Modbus Master quick reference (FC → Method)

FC (Hex)FC (Dec)Method NameEvent RaisedNotes
0x011ReadCoil(int SlaveId, int Start, int Len)_coilreadAlso used internally for connection heartbeat during Initialize()
0x022ReadDiscreteInput(int SlaveId, int Start, int Len)_discreteinputreadRead-only
0x033ReadHoldingRegisters(int SlaveId, int Start, int Len)_holdingregisterreadReturns short[]
0x044ReadInputRegisters(int SlaveId, int Start, int Len)_inputregisterreadReturns short[]
0x055WriteCoil(int SlaveId, int Offset, boolean Value)_writeresultSingle coil write
0x066WriteRegister(int SlaveId, int Offset, int Value)_writeresultSingle register write
0x0F15WriteCoils(int SlaveId, int Start, boolean[] Values)_writeresultMultiple coil write (added in V1.01)
0x1016WriteRegisters(int SlaveId, int Start, short[] Values)_writeresultMultiple register write
0x1723ReadWriteMultipleRegisters(int SlaveId, int ReadStart, int ReadLen, int WriteStart, short[] WriteValues)_holdingregisterread (success/failure) and _writeresult (write failure)Implemented as chained FC16 + FC3 (added in V1.01)


Enjoy...
 

Attachments

  • ModbusMaster.zip
    24.7 KB · Views: 26
  • ModbusMasterLib.zip
    234.9 KB · Views: 27
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 added the other FCs but had to manually create FC23. All in all, it only took a few hours to wrap and fully test with a Windows slave simulator.

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