Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[run]
omit =
pymodbus/repl/*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ test/__pycache__/
/doc/html/
/doc/_build/
.pytest_cache/
/.pymodhis
1 change: 1 addition & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ requirements_file: requirements-docs.txt
python:
extra_requirements:
- twisted
- torndo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch.

- documents
version: 3.5
14 changes: 14 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
Version 2.0.0rc2
-----------------------------------------------------------
**Note This is a Major release and might affect your existing Async client implementation. Refer examples on how to use the latest async clients.**

* Async client implementation based on Tornado, Twisted and asyncio with backward compatibility support for twisted client.
* Allow reusing existing[running] asyncio loop when creating async client based on asyncio.
* Allow reusing address for Modbus TCP sync server.
* Add support to install tornado as extra requirement while installing pymodbus.
* Support Pymodbus REPL
* Add support to python 3.7.
* Bug fix and enhancements in examples.


Version 2.0.0rc1
-----------------------------------------------------------
**Note This is a Major release and might affect your existing Async client implementation. Refer examples on how to use the latest async clients.**

* Async client implementation based on Tornado, Twisted and asyncio


Version 1.5.2
------------------------------------------------------------
* Fix serial client `is_socket_open` method
Expand Down
43 changes: 34 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ Client Features
* Full read/write protocol on discrete and register
* Most of the extended protocol (diagnostic/file/pipe/setting/information)
* TCP, UDP, Serial ASCII, Serial RTU, and Serial Binary
* asynchronous(powered by twisted) and synchronous versions
* asynchronous(powered by twisted/tornado/asyncio) and synchronous versions
* Payload builder/decoder utilities
* Pymodbus REPL for quick tests

------------------------------------------------------------
Server Features
Expand Down Expand Up @@ -93,9 +94,21 @@ trace them. I get a lot of email and sometimes these requests
get lost in the noise: http://groups.google.com/group/pymodbus or
at gitter: https://gitter.im/pymodbus_dev/Lobby

------------------------------------------------------------
============================================================
Pymodbus REPL (Read Evaluate Procee Loop)
============================================================
Starting with Pymodbus 2.x, pymodbus library comes with handy
Pymodbus REPL to quickly run the modbus clients in tcp/rtu modes.

Pymodbus REPL comes with many handy features such as payload decoder
to directly retrieve the values in desired format and supports all
the diagnostic function codes directly .

For more info on REPL refer `Pymodbus REPL <pymodbus/repl/README.md>`_

============================================================
Installing
------------------------------------------------------------
============================================================

You can install using pip or easy install by issuing the following
commands in a terminal window (make sure you have correct
Expand All @@ -104,6 +117,18 @@ permissions or a virtualenv currently running)::
easy_install -U pymodbus
pip install -U pymodbus

To Install pymodbus with twisted support run::

pip install -U pymodbus[twisted]

To Install pymodbus with tornado support run::

pip install -U pymodbus[tornado]

To Install pymodbus REPL::

pip install -U pymodbus[repl]

Otherwise you can pull the trunk source and install from there::

git clone git://github.com/bashwork/pymodbus.git
Expand All @@ -119,9 +144,9 @@ out all mentions of twisted. It should be noted that without twisted,
one will only be able to run the synchronized version as the
asynchronous versions uses twisted for its event loop.

------------------------------------------------------------
============================================================
Current Work In Progress
------------------------------------------------------------
============================================================

Since I don't have access to any live modbus devices anymore
it is a bit hard to test on live hardware. However, if you would
Expand Down Expand Up @@ -157,14 +182,14 @@ Use make to perform a range of activities
make tox run the tests on all Python versions
make clean cleanup all temporary files

------------------------------------------------------------
============================================================
Contributing
------------------------------------------------------------
============================================================
Just fork the repo and raise your PR against `dev` branch.

------------------------------------------------------------
============================================================
License Information
------------------------------------------------------------
============================================================

Pymodbus is built on top of code developed from/by:
* Copyright (c) 2001-2005 S.W.A.C. GmbH, Germany.
Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Welcome to PyModbus's documentation!

readme.rst
changelog.rst
repl.rst
source/example/modules.rst
source/library/modules.rst

Expand Down
4 changes: 4 additions & 0 deletions doc/repl.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Pymodbus REPL
=============

.. mdinclude:: ../pymodbus/repl/README.md
44 changes: 44 additions & 0 deletions doc/source/library/pymodbus.repl.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
pymodbus\.repl package
==========================

.. automodule:: pymodbus.repl
:members:
:undoc-members:
:show-inheritance:


Submodules
----------

pymodbus\.repl\.client module
-----------------------------------

.. automodule:: pymodbus.repl.client
:members:
:undoc-members:
:show-inheritance:

pymodbus\.repl\.completer module
-----------------------------------

.. automodule:: pymodbus.repl.completer
:members:
:undoc-members:
:show-inheritance:

pymodbus\.repl\.helper module
-----------------------------------

.. automodule:: pymodbus.repl.helper
:members:
:undoc-members:
:show-inheritance:


pymodbus\.repl\.main module
-----------------------------------

.. automodule:: pymodbus.repl.main
:members:
:undoc-members:
:show-inheritance:
1 change: 1 addition & 0 deletions doc/source/library/pymodbus.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Subpackages
pymodbus.framer
pymodbus.internal
pymodbus.server
pymodbus.repl


Submodules
Expand Down
77 changes: 76 additions & 1 deletion examples/common/async_asyncio_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
sys.stderr("This example needs to be run only on python 3.4 and above")
sys.exit(1)

from threading import Thread
import time
# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
Expand Down Expand Up @@ -129,8 +131,81 @@ async def start_async_test(client):
await asyncio.sleep(1)


if __name__ == '__main__':
def run_with_not_running_loop():
"""
A loop is created and is passed to ModbusClient factory to be used.

:return:
"""
log.debug("Running Async client with asyncio loop not yet started")
log.debug("------------------------------------------------------")
loop = asyncio.new_event_loop()
assert not loop.is_running()
new_loop, client = ModbusClient(schedulers.ASYNC_IO, port=5020, loop=loop)
loop.run_until_complete(start_async_test(client.protocol))
loop.close()
log.debug("--------------RUN_WITH_NOT_RUNNING_LOOP---------------")
log.debug("")


def run_with_already_running_loop():
"""
An already running loop is passed to ModbusClient Factory
:return:
"""
log.debug("Running Async client with asyncio loop already started")
log.debug("------------------------------------------------------")

def done(future):
log.info("Done !!!")

def start_loop(loop):
"""
Start Loop
:param loop:
:return:
"""
asyncio.set_event_loop(loop)
loop.run_forever()

loop = asyncio.new_event_loop()
t = Thread(target=start_loop, args=[loop])
t.daemon = True
# Start the loop
t.start()
assert loop.is_running()
asyncio.set_event_loop(loop)
loop, client = ModbusClient(schedulers.ASYNC_IO, port=5020, loop=loop)
future = asyncio.run_coroutine_threadsafe(
start_async_test(client.protocol), loop=loop)
future.add_done_callback(done)
while not future.done():
time.sleep(0.1)
loop.stop()
log.debug("--------DONE RUN_WITH_ALREADY_RUNNING_LOOP-------------")
log.debug("")


def run_with_no_loop():
"""
ModbusClient Factory creates a loop.
:return:
"""
loop, client = ModbusClient(schedulers.ASYNC_IO, port=5020)
loop.run_until_complete(start_async_test(client.protocol))
loop.close()


if __name__ == '__main__':
# Run with No loop
log.debug("Running Async client")
log.debug("------------------------------------------------------")
run_with_no_loop()

# Run with loop not yet started
run_with_not_running_loop()

# Run with already running loop
run_with_already_running_loop()
log.debug("---------------------RUN_WITH_NO_LOOP-----------------")
log.debug("")
13 changes: 10 additions & 3 deletions pymodbus/client/async/factory/tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,17 @@ def async_io_factory(host="127.0.0.1", port=Defaults.Port, framer=None,
"""
import asyncio
from pymodbus.client.async.asyncio import init_tcp_client
loop = kwargs.get("loop") or asyncio.get_event_loop()
loop = kwargs.get("loop") or asyncio.new_event_loop()
proto_cls = kwargs.get("proto_cls", None)
cor = init_tcp_client(proto_cls, loop, host, port)
client = loop.run_until_complete(asyncio.gather(cor))[0]
if not loop.is_running():
asyncio.set_event_loop(loop)
cor = init_tcp_client(proto_cls, loop, host, port)
client = loop.run_until_complete(asyncio.gather(cor))[0]
else:
cor = init_tcp_client(proto_cls, loop, host, port)
future = asyncio.run_coroutine_threadsafe(cor, loop=loop)
client = future.result()

return loop, client


Expand Down
Loading