Skip to content

Commit 66eeb41

Browse files
DCSBLCopilot
andauthored
Add product name to title of HomeWizard v2 API migration repair (home-assistant#155097)
Co-authored-by: Copilot <[email protected]>
1 parent 1bef707 commit 66eeb41

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

homeassistant/components/homewizard/__init__.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN
1212
from homeassistant.core import HomeAssistant
1313
from homeassistant.exceptions import ConfigEntryNotReady
14+
from homeassistant.helpers import device_registry as dr
1415
from homeassistant.helpers.aiohttp_client import async_get_clientsession
1516
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
1617

@@ -71,6 +72,25 @@ async def async_unload_entry(hass: HomeAssistant, entry: HomeWizardConfigEntry)
7172
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
7273

7374

75+
def get_main_device(
76+
hass: HomeAssistant, entry: HomeWizardConfigEntry
77+
) -> dr.DeviceEntry | None:
78+
"""Helper function to get the main device for the config entry."""
79+
device_registry = dr.async_get(hass)
80+
device_entries = dr.async_entries_for_config_entry(
81+
device_registry, config_entry_id=entry.entry_id
82+
)
83+
84+
if not device_entries:
85+
return None
86+
87+
# Get first device that is not a sub-device, as this is the main device in HomeWizard
88+
# This is relevant for the P1 Meter which may create sub-devices for external utility meters
89+
return next(
90+
(device for device in device_entries if device.via_device_id is None), None
91+
)
92+
93+
7494
async def async_check_v2_support_and_create_issue(
7595
hass: HomeAssistant, entry: HomeWizardConfigEntry
7696
) -> None:
@@ -79,6 +99,16 @@ async def async_check_v2_support_and_create_issue(
7999
if not await has_v2_api(entry.data[CONF_IP_ADDRESS], async_get_clientsession(hass)):
80100
return
81101

102+
title = entry.title
103+
104+
# Try to get the name from the device registry
105+
# This is to make it clearer which device needs reconfiguration, as the config entry title is kept default most of the time
106+
if main_device := get_main_device(hass, entry):
107+
device_name = main_device.name_by_user or main_device.name
108+
109+
if device_name and entry.title != device_name:
110+
title = f"{entry.title} ({device_name})"
111+
82112
async_create_issue(
83113
hass,
84114
DOMAIN,
@@ -88,7 +118,7 @@ async def async_check_v2_support_and_create_issue(
88118
learn_more_url="https://home-assistant.io/integrations/homewizard/#which-button-do-i-need-to-press-to-configure-the-device",
89119
translation_key="migrate_to_v2_api",
90120
translation_placeholders={
91-
"title": entry.title,
121+
"title": title,
92122
},
93123
severity=IssueSeverity.WARNING,
94124
data={"entry_id": entry.entry_id},

homeassistant/components/homewizard/strings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@
177177
},
178178
"issues": {
179179
"migrate_to_v2_api": {
180-
"title": "Update authentication method",
180+
"title": "Update the authentication method for {title}",
181181
"fix_flow": {
182182
"step": {
183183
"confirm": {

tests/components/homewizard/test_init.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
"""Tests for the homewizard component."""
22

33
from datetime import timedelta
4-
from unittest.mock import MagicMock
4+
from unittest.mock import MagicMock, patch
55
import weakref
66

77
from freezegun.api import FrozenDateTimeFactory
88
from homewizard_energy.errors import DisabledError, UnauthorizedError
99
import pytest
1010

11+
from homeassistant.components.homewizard import get_main_device
1112
from homeassistant.components.homewizard.const import DOMAIN
1213
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState
1314
from homeassistant.core import HomeAssistant
15+
from homeassistant.helpers import device_registry as dr, issue_registry as ir
1416

1517
from tests.common import MockConfigEntry, async_fire_time_changed
1618

@@ -122,6 +124,78 @@ async def test_load_detect_invalid_token(
122124
assert flow["context"].get("entry_id") == mock_config_entry_v2.entry_id
123125

124126

127+
@pytest.mark.usefixtures("mock_homewizardenergy")
128+
async def test_load_creates_repair_issue(
129+
hass: HomeAssistant,
130+
mock_config_entry: MockConfigEntry,
131+
mock_homewizardenergy: MagicMock,
132+
) -> None:
133+
"""Test setup creates repair issue for v2 API upgrade."""
134+
mock_config_entry.add_to_hass(hass)
135+
await hass.async_block_till_done()
136+
137+
with patch("homeassistant.components.homewizard.has_v2_api", return_value=True):
138+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
139+
140+
await hass.async_block_till_done()
141+
142+
issue_registry = ir.async_get(hass)
143+
144+
issue = issue_registry.async_get_issue(
145+
domain=DOMAIN, issue_id=f"migrate_to_v2_api_{mock_config_entry.entry_id}"
146+
)
147+
assert issue is not None
148+
149+
# Make sure title placeholder is set correctly
150+
assert issue.translation_placeholders["title"] == "Device"
151+
152+
153+
@pytest.mark.usefixtures("mock_homewizardenergy")
154+
async def test_load_creates_repair_issue_when_name_is_updated(
155+
hass: HomeAssistant,
156+
mock_config_entry: MockConfigEntry,
157+
mock_homewizardenergy: MagicMock,
158+
) -> None:
159+
"""Test setup creates repair issue for v2 API upgrade and updates title when device name changes."""
160+
mock_config_entry.add_to_hass(hass)
161+
await hass.async_block_till_done()
162+
163+
with patch("homeassistant.components.homewizard.has_v2_api", return_value=True):
164+
await hass.config_entries.async_setup(mock_config_entry.entry_id)
165+
166+
await hass.async_block_till_done()
167+
168+
issue_registry = ir.async_get(hass)
169+
issue_id = f"migrate_to_v2_api_{mock_config_entry.entry_id}"
170+
171+
issue = issue_registry.async_get_issue(domain=DOMAIN, issue_id=issue_id)
172+
assert issue is not None
173+
174+
# Initial title should be "Device"
175+
assert issue.translation_placeholders["title"] == "Device"
176+
177+
# Update the device name
178+
device_registry = dr.async_get(hass)
179+
device = get_main_device(hass, mock_config_entry)
180+
181+
# Update device name
182+
device_registry.async_update_device(
183+
device_id=device.id,
184+
name_by_user="My HomeWizard Device",
185+
)
186+
187+
# Reload integration to trigger issue update
188+
with patch("homeassistant.components.homewizard.has_v2_api", return_value=True):
189+
await hass.config_entries.async_reload(mock_config_entry.entry_id)
190+
await hass.async_block_till_done()
191+
192+
issue = issue_registry.async_get_issue(domain=DOMAIN, issue_id=issue_id)
193+
assert issue is not None
194+
195+
# Title should now reflect updated device name
196+
assert issue.translation_placeholders["title"] == "Device (My HomeWizard Device)"
197+
198+
125199
@pytest.mark.usefixtures("mock_homewizardenergy")
126200
async def test_load_removes_reauth_flow(
127201
hass: HomeAssistant,

0 commit comments

Comments
 (0)