uModbus or (μModbus) is a pure Python implementation of the Modbus protocol as described in the MODBUS Application Protocol Specification V1.1b3. uModbus implements both a Modbus client (both TCP and RTU) and a Modbus server (both TCP and RTU). The "u" or "μ" in the name comes from the the SI prefix "micro-". uModbus is very small and lightweight. The source can be found on GitHub. Documentation is available at Read the Docs.
Creating a Modbus TCP server is easy:
#!/usr/bin/env python# scripts/examples/simple_tcp_server.pyimportloggingfromsocketserverimportTCPServerfromcollectionsimportdefaultdictfromargparseimportArgumentParserfromumodbusimportconffromumodbus.server.tcpimportRequestHandler, get_serverfromumodbus.utilsimportlog_to_stream# Add stream handler to logger 'uModbus'.log_to_stream(level=logging.DEBUG)
# A very simple data store which maps addresses against their values.data_store=defaultdict(int)
# Enable values to be signed (default is False).conf.SIGNED_VALUES=True# Parse command line argumentsparser=ArgumentParser()
parser.add_argument("-b", "--bind", default="localhost:502")
args=parser.parse_args()
if":"notinargs.bind:
args.bind+=":502"host, port=args.bind.rsplit(":", 1)
port=int(port)
TCPServer.allow_reuse_address=Truetry:
app=get_server(TCPServer, (host, port), RequestHandler)
exceptPermissionError:
print("You don't have permission to bind on {}".format(args.bind))
print("Hint: try with a different port (ex: --bind localhost:50200)")
exit(1)
@app.route(slave_ids=[1], function_codes=[1, 2], addresses=list(range(0, 10)))defread_data_store(slave_id, function_code, address):
"""" Return value of address. """returndata_store[address]
@app.route(slave_ids=[1], function_codes=[5, 15], addresses=list(range(0, 10)))defwrite_data_store(slave_id, function_code, address, value):
"""" Set value for address. """data_store[address] =valueif__name__=='__main__':
try:
app.serve_forever()
finally:
app.shutdown()
app.server_close()Doing a Modbus request requires even less code:
#!/usr/bin/env python# scripts/examples/simple_tcp_client.pyfromargparseimportArgumentParserfromsocketimportcreate_connectionfromumodbusimportconffromumodbus.clientimporttcp# Enable values to be signed (default is False).conf.SIGNED_VALUES=True# Parse command line argumentsparser=ArgumentParser()
parser.add_argument("-a", "--address", default="localhost:502")
args=parser.parse_args()
if":"notinargs.address:
args.address+=":502"host, port=args.address.rsplit(":", 1)
port=int(port)
# Returns a message or Application Data Unit (ADU) specific for doing# Modbus TCP/IP.message=tcp.write_multiple_coils(slave_id=1, starting_address=1, values=[1, 0, 1, 1])
withcreate_connection((host, port)) assock:
# Response depends on Modbus function code. This particular returns the# amount of coils written, in this case it is.response=tcp.send_message(message, sock)The following functions have been implemented for Modbus TCP and Modbus RTU:
- 01: Read Coils
- 02: Read Discrete Inputs
- 03: Read Holding Registers
- 04: Read Input Registers
- 05: Write Single Coil
- 06: Write Single Register
- 15: Write Multiple Coils
- 16: Write Multiple Registers
Other featues:
- Support for signed and unsigned register values.
uModbus software is licensed under Mozilla Public License. © 2018 Advanced Climate Systems.