Handle failed connection attempts in opentherm_gw (#75961)

This commit is contained in:
mvn23 2022-07-31 12:21:25 +02:00 committed by GitHub
parent 377f56ff5f
commit abb7495ced
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 8 deletions

View file

@ -1,9 +1,11 @@
"""Support for OpenTherm Gateway devices."""
import asyncio
from datetime import date, datetime
import logging
import pyotgw
import pyotgw.vars as gw_vars
from serial import SerialException
import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
@ -23,6 +25,7 @@ from homeassistant.const import (
Platform,
)
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.typing import ConfigType
@ -37,6 +40,7 @@ from .const import (
CONF_PRECISION,
CONF_READ_PRECISION,
CONF_SET_PRECISION,
CONNECTION_TIMEOUT,
DATA_GATEWAYS,
DATA_OPENTHERM_GW,
DOMAIN,
@ -107,8 +111,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
config_entry.add_update_listener(options_updated)
# Schedule directly on the loop to avoid blocking HA startup.
hass.loop.create_task(gateway.connect_and_subscribe())
try:
await asyncio.wait_for(
gateway.connect_and_subscribe(),
timeout=CONNECTION_TIMEOUT,
)
except (asyncio.TimeoutError, ConnectionError, SerialException) as ex:
raise ConfigEntryNotReady(
f"Could not connect to gateway at {gateway.device_path}: {ex}"
) from ex
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
@ -428,6 +439,9 @@ class OpenThermGatewayDevice:
async def connect_and_subscribe(self):
"""Connect to serial device and subscribe report handler."""
self.status = await self.gateway.connect(self.device_path)
if not self.status:
await self.cleanup()
raise ConnectionError
version_string = self.status[gw_vars.OTGW].get(gw_vars.OTGW_ABOUT)
self.gw_version = version_string[18:] if version_string else None
_LOGGER.debug(

View file

@ -26,6 +26,7 @@ from .const import (
CONF_READ_PRECISION,
CONF_SET_PRECISION,
CONF_TEMPORARY_OVRD_MODE,
CONNECTION_TIMEOUT,
)
@ -62,15 +63,21 @@ class OpenThermGwConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
otgw = pyotgw.OpenThermGateway()
status = await otgw.connect(device)
await otgw.disconnect()
if not status:
raise ConnectionError
return status[gw_vars.OTGW].get(gw_vars.OTGW_ABOUT)
try:
res = await asyncio.wait_for(test_connection(), timeout=10)
except (asyncio.TimeoutError, SerialException):
await asyncio.wait_for(
test_connection(),
timeout=CONNECTION_TIMEOUT,
)
except asyncio.TimeoutError:
return self._show_form({"base": "timeout_connect"})
except (ConnectionError, SerialException):
return self._show_form({"base": "cannot_connect"})
if res:
return self._create_entry(gw_id, name, device)
return self._create_entry(gw_id, name, device)
return self._show_form()

View file

@ -25,6 +25,8 @@ CONF_READ_PRECISION = "read_precision"
CONF_SET_PRECISION = "set_precision"
CONF_TEMPORARY_OVRD_MODE = "temporary_override_mode"
CONNECTION_TIMEOUT = 10
DATA_GATEWAYS = "gateways"
DATA_OPENTHERM_GW = "opentherm_gw"

View file

@ -12,7 +12,8 @@
"error": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"id_exists": "Gateway id already exists",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"timeout_connect": "[%key:common::config_flow::error::timeout_connect%]"
}
},
"options": {

View file

@ -164,7 +164,7 @@ async def test_form_connection_timeout(hass):
)
assert result2["type"] == "form"
assert result2["errors"] == {"base": "cannot_connect"}
assert result2["errors"] == {"base": "timeout_connect"}
assert len(mock_connect.mock_calls) == 1