Migrating PLC4Py from 0.13.1 to 1.0.0

This page covers the Python API. The changes to connection strings, tag addresses and defaults that apply to every language are described on the overview page.

PLC4Py is not ready for production usage and is still installed from the Git repository rather than from PyPI - see Getting Started with Python. It ships Modbus and UMAS drivers. This page is short because there is genuinely little to do.

Short version

The PLC4Py API did not change. PlcDriverManager, the connection, the request builders and the response types are the same as in 0.13.1. Code that ran against 0.13.1 runs against 1.0.0.

import asyncio
from plc4py.PlcDriverManager import PlcDriverManager

# unchanged between 0.13.1 and 1.0.0
async def main():
    async with PlcDriverManager().connection("modbus://127.0.0.1:5020") as connection:
        ...

The changes below are additive, or they are runtime behaviour.

Message nesting is bounded

A generated parser refuses a message that nests its types deeper than 1024 levels. Several protocol types contain themselves, so the depth of the value tree is the sender’s to choose and one level costs a single byte on the wire; deep enough, that used to exhaust the interpreter’s recursion limit inside the parser, where it is neither a parse failure the driver can report nor an error the receive path contains.

Set the PLC4X_MAX_NESTING_DEPTH environment variable for a device whose messages genuinely nest deeper. It means the same thing in every PLC4X binding, and a value that is not a positive number leaves the default in place with a warning.

The deepest message in the project’s own testsuites nests 36 levels, so this bounds only what no real device sends.

Tag addresses are unchanged

This is the one place where PLC4Py now differs from PLC4J and PLC4Go, and it is worth being explicit about it.

1.0.0 introduced one array notation across all Java and Go drivers, in which the selection is written before the type and [4] means "the element at index 4":

holding-register:1[0..3]:INT     # PLC4J and PLC4Go in 1.0.0

PLC4Py did not move. Its Modbus tag pattern still reads the old count-after-type form, in which [4] means "four elements":

holding-register:1:INT[4]        # PLC4Py, both in 0.13.1 and in 1.0.0

So your existing PLC4Py addresses keep working unchanged - but an address copied from the Addressing arrays page, or from a working PLC4J application, will not parse. Read the array-notation documentation as describing PLC4J and PLC4Go, not PLC4Py.

Modbus arrays and strings

The way Modbus register values are packed and unpacked moved out of the mspec and into ModbusRegisterCodec implementations, and STRING and WSTRING were added to the Modbus data types. This is internal to the driver; the tag addresses and the returned PlcValue types are unchanged.

Generated protocol classes

If you import from plc4py.protocols.* directly - which is generated code, not the public API - note that the UMAS constants class was renamed:

# 0.13.1
from plc4py.protocols.umas.readwrite.UmasConstants import UmasConstants

# 1.0.0
from plc4py.protocols.umas.readwrite.Constants import Constants

Application code using PlcDriverManager and the request builders is not affected.

Building

The PLC4X build migrated to Apache Maven 4. This only concerns you if you build PLC4Py from the PLC4X source tree with -Pwith-python; pip install . inside the plc4py directory is unchanged.