Skip to content

Commit

Permalink
Move async_timeout.timeout() to also cover the TCP codepath
Browse files Browse the repository at this point in the history
There have recently been [reports of `RuntimeError: coroutine ignored
GeneratorExit`] which are presumably triggered by timeouts on the
socket, without being raised as `TimeoutError`.  This case seems to be
mitigated by timing out the request after a default of 10 seconds which
doesn't give `GeneratorExit` - triggered by something yet unknown -
enough time to surface.

[reports of `RuntimeError: coroutine ignored GeneratorExit`]: robbinjanssen/home-assistant-omnik-inverter#116
  • Loading branch information
MarijnS95 committed Feb 18, 2023
1 parent 1877947 commit e845076
Showing 1 changed file with 52 additions and 37 deletions.
89 changes: 52 additions & 37 deletions omnikinverter/omnikinverter.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,14 @@ async def request(
auth = aiohttp.BasicAuth(self.username, self.password)

try:
async with async_timeout.timeout(self.request_timeout):
response = await self.session.request(
method,
url,
auth=auth,
params=params,
headers=headers,
)
response.raise_for_status()
except asyncio.TimeoutError as exception:
raise OmnikInverterConnectionError(
"Timeout occurred while connecting to Omnik Inverter device"
) from exception
response = await self.session.request(
method,
url,
auth=auth,
params=params,
headers=headers,
)
response.raise_for_status()
except (ClientError, ClientResponseError) as exception:
raise OmnikInverterConnectionError(
"Error occurred while communicating with Omnik Inverter device"
Expand Down Expand Up @@ -185,20 +180,30 @@ async def inverter(self) -> Inverter:
A Inverter data object from the Omnik Inverter.
Raises:
OmnikInverterConnectionError: An error occurred while communicating
with the Omnik Inverter.
OmnikInverterError: Unknown source type.
"""
if self.source_type == "json":
data = await self.request("status.json", params={"CMD": "inv_query"})
return Inverter.from_json(json.loads(data))
if self.source_type == "html":
data = await self.request("status.html")
return Inverter.from_html(data)
if self.source_type == "javascript":
data = await self.request("js/status.js")
return Inverter.from_js(data)
if self.source_type == "tcp":
fields = await self.tcp_request()
return Inverter.from_tcp(fields)
try:
async with async_timeout.timeout(self.request_timeout):
if self.source_type == "json":
data = await self.request(
"status.json", params={"CMD": "inv_query"}
)
return Inverter.from_json(json.loads(data))
if self.source_type == "html":
data = await self.request("status.html")
return Inverter.from_html(data)
if self.source_type == "javascript":
data = await self.request("js/status.js")
return Inverter.from_js(data)
if self.source_type == "tcp":
fields = await self.tcp_request()
return Inverter.from_tcp(fields)
except asyncio.TimeoutError as exception:
raise OmnikInverterConnectionError(
"Timeout occurred while connecting to Omnik Inverter device"
) from exception

raise OmnikInverterError(f"Unknown source type `{self.source_type}`")

Expand All @@ -209,20 +214,30 @@ async def device(self) -> Device:
A Device data object from the Omnik Inverter. None on the "tcp" source_type.
Raises:
OmnikInverterConnectionError: An error occurred while communicating
with the Omnik Inverter.
OmnikInverterError: Unknown source type.
"""
if self.source_type == "json":
data = await self.request("status.json", params={"CMD": "inv_query"})
return Device.from_json(json.loads(data))
if self.source_type == "html":
data = await self.request("status.html")
return Device.from_html(data)
if self.source_type == "javascript":
data = await self.request("js/status.js")
return Device.from_js(data)
if self.source_type == "tcp":
# None of the fields are available through a TCP data dump.
return Device()
try:
async with async_timeout.timeout(self.request_timeout):
if self.source_type == "json":
data = await self.request(
"status.json", params={"CMD": "inv_query"}
)
return Device.from_json(json.loads(data))
if self.source_type == "html":
data = await self.request("status.html")
return Device.from_html(data)
if self.source_type == "javascript":
data = await self.request("js/status.js")
return Device.from_js(data)
if self.source_type == "tcp":
# None of the fields are available through a TCP data dump.
return Device()
except asyncio.TimeoutError as exception:
raise OmnikInverterConnectionError(
"Timeout occurred while connecting to Omnik Inverter device"
) from exception

raise OmnikInverterError(f"Unknown source type `{self.source_type}`")

Expand Down

0 comments on commit e845076

Please sign in to comment.