wasilukm / hoymiles_modbus

MIT License
13 stars 5 forks source link

IndexError: list assignment index out of range #4

Open IDeserveToBeWrited opened 2 years ago

IDeserveToBeWrited commented 2 years ago

Description

I'm using the library in a script I've written to put the data to influxdb for Grafana. In the script I'm getting the data from DTU (pro), sending data to influx, waiting 15 seconds and looping indefinitely.

Script was working for 25 minutes, stopped working for 17 minutes, worked for 8 and stopped working for 45 minutes now, as seen at this graph.

firefox_2022-04-22_20-09-24

Through the first gap you can see there was electricity generated so the microinverters didn't go to sleep (as fronius inverters do when there's no electricity generated for a while)

What I Did

I'm calling the library in the script

plant_data = HoymilesModbusTCP('IP').plant_data

and getting

Traceback (most recent call last):
  File "hoymiles.py", line 80, in <module>
    plant_data = HoymilesModbusTCP('IP').plant_data
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 108, in plant_data
    microinverter_data = self.microinverter_data
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 85, in microinverter_data
    result = self._read_registers(client, start_address, 20)
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 69, in _read_registers
    result = client.read_holding_registers(start_address, count, unit=1)
  File "/home/pi/.local/lib/python3.7/site-packages/pymodbus/client/common.py", line 114, in read_holding_registers
    return self.execute(request)
  File "/home/pi/.local/lib/python3.7/site-packages/pymodbus/client/sync.py", line 109, in execute
    return self.transaction.execute(request)
  File "/home/pi/.local/lib/python3.7/site-packages/pymodbus/transaction.py", line 210, in execute
    request.unit_id)
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 27, in processIncomingPacket
    fixed_data = self._data_length_fixer(data)
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 23, in _data_length_fixer
    fixed_packet[8] = len(fixed_packet[9:])
IndexError: list assignment index out of range

I tried my script on Windows 10 machine with python 3.10 and getting the same results, even when calling just the HoymilesModbusTCP('IP').plant_data method from python command line. Calling without .plant_data gets

>>> plant_data = HoymilesModbusTCP('IP')
>>> print(plant_data)
<hoymiles_modbus.client.HoymilesModbusTCP object at 0x75f09810>
>>>

Now the sun definitely shut down production and if the microinverters stop communicating after that, they definitely did. I just don't understand the gap. Forecast says it'll cloudy tomorrow, but if anything changes with the sun, I'll update.

EDIT1: It's still mostly intermitten for some reason. firefox_2022-04-23_14-12-10 Hoymiles website looks ok.

firefox_2022-04-23_14-14-16

EDIT2: Just saw you committed a fix, I upgraded the package and restarted the script, will update the effect soon. And I'd like to thank you for this project and a very fast reaction to my issue. Thank you.

IDeserveToBeWrited commented 2 years ago

With the 0.2.1 version it worked for ~hour and started crashing with

Traceback (most recent call last):
  File "/home/pi/skrypty/hoymiles.py", line 80, in <module>
    plant_data = HoymilesModbusTCP('IP').plant_data
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 109, in plant_data
    microinverter_data = self.microinverter_data
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 86, in microinverter_data
    result = self._read_registers(client, start_address, 20)
  File "/home/pi/.local/lib/python3.7/site-packages/hoymiles_modbus/client.py", line 72, in _read_registers
    raise result
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
wasilukm commented 2 years ago

@IDeserveToBeWrited thank you for submitting the issue. You forced me to finally fix this IndexError. However please note that the fix meant only to make sure that proper exception will be raised to tell the end user what is really wrong. In your case it seems to be working, you have got ModbusIOException, which says that a response from a target device (DTU) could not be received. This suggest that there is something wrong with a communication to DTU, which unlikely is hoymiles_modbus library issue.

From my observations HM DUTs are not the most stable devices. In the past I observed similar issues as yours, including necessity of restarting (power cycle) of the whole DTU. Currently, my application is working more or less stable. There are still some communication issues but very sporadic - something about two issues (no responses) per week. I don't know what really helped but here is what I have done:

You may also consider adding logging to your script, this will maybe tell more about your issue: https://pymodbus.readthedocs.io/en/latest/source/example/modbus_logging.html

IDeserveToBeWrited commented 2 years ago
  • made sure that DTU has IP address reservation on a router

  • made sure that DTU power supply is tightly inserted to the power outlet and is not a subject of random poking

  • no WiFi on a route to DTU

  • increased query time to 60 sec

All those points are met basically from the start. Connection between the Pi and DTU is 100% wired, DTU has it's adress in the DHCP server, only the query time at first was 15 seconds, but after writing this issue I raised it to 60 and it did not help in any noticable manner.

I'm at a very beginner level of python at best, but I'll try the modbus logging to see what's going on.

IDeserveToBeWrited commented 2 years ago

Tried logging with this script

import logging
import logging.handlers as Handlers
from hoymiles_modbus.client import HoymilesModbusTCP
import time
from datetime import datetime
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
START = datetime.now()
print("start", START.strftime("%H:%M:%S"))

while True:
    now = datetime.now()
    END = now - START
    END = str(END).split(".")[0]
    current_time = now.strftime("%H:%M:%S")
    print("jest godzina", current_time, "Dzialam juz", END)
    print("request")
    plant_data = HoymilesModbusTCP('192.168.13.245')
    print("request done")
    print(".plant_data request")
    print(plant_data.plant_data)
    print(".plant_data request done, sleeping 60")
    time.sleep(60)

and got this log hoytest.log

Looks to me like DTU issue, as the mid-exchange the data received just stops (0 received) . That's a bummer, but thank you for your help.

wasilukm commented 2 years ago

Thanks for the information. What are you going to do now? Do you consider contacting Hoymiles support?

IDeserveToBeWrited commented 2 years ago

I very much doubt they would do anything as the hoymiles cloud works just fine and I think they rather did not intend for anyone to get the data either from the could or straight from the DTU as I did not find any publicly available API for the web or the DTU. Apart from this I found only one other project and it was using selenium to scrape the data from the webpage. I made a new cable, straight from the DTU to the switch that the Pi is plugged in to. I doubt that was the case, but at least it will confirm if the DTU is just shit.