Skip to main content

Agile-maintained Python wrapper for the TwinCAT ADS library, based on pyads

Project description

pyads-agile

pyads-agile is a Python wrapper for the Beckhoff TwinCAT ADS library.

This distribution is maintained by Agile Automation Technologies GmbH and is based on the excellent upstream pyads project created by Stefan Lehmann: https://github.com/stlehmann/pyads

pyads-agile intentionally stays drop-in compatible with pyads. The public API, module name (import pyads), and supported interpreter/OS matrix mirror upstream, so existing applications can switch distributions without code changes. Current validated support target is Python 3.13 (CI runs on 3.13).

Attribution

  • Original project: pyads by Stefan Lehmann
  • Fork maintainer: Filippo Boido filippo.boido@agileautomation.eu (Agile Automation Technologies GmbH)
  • License: MIT
  • This repository keeps upstream credit and license notices as required

See ACKNOWLEDGMENTS.md for details.

Installation

Install the distribution:

pip install pyads-agile

Import stays compatible:

import pyads

Versioning

pyads-agile uses its own independent Semantic Versioning (MAJOR.MINOR.PATCH). It does not mirror upstream pyads version numbers.

Scope

This package provides Python APIs for communicating with TwinCAT devices using:

  • TcAdsDll.dll on Windows
  • adslib.so on Linux

Agile-specific enhancements

Beyond compatibility, this fork currently focuses on improved RPC ergonomics:

  • Convenient RPC object proxies. Connection.get_object() exposes TwinCAT function blocks as Python objects and lets you configure return and parameter types per method:

    TwinCAT requirement: each callable method must be annotated in PLC code with {attribute 'TcRpcEnable'} directly above the method declaration.

    rpc = plc.get_object(
        "GVL.fbTestRemoteMethodCall",
        method_return_types={"m_iSimpleCall": pyads.PLCTYPE_INT},
    )
    result = rpc.m_iSimpleCall()
    
  • Multi-parameter RPC calls with native syntax. Configure method signatures once and then call methods like normal Python methods:

    rpc = plc.get_object(
        "GVL.fbTestRemoteMethodCall",
        method_return_types={"m_iSum": pyads.PLCTYPE_INT},
        method_parameters={"m_iSum": [pyads.PLCTYPE_INT, pyads.PLCTYPE_INT]},
    )
    result = rpc.m_iSum(5, 5)
    
  • Typed RPC interfaces for IntelliSense. Decorate a Python class with @pyads.ads_path("GVL.fbTestRemoteMethodCall"), annotate method arguments and return types with TwinCAT PLC types, and pass the class into Connection.get_object. The returned proxy is typed as your class so IDEs can offer completions:

    @pyads.ads_path("GVL.fbTestRemoteMethodCall")
    class FB_TestRemoteMethodCall:
        def m_iSum(
            self,
            a: pyads.PLCTYPE_INT,
            b: pyads.PLCTYPE_INT,
        ) -> pyads.PLCTYPE_INT:
            ...
    
    rpc = plc.get_object(FB_TestRemoteMethodCall)
    result = rpc.m_iSum(5, 5)
    

    You can still use low-level direct calls when needed:

    result = plc.call_rpc_method(
        "GVL.fbTestRemoteMethodCall#m_iSimpleCall",
        return_type=pyads.PLCTYPE_INT,
        write_value=42,
        write_type=pyads.PLCTYPE_INT,
    )
    
  • Serialized async ADS runtime. AsyncConnection executes all ADS calls on a dedicated worker thread per connection (in-order, race-safe on connection state), and exposes awaitable helpers and submit-style futures:

    import asyncio
    import pyads
    
    async def main() -> None:
        async with pyads.AsyncConnection("127.0.0.1.1.1", pyads.PORT_TC3PLC1) as plc:
            fut = plc.submit_sum_read(["GVL.int_val", "GVL.bool_val"])
            # ... do other work
            values = await fut
    
            await plc.sum_write({"GVL.int_val": int(values["GVL.int_val"]) + 1})
    
    asyncio.run(main())
    
  • Async wrappers for the synchronous pyads Connection API. AsyncConnection now mirrors the core synchronous read/write surface while keeping single-threaded serialized execution under the hood. For most methods you get both:

    • submit_* returning asyncio.Future
    • async method variant that awaits the same operation

    Covered wrappers include:

    • read, write, read_write
    • read_by_name, write_by_name
    • read_structure_by_name, write_structure_by_name
    • read_state, read_device_info, write_control
    • get_local_address, get_handle, release_handle, set_timeout
    • sum_read / sum_write (submit_sum_read / submit_sum_write)
    import asyncio
    import pyads
    
    async def main() -> None:
        async with pyads.AsyncConnection("127.0.0.1.1.1", pyads.PORT_TC3PLC1) as plc:
            # Await-style
            value = await plc.read_by_name("GVL.int_val", pyads.PLCTYPE_INT)
            await plc.write_by_name("GVL.int_val", value + 1, pyads.PLCTYPE_INT)
    
            # Submit-style
            fut = plc.submit_read_state()
            state = await fut
            print(state)
    
    asyncio.run(main())
    
  • Async typed RPC objects. Use @pyads.ads_async_path(...) with AsyncConnection.get_async_object(...) for type-safe async RPC interfaces. Method calls return asyncio.Future objects:

    @pyads.ads_async_path("GVL.fbTestRemoteMethodCall")
    class FB_TestRemoteMethodCall:
        def m_iSum(
            self,
            a: pyads.PLCTYPE_INT,
            b: pyads.PLCTYPE_INT,
        ) -> asyncio.Future[pyads.PLCTYPE_INT]:
            ...
    
    async def main(plc: pyads.AsyncConnection) -> None:
        rpc = plc.get_async_object(FB_TestRemoteMethodCall)
        future = rpc.m_iSum(5, 5)
        result = await future
        print(result)
    
  • Native stepchain async RPC interfaces. Use @pyads.ads_stepchain_path(...) to tell the async proxy that this is a long-running state-machine call. Calls return a StepChainOperation containing:

    • accepted: RPC-return phase
    • done: completion phase based on PLC status fields
    • await op: completion snapshot with the latest ADS status symbol values Use the convenience alias pyads.StepChainOp when you don't need to specialize the generic payload type.
    @pyads.ads_stepchain_path(
        "GVL.fbTestRemoteStepChainMethodCall",
        # Optional defaults shown explicitly:
        completion="poll",  # or "notify"
        status_field="stStepStatus",
        request_id_field="udiRequestId",
        request_id_arg="udiRequestId",
        busy_field="xBusy",
        done_field="xDone",
        error_field="xError",
        error_code_field="diErrorCode",
    )
    class FB_TestRemoteStepChainMethodCall:
        def m_xStartStepChain(
            self,
            udiRequestId: pyads.PLCTYPE_UDINT,
        ) -> pyads.StepChainOp:
            ...
    
    async def run_stepchain(plc: pyads.AsyncConnection) -> None:
        rpc = plc.get_async_object(FB_TestRemoteStepChainMethodCall)
        status_root = rpc.status_symbol()
    
        # udiRequestId is auto-generated if omitted.
        op: pyads.StepChainOp = rpc.m_xStartStepChain()
    
        accepted = await op.accepted
        if not accepted:
            raise RuntimeError("Stepchain start rejected by PLC.")
    
        # Wait until status reports completion or error and capture snapshot.
        completion_snapshot = await op
        request_id_symbol = f"{status_root}.udiRequestId"
        print("Completed request", completion_snapshot[request_id_symbol])
    
        # Built-in framework status read (predefined structure)
        status = await rpc.read_status()
        print(status["udiStep"], status["sStepName"])
    

    Completion backend options:

    • completion="poll": periodic sum_read checks (poll_interval/timeout_s)
    • completion="notify": ADS notifications trigger status reads in asyncio

    Built-in predefined stepchain status fields:

    • udiRequestId, xBusy, xDone, xError, diErrorCode, udiStep, sStepName

Features

  • connect to remote TwinCAT devices
  • create routes on Linux and on remote PLCs
  • support for TwinCAT 2 and TwinCAT 3
  • read and write values by name or by address
  • read and write DUTs (structures)
  • notification callbacks
  • typed RPC interfaces via @pyads.ads_path(...)
  • async typed RPC interfaces via @pyads.ads_async_path(...)
  • serialized asyncio runtime via pyads.AsyncConnection
  • async wrappers for core sync ADS methods (submit_* + awaitable variants)
  • async typed RPC proxies via get_async_object(...)
  • native stepchain async RPC flow via @pyads.ads_stepchain_path(...)
  • stepchain completion backends: polling (poll) and notification-driven (notify)

Basic usage

import pyads

plc = pyads.Connection("127.0.0.1.1.1", pyads.PORT_TC3PLC1)
plc.open()
i = plc.read_by_name("GVL.int_val")
plc.write_by_name("GVL.int_val", i)
plc.close()

Contribution Policy

This repository is maintained on a best-effort basis for internal and product needs.

At this time, we do not accept unsolicited pull requests, and we may not be able to respond to feature requests or general support issues.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyads_agile-0.3.1.tar.gz (302.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyads_agile-0.3.1-py3-none-win_arm64.whl (94.9 kB view details)

Uploaded Python 3Windows ARM64

pyads_agile-0.3.1-py3-none-win_amd64.whl (94.9 kB view details)

Uploaded Python 3Windows x86-64

pyads_agile-0.3.1-py3-none-win32.whl (94.9 kB view details)

Uploaded Python 3Windows x86

pyads_agile-0.3.1-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (259.5 kB view details)

Uploaded Python 3manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

pyads_agile-0.3.1-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (237.7 kB view details)

Uploaded Python 3manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

pyads_agile-0.3.1-py3-none-macosx_11_0_arm64.whl (189.9 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

pyads_agile-0.3.1-py3-none-macosx_10_15_x86_64.whl (195.7 kB view details)

Uploaded Python 3macOS 10.15+ x86-64

File details

Details for the file pyads_agile-0.3.1.tar.gz.

File metadata

  • Download URL: pyads_agile-0.3.1.tar.gz
  • Upload date:
  • Size: 302.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyads_agile-0.3.1.tar.gz
Algorithm Hash digest
SHA256 8d689bdc047c34df34d0183a8db4e6cffd7ff6ba09a9877031f3eb04f1e0ddd9
MD5 9d97e179e7e4c988ace37d4b669582f3
BLAKE2b-256 57093a3e1654cdcf31c7d342ab73704ea127a309d1debabc095d290ff0fa4d85

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1.tar.gz:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-win_arm64.whl.

File metadata

  • Download URL: pyads_agile-0.3.1-py3-none-win_arm64.whl
  • Upload date:
  • Size: 94.9 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyads_agile-0.3.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 2452784561004028efc8036fcc7b62b29d55229c0e751b79ad9cac8a0f10d79a
MD5 2e9237dcd452d3ebfc0d500fcb020301
BLAKE2b-256 9e5228e6e1ffa5e18dcfdb92ce043c92c06ed250d2cda2b4ade422669f26f0d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-win_arm64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: pyads_agile-0.3.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 94.9 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyads_agile-0.3.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 bf49587c559387fce5677d135fdf5240891f103efb154cba1f31862913a7d121
MD5 61889f7edac064d4f99fb4e6c5e57f50
BLAKE2b-256 7481a26efcb883286c7d13e8d137ed28d43d4cd06cf21467f5bc28f476bfd21c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-win_amd64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-win32.whl.

File metadata

  • Download URL: pyads_agile-0.3.1-py3-none-win32.whl
  • Upload date:
  • Size: 94.9 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyads_agile-0.3.1-py3-none-win32.whl
Algorithm Hash digest
SHA256 d7576659913e311b0d4a841cf7932f63d9d180a27c2f3c3326338b1f5567dfd8
MD5 9646bad9824d5b2ab00acfb848507c11
BLAKE2b-256 8c88425ff2f768605540a45a3bfc4375160dd629dcba2191582415eafc5a25cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-win32.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyads_agile-0.3.1-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ee024e687f5fd2d7d8a49b86fa1638d9691b26a75e647c51deee0492df3f6d2e
MD5 4fe0654203dce8505f46bd1f68e3ea6b
BLAKE2b-256 cd9582bdb21efae430269977cc35437aca9cd5400e36839365149c27d1d13c38

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pyads_agile-0.3.1-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 782902cfbd541ea0ae1ecd89f7906f28caf3af90306e8ef23d42aad75d11674e
MD5 dc76ec87b1a9a6a40818d9ab6fbf7a29
BLAKE2b-256 193066a428fb0b8922e385100e4ad03a45ebfa0d7af041dc4f9f2dfa1b696f72

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyads_agile-0.3.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 441df621a826a1d21b954e7103d7d3f3003dacaa1522273e2e2c140f988ecc11
MD5 9f2f283494f7f6fff7f2b4665259aba6
BLAKE2b-256 57cf8104c98aca0ad107ff195a1c5067394f3da0ed037c98983921a6ebdbba03

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-macosx_11_0_arm64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyads_agile-0.3.1-py3-none-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for pyads_agile-0.3.1-py3-none-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 f3b3f566cc4091c07077ce50296cdbc7c20fd54860972440dc2d42137cdabe8c
MD5 84b7fb2f8e2f8a73e71dfa2b54059bad
BLAKE2b-256 1dbfb5091a56bb1f864a9a261fa3bdb99cff15eba9f6c1f61f51767f126823ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyads_agile-0.3.1-py3-none-macosx_10_15_x86_64.whl:

Publisher: python-publish.yml on AgileAutomationTechnologies/pyads-agile

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page