-
Notifications
You must be signed in to change notification settings - Fork 951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offset registers > 100 responding IllegalAddress in TCP server mode #1529
Comments
Since you are not sharing parts of the relevant code, it is quite hard to tell. However this could very well be caused by a wrong or missing slave_id in the client call, or in the server setup. |
You say that <100 works fine (no log supplied) so it cannot be the slave_id unless you use different calls. |
It seems to be a problem in your code, just added a test case that tests SparseDatablock with your setup. |
Sorry guys, i just got confused with address and count values... i must read the holding register with -1 offset at address to read correctly... server.py: import asyncio
import logging
import os
from helper import get_commandline
from pymodbus import __version__ as pymodbus_version
from pymodbus.datastore import (
ModbusSequentialDataBlock,
ModbusServerContext,
ModbusSlaveContext,
ModbusSparseDataBlock,
)
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.server import (
StartAsyncSerialServer,
StartAsyncTcpServer,
)
_logger = logging.getLogger()
def setup_server(description=None, context=None, cmdline=None):
"""Run server setup."""
args = get_commandline(server=True, description=description, cmdline=cmdline)
print(args)
if context:
args.context = context
if not args.context:
_logger.info("### Create datastore")
#simulating devices for unicoba POC
sc501_datablock = ModbusSparseDataBlock({
20000: [45, 241, 48], #ACDC Output current, input voltage and output voltage
20008: 38, #Ambient temperature ACDC
20023: [0, 0, 0, 0, 0, 0], #Alarms rectifier
22001: 23, #Output current DCDC
22003: 48, #Output Voltage DCDC
30052: [4, 2, 1], #Alarms counts
48030: [0, 0], #LVD alarm state
48040: [0, 0], #batt + fuse alarm
48050: [0, 0], #batt - fuse alarm
48060: [0, 0], #batt alarm
48140: [0x4208,0xcccd], #Ambient temperature alarm
48146: [0x42ad, 0x0000], #Humidity alarm
48170: [0,0,0,0,0,0], #Alarms type and classication
48190: [0,0], #BMS alarm
48200: [0,0], #ACDC rectifier alarm
48204: [0,0], #Solar converter alarm
48216: [0,0], #DCDC rectifier alarm
})
Battery_datablock = ModbusSparseDataBlock({
1: 6720,
2: 130,
3: [4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200,4200],
19: [39,40,43,2100,170,69,80,2,0,0,0],
30: [0x0D,0xFE],
32: [0,0,32,32],
37: [16,3920],
62: [0,0,0,0,0,0,0,0,0,0,0],
81: [0,0,0,0],
91: [0,0,0,0,0,0,0,0,0,0,0],
105: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24],
117: [56, 30, 33, 52, 30, 34]
})
context = {
0x01: ModbusSlaveContext(
hr=sc501_datablock,
),
0x02: ModbusSlaveContext(
hr=Battery_datablock,
),
}
single = False
args.context = ModbusServerContext(slaves=context, single=single)
args.identity = ModbusDeviceIdentification(
info_name={
"VendorName": "Pymodbus",
"ProductCode": "PM",
"VendorUrl": "https://github.com/pymodbus-dev/pymodbus/",
"ProductName": "Pymodbus Server",
"ModelName": "Pymodbus Server",
"MajorMinorRevision": pymodbus_version,
}
)
return args
async def run_async_server(args):
"""Run server."""
txt = f"### start ASYNC server, listening on {args.port} - {args.comm}"
_logger.info(txt)
if args.comm == "tcp":
address = ("", args.port) if args.port else None
server = await StartAsyncTcpServer(
context=args.context, # Data storage
identity=args.identity, # server identify
address=address, # listen address
framer=args.framer, # The framer strategy to use
allow_reuse_address=True, # allow the reuse of an address
)
elif args.comm == "serial":
server = await StartAsyncSerialServer(
context=args.context, # Data storage
identity=args.identity, # server identify
port=args.port, # serial port
framer=args.framer, # The framer strategy to use
baudrate=args.baudrate, # The baud rate to use for the serial device
)
return server
if __name__ == "__main__":
run_args = setup_server(description="Run asynchronous server.")
asyncio.run(run_async_server(run_args), debug=True) test.py: import time
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("127.0.0.1",5020)
battery_address = 2
# addres, value count
registers= [(0, 1),
(1, 1),
(2, 16),
(18, 11),
(29, 2),
(31, 4),
(33, 2),
(61, 11),
(80, 4),
(90, 11),
(104, 24),
(117, 6)]
for register in registers:
print('Reading holding register Offset {:d}, {:d} value(s)'.format(register[0], register[1]))
for i in range(0, register[1]):
time.sleep(0.1)
request = client.read_holding_registers(register[0]+i,1,battery_address)
if request.function_code < 0x80:
print('register {:d} : {:d}'.format(register[0]+i,request.registers[0]))
else:
print('register {:d} error:'.format(register[0]+i))
print(request) thanks for the patience! |
Versions
Pymodbus Specific
Description
Simulating devices with sparse DataBlock using offsets > 100 is reporting Illegal Address.
Code and Logs
Config of server:
My code after requesting some holding registers, all offset < 100 works fine:
Server response:
Anyone have an idea how to deal with?
The text was updated successfully, but these errors were encountered: