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
8 changes: 0 additions & 8 deletions .pydevproject

This file was deleted.

60 changes: 26 additions & 34 deletions doc/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,46 @@ These examples are considered essential usage examples, and are guaranteed to wo
because they are tested automatilly with each dev branch commit using CI.


Asynchronous Client Example
Asynchronous client Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_async.py

Asynchronous Client basic calls example
Asynchronous client basic calls example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_calls.py

Modbus Payload Example
^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_payload.py
Asynchronous server example
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/server_async.py

Synchronous Client Example
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_sync.py
Build bcd Payload example
^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/build_bcd_payload.py

Forwarder Example
^^^^^^^^^^^^^^^^^
Message generator example
^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/message_generator.py

Message Parser example
^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/message_parser.py

Modbus forwarder Example
^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/modbus_forwarder.py

Asynchronous server example
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/server_async.py
Modbus payload client Example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_payload.py

Modbus Payload Server example
Modbus payload Server example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/server_payload.py

Synchronous client Example
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/client_sync.py

Synchronous server example
^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/server_sync.py
Expand Down Expand Up @@ -74,18 +86,10 @@ These examples have not been upgraded to v3.0.0 but are still relevant.
Help is wanted to upgrade the examples.


Bcd Payload example
^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/bcd_payload.py

Callback Server example
^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/callback_server.py

Concurrent Client example
^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/concurrent_client.py

Custom Message example
^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/custom_message.py
Expand All @@ -98,18 +102,6 @@ Deviceinfo showcase server example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/deviceinfo_showcase_server.py

Message Generator example
^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/message_generator.py

Message Parser example
^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/message_parser.py

Modbus Mapper example
^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/modbus_mapper.py

Modbus Saver example
^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../examples/v2.5.3/modbus_saver.py
Expand Down
31 changes: 18 additions & 13 deletions examples/v2.5.3/bcd_payload.py → examples/build_bcd_payload.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# pylint: disable=missing-type-doc,missing-param-doc,differing-param-doc,missing-raises-doc,missing-any-param-doc
"""Modbus BCD Payload Builder.

This is an example of building a custom payload builder
Expand All @@ -13,10 +12,10 @@
from pymodbus.utilities import pack_bitstring, unpack_bitstring


def convert_to_bcd(decimal):
def convert_to_bcd(decimal: float) -> int:
"""Convert a decimal value to a bcd value

:param value: The decimal value to to pack into bcd
:param decimal: The decimal value to to pack into bcd
:returns: The number in bcd form
"""
place, bcd = 0, 0
Expand All @@ -28,10 +27,10 @@ def convert_to_bcd(decimal):
return bcd


def convert_from_bcd(bcd):
def convert_from_bcd(bcd: int) -> int:
"""Convert a bcd value to a decimal value

:param value: The value to unpack from bcd
:param bcd: The value to unpack from bcd
:returns: The number in decimal form
"""
place, decimal = 1, 0
Expand All @@ -43,7 +42,7 @@ def convert_from_bcd(bcd):
return decimal


def count_bcd_digits(bcd):
def count_bcd_digits(bcd: int) -> int:
"""Count the number of digits in a bcd value

:param bcd: The bcd number to count the digits of
Expand Down Expand Up @@ -101,22 +100,23 @@ def build(self):
string = string + ("\x00" * (length % 2))
return [string[i : i + 2] for i in range(0, length, 2)]

def add_bits(self, values):
def add_bits(self, values: int) -> int:
"""Add a collection of bits to be encoded

If these are less than a multiple of eight,
they will be left padded with 0 bits to make
it so.

:param value: The value to add to the buffer
:param values: The value to add to the buffer
"""
value = pack_bitstring(values)
self._payload.append(value)

def add_number(self, value, size=None):
def add_number(self, value: int, size: int = None):
"""Add any 8bit numeric type to the buffer

:param value: The value to add to the buffer
:param size: Size of buffer
"""
encoded = []
value = convert_to_bcd(value)
Expand All @@ -128,7 +128,7 @@ def add_number(self, value, size=None):
size -= 1
self._payload.extend(encoded)

def add_string(self, value):
def add_string(self, value: str):
"""Add a string to the buffer

:param value: The value to add to the buffer
Expand All @@ -155,7 +155,7 @@ def __init__(self, payload):
self._pointer = 0x00

@staticmethod
def fromRegisters(registers, endian=Endian.Little): # pylint: disable=invalid-name
def fromRegisters(registers: int, endian: str = Endian.Little):
"""Initialize a payload decoder

with the result of reading a collection of registers from a modbus device.
Expand All @@ -167,14 +167,15 @@ def fromRegisters(registers, endian=Endian.Little): # pylint: disable=invalid-n
:param registers: The register results to initialize with
:param endian: The endianness of the payload
:returns: An initialized PayloadDecoder
:raises ParameterException: parameter exception
"""
if isinstance(registers, list): # repack into flat binary
payload = "".join(pack(">H", x) for x in registers)
return BinaryPayloadDecoder(payload, endian)
raise ParameterException("Invalid collection of registers supplied")

@staticmethod
def fromCoils(coils, endian=Endian.Little): # pylint: disable=invalid-name
def fromCoils(coils: int, endian: str = Endian.Little):
"""Initialize a payload decoder.

with the result of reading a collection of coils from a modbus device.
Expand All @@ -184,6 +185,7 @@ def fromCoils(coils, endian=Endian.Little): # pylint: disable=invalid-name
:param coils: The coil results to initialize with
:param endian: The endianness of the payload
:returns: An initialized PayloadDecoder
:raises ParameterException: parameter exception
"""
if isinstance(coils, list):
payload = pack_bitstring(coils)
Expand All @@ -206,7 +208,7 @@ def decode_bits(self):
handle = self._payload[self._pointer - 1 : self._pointer]
return unpack_bitstring(handle)

def decode_string(self, size=1):
def decode_string(self, size: int = 1):
"""Decode a string from the buffer

:param size: The size of the string to decode
Expand All @@ -215,6 +217,9 @@ def decode_string(self, size=1):
return self._payload[self._pointer - size : self._pointer]


if __name__ == "__main__":
print("Test")

# --------------------------------------------------------------------------- #
# Exported Identifiers
# --------------------------------------------------------------------------- #
Expand Down
20 changes: 10 additions & 10 deletions examples/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ async def _handle_discrete_input(client):
async def _handle_holding_registers(client):
"""Read/write holding registers."""
_logger.info("### write holding register and read holding registers")
_check_call(await client.write_register(3, 17, slave=SLAVE))
_check_call(await client.write_register(3, 21, slave=SLAVE))
rr = None
rr = _check_call(await client.read_holding_registers(3, 1, slave=SLAVE))
assert rr.registers[0] == 17
rr = _check_call(await client.read_holding_registers(4, 2, slave=SLAVE))
assert rr.registers[0] == 9
assert rr.registers[1] == 27177
assert rr.registers[0] == 17
assert rr.registers[1] == 17
rr = _check_call(await client.read_holding_registers(3, 1, slave=SLAVE))
assert rr.registers[0] == 21


async def _execute_information_requests(client):
Expand All @@ -65,7 +65,7 @@ async def _execute_information_requests(client):
rr = _check_call(
await client.execute(req_mei.ReadDeviceInformationRequest(slave=SLAVE))
)
assert rr.information[0] == b"pymodbus"
assert rr.information[0] == b"Pymodbus"


async def _execute_diagnostic_requests(client):
Expand All @@ -86,11 +86,11 @@ async def _execute_diagnostic_requests(client):

async def run_async_calls(client):
"""Demonstrate basic read/write calls."""
await _handle_coils(client)
await _handle_discrete_input(client)
await _handle_holding_registers(client)
# await _handle_coils(client)
# await _handle_discrete_input(client)
# await _handle_holding_registers(client)
await _execute_information_requests(client)
await _execute_diagnostic_requests(client)
# await _execute_diagnostic_requests(client)


if __name__ == "__main__":
Expand Down
16 changes: 8 additions & 8 deletions examples/contrib/serial_forwarder.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
from pymodbus.server.async_io import ModbusTcpServer


FORMAT = "%(asctime)-15s %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s"
logging.basicConfig(format=FORMAT)
_logger = logging.getLogger()


Expand Down Expand Up @@ -60,10 +58,14 @@ async def stop(self):

def get_commandline():
"""Read and validate command line arguments"""
logchoices = ["critical", "error", "warning", "info", "debug"]

parser = argparse.ArgumentParser(description="Command line options")
parser.add_argument("--log", help=",".join(logchoices), default="info", type=str)
parser.add_argument(
"--log",
choices=["critical", "error", "warning", "info", "debug"],
help="set log level, default is info",
default="info",
type=str,
)
parser.add_argument(
"--port", help="RTU serial port", default="/dev/ttyUSB0", type=str
)
Expand All @@ -77,9 +79,7 @@ def get_commandline():
args = parser.parse_args()

# set defaults
_logger.setLevel(
args.log.upper() if args.log.lower() in logchoices else logging.INFO
)
_logger.setLevel(args.log.upper())
if not args.slaves:
args.slaves = {1, 2, 3}
return args.port, args.baudrate, args.server_port, args.server_ip, args.slaves
Expand Down
10 changes: 5 additions & 5 deletions examples/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import argparse
import dataclasses
import logging
from dataclasses import dataclass

from pymodbus import pymodbus_apply_logging_config
from pymodbus.transaction import (
Expand All @@ -22,7 +21,7 @@
_logger = logging.getLogger()


@dataclass
@dataclasses.dataclass
class Commandline:
"""Simulate commandline parameters.

Expand All @@ -40,15 +39,16 @@ class Commandline:
slaves = None
client_port = None
client = None
log = "debug"

@classmethod
def copy(cls):
"""Copy Commandline"""
"""Copy kl"""
to_copy = cls()
return dataclasses.replace(to_copy)


def get_commandline(server=False, description=None, extras=None):
def get_commandline(server=False, description=None, extras=None, cmdline=None):
"""Read and validate command line arguments"""
parser = argparse.ArgumentParser(description=description)
parser.add_argument(
Expand Down Expand Up @@ -113,7 +113,7 @@ def get_commandline(server=False, description=None, extras=None):
if extras:
for extra in extras:
parser.add_argument(extra[0], **extra[1])
args = parser.parse_args()
args = parser.parse_args(cmdline)

# set defaults
comm_defaults = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@
modbus_diag.ReturnBusCommunicationErrorCountResponse,
modbus_diag.ReturnBusExceptionErrorCountResponse,
modbus_diag.ReturnSlaveMessageCountResponse,
modbus_diag.ReturnSlaveNoReponseCountResponse,
modbus_diag.ReturnSlaveNoResponseCountResponse,
modbus_diag.ReturnSlaveNAKCountResponse,
modbus_diag.ReturnSlaveBusyCountResponse,
modbus_diag.ReturnSlaveBusCharacterOverrunCountResponse,
Expand Down Expand Up @@ -271,10 +271,8 @@ def get_options():
return opt


def main():
def main(option):
"""Run main runner function"""
option = get_options()

if option.debug:
try:
modbus_log.setLevel(logging.DEBUG)
Expand All @@ -292,4 +290,4 @@ def main():


if __name__ == "__main__":
main()
main(get_options())
Loading