Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Jan 5, 2025
2 parents ee018e0 + ea0bc1d commit 7fc8d3e
Show file tree
Hide file tree
Showing 31 changed files with 891 additions and 1,128 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ helps make pymodbus a better product.

:ref:`Authors`: contains a complete list of volunteers have contributed to each major version.

Version 3.8.3
-------------
* Remove deprecate from payload. (#2532)
* Add background parameter to servers. (#2529)
* Split async_io.py and simplify server start/stop. (#2528)
* Update custom_msg example to include server. (#2527)
* Move repl doc to repl repo. (#2522)
* Add API to set max until disconnect. (#2521)

Version 3.8.2
-------------
* Asyncio future removed from sync client. (#2514)
Expand All @@ -31,7 +40,7 @@ Version 3.8.0
* Add trace API to server. (#2479)
* Add trace API for client. (#2478)
* Integrate TransactionManager in server. (#2475)
* Rename test/sub_. (#2473)
* Rename test/sub. (#2473)
* Check server closes file descriptors. (#2472)
* Update http_server.py (#2471)
* Restrict write_registers etc to list[int]. (#2469)
Expand Down
4 changes: 2 additions & 2 deletions MAKE_RELEASE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Prepare/make release on dev.
* Control / Update API_changes.rst
* Update CHANGELOG.rst
* Add commits from last release, but selectively !
git log --oneline v3.8.0..HEAD > commit.log
git log --pretty="%an" v3.8.0..HEAD | sort -uf > authors.log
git log --oneline v3.8.3..HEAD > commit.log
git log --pretty="%an" v3.8.3..HEAD | sort -uf > authors.log
update AUTHORS.rst and CHANGELOG.rst
cd doc; ./build_html
* rm -rf build/* dist/*
Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ Our releases is defined as X.Y.Z, and we have strict rules what to release when:

Upgrade examples:

- 3.6.1 -> 3.6.9: just plugin the new version, no changes needed.
- 3.6.1 -> 3.7.0: Smaller changes to the pymodbus calls might be needed
- 3.8.1 -> 3.8.3: just plugin the new version, no changes needed.
- 3.7.1 -> 3.8.0: Smaller changes to the pymodbus calls might be needed
- 2.5.4 -> 3.0.0: Major changes in the application might be needed

Current release is `3.8.2 <https://github.com/pymodbus-dev/pymodbus/releases/tag/v3.8.2>`_.
Current release is `3.8.3 <https://github.com/pymodbus-dev/pymodbus/releases/tag/v3.8.3>`_.

Bleeding edge (not released) is `dev <https://github.com/pymodbus-dev/pymodbus/tree/dev>`_.

Expand Down
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"sphinx_rtd_theme",
"sphinx.ext.autosectionlabel"
]
source_suffix = [".rst"]
source_suffix = {'.rst': 'restructuredtext'}
root_doc = "index"
project = "PyModbus"
copyright = "See license"
Expand Down
Binary file modified doc/source/_static/examples.tgz
Binary file not shown.
Binary file modified doc/source/_static/examples.zip
Binary file not shown.
8 changes: 4 additions & 4 deletions doc/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ Source: :github:`examples/client_calls.py`
:noindex:


Client custom message
^^^^^^^^^^^^^^^^^^^^^
Source: :github:`examples/client_custom_msg.py`
Custom message
^^^^^^^^^^^^^^
Source: :github:`examples/custom_msg.py`

.. automodule:: examples.client_custom_msg
.. automodule:: examples.custom_msg
:undoc-members:
:noindex:

Expand Down
307 changes: 2 additions & 305 deletions doc/source/repl.rst

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions doc/source/roadmap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,20 @@ It is the community that decides how pymodbus evolves NOT the maintainers !

The following bullet points are what the maintainers focus on:

- 3.8.3 bug fix release, with:
- 3.8.4 bug fix release, with:
- Currently not planned
- 3.9.0, with:
- All of branch wait_next_api
- ModbusControlBlock pr slave
- New custom PDU (function codes)
- Simulator datastore, with simple configuration
- Remove remote_datastore
- Remove BinaryPayload
- 4.0.0, with:
- Remove BinaryPayload
- Server becomes Simulator
- New serial forwarder
- client async with sync/async API
- Only one datastore, but with different API`s
- Simulator standard in server
- GUI client, to analyze devices
- GUI server, to simulate devices

Expand Down
2 changes: 1 addition & 1 deletion examples/contrib/serial_forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pymodbus.client import ModbusSerialClient
from pymodbus.datastore import ModbusServerContext
from pymodbus.datastore.remote import RemoteSlaveContext
from pymodbus.server.async_io import ModbusTcpServer
from pymodbus.server import ModbusTcpServer


_logger = logging.getLogger(__file__)
Expand Down
46 changes: 31 additions & 15 deletions examples/client_custom_msg.py → examples/custom_msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@

from pymodbus import FramerType
from pymodbus.client import AsyncModbusTcpClient as ModbusClient
from pymodbus.datastore import (
ModbusSequentialDataBlock,
ModbusServerContext,
ModbusSlaveContext,
)
from pymodbus.exceptions import ModbusIOException
from pymodbus.pdu import ExceptionResponse, ModbusPDU
from pymodbus.pdu import ModbusPDU
from pymodbus.pdu.bit_message import ReadCoilsRequest
from pymodbus.server import ServerAsyncStop, StartAsyncTcpServer


# --------------------------------------------------------------------------- #
Expand All @@ -31,7 +37,7 @@
# --------------------------------------------------------------------------- #


class CustomModbusPDU(ModbusPDU):
class CustomModbusResponse(ModbusPDU):
"""Custom modbus response."""

function_code = 55
Expand Down Expand Up @@ -73,7 +79,7 @@ def __init__(self, address=None, slave=1, transaction=0):
"""Initialize."""
super().__init__(dev_id=slave, transaction_id=transaction)
self.address = address
self.count = 16
self.count = 2

def encode(self):
"""Encode."""
Expand All @@ -83,14 +89,10 @@ def decode(self, data):
"""Decode."""
self.address, self.count = struct.unpack(">HH", data)

def execute(self, context):
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Execute."""
if not 1 <= self.count <= 0x7D0:
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(self.function_code, self.address, self.count):
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
values = context.getValues(self.function_code, self.address, self.count)
return CustomModbusPDU(values)
_ = context
return CustomModbusResponse()


# --------------------------------------------------------------------------- #
Expand Down Expand Up @@ -119,14 +121,25 @@ def __init__(self, address, slave=1, transaction=0):

async def main(host="localhost", port=5020):
"""Run versions of read coil."""
store = ModbusServerContext(slaves=ModbusSlaveContext(
di=ModbusSequentialDataBlock(0, [17] * 100),
co=ModbusSequentialDataBlock(0, [17] * 100),
hr=ModbusSequentialDataBlock(0, [17] * 100),
ir=ModbusSequentialDataBlock(0, [17] * 100),
),
single=True
)
task = asyncio.create_task(StartAsyncTcpServer(
context=store,
address=(host, port),
custom_functions=[CustomRequest])
)
await asyncio.sleep(0.1)
async with ModbusClient(host=host, port=port, framer=FramerType.SOCKET) as client:
await client.connect()

# create a response object to control it works
CustomModbusPDU()

# new modbus function code.
client.register(CustomModbusPDU)
# add new modbus function code.
client.register(CustomModbusResponse)
slave=1
request1 = CustomRequest(32, slave=slave)
try:
Expand All @@ -140,6 +153,9 @@ async def main(host="localhost", port=5020):
request2 = Read16CoilsRequest(32, slave)
result = await client.execute(False, request2)
print(result)
await ServerAsyncStop()
task.cancel()
await task


if __name__ == "__main__":
Expand Down
17 changes: 6 additions & 11 deletions examples/server_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,15 @@ def setup_server(description=None, context=None, cmdline=None):
return args


async def run_async_server(args):
async def run_async_server(args) -> None:
"""Run server."""
txt = f"### start ASYNC server, listening on {args.port} - {args.comm}"
_logger.info(txt)
server = None
if args.comm == "tcp":
address = (args.host if args.host else "", args.port if args.port else None)
server = await StartAsyncTcpServer(
await StartAsyncTcpServer(
context=args.context, # Data storage
identity=args.identity, # server identify
# TBD host=
# TBD port=
address=address, # listen address
# custom_functions=[], # allow custom handling
framer=args.framer, # The framer strategy to use
Expand All @@ -160,7 +157,7 @@ async def run_async_server(args):
args.host if args.host else "127.0.0.1",
args.port if args.port else None,
)
server = await StartAsyncUdpServer(
await StartAsyncUdpServer(
context=args.context, # Data storage
identity=args.identity, # server identify
address=address, # listen address
Expand All @@ -173,7 +170,7 @@ async def run_async_server(args):
elif args.comm == "serial":
# socat -d -d PTY,link=/tmp/ptyp0,raw,echo=0,ispeed=9600
# PTY,link=/tmp/ttyp0,raw,echo=0,ospeed=9600
server = await StartAsyncSerialServer(
await StartAsyncSerialServer(
context=args.context, # Data storage
identity=args.identity, # server identify
# timeout=1, # waiting time for request to complete
Expand All @@ -190,9 +187,8 @@ async def run_async_server(args):
)
elif args.comm == "tls":
address = (args.host if args.host else "", args.port if args.port else None)
server = await StartAsyncTlsServer(
await StartAsyncTlsServer(
context=args.context, # Data storage
host="localhost", # define tcp address where to connect to.
# port=port, # on which port
identity=args.identity, # server identify
# custom_functions=[], # allow custom handling
Expand All @@ -210,10 +206,9 @@ async def run_async_server(args):
# broadcast_enable=False, # treat slave 0 as broadcast address,
# timeout=1, # waiting time for request to complete
)
return server


async def async_helper():
async def async_helper() -> None:
"""Combine setup and run."""
_logger.info("Starting...")
run_args = setup_server(description="Run asynchronous server.")
Expand Down
21 changes: 8 additions & 13 deletions examples/server_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,15 @@
_logger.setLevel("DEBUG")


def run_sync_server(args):
def run_sync_server(args) -> None:
"""Run server."""
txt = f"### start SYNC server, listening on {args.port} - {args.comm}"
_logger.info(txt)
server = None
if args.comm == "tcp":
address = ("", args.port) if args.port else None
server = StartTcpServer(
StartTcpServer(
context=args.context, # Data storage
identity=args.identity, # server identify
# TBD host=
# TBD port=
address=address, # listen address
# custom_functions=[], # allow custom handling
framer=args.framer, # The framer strategy to use
Expand All @@ -83,7 +80,7 @@ def run_sync_server(args):
)
elif args.comm == "udp":
address = ("127.0.0.1", args.port) if args.port else None
server = StartUdpServer(
StartUdpServer(
context=args.context, # Data storage
identity=args.identity, # server identify
address=address, # listen address
Expand All @@ -96,7 +93,7 @@ def run_sync_server(args):
elif args.comm == "serial":
# socat -d -d PTY,link=/tmp/ptyp0,raw,echo=0,ispeed=9600
# PTY,link=/tmp/ttyp0,raw,echo=0,ospeed=9600
server = StartSerialServer(
StartSerialServer(
context=args.context, # Data storage
identity=args.identity, # server identify
# timeout=1, # waiting time for request to complete
Expand All @@ -113,9 +110,8 @@ def run_sync_server(args):
)
elif args.comm == "tls":
address = ("", args.port) if args.port else None
server = StartTlsServer(
StartTlsServer(
context=args.context, # Data storage
host="localhost", # define tcp address where to connect to.
# port=port, # on which port
identity=args.identity, # server identify
# custom_functions=[], # allow custom handling
Expand All @@ -133,14 +129,13 @@ def run_sync_server(args):
# broadcast_enable=False, # treat slave 0 as broadcast address,
# timeout=1, # waiting time for request to complete
)
return server


def sync_helper():
def sync_helper() -> None:
"""Combine setup and run."""
run_args = server_async.setup_server(description="Run synchronous server.")
server = run_sync_server(run_args)
server.shutdown()
run_sync_server(run_args)
# server.shutdown()


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion pymodbus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
from pymodbus.pdu import ExceptionResponse


__version__ = "3.8.2"
__version__ = "3.8.3"
__version_full__ = f"[pymodbus, version {__version__}]"
Loading

0 comments on commit 7fc8d3e

Please sign in to comment.