Use more specific exception and simplify aurora_abb_powerone (#73338)

* Use more specific exception for comms timeout

* Remove defered uniqueid assigner now yaml has gone

Co-authored-by: Dave T <davet2001@users.noreply.github.com>
This commit is contained in:
Dave T 2022-06-13 08:36:46 +01:00 committed by GitHub
parent a0974e0c72
commit b261f0fb41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 14 additions and 58 deletions

View File

@ -10,15 +10,13 @@
import logging import logging
from aurorapy.client import AuroraError, AuroraSerialClient from aurorapy.client import AuroraSerialClient
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ADDRESS, CONF_PORT, Platform from homeassistant.const import CONF_ADDRESS, CONF_PORT, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from .config_flow import validate_and_connect from .const import DOMAIN
from .const import ATTR_SERIAL_NUMBER, DOMAIN
PLATFORMS = [Platform.SENSOR] PLATFORMS = [Platform.SENSOR]
@ -31,42 +29,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
comport = entry.data[CONF_PORT] comport = entry.data[CONF_PORT]
address = entry.data[CONF_ADDRESS] address = entry.data[CONF_ADDRESS]
ser_client = AuroraSerialClient(address, comport, parity="N", timeout=1) ser_client = AuroraSerialClient(address, comport, parity="N", timeout=1)
# To handle yaml import attempts in darkness, (re)try connecting only if
# unique_id not yet assigned.
if entry.unique_id is None:
try:
res = await hass.async_add_executor_job(
validate_and_connect, hass, entry.data
)
except AuroraError as error:
if "No response after" in str(error):
raise ConfigEntryNotReady("No response (could be dark)") from error
_LOGGER.error("Failed to connect to inverter: %s", error)
return False
except OSError as error:
if error.errno == 19: # No such device.
_LOGGER.error("Failed to connect to inverter: no such COM port")
return False
_LOGGER.error("Failed to connect to inverter: %s", error)
return False
else:
# If we got here, the device is now communicating (maybe after
# being in darkness). But there's a small risk that the user has
# configured via the UI since we last attempted the yaml setup,
# which means we'd get a duplicate unique ID.
new_id = res[ATTR_SERIAL_NUMBER]
# Check if this unique_id has already been used
for existing_entry in hass.config_entries.async_entries(DOMAIN):
if existing_entry.unique_id == new_id:
_LOGGER.debug(
"Remove already configured config entry for id %s", new_id
)
hass.async_create_task(
hass.config_entries.async_remove(entry.entry_id)
)
return False
hass.config_entries.async_update_entry(entry, unique_id=new_id)
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = ser_client hass.data.setdefault(DOMAIN, {})[entry.entry_id] = ser_client
hass.config_entries.async_setup_platforms(entry, PLATFORMS) hass.config_entries.async_setup_platforms(entry, PLATFORMS)

View File

@ -5,7 +5,7 @@ from collections.abc import Mapping
import logging import logging
from typing import Any from typing import Any
from aurorapy.client import AuroraError, AuroraSerialClient from aurorapy.client import AuroraError, AuroraSerialClient, AuroraTimeoutError
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
@ -102,21 +102,15 @@ class AuroraSensor(AuroraEntity, SensorEntity):
self._attr_native_value = round(energy_wh / 1000, 2) self._attr_native_value = round(energy_wh / 1000, 2)
self._attr_available = True self._attr_available = True
except AuroraTimeoutError:
self._attr_state = None
self._attr_native_value = None
self._attr_available = False
_LOGGER.debug("No response from inverter (could be dark)")
except AuroraError as error: except AuroraError as error:
self._attr_state = None self._attr_state = None
self._attr_native_value = None self._attr_native_value = None
self._attr_available = False self._attr_available = False
# aurorapy does not have different exceptions (yet) for dealing
# with timeout vs other comms errors.
# This means the (normal) situation of no response during darkness
# raises an exception.
# aurorapy (gitlab) pull request merged 29/5/2019. When >0.2.6 is
# released, this could be modified to :
# except AuroraTimeoutError as e:
# Workaround: look at the text of the exception
if "No response after" in str(error):
_LOGGER.debug("No response from inverter (could be dark)")
else:
raise error raise error
finally: finally:
if self._attr_available != self.available_prev: if self._attr_available != self.available_prev:

View File

@ -2,7 +2,7 @@
from logging import INFO from logging import INFO
from unittest.mock import patch from unittest.mock import patch
from aurorapy.client import AuroraError from aurorapy.client import AuroraError, AuroraTimeoutError
from serial.tools import list_ports_common from serial.tools import list_ports_common
from homeassistant import config_entries, data_entry_flow, setup from homeassistant import config_entries, data_entry_flow, setup
@ -127,7 +127,7 @@ async def test_form_invalid_com_ports(hass):
with patch( with patch(
"aurorapy.client.AuroraSerialClient.connect", "aurorapy.client.AuroraSerialClient.connect",
side_effect=AuroraError("...No response after..."), side_effect=AuroraTimeoutError("...No response after..."),
return_value=None, return_value=None,
): ):
result2 = await hass.config_entries.flow.async_configure( result2 = await hass.config_entries.flow.async_configure(

View File

@ -2,7 +2,7 @@
from datetime import timedelta from datetime import timedelta
from unittest.mock import patch from unittest.mock import patch
from aurorapy.client import AuroraError from aurorapy.client import AuroraError, AuroraTimeoutError
from homeassistant.components.aurora_abb_powerone.const import ( from homeassistant.components.aurora_abb_powerone.const import (
ATTR_DEVICE_NAME, ATTR_DEVICE_NAME,
@ -126,7 +126,7 @@ async def test_sensor_dark(hass):
# sunset # sunset
with patch("aurorapy.client.AuroraSerialClient.connect", return_value=None), patch( with patch("aurorapy.client.AuroraSerialClient.connect", return_value=None), patch(
"aurorapy.client.AuroraSerialClient.measure", "aurorapy.client.AuroraSerialClient.measure",
side_effect=AuroraError("No response after 10 seconds"), side_effect=AuroraTimeoutError("No response after 10 seconds"),
): ):
async_fire_time_changed(hass, utcnow + timedelta(seconds=60)) async_fire_time_changed(hass, utcnow + timedelta(seconds=60))
await hass.async_block_till_done() await hass.async_block_till_done()
@ -144,7 +144,7 @@ async def test_sensor_dark(hass):
# sunset # sunset
with patch("aurorapy.client.AuroraSerialClient.connect", return_value=None), patch( with patch("aurorapy.client.AuroraSerialClient.connect", return_value=None), patch(
"aurorapy.client.AuroraSerialClient.measure", "aurorapy.client.AuroraSerialClient.measure",
side_effect=AuroraError("No response after 10 seconds"), side_effect=AuroraTimeoutError("No response after 10 seconds"),
): ):
async_fire_time_changed(hass, utcnow + timedelta(seconds=60)) async_fire_time_changed(hass, utcnow + timedelta(seconds=60))
await hass.async_block_till_done() await hass.async_block_till_done()