-
Notifications
You must be signed in to change notification settings - Fork 1k
Closed
Description
Discussed in #2687
Originally posted by symygy July 16, 2025
I am trying to create simple SerialModbusServer using pymodbus library and then I want to read some not exisiting registers. I expect getting a modbus "Illegal Data Address" error but as I understand it correctly I'm getting "Slave Device Failue".
demo code:
# server_test.py
# pymodbus 3.11.0
from pymodbus.datastore import ModbusDeviceContext, ModbusSparseDataBlock, ModbusServerContext
from pymodbus.server import StartTcpServer
from pymodbus import pymodbus_apply_logging_config
def run_server():
pymodbus_apply_logging_config("DEBUG")
num_registers = 100
store = ModbusDeviceContext(
hr=ModbusSparseDataBlock({i: 17 for i in range(num_registers)}) # addresses 0-99
)
context = ModbusServerContext(devices=store, single=True)
StartTcpServer(
context=context,
address=("localhost", 5020), # Use unprivileged port
)
if __name__ == "__main__":
run_server()
# client_test.py
# pymodbus 3.11.0
import argparse
from pymodbus.client import ModbusTcpClient
def test_virtual_device(reg):
client = ModbusTcpClient(host="localhost", port=5020)
print(f"\n--- Reading register {reg} ---")
result = client.read_holding_registers(address=reg, count=1, device_id=1)
if result.isError():
exc_code = result.exception_code
print(f"Exception code 0x{exc_code:02X}")
if exc_code == result.ILLEGAL_ADDRESS:
print("ILLEGAL DATA ADDRESS")
elif exc_code == result.DEVICE_FAILURE:
print("DEVICE FAILURE")
else:
print(f"Register {reg} value: {result.registers[0]}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Read a holding register from a Modbus TCP server.")
parser.add_argument(
"reg",
type=int,
default=1000,
help="Register address to read (default: 1000)"
)
args = parser.parse_args()
test_virtual_device(reg=args.reg)
alex@antorak:~/Desktop$ python3 client_test.py 99
--- Reading register 99 ---
Exception code 0x04
DEVICE FAILURE
alex@antorak:~/Desktop$ python3 client_test.py 1
--- Reading register 1 ---
Register 1 value: 17
Metadata
Metadata
Assignees
Labels
No labels