CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pymodbustcp

A simple Modbus/TCP client library for Python

Pending
Overview
Eval results
Files

utils.mddocs/

Data Utilities

Utility functions for data type conversion, bit manipulation, IEEE 754 floating point encoding/decoding, and protocol validation. These functions are essential for working with Modbus data types and converting between different representations.

Capabilities

Data Type Conversion

Functions for converting between different data representations commonly used in industrial automation.

def word_list_to_long(val_list, big_endian=True, long_long=False):
    """
    Convert word list to long integers.
    
    Parameters:
        val_list (list[int]): List of 16-bit words (0-65535)
        big_endian (bool): Byte order (default: True)
        long_long (bool): Use 64-bit integers instead of 32-bit (default: False)
    
    Returns:
        list[int]: List of 32-bit or 64-bit integers
    """

def long_list_to_word(val_list, big_endian=True, long_long=False):
    """
    Convert long integers to word list.
    
    Parameters:
        val_list (list[int]): List of 32-bit or 64-bit integers
        big_endian (bool): Byte order (default: True)
        long_long (bool): Input integers are 64-bit (default: False)
    
    Returns:
        list[int]: List of 16-bit words (0-65535)
    """

def get_2comp(val_int, val_size=16):
    """
    Convert unsigned integer to two's complement signed integer.
    
    Parameters:
        val_int (int): Unsigned integer value
        val_size (int): Bit size (8, 16, 32, or 64, default: 16)
    
    Returns:
        int: Signed integer in two's complement format
    """

def get_list_2comp(val_list, val_size=16):
    """
    Convert list of unsigned integers to two's complement signed integers.
    
    Parameters:
        val_list (list[int]): List of unsigned integer values
        val_size (int): Bit size for each value (default: 16)
    
    Returns:
        list[int]: List of signed integers in two's complement format
    """

IEEE 754 Floating Point

Functions for encoding and decoding IEEE 754 floating point numbers commonly used in Modbus applications.

def decode_ieee(val_int, double=False):
    """
    Decode IEEE 754 floating point from integer representation.
    
    Parameters:
        val_int (int): Integer representation of IEEE 754 float
        double (bool): Use double precision (64-bit) instead of single (32-bit, default: False)
    
    Returns:
        float: Decoded floating point value
    """

def encode_ieee(val_float, double=False):
    """
    Encode floating point value as IEEE 754 integer representation.
    
    Parameters:
        val_float (float): Floating point value to encode
        double (bool): Use double precision (64-bit) instead of single (32-bit, default: False)
    
    Returns:
        int: IEEE 754 integer representation
    """

Bit Manipulation

Functions for working with individual bits within integers.

def get_bits_from_int(val_int, val_size=16):
    """
    Extract bit list from integer value.
    
    Parameters:
        val_int (int): Integer value
        val_size (int): Number of bits to extract (default: 16)
    
    Returns:
        list[bool]: List of bit values (LSB first)
    """

def test_bit(value, offset):
    """
    Test if a specific bit is set in an integer.
    
    Parameters:
        value (int): Integer value to test
        offset (int): Bit position (0 = LSB)
    
    Returns:
        bool: True if bit is set, False otherwise
    """

def set_bit(value, offset):
    """
    Set a specific bit in an integer.
    
    Parameters:
        value (int): Original integer value
        offset (int): Bit position to set (0 = LSB)
    
    Returns:
        int: Integer with specified bit set
    """

def reset_bit(value, offset):
    """
    Clear a specific bit in an integer.
    
    Parameters:
        value (int): Original integer value
        offset (int): Bit position to clear (0 = LSB)
    
    Returns:
        int: Integer with specified bit cleared
    """

def toggle_bit(value, offset):
    """
    Toggle a specific bit in an integer.
    
    Parameters:
        value (int): Original integer value
        offset (int): Bit position to toggle (0 = LSB)
    
    Returns:
        int: Integer with specified bit toggled
    """

def byte_length(bit_length):
    """
    Calculate the number of bytes needed to store a given number of bits.
    
    Parameters:
        bit_length (int): Number of bits
    
    Returns:
        int: Number of bytes needed
    """

Protocol Utilities

Functions for protocol validation and checksum calculation.

def crc16(frame):
    """
    Calculate CRC16 checksum for Modbus RTU frames.
    
    Parameters:
        frame (bytes): Frame data to calculate checksum for
    
    Returns:
        int: CRC16 checksum value
    """

def valid_host(host_str):
    """
    Validate hostname or IP address format.
    
    Parameters:
        host_str (str): Hostname or IP address string
    
    Returns:
        bool: True if format is valid, False otherwise
    """

Usage Examples

Working with Floating Point Values

from pyModbusTCP.utils import encode_ieee, decode_ieee, long_list_to_word, word_list_to_long
from pyModbusTCP.client import ModbusClient

client = ModbusClient(host="192.168.1.100", auto_open=True)

# Write a floating point value
temperature = 23.45
encoded_temp = encode_ieee(temperature)
register_list = long_list_to_word([encoded_temp], big_endian=True)
client.write_multiple_registers(100, register_list)

# Read and decode floating point value
registers = client.read_holding_registers(100, 2)
if registers:
    temp_as_int = word_list_to_long(registers, big_endian=True)[0]
    decoded_temp = decode_ieee(temp_as_int)
    print(f"Temperature: {decoded_temp}°C")

Bit Manipulation Example

from pyModbusTCP.utils import get_bits_from_int, set_bit, reset_bit, test_bit

# Extract individual bits from a register value
register_value = 0b1101001010110011  # 54451
bits = get_bits_from_int(register_value, 16)
print(f"Bits: {bits}")  # [True, True, False, False, ...]

# Manipulate individual bits
value = 0b00001111  # 15
value = set_bit(value, 4)    # Set bit 4: 0b00011111 (31)
value = reset_bit(value, 0)  # Clear bit 0: 0b00011110 (30)
is_set = test_bit(value, 1)  # Test bit 1: True
print(f"Final value: {value}, bit 1 set: {is_set}")

Data Type Conversion Example

from pyModbusTCP.utils import word_list_to_long, long_list_to_word, get_2comp

# Convert 32-bit integers to register pairs
values_32bit = [1234567890, -987654321]
registers = long_list_to_word(values_32bit, big_endian=True)
print(f"Registers: {registers}")  # [18838, 722, 50042, 35023]

# Convert back to 32-bit integers
converted_back = word_list_to_long(registers, big_endian=True)
print(f"Converted back: {converted_back}")  # [1234567890, 4265312975]

# Handle signed values with two's complement
signed_values = [get_2comp(val, 32) for val in converted_back]
print(f"Signed values: {signed_values}")  # [1234567890, -987654321]

Working with Double Precision Floats

from pyModbusTCP.utils import encode_ieee, decode_ieee, long_list_to_word, word_list_to_long

# Encode double precision float (64-bit)
precise_value = 3.141592653589793
encoded = encode_ieee(precise_value, double=True)
print(f"Encoded: {encoded}")

# Convert to 4 registers for Modbus transmission
registers = long_list_to_word([encoded], big_endian=True, long_long=True)
print(f"Registers: {registers}")  # List of 4 registers

# Decode back to double precision
combined = word_list_to_long(registers, big_endian=True, long_long=True)[0]
decoded = decode_ieee(combined, double=True)
print(f"Decoded: {decoded}")  # 3.141592653589793

Protocol Validation

from pyModbusTCP.utils import valid_host, crc16

# Validate host addresses
hosts = ["192.168.1.1", "localhost", "invalid@host", "::1", "example.com"]
for host in hosts:
    is_valid = valid_host(host)
    print(f"{host}: {'valid' if is_valid else 'invalid'}")

# Calculate CRC16 for Modbus RTU frame
frame = b'\x01\x03\x00\x00\x00\x0A'  # Read holding registers request
checksum = crc16(frame)
print(f"CRC16: 0x{checksum:04X}")

# Complete frame with CRC
full_frame = frame + checksum.to_bytes(2, 'little')
print(f"Complete frame: {full_frame.hex()}")

Bit Pattern Analysis

from pyModbusTCP.utils import get_bits_from_int, byte_length

# Analyze status register bits
status_register = 0b1010001100110101  # 41269
status_bits = get_bits_from_int(status_register, 16)

# Define bit meanings
bit_names = [
    "System Ready", "Error Active", "Manual Mode", "Auto Mode",
    "Motor 1 Run", "Motor 2 Run", "Pump Active", "Heater On",
    "Alarm 1", "Alarm 2", "Service Required", "Door Open",
    "Temperature OK", "Pressure OK", "Flow OK", "Reserved"
]

print("System Status:")
for i, (name, state) in enumerate(zip(bit_names, status_bits)):
    print(f"  Bit {i:2d} - {name:15s}: {'ON' if state else 'OFF'}")

# Calculate storage requirements
num_status_bits = 16
bytes_needed = byte_length(num_status_bits)
print(f"Storage required: {bytes_needed} bytes for {num_status_bits} bits")

Integration with Client/Server

These utility functions integrate seamlessly with the client and server operations:

from pyModbusTCP.client import ModbusClient
from pyModbusTCP.server import ModbusServer, DataBank
from pyModbusTCP.utils import encode_ieee, decode_ieee, word_list_to_long, long_list_to_word

# Server side: Store floating point values
data_bank = DataBank()
temp_values = [23.45, 24.67, 22.89]  # Temperature readings

for i, temp in enumerate(temp_values):
    encoded = encode_ieee(temp)
    registers = long_list_to_word([encoded], big_endian=True)
    data_bank.set_holding_registers(i * 2, registers)  # 2 registers per float

server = ModbusServer(data_bank=data_bank)
server.start()

# Client side: Read and decode floating point values
client = ModbusClient(auto_open=True)
temperatures = []

for i in range(3):
    registers = client.read_holding_registers(i * 2, 2)
    if registers:
        temp_int = word_list_to_long(registers, big_endian=True)[0]
        temperature = decode_ieee(temp_int)
        temperatures.append(temperature)

print(f"Temperatures: {temperatures}")

Install with Tessl CLI

npx tessl i tessl/pypi-pymodbustcp

docs

client.md

constants.md

index.md

server.md

utils.md

tile.json