squishykid / solax

🌞 Solax Inverter API Wrapper
MIT License
97 stars 57 forks source link

X1-Boost-Air-Mini work around for aiohttp's bad header/(due to fake password prompt?) #48

Open Johnreidsilver opened 2 years ago

Johnreidsilver commented 2 years ago

aiohttp seems to be very peculiar regarding illegal headers, while curl and requests work fine it throws an error with X1-Boost-Air-Mini. Perhaps due to the fake password prompt that we can see in a browser at the local API URL: http://5.8.8.8/?optType=ReadRealTimeData

Running:

async def work():
    r = solax.inverter.X1Mini('5.8.8.8',80)
    return (await r.get_data())

loop = asyncio.new_event_loop()
#loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
data = loop.run_until_complete(work())

returns: aiohttp.client_exceptions.ClientResponseError: 400, message='invalid character in header'

but launching python3 with: AIOHTTP_NO_EXTENSIONS=1 python3

returns fine InverterResponse(data={'PV1 Current': 0.4, 'PV2 Current': 0.0, 'PV1 Voltage': 140.5, 'PV2 Voltage': 0.0, 'Output Current': 0.5, 'Network Voltage': 245.4, 'AC Power': 77.0, 'Inverter Temperature': 31.0, "Today's Energy": 4.3, 'Total Energy': 7265.7, 'Exported Power': 0.0, 'PV1 Power': 87.0, 'PV2 Power': 0.0, 'Total Feed-in Energy': 0.0, 'Total Consumption': 0.0, 'Power Now': 0.0, 'Grid Frequency': 50.03}, serial_number='redacted', version='2.31.3', type='X1-Boost-Air-Mini')

Likewise launching HomeAssistant with this variable also makes the data fetch work AIOHTTP_NO_EXTENSIONS=1 hass

perhaps this should be the default behavior set within the program (is there any gain to having aiohttp pickiness enabled?)

import os
os.environ["AIOHTTP_NO_EXTENSIONS"] = "1"

added these lines to the hass launcher and it's working fine now just by calling hass from the prompt /srv/homeassistant/bin/hass

squishykid commented 2 years ago

Hi @Johnreidsilver, is there a chance you could please share a packet capture, one with AIOHTTP_NO_EXTENSIONS set, and another with AIOHTTP_NO_EXTENSIONS unset? The packet capture should show the TCP conversation between your computer and the inverter. This will let us see what is going over the wire.

If you need some help with producing the packet capture, you could use tools such as Wireshark. Let me know if you need more help and I can get you sorted :)

Johnreidsilver commented 2 years ago

Thanks for looking into this. Attached packets made with tcpdump sudo tcpdump -i w0 -w TCPDUMP.txt

Python 3.6.9 pip3 freeze aiohttp==3.7.4.post0 solax==0.2.8

looking at the packets the data is in both with and without extensions disabled, but aiohttp seems to get halted with the error when extensions aren't disabled TCPDUMP.txt DUMPwithAIOHTTP_NO_EXTENSIONS.txt

on another newer system I have solax 0.2.10 python 3.8.10 aiohttp 3.7.4.post0 and it fails even after setting AIOHTTP_NO_EXTENSIONS=1

async def work():
    r = solax.inverters.X1Mini('192.168.0.103',80)
    return (await r.get_data())

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
data = loop.run_until_complete(work())
aiohttp.client_exceptions.ClientPayloadError: Response payload is not completed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "<stdin>", line 3, in work
  File "/home/username/.local/lib/python3.8/site-packages/solax/inverter.py", line 38, in get_data
    raise InverterError(msg, str(self.__class__.__name__)) from ex
solax.inverter.InverterError: ('Could not connect to inverter endpoint', 'X1Mini')

DUMP-solax0.2.10.txt

Curl works fine in both systems curl -X POST --header 'X-Forwarded-For:5.8.8.8' http://192.168.0.103/?optType=ReadRealTimeData

{"type":"X1-Boost-Air-Mini","SN":"SWXXXXXXX","ver":"2.31.3","Data":[8.5,0.0,138.8,0.0,4.7,238.9,1133,41,2.8,8371.6,0,1184,0,0.00,0.00,0,0,0,0.0,0.0,0.00,0.00,0,0,0,0.0,0.0,0.00,0.00,0,0,0,0.0,0.0,0,0,0,0,0,0,0,0.00,0.00,0,0,0,0,0,0,0,49.99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2],"Information":[1.500,4,"X1-Boost-Air-Mini","XM****",1,3.20,1.07,1.09,0.00]}

VadimKraus commented 2 years ago

Did you try using the discovery method, cause it looks like you are using the wrong inverter to connect, in the 0.2.10 example

Johnreidsilver commented 2 years ago

No, my commands were exactly as above. Will test with solax.inverters.x1_boost when possible https://github.com/squishykid/solax/blob/master/solax/inverters/x1_boost.py