pyModbusTCP

repository·master·Indexed 43 days ago

https://github.com/sourceperl/pymodbustcp

A Python library for interacting with Modbus/TCP servers. It provides a ModbusClient for reading and writing coils and registers, a ModbusServer for hosting Modbus services, and a utils module for data transformations such as IEEE floating-point and two's complement conversions.

Tokens
12.8K
Snippets
48
Records
60
Agent score
55%

What's inside pyModbusTCP

  1. Important notice regarding example compatibility

    master
    The examples provided in the examples/ directory are designed to work with the version of pyModbusTCP currently present in this repository. They may not be compatible with the version available on PyPI, which is always the latest stable release and may differ from the development version used in these examples.
  2. Manage TCP connections in ModbusClient

    master

    Since version 0.2.0, pyModbusTCP uses an "auto open" mode by default to manage TCP connections.

    Auto Open Modes

    • Keep connection open (Default): The connection stays open for subsequent requests.
      c = ModbusClient(host="localhost", auto_open=True, auto_close=False)
    • Open/Close per request: The socket is opened before a request and closed immediately after.
      c = ModbusClient(host="localhost", auto_open=True, auto_close=True)

    Manual Connection Management

    You can disable auto-management and control the socket manually using .open() and .close().

    # Disable auto management
    c = ModbusClient(host="localhost", auto_open=False, auto_close=False)
    
    # Manually open, perform operations, then close
    if c.open():
        regs_list_1 = c.read_holding_registers(0, 10)
        regs_list_2 = c.read_holding_registers(55, 10)
        c.close()
    c = ModbusClient(host="localhost", auto_open=True, auto_close=False)
  3. Install pyModbusTCP

    master

    You can install the stable version of pyModbusTCP via PyPI or install directly from GitHub.

    From PyPI

    To install the latest stable version:

    sudo pip3 install pyModbusTCP

    To upgrade an existing installation:

    sudo pip3 install pyModbusTCP --upgrade

    To install a specific version (e.g., v0.1.10):

    sudo pip3 install pyModbusTCP==v0.1.10

    From GitHub

    Clone the repository and install using setup.py:

    git clone https://github.com/sourceperl/pyModbusTCP.git
    cd pyModbusTCP
    sudo python setup.py install

    Note: Replace python with your specific target version (e.g., python3.9).

  4. Configure Twine with ~/.pypirc

    master

    Configure your PyPI and PyPI Test credentials by creating a ~/.pypirc file. This file defines the index-servers (pypi and pypitest) and their respective repository URLs and authentication tokens.

    Note: Use __token__ as the username and your actual API token as the password.

    cat <<EOT >> ~/.pypirc
    [distutils]
    index-servers =
      pypi
      pypitest
    
    [pypi]
    repository: https://upload.pypi.org/legacy/
    username: __token__
    password: mytoken
    
    [pypitest]
    repository: https://test.pypi.org/legacy/
    username: __token__
    password: mytoken
    EOT
  5. Use utils for Modbus data mangling

    master

    The pyModbusTCP.utils module provides helper functions for converting Modbus register data into usable Python types, such as handling two's complement, bit manipulation, and floating-point conversions.

    Two's Complement (Negative Numbers)

    Convert 16-bit register lists to signed integers:

    from pyModbusTCP import utils
    list_16_bits = [0x0000, 0xFFFF, 0x00FF, 0x8001]
    print(utils.get_list_2comp(list_16_bits, 16)) # [0, -1, 255, -32767]

    Bit Manipulation

    Convert an integer to an array of booleans:

    from pyModbusTCP import utils
    print(utils.get_bits_from_int(0x05, val_size=8)) # [True, False, True, False, False, False, False, False]

    32-bit Register Conversion (Long Format)

    Convert a list of 16-bit words into 32-bit integers (supports Big and Little Endian):

    from pyModbusTCP import utils
    list_16_bits = [0x0123, 0x4567, 0xdead, 0xbeef]
    
    # Big Endian (Default)
    list_32_bits = utils.word_list_to_long(list_16_bits)
    
    # Little Endian
    list_32_bits = utils.word_list_to_long(list_16_bits, big_endian=False)

    IEEE Floating-Point Conversion

    Encode/decode 32-bit (single) or 64-bit (double) precision floats:

    from pyModbusTCP import utils
    
    # 32-bit Single Precision
    encoded = utils.encode_ieee(0.3)
    decoded = utils.decode_ieee(encoded)
    
    # 64-bit Double Precision
    encoded_64 = utils.encode_ieee(6.62606957e-34, double=True)
    decoded_64 = utils.decode_ieee(encoded_64, double=True)
    from pyModbusTCP import utils
    # Example: get signed 16-bit integers from a list
    print(utils.get_list_2comp([0xFFFF], 16))
  6. Understand Modbus function code handling in the server

    master

    The ModbusServer implementation automatically routes incoming Modbus requests to specific internal handlers based on the function code. If a requested function code is not recognized or is not callable, the server responds with an EXP_ILLEGAL_FUNCTION exception.

    Supported function codes handled by the server include:

    • READ_COILS (0x01)
    • READ_DISCRETE_INPUTS (0x02)
    • READ_HOLDING_REGISTERS (0x03)
    • READ_INPUT_REGISTERS (0x04)
    • WRITE_SINGLE_COIL (0x05)
    • WRITE_SINGLE_REGISTER (0x06)
    • WRITE_MULTIPLE_COILS (0x0F)
    • WRITE_MULTIPLE_REGISTERS (0x10)
    • WRITE_READ_MULTIPLE_REGISTERS (0x17)
    • MEI_TYPE_READ_DEVICE_ID (0x2B)
  7. Understand Modbus TCP Frame structure (MBAP and PDU)

    master

    A Modbus TCP frame consists of an MBAP (Modbus Application Protocol) header and a PDU (Protocol Data Unit).

    MBAP (Modbus Application Protocol)

    Contains:

    • transaction_id: 2 bytes
    • protocol_id: 2 bytes (must be 0)
    • length: 2 bytes (number of remaining bytes)
    • unit_id: 1 byte

    PDU (Protocol Data Unit)

    Contains:

    • func_code: The Modbus function code.
    • except_code: Present if the function code indicates an error (is_except is true).

    Key Properties:

    • Frame.raw: Returns the full concatenated bytes of MBAP and PDU.
    • PDU.is_except: Returns True if the function code is > 0x7F.
    • PDU.is_valid: Checks if the PDU has at least 2 bytes.
  8. Debug ModbusClient frame exchanges

    master

    To inspect the raw Modbus frames (Tx/Rx) being sent and received, enable debug logging for the pyModbusTCP.client logger using the standard Python logging module.

    import logging
    from pyModbusTCP.client import ModbusClient
    
    # Enable debug level to see frame exchanges
    logging.basicConfig()
    logging.getLogger('pyModbusTCP.client').setLevel(logging.DEBUG)
    
    c = ModbusClient(host="localhost", port=502)
    c.read_coils(0)

    Example Output: DEBUG:pyModbusTCP.client:(localhost:502:1) Tx [8F 8A 00 00 00 06 01] 01 00 00 00 01
    DEBUG:pyModbusTCP.client:(localhost:502:1) Rx [8F 8A 00 00 00 04 01] 01 01 00

    import logging
    logging.getLogger('pyModbusTCP.client').setLevel(logging.DEBUG)