1313from music_assistant_models .api import ServerInfoMessage
1414import voluptuous as vol
1515
16- from homeassistant .config_entries import SOURCE_IGNORE , ConfigFlow , ConfigFlowResult
16+ from homeassistant .config_entries import ConfigFlow , ConfigFlowResult
1717from homeassistant .const import CONF_URL
1818from homeassistant .core import HomeAssistant
1919from homeassistant .helpers import aiohttp_client
2020from homeassistant .helpers .service_info .zeroconf import ZeroconfServiceInfo
2121
2222from .const import DOMAIN , LOGGER
2323
24- DEFAULT_URL = "http://mass.local:8095"
2524DEFAULT_TITLE = "Music Assistant"
25+ DEFAULT_URL = "http://mass.local:8095"
2626
2727
28- def get_manual_schema (user_input : dict [str , Any ]) -> vol .Schema :
29- """Return a schema for the manual step."""
30- default_url = user_input .get (CONF_URL , DEFAULT_URL )
31- return vol .Schema (
32- {
33- vol .Required (CONF_URL , default = default_url ): str ,
34- }
35- )
28+ STEP_USER_SCHEMA = vol .Schema ({vol .Required (CONF_URL ): str })
3629
3730
38- async def get_server_info (hass : HomeAssistant , url : str ) -> ServerInfoMessage :
31+ async def _get_server_info (hass : HomeAssistant , url : str ) -> ServerInfoMessage :
3932 """Validate the user input allows us to connect."""
4033 async with MusicAssistantClient (
4134 url , aiohttp_client .async_get_clientsession (hass )
@@ -52,25 +45,17 @@ class MusicAssistantConfigFlow(ConfigFlow, domain=DOMAIN):
5245
5346 def __init__ (self ) -> None :
5447 """Set up flow instance."""
55- self .server_info : ServerInfoMessage | None = None
48+ self .url : str | None = None
5649
5750 async def async_step_user (
5851 self , user_input : dict [str , Any ] | None = None
5952 ) -> ConfigFlowResult :
6053 """Handle a manual configuration."""
6154 errors : dict [str , str ] = {}
55+
6256 if user_input is not None :
6357 try :
64- self .server_info = await get_server_info (
65- self .hass , user_input [CONF_URL ]
66- )
67- await self .async_set_unique_id (
68- self .server_info .server_id , raise_on_progress = False
69- )
70- self ._abort_if_unique_id_configured (
71- updates = {CONF_URL : user_input [CONF_URL ]},
72- reload_on_update = True ,
73- )
58+ server_info = await _get_server_info (self .hass , user_input [CONF_URL ])
7459 except CannotConnect :
7560 errors ["base" ] = "cannot_connect"
7661 except InvalidServerVersion :
@@ -79,85 +64,66 @@ async def async_step_user(
7964 LOGGER .exception ("Unexpected exception" )
8065 errors ["base" ] = "unknown"
8166 else :
67+ await self .async_set_unique_id (
68+ server_info .server_id , raise_on_progress = False
69+ )
70+ self ._abort_if_unique_id_configured (
71+ updates = {CONF_URL : user_input [CONF_URL ]}
72+ )
73+
8274 return self .async_create_entry (
8375 title = DEFAULT_TITLE ,
84- data = {
85- CONF_URL : user_input [CONF_URL ],
86- },
76+ data = {CONF_URL : user_input [CONF_URL ]},
8777 )
8878
89- return self . async_show_form (
90- step_id = "user" , data_schema = get_manual_schema ( user_input ), errors = errors
91- )
79+ suggested_values = user_input
80+ if suggested_values is None :
81+ suggested_values = { CONF_URL : DEFAULT_URL }
9282
93- return self .async_show_form (step_id = "user" , data_schema = get_manual_schema ({}))
83+ return self .async_show_form (
84+ step_id = "user" ,
85+ data_schema = self .add_suggested_values_to_schema (
86+ STEP_USER_SCHEMA , suggested_values
87+ ),
88+ errors = errors ,
89+ )
9490
9591 async def async_step_zeroconf (
9692 self , discovery_info : ZeroconfServiceInfo
9793 ) -> ConfigFlowResult :
98- """Handle a discovered Mass server.
99-
100- This flow is triggered by the Zeroconf component. It will check if the
101- host is already configured and delegate to the import step if not.
102- """
103- # abort if discovery info is not what we expect
104- if "server_id" not in discovery_info .properties :
105- return self .async_abort (reason = "missing_server_id" )
106-
107- self .server_info = ServerInfoMessage .from_dict (discovery_info .properties )
108- await self .async_set_unique_id (self .server_info .server_id )
94+ """Handle a zeroconf discovery for a Music Assistant server."""
95+ try :
96+ server_info = ServerInfoMessage .from_dict (discovery_info .properties )
97+ except LookupError :
98+ return self .async_abort (reason = "invalid_discovery_info" )
10999
110- # Check if we already have a config entry for this server_id
111- existing_entry = self .hass .config_entries .async_entry_for_domain_unique_id (
112- DOMAIN , self .server_info .server_id
113- )
100+ self .url = server_info .base_url
114101
115- if existing_entry :
116- # If the entry was ignored or disabled, don't make any changes
117- if existing_entry .source == SOURCE_IGNORE or existing_entry .disabled_by :
118- return self .async_abort (reason = "already_configured" )
102+ await self .async_set_unique_id (server_info .server_id )
103+ self ._abort_if_unique_id_configured (updates = {CONF_URL : self .url })
119104
120- # Test connectivity to the current URL first
121- current_url = existing_entry .data [CONF_URL ]
122- try :
123- await get_server_info (self .hass , current_url )
124- # Current URL is working, no need to update
125- return self .async_abort (reason = "already_configured" )
126- except CannotConnect :
127- # Current URL is not working, update to the discovered URL
128- # and continue to discovery confirm
129- self .hass .config_entries .async_update_entry (
130- existing_entry ,
131- data = {** existing_entry .data , CONF_URL : self .server_info .base_url },
132- )
133- # Schedule reload since URL changed
134- self .hass .config_entries .async_schedule_reload (existing_entry .entry_id )
135- else :
136- # No existing entry, proceed with normal flow
137- self ._abort_if_unique_id_configured ()
138-
139- # Test connectivity to the discovered URL
140105 try :
141- await get_server_info (self .hass , self .server_info . base_url )
106+ await _get_server_info (self .hass , self .url )
142107 except CannotConnect :
143108 return self .async_abort (reason = "cannot_connect" )
109+
144110 return await self .async_step_discovery_confirm ()
145111
146112 async def async_step_discovery_confirm (
147113 self , user_input : dict [str , Any ] | None = None
148114 ) -> ConfigFlowResult :
149115 """Handle user-confirmation of discovered server."""
150116 if TYPE_CHECKING :
151- assert self .server_info is not None
117+ assert self .url is not None
118+
152119 if user_input is not None :
153120 return self .async_create_entry (
154121 title = DEFAULT_TITLE ,
155- data = {
156- CONF_URL : self .server_info .base_url ,
157- },
122+ data = {CONF_URL : self .url },
158123 )
124+
159125 self ._set_confirm_only ()
160126 return self .async_show_form (
161127 step_id = "discovery_confirm" ,
162- description_placeholders = {"url" : self .server_info . base_url },
128+ description_placeholders = {"url" : self .url },
163129 )
0 commit comments