Handle unsupported devices for the my-PV integration (#183920)

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
rrooggiieerr
2026-10-05 11:54:41 +00:00
committed by Franck Nijhof
co-authored by Copilot Autofix powered by AI
parent 692bd453cf
commit bd77abd265
5 changed files with 105 additions and 6 deletions
+11 -2
View File
@@ -1,11 +1,15 @@
"""The my-PV integration for Home Assistant."""
from my_pv import MyPVLocalDevice
from my_pv.exceptions import MyPVAuthenticationError
from my_pv.exceptions import MyPVAuthenticationError, MyPVDeviceNotSupportedError
from homeassistant.const import CONF_HOST, CONF_PASSWORD, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.exceptions import (
ConfigEntryAuthFailed,
ConfigEntryError,
ConfigEntryNotReady,
)
from .const import DOMAIN
from .coordinator import MyPVConfigEntry, MyPVCoordinator
@@ -36,6 +40,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: MyPVConfigEntry) -> bool
translation_domain=DOMAIN,
translation_key="auth_error",
) from exc
except MyPVDeviceNotSupportedError as exc:
raise ConfigEntryError(
translation_domain=DOMAIN,
translation_key="unsupported_device",
) from exc
coordinator = MyPVCoordinator(hass, entry, device)
@@ -5,7 +5,7 @@ import logging
from typing import Any, Final, override
from my_pv import MyPVLocalDevice
from my_pv.exceptions import MyPVAuthenticationError
from my_pv.exceptions import MyPVAuthenticationError, MyPVDeviceNotSupportedError
import probatio
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
@@ -93,6 +93,8 @@ class MyPVConfigFlow(ConfigFlow, domain=DOMAIN):
return self.async_abort(reason="cannot_connect")
except MyPVAuthenticationError:
password_needed = True
except MyPVDeviceNotSupportedError:
return self.async_abort(reason="unsupported_device")
finally:
await device.disconnect()
@@ -142,6 +144,8 @@ class MyPVConfigFlow(ConfigFlow, domain=DOMAIN):
errors[CONF_BASE] = "cannot_connect"
except MyPVAuthenticationError:
password_needed = True
except MyPVDeviceNotSupportedError:
return self.async_abort(reason="unsupported_device")
finally:
await device.disconnect()
+5 -1
View File
@@ -7,7 +7,8 @@
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"unique_id_mismatch": "The device serial number does not match the original device."
"unique_id_mismatch": "The device serial number does not match the original device.",
"unsupported_device": "This my-PV device is not supported."
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
@@ -182,6 +183,9 @@
},
"unknown_error": {
"message": "The device could not complete the requested action."
},
"unsupported_device": {
"message": "This my-PV device is not supported."
}
}
}
+62 -1
View File
@@ -3,7 +3,7 @@
from ipaddress import ip_address
from unittest.mock import AsyncMock
from my_pv.exceptions import MyPVAuthenticationError
from my_pv.exceptions import MyPVAuthenticationError, MyPVDeviceNotSupportedError
import pytest
from homeassistant import config_entries
@@ -90,6 +90,32 @@ async def test_step_user_already_configured(
assert result["reason"] == "already_configured"
async def test_step_user_unsupported_device(
hass: HomeAssistant,
mock_my_pv_client: AsyncMock,
) -> None:
"""Test if we get the local setup form with error if the device is not supported."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
assert not result["errors"]
mock_my_pv_client.connect.side_effect = MyPVDeviceNotSupportedError
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_HOST: "127.0.0.1",
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_device"
async def test_step_user_cannot_connect(
hass: HomeAssistant,
mock_my_pv_client: AsyncMock,
@@ -299,6 +325,41 @@ async def test_step_discovery_already_configured(
assert result["reason"] == "already_configured"
@pytest.mark.parametrize(
("source", "data"),
[
(
config_entries.SOURCE_DHCP,
DHCP_DISCOVERY,
),
(
config_entries.SOURCE_ZEROCONF,
ZEROCONF_DISCOVERY,
),
],
)
@pytest.mark.usefixtures("mock_my_pv_client")
async def test_step_discovery_unsupported_device(
hass: HomeAssistant,
mock_my_pv_client: AsyncMock,
source: str,
data: BaseServiceInfo,
) -> None:
"""Test discovery of an unsupported device."""
mock_my_pv_client.connect.side_effect = MyPVDeviceNotSupportedError
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={
"source": source,
},
data=data,
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "unsupported_device"
@pytest.mark.parametrize(
("source", "data"),
[
+22 -1
View File
@@ -2,7 +2,11 @@
from unittest.mock import AsyncMock
from my_pv.exceptions import MyPVAuthenticationError, MyPVConnectionError
from my_pv.exceptions import (
MyPVAuthenticationError,
MyPVConnectionError,
MyPVDeviceNotSupportedError,
)
import pytest
from homeassistant.config_entries import ConfigEntryState
@@ -41,6 +45,23 @@ async def test_setup_entry_cannot_connect(
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_setup_entry_unsupported_device(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_my_pv_client: AsyncMock,
) -> None:
"""Test setup of a config entry when device is not supported."""
mock_config_entry.add_to_hass(hass)
mock_my_pv_client.connect.side_effect = MyPVDeviceNotSupportedError()
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert mock_config_entry.state is ConfigEntryState.SETUP_ERROR
assert mock_config_entry.error_reason_translation_key == "unsupported_device"
async def test_setup_entry_auth_error(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,