async-modbus


Nameasync-modbus JSON
Version 0.2.2 PyPI version JSON
download
home_pagehttps://github.com/tiagocoutinho/async_modbus
SummaryAsync ModBus python library
upload_time2024-12-12 09:22:50
maintainerNone
docs_urlNone
authorTiago Coutinho
requires_python>=3.6
licenseGNU General Public License v3
keywords modbus tcp rtu async_modbus asyncio
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Async ModBus

[![Async Modbus][pypi-version]](https://pypi.python.org/pypi/async_modbus)
[![Python Versions][pypi-python-versions]](https://pypi.python.org/pypi/async_modbus)
[![CI Status][CI]](https://github.com/tiagocoutinho/async_modbus/actions/workflows/ci.yml)
![License][license]
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)


Asynchronous (as in python async/await) modbus python 3 client library.
A thin layer on on top of the venerable
[umodbus](https://github.com/AdvancedClimateSystems/uModbus) library providing
an object oriented client API.

async_modbus is async library agnostic. You should be able to use it with
[asyncio](https://docs.python.org/3/library/asyncio.html),
[curio](https://curio.rtfd.io), [trio](https://trio.rtfd.io) or
[anyio](https://anyio.rtfd.io).

It expects an object with the same interface as
[StreamReader](https://docs.python.org/3/library/asyncio-stream.html#streamreader)
and
[StreamWriter](https://docs.python.org/3/library/asyncio-stream.html#streamwriter)
so you may need to write a thin wrapper if you are not using asyncio.
The examples below show how to use it with curio.

Note: the `modbus_for_url()` relies on the
[connio](https://github.com/tiagocoutinho/connio) library which relies on
the asyncio event loop so you it's usage is limited to asyncio applications.


## Why another modbus library?

This library is not a re-implementation of the ModBus communication protocol.
You can view it instead as a complement to the
[umodbus](https://github.com/AdvancedClimateSystems/uModbus) library.

Here is what async_modbus provides on top of umodbus:

* Simple yet powerful object oriented API
* Convenient `modbus_for_url()` helper function. Type an URL and you're ready
  to go.
* when appropriate, [numpy](https://numpy.org) arrays are used. It's usage not
  only reduces the memory footprint and increases speed, but also makes it easy
  for users to efficiently reformat data.
* Compatible with the [connio](https://github.com/tiagocoutinho/connio),
  [sockio](https://github.com/tiagocoutinho/sockio) and
  [serialio](https://github.com/tiagocoutinho/serialio) libraries which provide
  transparent socket re-connection among other features.


## Installation

From within your favorite python environment type:

`$ pip install async_modbus`

Numpy will be used if installed. You can install it yourself, or include the optional dependency:

`$ pip install async_modbus[numpy]`

## Library

The core of the async_modbus library consists of a `modbus_for_url()` function
and the two classes `AsyncTCPClient` and `AsyncRTUClient`.

Here are some examples:

### asyncio examples

*simple TCP client*

```python
import asyncio

import numpy

from async_modbus import modbus_for_url


async def main():

    client = modbus_for_url("tcp://localhost:15020")

    values = numpy.array([1, 0, 1, 1])  # would also work with list<bool or int>
    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_coils(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()


asyncio.run(main())
```

*RTU on local serial line with custom serial options*

```python
import asyncio

from async_modbus import modbus_for_url


async def main():

    client = modbus_for_url("serial:///dev/ttyS0", {"baudrate":19200, "parity":"E"})

    values = [1, 0, 1, 1]
    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_discrete_inputs(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()


asyncio.run(main())
```

*RTU over remote serial line using RFC2217*

```python
import asyncio

from async_modbus import modbus_for_url


async def main():

    client = modbus_for_url("rfc2217://moxa.acme.org:6610")

    values = [1, 0, 1, 1]
    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_discrete_inputs(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()


asyncio.run(main())
```

*asyncio TCP streams*

```python
import asyncio

import numpy

from async_modbus import AsyncTCPClient


async def main():

    reader, writer = await asyncio.open_connection('localhost', 15020)
    client = AsyncTCPClient((reader, writer))

    values = numpy.array([0, 2**15 - 1, 10, 3, 32766])
    reply = await client.write_registers(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_holding_registers(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()

    writer.close()
    await writer.wait_closed()


asyncio.run(main())
```

*async serial line RTU using remote raw TCP*

```python
import asyncio

import numpy

from async_modbus import AsyncRTUClient
from serial_asyncio import open_serial_connection


async def main():

    reader, writer = await open_serial_connection(url="socket://moxa.acme.org:6610")
    client = AsyncRTUClient((reader, writer))

    values = [0, 2**15 - 1, 10, 3, 32766]
    reply = await client.write_registers(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_input_registers(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()

    writer.close()
    await writer.wait_closed()


asyncio.run(main())
```

### curio examples

**curio TCP streams**

```python
import curio
from async_modbus import AsyncTCPClient


async def main():

    sock = await curio.open_connection("0", 15020)
    client = AsyncTCPClient(sock.as_stream())

    values = [1, 0, 1, 1]
    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)
    assert reply is len(values)

    reply = await client.read_coils(slave_id=1, starting_address=1, quantity=len(values))
    assert (reply == values).all()

    await sock.close()
```


## Credits

### Development Lead

* Tiago Coutinho <coutinhotiago@gmail.com>

### Contributors

None yet. Why not be the first?

### Special thanks to

* [umodbus](https://github.com/AdvancedClimateSystems/uModbus)
* [numpy](https://numpy.org)


[pypi-python-versions]: https://img.shields.io/pypi/pyversions/async_modbus.svg
[pypi-version]: https://img.shields.io/pypi/v/async_modbus.svg
[pypi-status]: https://img.shields.io/pypi/status/async_modbus.svg
[license]: https://img.shields.io/pypi/l/async_modbus.svg
[CI]: https://github.com/tiagocoutinho/async_modbus/actions/workflows/ci.yml/badge.svg

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/tiagocoutinho/async_modbus",
    "name": "async-modbus",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "modbus, tcp, rtu, async_modbus, asyncio",
    "author": "Tiago Coutinho",
    "author_email": "coutinhotiago@gmail.com",
    "download_url": null,
    "platform": null,
    "description": "# Async ModBus\n\n[![Async Modbus][pypi-version]](https://pypi.python.org/pypi/async_modbus)\n[![Python Versions][pypi-python-versions]](https://pypi.python.org/pypi/async_modbus)\n[![CI Status][CI]](https://github.com/tiagocoutinho/async_modbus/actions/workflows/ci.yml)\n![License][license]\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)\n\n\nAsynchronous (as in python async/await) modbus python 3 client library.\nA thin layer on on top of the venerable\n[umodbus](https://github.com/AdvancedClimateSystems/uModbus) library providing\nan object oriented client API.\n\nasync_modbus is async library agnostic. You should be able to use it with\n[asyncio](https://docs.python.org/3/library/asyncio.html),\n[curio](https://curio.rtfd.io), [trio](https://trio.rtfd.io) or\n[anyio](https://anyio.rtfd.io).\n\nIt expects an object with the same interface as\n[StreamReader](https://docs.python.org/3/library/asyncio-stream.html#streamreader)\nand\n[StreamWriter](https://docs.python.org/3/library/asyncio-stream.html#streamwriter)\nso you may need to write a thin wrapper if you are not using asyncio.\nThe examples below show how to use it with curio.\n\nNote: the `modbus_for_url()` relies on the\n[connio](https://github.com/tiagocoutinho/connio) library which relies on\nthe asyncio event loop so you it's usage is limited to asyncio applications.\n\n\n## Why another modbus library?\n\nThis library is not a re-implementation of the ModBus communication protocol.\nYou can view it instead as a complement to the\n[umodbus](https://github.com/AdvancedClimateSystems/uModbus) library.\n\nHere is what async_modbus provides on top of umodbus:\n\n* Simple yet powerful object oriented API\n* Convenient `modbus_for_url()` helper function. Type an URL and you're ready\n  to go.\n* when appropriate, [numpy](https://numpy.org) arrays are used. It's usage not\n  only reduces the memory footprint and increases speed, but also makes it easy\n  for users to efficiently reformat data.\n* Compatible with the [connio](https://github.com/tiagocoutinho/connio),\n  [sockio](https://github.com/tiagocoutinho/sockio) and\n  [serialio](https://github.com/tiagocoutinho/serialio) libraries which provide\n  transparent socket re-connection among other features.\n\n\n## Installation\n\nFrom within your favorite python environment type:\n\n`$ pip install async_modbus`\n\nNumpy will be used if installed. You can install it yourself, or include the optional dependency:\n\n`$ pip install async_modbus[numpy]`\n\n## Library\n\nThe core of the async_modbus library consists of a `modbus_for_url()` function\nand the two classes `AsyncTCPClient` and `AsyncRTUClient`.\n\nHere are some examples:\n\n### asyncio examples\n\n*simple TCP client*\n\n```python\nimport asyncio\n\nimport numpy\n\nfrom async_modbus import modbus_for_url\n\n\nasync def main():\n\n    client = modbus_for_url(\"tcp://localhost:15020\")\n\n    values = numpy.array([1, 0, 1, 1])  # would also work with list<bool or int>\n    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_coils(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n\nasyncio.run(main())\n```\n\n*RTU on local serial line with custom serial options*\n\n```python\nimport asyncio\n\nfrom async_modbus import modbus_for_url\n\n\nasync def main():\n\n    client = modbus_for_url(\"serial:///dev/ttyS0\", {\"baudrate\":19200, \"parity\":\"E\"})\n\n    values = [1, 0, 1, 1]\n    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_discrete_inputs(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n\nasyncio.run(main())\n```\n\n*RTU over remote serial line using RFC2217*\n\n```python\nimport asyncio\n\nfrom async_modbus import modbus_for_url\n\n\nasync def main():\n\n    client = modbus_for_url(\"rfc2217://moxa.acme.org:6610\")\n\n    values = [1, 0, 1, 1]\n    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_discrete_inputs(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n\nasyncio.run(main())\n```\n\n*asyncio TCP streams*\n\n```python\nimport asyncio\n\nimport numpy\n\nfrom async_modbus import AsyncTCPClient\n\n\nasync def main():\n\n    reader, writer = await asyncio.open_connection('localhost', 15020)\n    client = AsyncTCPClient((reader, writer))\n\n    values = numpy.array([0, 2**15 - 1, 10, 3, 32766])\n    reply = await client.write_registers(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_holding_registers(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n    writer.close()\n    await writer.wait_closed()\n\n\nasyncio.run(main())\n```\n\n*async serial line RTU using remote raw TCP*\n\n```python\nimport asyncio\n\nimport numpy\n\nfrom async_modbus import AsyncRTUClient\nfrom serial_asyncio import open_serial_connection\n\n\nasync def main():\n\n    reader, writer = await open_serial_connection(url=\"socket://moxa.acme.org:6610\")\n    client = AsyncRTUClient((reader, writer))\n\n    values = [0, 2**15 - 1, 10, 3, 32766]\n    reply = await client.write_registers(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_input_registers(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n    writer.close()\n    await writer.wait_closed()\n\n\nasyncio.run(main())\n```\n\n### curio examples\n\n**curio TCP streams**\n\n```python\nimport curio\nfrom async_modbus import AsyncTCPClient\n\n\nasync def main():\n\n    sock = await curio.open_connection(\"0\", 15020)\n    client = AsyncTCPClient(sock.as_stream())\n\n    values = [1, 0, 1, 1]\n    reply = await client.write_coils(slave_id=1, starting_address=1, values=values)\n    assert reply is len(values)\n\n    reply = await client.read_coils(slave_id=1, starting_address=1, quantity=len(values))\n    assert (reply == values).all()\n\n    await sock.close()\n```\n\n\n## Credits\n\n### Development Lead\n\n* Tiago Coutinho <coutinhotiago@gmail.com>\n\n### Contributors\n\nNone yet. Why not be the first?\n\n### Special thanks to\n\n* [umodbus](https://github.com/AdvancedClimateSystems/uModbus)\n* [numpy](https://numpy.org)\n\n\n[pypi-python-versions]: https://img.shields.io/pypi/pyversions/async_modbus.svg\n[pypi-version]: https://img.shields.io/pypi/v/async_modbus.svg\n[pypi-status]: https://img.shields.io/pypi/status/async_modbus.svg\n[license]: https://img.shields.io/pypi/l/async_modbus.svg\n[CI]: https://github.com/tiagocoutinho/async_modbus/actions/workflows/ci.yml/badge.svg\n",
    "bugtrack_url": null,
    "license": "GNU General Public License v3",
    "summary": "Async ModBus python library",
    "version": "0.2.2",
    "project_urls": {
        "Homepage": "https://github.com/tiagocoutinho/async_modbus"
    },
    "split_keywords": [
        "modbus",
        " tcp",
        " rtu",
        " async_modbus",
        " asyncio"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "878dc18aa8328cebfa6231e6536b2c910c5e966911ed3ce9332ce57c02e881a6",
                "md5": "2a8de690d927a97e1e90ec30a4d799db",
                "sha256": "85743a80b8cca18912e2aa2b91741cc479097e0c286137f2d80848444f5e6efa"
            },
            "downloads": -1,
            "filename": "async_modbus-0.2.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2a8de690d927a97e1e90ec30a4d799db",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 10912,
            "upload_time": "2024-12-12T09:22:50",
            "upload_time_iso_8601": "2024-12-12T09:22:50.452354Z",
            "url": "https://files.pythonhosted.org/packages/87/8d/c18aa8328cebfa6231e6536b2c910c5e966911ed3ce9332ce57c02e881a6/async_modbus-0.2.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-12 09:22:50",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "tiagocoutinho",
    "github_project": "async_modbus",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "async-modbus"
}
        
Elapsed time: 0.37370s