Skip to content

Commit 4fcbcad

Browse files
rihokirssclaude
andcommitted
Add IP address configuration through Home Assistant UI
- Enhanced options flow to allow IP address and name changes - Added connection testing for new IP addresses - Fixed deprecated config_entry assignment in OptionsFlowHandler - Added automatic integration reload when configuration changes - IP changes are now possible through Settings > Devices & Services > Configure 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 3bc4292 commit 4fcbcad

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

custom_components/yamaha_rn301/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@ def setup(hass, config):
1818
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
1919
"""Set up Yamaha R-N301 receiver from a config entry."""
2020
await hass.config_entries.async_forward_entry_setups(entry, ["media_player"])
21+
22+
# Listen for config entry updates
23+
entry.async_on_unload(entry.add_update_listener(update_listener))
24+
2125
return True
2226

27+
async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
28+
"""Handle config entry update."""
29+
await hass.config_entries.async_reload(entry.entry_id)
30+
2331
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
2432
"""Handle removal of receiver entry."""
2533
return await hass.config_entries.async_unload_platforms(entry, ["media_player"])

custom_components/yamaha_rn301/config_flow.py

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ async def async_step_user(self, user_input=None):
5454
@callback
5555
def async_get_options_flow(config_entry):
5656
"""Return the options flow for this config entry."""
57-
return OptionsFlowHandler(config_entry)
57+
return OptionsFlowHandler()
5858

5959
async def _test_connection(self, host, hass):
6060
"""Test connection to Yamaha receiver."""
@@ -73,18 +73,54 @@ async def _test_connection(self, host, hass):
7373
class OptionsFlowHandler(config_entries.OptionsFlow):
7474
"""Handle integration options flow."""
7575

76-
def __init__(self, config_entry):
77-
"""Constructor that stores the config entry."""
78-
self.config_entry = config_entry
79-
8076
async def async_step_init(self, user_input=None):
8177
"""Initial step of the options flow."""
78+
errors = {}
79+
8280
if user_input is not None:
83-
return self.async_create_entry(title="", data=user_input)
81+
# If host was changed, test the new connection
82+
if CONF_HOST in user_input:
83+
host = user_input[CONF_HOST]
84+
if host != self.config_entry.data.get(CONF_HOST):
85+
# Test new host
86+
if not await self._test_connection(host):
87+
errors["base"] = "cannot_connect"
88+
else:
89+
# Update the config entry with new host
90+
new_data = dict(self.config_entry.data)
91+
new_data[CONF_HOST] = host
92+
# Also update name if changed
93+
if CONF_NAME in user_input:
94+
new_data[CONF_NAME] = user_input[CONF_NAME]
95+
self.hass.config_entries.async_update_entry(
96+
self.config_entry, data=new_data
97+
)
98+
99+
if not errors:
100+
return self.async_create_entry(title="", data={})
84101

102+
current_host = self.config_entry.data.get(CONF_HOST, "")
103+
current_name = self.config_entry.data.get(CONF_NAME, DEFAULT_NAME)
104+
85105
return self.async_show_form(
86106
step_id="init",
87107
data_schema=vol.Schema({
88-
vol.Optional("scan_interval", default=30): int,
89-
})
108+
vol.Required(CONF_HOST, default=current_host): str,
109+
vol.Required(CONF_NAME, default=current_name): str,
110+
}),
111+
errors=errors
90112
)
113+
114+
async def _test_connection(self, host):
115+
"""Test connection to Yamaha receiver."""
116+
try:
117+
url = f"http://{host}/YamahaRemoteControl/ctrl"
118+
data = '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="GET"><Main_Zone><Basic_Status>GetParam</Basic_Status></Main_Zone></YAMAHA_AV>'
119+
120+
session = async_get_clientsession(self.hass)
121+
timeout = aiohttp.ClientTimeout(total=DEFAULT_TIMEOUT)
122+
123+
async with session.post(url, data=data, timeout=timeout) as response:
124+
return response.status == 200
125+
except Exception:
126+
return False

0 commit comments

Comments
 (0)