mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Handle failed connection attempts in opentherm_gw (#75961)
This commit is contained in:
parent
377f56ff5f
commit
abb7495ced
@ -1,9 +1,11 @@
|
|||||||
"""Support for OpenTherm Gateway devices."""
|
"""Support for OpenTherm Gateway devices."""
|
||||||
|
import asyncio
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import pyotgw
|
import pyotgw
|
||||||
import pyotgw.vars as gw_vars
|
import pyotgw.vars as gw_vars
|
||||||
|
from serial import SerialException
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||||
@ -23,6 +25,7 @@ from homeassistant.const import (
|
|||||||
Platform,
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall
|
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 import config_validation as cv, device_registry as dr
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
@ -37,6 +40,7 @@ from .const import (
|
|||||||
CONF_PRECISION,
|
CONF_PRECISION,
|
||||||
CONF_READ_PRECISION,
|
CONF_READ_PRECISION,
|
||||||
CONF_SET_PRECISION,
|
CONF_SET_PRECISION,
|
||||||
|
CONNECTION_TIMEOUT,
|
||||||
DATA_GATEWAYS,
|
DATA_GATEWAYS,
|
||||||
DATA_OPENTHERM_GW,
|
DATA_OPENTHERM_GW,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -107,8 +111,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
|
|
||||||
config_entry.add_update_listener(options_updated)
|
config_entry.add_update_listener(options_updated)
|
||||||
|
|
||||||
# Schedule directly on the loop to avoid blocking HA startup.
|
try:
|
||||||
hass.loop.create_task(gateway.connect_and_subscribe())
|
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)
|
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||||
|
|
||||||
@ -428,6 +439,9 @@ class OpenThermGatewayDevice:
|
|||||||
async def connect_and_subscribe(self):
|
async def connect_and_subscribe(self):
|
||||||
"""Connect to serial device and subscribe report handler."""
|
"""Connect to serial device and subscribe report handler."""
|
||||||
self.status = await self.gateway.connect(self.device_path)
|
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)
|
version_string = self.status[gw_vars.OTGW].get(gw_vars.OTGW_ABOUT)
|
||||||
self.gw_version = version_string[18:] if version_string else None
|
self.gw_version = version_string[18:] if version_string else None
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
|
@ -26,6 +26,7 @@ from .const import (
|
|||||||
CONF_READ_PRECISION,
|
CONF_READ_PRECISION,
|
||||||
CONF_SET_PRECISION,
|
CONF_SET_PRECISION,
|
||||||
CONF_TEMPORARY_OVRD_MODE,
|
CONF_TEMPORARY_OVRD_MODE,
|
||||||
|
CONNECTION_TIMEOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -62,15 +63,21 @@ class OpenThermGwConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
otgw = pyotgw.OpenThermGateway()
|
otgw = pyotgw.OpenThermGateway()
|
||||||
status = await otgw.connect(device)
|
status = await otgw.connect(device)
|
||||||
await otgw.disconnect()
|
await otgw.disconnect()
|
||||||
|
if not status:
|
||||||
|
raise ConnectionError
|
||||||
return status[gw_vars.OTGW].get(gw_vars.OTGW_ABOUT)
|
return status[gw_vars.OTGW].get(gw_vars.OTGW_ABOUT)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = await asyncio.wait_for(test_connection(), timeout=10)
|
await asyncio.wait_for(
|
||||||
except (asyncio.TimeoutError, SerialException):
|
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"})
|
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()
|
return self._show_form()
|
||||||
|
|
||||||
|
@ -25,6 +25,8 @@ CONF_READ_PRECISION = "read_precision"
|
|||||||
CONF_SET_PRECISION = "set_precision"
|
CONF_SET_PRECISION = "set_precision"
|
||||||
CONF_TEMPORARY_OVRD_MODE = "temporary_override_mode"
|
CONF_TEMPORARY_OVRD_MODE = "temporary_override_mode"
|
||||||
|
|
||||||
|
CONNECTION_TIMEOUT = 10
|
||||||
|
|
||||||
DATA_GATEWAYS = "gateways"
|
DATA_GATEWAYS = "gateways"
|
||||||
DATA_OPENTHERM_GW = "opentherm_gw"
|
DATA_OPENTHERM_GW = "opentherm_gw"
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
"error": {
|
"error": {
|
||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||||
"id_exists": "Gateway id already exists",
|
"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": {
|
"options": {
|
||||||
|
@ -164,7 +164,7 @@ async def test_form_connection_timeout(hass):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result2["type"] == "form"
|
assert result2["type"] == "form"
|
||||||
assert result2["errors"] == {"base": "cannot_connect"}
|
assert result2["errors"] == {"base": "timeout_connect"}
|
||||||
assert len(mock_connect.mock_calls) == 1
|
assert len(mock_connect.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user