favalex / modbus-cli

Command line tool to access Modbus devices
Mozilla Public License 2.0
158 stars 30 forks source link

Issue of GW or modbus-cli? #25

Open StefanR71 opened 4 months ago

StefanR71 commented 4 months ago

Hello,

i'm successfully querying my daikin heatpumps HomeHub modbus TCP interface:

root@srv44:/haus/strom# modbus -s 1 -r /haus/heizung/register 192.168.77.82:502 reg* -v Parsed 20 registers definitions from 2 files → < 15 5c 00 00 00 06 01 03 00 00 00 04 > → < e4 26 00 00 00 06 01 03 00 09 00 01 > → < a5 63 00 00 00 06 01 03 00 0b 00 01 > → < 07 f2 00 00 00 06 01 04 00 1d 00 02 > → < d4 3c 00 00 00 06 01 04 00 22 00 01 > → < c3 78 00 00 00 06 01 04 00 24 00 02 > → < d0 34 00 00 00 06 01 04 00 27 00 06 > → < 6f bf 00 00 00 06 01 04 00 30 00 01 > → < e4 f8 00 00 00 06 01 04 00 33 00 02 > ← < 15 5c 00 00 00 0b 01 03 08 00 2a 00 12 00 01 00 01 > 17 bytes ← [42, 18, 1, 1] reg_soll_heizen: 42 0x2a reg_soll_kuehlen: 18 0x12 reg_hk_mode: 1 0x1 heizen. reg_hk_status: 1 0x1 ein ← < e4 26 00 00 00 05 01 03 02 00 32 > 11 bytes ← [50] reg_soll_warmwasser: 50 0x32 ← < a5 63 00 00 00 05 01 03 02 00 01 > 11 bytes ← [1] reg_ww_status: 1 0x1 ein ← < 07 f2 00 00 00 07 01 04 04 00 01 00 01 > 13 bytes ← [1, 1] reg_pumpe: 1 0x1 ein reg_verdichter: 1 0x1 ein ← < d4 3c 00 00 00 05 01 04 02 00 00 > 11 bytes ← [0] reg_abtauen: 0 0x0 aus ← < c3 78 00 00 00 07 01 04 04 00 01 00 01 > 13 bytes ← [1, 1] reg_dreiwege: 1 0x1 brauchwasser reg_hk_mode_ist: 1 0x1 heizen. ← < d0 34 00 00 00 0f 01 04 0c 12 3e 12 34 10 54 11 80 01 b8 0e d8 > 21 bytes ← [4670, 4660, 4180, 4480, 440, 3800] reg_vorlauf_phe: 4670 0x123e reg_vorlauf_buh: 4660 0x1234 reg_rucklauf: 4180 0x1054 reg_ist_warmwasser: 4480 0x1180 reg_aussentemperatur: 440 0x1b8 reg_kaeltemittel: 3800 0xed8 ← < 6f bf 00 00 00 05 01 04 02 0b 04 > 11 bytes ← [2820] reg_durchfluss: 2820 0xb04 ← < e4 f8 00 00 00 07 01 04 04 00 01 00 01 > 13 bytes ← [1, 1] reg_warmwasser: 1 0x1 betrieb. reg_raumheizung: 1 0x1 betrieb. root@srv44:/haus/strom#

This is working perfect, but i need to connect a modbus RTU device the the heatpump und the HomeHub can't use TCP and RTU at the same time. So i tryed to use a Modbus TCP/RTU gareway, but here i can't query all the values:

root@srv44:/haus/strom# modbus -s 1 -r /haus/heizung/register 192.168.77.86:502 reg* -v Parsed 20 registers definitions from 2 files → < a3 4e 00 00 00 06 01 03 00 00 00 04 > → < bc be 00 00 00 06 01 03 00 09 00 01 > → < a2 ca 00 00 00 06 01 03 00 0b 00 01 > → < 8f 3e 00 00 00 06 01 04 00 1d 00 02 > → < 3d 1a 00 00 00 06 01 04 00 22 00 01 > → < 9e 9e 00 00 00 06 01 04 00 24 00 02 > → < 10 08 00 00 00 06 01 04 00 27 00 06 > → < de e4 00 00 00 06 01 04 00 30 00 01 > → < b5 1f 00 00 00 06 01 04 00 33 00 02 > ← < a3 4e 00 00 00 0b 01 03 08 00 2a 00 12 00 01 00 01 > 17 bytes ← [42, 18, 1, 1] reg_soll_heizen: 42 0x2a reg_soll_kuehlen: 18 0x12 reg_hk_mode: 1 0x1 heizen. reg_hk_status: 1 0x1 ein Traceback (most recent call last): File "/usr/local/bin/modbus", line 110, in main() File "/usr/local/bin/modbus", line 103, in main connect_to_device(args).perform_accesses(parse_accesses(args.access, definitions, args.byte_order, args.silent), definitions).close() File "/usr/local/lib/python3.10/dist-packages/modbus_cli/modbus_tcp.py", line 63, in perform_accesses access.read_registers_receive(self) File "/usr/local/lib/python3.10/dist-packages/modbus_cli/access.py", line 146, in read_registers_receive words = modbus.receive(self.request) File "/usr/local/lib/python3.10/dist-packages/modbus_cli/modbus_tcp.py", line 29, in receive header = self.receive_n(6) File "/usr/local/lib/python3.10/dist-packages/modbus_cli/modbus_tcp.py", line 44, in receive_n data += self.connection.recv(n - len(data)) TimeoutError: timed out root@srv44:/haus/strom#

Looks like the gateway is sending only the first packet of the answers...

Have you seen such behavior in the past? Is this a issue of the gateway or in this software?

Kind regards Stefan

StefanR71 commented 4 months ago

Okay, i'm getting one step forward.

It seems that the Mobus TCP/RTU gateway don't like TCP payloads with more than one Modbus TCP packet inside.

Here from a Wireshark trace:

image

The first query has only one Modbus TCP inside:

image

And the second query has 2 Modbus TCP Packets inside:

image

From that i'm not getting an answer and i don't see it on the RTU side with a serial monitor. The gateway seems to drop that packet.

How does the modbus-cli decide if he is putting Modbus TCP parts in a single TCP or in multiple packets?

What i'm wondering about, the first TCP Packet contains every time a single Modbus TCP part and the second TCP Frame every time the rest. For my query of 20 registers, there where 4 registers in a first packet and then the rest of the 16 registers are in additional 8 Modbus TCP packets in a single TCP Payload

I think more than one Modbus TCP part in a single TCP payload is o.k. because my heatpump answers to it when i switch it to Modbus TCP and when using the same command. But is it possible to create some workaround, to put only one Modbus TCP frame in each TCP payload?

I'm also in touch with the support from the gateway vendor, i hope they will fix that...

favalex commented 4 months ago

Hi,

I don't have any way to check this right now, but I suspect the OS is the one deciding to split the TCP stream in that way. You can verify what is being sent at the application level by printing the request here https://github.com/favalex/modbus-cli/blob/c889b6d5f463d4f4de3cc4dfc43924f23076cf41/modbus_cli/modbus_tcp.py#L26

At the application level there is some logic to try to merge accesses to contiguous registers, you can try removing group_accesses and just return the accesses here https://github.com/favalex/modbus-cli/blob/c889b6d5f463d4f4de3cc4dfc43924f23076cf41/modbus_cli/access.py#L323

And there is one more layer involved, the library actually serializing the requests to bytes https://pypi.org/project/uModbus/ before they are sent over TCP. Maybe the splitting happens there.

StefanR71 commented 4 months ago

Thank you for the answer, i have tryed to change the line 323 to:

return accesses

and the result is, that the first TCP payload contains one register to query. And the second TCP payload contains 19 Modbus TCP Parts...

It seems that i must search one layer deeper who is creating the TCP payload.

StefanR71 commented 4 months ago

Okay, i use a different method to query all the values and control my heatpump.

I programed an ESP32 with Modbus RTU adapter and this works perfect for me.

And i got a info from the gateway vendor, he confirms my findings, but i think they are not changing their product...