pymodbus icon indicating copy to clipboard operation
pymodbus copied to clipboard

Fix async unit

Open mdavidsaver opened this issue 2 years ago • 3 comments

An attempt to fix #624, at least for asyncio. I'm not certain how unit ID should be handled here. Can a client have requests to multiple unit IDs in-flight? I've tried to account for this possibility by storing all unit IDs requested since the last (re)connect. If this isn't necessary, a simpler solution would be to only remember the most recently sent unit ID.

If this is seen as a reasonable approach, I will expand to the other async backends (although I'm only using/testing with asyncio).

mdavidsaver avatar Sep 05 '21 18:09 mdavidsaver

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

sonarcloud[bot] avatar Sep 05 '21 22:09 sonarcloud[bot]

@mdavidsaver thanks for the PR and apologies for the delay. I am going to keep this in review for some more time. I do not have a strong opinion for storing the unit id's . This is something that a modbus application should handle which uses pymodbus as a driver and not pymodbus itself. Please correct me if I am not understanding this PR properly.

dhoomakethu avatar Oct 17 '21 05:10 dhoomakethu

I think there are a bigger misunderstanding here (Or it is in my head). UnitId in tcp is the same as slaveid in serial, so why do we want to keep track of that ???

I believe #624 is true but a whole different problem.

janiversen avatar Jul 26 '22 21:07 janiversen

According to the modbus protocol there can only be one request "in flight" at one connection. Please unitId addresses the slave (device) on the open connection, so we have to wait until a response is received before continuing.

We should try with a simpler solution. I can see that unitId is missing is some calls (at least in the documentation).

janiversen avatar Aug 16 '22 15:08 janiversen

According to the modbus protocol there can only be one request "in flight" at one connection

Is this still valid for Modbus TCP? That protocol specification equips the server to have multiple active transactions, and specifies "Several MODBUS transactions can be activated simultaneously on the same TCP Connection." It also includes the "Transaction Identifier" field in the MBAP header which would seem to facilitate this.

P.S. Great to see all the work you're doing lately 👍 .

tracernz avatar Aug 26 '22 11:08 tracernz

The server must be able to handle multiple transactions because it can have multiple clients connected, that is true for a number of the transport protocols. The server do not need to store the transactions since it is part of the request, which are used to form the response.

A client however connect to 1 server with a socket (tcp etc.) or a physical line, and can therefore only have one transaction outstanding. A client can support multiple devices using multiple sockets or multiple serial lines, but in that case each connection can use the same transaction. In our case 1 instance of modbusClient can only handle 1 connection so no need to store transactions.

janiversen avatar Aug 26 '22 11:08 janiversen

thanks for the nice words.

janiversen avatar Aug 26 '22 11:08 janiversen

These are the key passages from the "MODBUS Messaging on TCP/IP Implementation Guide V1.0b" I refer to: image image image

A limit of 1 is no problem; the spec allows this, so I guess it's fine 😀 . In any case, I think this is a much bigger topic than the original issue referenced here, and the more I read the spec the more vague the descriptions appear 😆 .

tracernz avatar Aug 26 '22 11:08 tracernz

Your reference is correct, but you are referencing a gateway which is more correctly named a forwarder, this is a different topic, because that can e.g. have 1 server (tcp) and multiple clients (serial).

I have yet to see a end-device that allows multiple requests, nor do I understand the need for that....think about it send the following:

read_register()
write_register()

the device (server) might decide to do the write first...because there are no demand that transactions ids are handled in ascending sequence.

But for a forwarder the following example makes a lot of sense:

read_register(slave=1)
write_register(slave=2)
read_register(slave=3)

and the forwarder must be able to handle that.

We have hard coded limit=1, and no intention of changing that for the above reasons.

The description is not vague, you just need to see it together with the different device types.

janiversen avatar Aug 26 '22 11:08 janiversen