Skip to content
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

WiNet-S dongle 'unable to decode request' #8

Closed
bohdan-s opened this issue Nov 3, 2021 · 23 comments
Closed

WiNet-S dongle 'unable to decode request' #8

bohdan-s opened this issue Nov 3, 2021 · 23 comments

Comments

@bohdan-s
Copy link

bohdan-s commented Nov 3, 2021

Hi,
I have a SunGrow SG7.0RT with a new WiNet-S dongle. I have been unable to connect using any of the scripts. It looks like they may be using a new encryption key?

EDIT: Full log using "SungrowModbusTcpClient"

bohdans@Bohdans-MBP solariot % ./solariot.py -vv
INFO:root:Loaded config sungrow-sg7rt
INFO:root:Creating SungrowModbusTcpClient
INFO:root:Connecting
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55739)
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55740)
INFO:root:Connected
INFO:root:No MQTT configuration detected
INFO:root:No InfluxDB configuration detected
INFO:root:No PVOutput configuration detected
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55741)
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55742)
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55743)
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55744)
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55745)
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55746)
DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x4 0x13 0x88 0x0 0x64
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x0 0x1 0x0 0x0 0x0 0x2 0x1 0x84 0x2
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x2 0x1 0x84 0x2
DEBUG:pymodbus.factory:Factory Response[132]
ERROR:pymodbus.factory:index out of range
ERROR:pymodbus.transaction:Modbus Error: [Input/Output] Unable to decode request
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/transaction.py", line 208, in execute
self.client.framer.processIncomingPacket(response,
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 153, in processIncomingPacket
self._process(callback)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 175, in _process
raise ModbusIOException("Unable to decode request")
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request
WARNING:root:Modbus connection failed
WARNING:root:Failed to scrape inverter, sleeping until next scan

@rpvelloso
Copy link
Owner

did you try using unencrypted connection?

@bohdan-s
Copy link
Author

bohdan-s commented Nov 3, 2021

Yes, I have tried both solariot and ModbusTCP2MQTT. Both with the standard and the sungrow-modbus library options.
I get the same message of "index out of range"

Below log is using "ModbusTcpClient"

bohdans@Bohdans-MBP solariot % ./solariot.py -vv
INFO:root:Loaded config sungrow-sg7rt
INFO:root:Creating ModbusTcpClient
INFO:root:Connecting
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55734)
INFO:root:Connected
INFO:root:No MQTT configuration detected
INFO:root:No InfluxDB configuration detected
INFO:root:No PVOutput configuration detected
DEBUG:pymodbus.client.sync:Connection to Modbus server established. Socket ('192.168.1.148', 55735)
DEBUG:pymodbus.transaction:Current transaction state - IDLE
DEBUG:pymodbus.transaction:Running transaction 1
DEBUG:pymodbus.transaction:SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x4 0x13 0x88 0x0 0x64
DEBUG:pymodbus.client.sync:New Transaction state 'SENDING'
DEBUG:pymodbus.transaction:Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG:pymodbus.transaction:Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG:pymodbus.transaction:RECV: 0x0 0x1 0x0 0x0 0x0 0x2 0x1 0x84 0x2
DEBUG:pymodbus.framer.socket_framer:Processing: 0x0 0x1 0x0 0x0 0x0 0x2 0x1 0x84 0x2
DEBUG:pymodbus.factory:Factory Response[132]
ERROR:pymodbus.factory:index out of range
ERROR:pymodbus.transaction:Modbus Error: [Input/Output] Unable to decode request
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/transaction.py", line 208, in execute
self.client.framer.processIncomingPacket(response,
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 153, in processIncomingPacket
self._process(callback)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 175, in _process
raise ModbusIOException("Unable to decode request")
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request
WARNING:root:Modbus connection failed
WARNING:root:Failed to scrape inverter, sleeping until next scan

@rpvelloso
Copy link
Owner

@tjhowse do you have any idea what this might be? I've read somewhere that sungrow uses a 'custom modbus' with peculiarities. Maybe that's it. Those packets don't seem to be encrypted.

@bohdan-s
Copy link
Author

bohdan-s commented Nov 4, 2021

Thank you, it didn't look encrypted. Maybe they dropped it in the new dongles.
Interesting that Solariot/Modbus4MQTT both can't read the output with either modbus library

@rpvelloso
Copy link
Owner

I think you will need to debug pymodbus with your inverter and code a custom client for it.

@tjhowse
Copy link
Contributor

tjhowse commented Nov 4, 2021

I'd suggest running a wireshark/tshark capture of the traffic to/from the inverter and posting the capture file here. It looks as though the inverter is responding with a malformed, but unencrypted, response. I hope this doesn't mean Sungrow have released a new variant of their interface >.<

@bohdan-s
Copy link
Author

bohdan-s commented Nov 4, 2021

Thanks, i'll run a wireshark dump and post it here shortly.

I'll post the Modbus4MQTT log below as well for completeness.

2021-11-04 14:51:17 INFO Starting modbus4mqtt v0.5.0
2021-11-04 14:51:17 INFO Connected to MQTT.
2021-11-04 14:51:17 ERROR index out of range
2021-11-04 14:51:17 ERROR Modbus Error: [Input/Output] Unable to decode request
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/transaction.py", line 208, in execute
self.client.framer.processIncomingPacket(response,
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 153, in processIncomingPacket
self._process(callback)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 175, in _process
raise ModbusIOException("Unable to decode request")
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request
2021-11-04 14:51:17 ERROR Failed to read 1 input table registers starting from 5001: Modbus Error: [Input/Output] Unable to decode request
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 142, in _scan_value_range
return result.registers
AttributeError: 'ModbusIOException' object has no attribute 'registers'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 71, in poll
values = self._scan_value_range(table, group, self._scan_batching)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 145, in _scan_value_range
raise ValueError("Failed to read {} {} table registers starting from {}: {}".format(count, table, start, result))

@bohdan-s
Copy link
Author

bohdan-s commented Nov 4, 2021

WiNet-S Captured.pcapng.zip
Hi, please find attached wireshark capture. I am not sure what it "should" look like to make sense. I can see some malformed packet messages though.

@bohdan-s
Copy link
Author

@tjhowse I can see you have been active in this area (and whirlpool).
Is there anywhere you can recommend I start to look into this?
Sungrow have support have said I am on the latest Firmware for the inverter and wifi dongle.
I have tried moving to Ethernet instead of Wifi but get the same response.

I downloaded ComTest Pro and had a bit of a play around using the Modbus map Sungrow supplied.

What I have found out is I can read the holding registers (4x) without issue:
15:16:23.156: -> [00h] [00h] [00h] [00h] [00h] [06h] [01h] [03h] [13h] [87h] [00h] [05h]
15:16:23.371: <- [00h] [00h] [00h] [00h] [00h] [0Dh] [01h] [03h] [0Ah] [07h] [E5h] [00h] [0Bh] [00h] [0Ch] [00h]
So thats 5000 -> 5005 (holding registers 4x) which gives me 2021 11 12 15 16 = 2021/11/12 03:16PM. Which is the system clock.

So this seems to be an issue only with the read-only registers (3x type). I will keep playing around and see what I can find.

@bohdan-s
Copy link
Author

Ok, lots of learning about modbus,
This helps: https://www.simplymodbus.ca/exceptions.htm

Sungrow communication protocol PDF says "Address of 3x is read-only register, supporting the CMD code inquiry of 0x04"
So to read the device type code, for example, I would send function 4, 4999 (address 5000 - 1).
[00h] [00h] [00h] [00h] [00h] [06h] [01h] [04h] [13h] [8Bh] [00h] [01h]
This then returns:
[00h] [00h] [00h] [00h] [00h] [02h] [01h] [84h] [02h]
with x04 being return with highest bit (8) as x84 signifying an error and the error code following of x02.
Looking at above link that means "Illegal Data Address"

So long story short, it seems with the WiNet-S dongles you can no longer access the read-only register of modbus. :(

@bohdan-s
Copy link
Author

Last thought, could there be some sort of "auth" packet or key transfer that has to take place first before it will respond to the 3x (0x04) read-only enquiries?

@tjhowse
Copy link
Contributor

tjhowse commented Nov 12, 2021

That is some excellent investigation. I think it would be worthwhile poking at the other tables on the device (holding, coils and input) and see if any of them are readable. In the wireshark log you provided it looks like the dongle responds with a completely malformed message, rather than a modbus-compliant rejection.
Are you able to log into the dongle's web page with "admin" and "pw8888" and have a poke around to see if there is any configuration relevant to the modbus interface?
Could you try downgrading the firmware in the iSolarHome app or via the web interface?

@bohdan-s
Copy link
Author

bohdan-s commented Nov 13, 2021

@tjhowse any hints on how to downgrade the firmware?
yup already looked at the interface, there are 3 modbus "ports" and when I connect to test i see connection listed.
I have looked at 3x (read-only) 4x (holding) and 4x holding is the only one i got working. What are the other 2? I don't want to write anything by mistake :/ There is a note in the PDF about 0x10 and 0x06 for write-in?
I have attached the reference PDF I have been using that was supplied by SunGrow.
TI_20210716_Communication Protocol of PV Grid-Connected String Inverters_V1.1.37_EN.pdf

Address type Address of 3x type is read-only register, supporting the CMD code inquiry of 0x04. Address of 4x type is holding register, supporting the CMD code inquiry of 0x03, and CMD codes write-in of 0x10 and 0x06. CMD codes 0x10 and 0x06 support the broadcast address. Support Modbus error code 02 (address error), 04 (setting failure). Visit all registers by subtracting 1 from the register address. Example: if the address is 5000 –5001, visit it using address 4999 –5000. Entering “01 04 1387 00 02 + CRC” to check the data of address 5000 –5001.

@bohdan-s
Copy link
Author

bohdan-s commented Nov 15, 2021

If I log into the dongles web interface, Select Device Monitoring > General Parameters > Read-Back of Address type 3x I can read the values.
So the dongle is reading the values, but I am unable to read those values over the Modbus TCP interface presented by the dongle.
:(

@tjhowse
Copy link
Contributor

tjhowse commented Nov 15, 2021 via email

@bohdan-s
Copy link
Author

Let me have a look at the web interface a little more.
Do you know where I can download firmware from? I can see the option in the app for the latest firmware, but can not find an FTP or Webserver I could download from to force a downgrade.

@bohdan-s
Copy link
Author

bohdan-s commented Nov 15, 2021

Nothing interesting in the requests,
Unless I was to go down the route of trying to build a script to query HTTP instead of modbus.

http://192.168.1.45/device/getParam?dev_id=1&dev_type=21&dev_code=9276&type=3&param_addr=5000&param_num=1&param_type=1&token=xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&lang=en_us&time123456=1636938350393

Edit: interestingly the token is the same from any browser or PC and works without logon to the web interface first.
I am starting to think the Modbus TCP issue might actually be a bug in the firmware, so not much i can do :(

@tjhowse
Copy link
Contributor

tjhowse commented Nov 15, 2021

The iSolarCloud app used to have a "Firmware Download" section on the "..." menu:
image

However it looks like that has been removed in newer versions. Tonight I will see if I can dig up the URL it was querying to provide the download list. It may have been locked down. :(

@bohdan-s
Copy link
Author

Yes, I have the option (its in a slightly different location now).
It gives you a list of models and then presents the latest firmware. Doesn't seem to be able to get older versions.
Might so some MITM of the app and see if I can find the download location.

@bohdan-s
Copy link
Author

Ok, So I have learnt a lot about Modbus that I didn't know a few days ago.

First, I tried sending the "Public key" request as per https://whrl.pl/Rf8BQT
Screenshot 2021-11-16 100844
As you can see, it throws the same error. So its not a key change issue.

I have scanned (to the best of my skills) as much of ModBus as I can, and everything returns the error except the holding registers. So it looks like the Modbus protocol has been crippled on the WiNet-S dongle.

Now, off the modbus part, I have spent some time pulling apart the app.
All messages to iSolarCloud and the App in Local mode is via MQTT that seems to be using encrypted messages.

I have tried some MITM and some reverse engineering of the app, but I have been unable to locate a way to list or download previous firmwares.

@tjhowse if you can dig up the URL for firmwares, downgrading is the only real option left at the moment. Otherwise looks like unless Sungrow push a firmware with it enabled again WiNet-S dongle users are out of luck :(

@tjhowse
Copy link
Contributor

tjhowse commented Nov 23, 2021

I got a response back from my solar system installer - I asked for a quote on a WiNet-S dongle so I could experiment on it. Apparently it's incompatible with my SH5k-20 and they don't want to sell me one, :(

@bohdan-s
Copy link
Author

I am going to close this issue, as it seems the WiNet-S dongle has a broken Modbus TCP implementation.
For anyone who finds this in the future, I have written a HORRIBLE Modbus over HTTP module here: https://github.com/bohdan-s/SungrowModbusWebClient

@nutterthanos
Copy link

@tjhowse if you can dig up the URL for firmwares, downgrading is the only real option left at the moment. Otherwise looks like unless Sungrow push a firmware with it enabled again WiNet-S dongle users are out of luck :(

the list of firmware comes through https://augateway.isolarcloud.com/v1/devService/getDeviceTypeAndModelInfoByPage
unfortunately it gets the url of the firmware files through this request https://augateway.isolarcloud.com/v1/devService/getOnlineUpgradeFileList
and there is no way to ask it to get older version
and its all encoded/encrypted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants