|
35 | 35 | from homeassistant.core import HomeAssistant, callback |
36 | 36 | from homeassistant.data_entry_flow import AbortFlow |
37 | 37 | from homeassistant.exceptions import HomeAssistantError |
| 38 | +from homeassistant.helpers import selector |
38 | 39 | from homeassistant.helpers.hassio import is_hassio |
39 | 40 | from homeassistant.helpers.service_info.hassio import HassioServiceInfo |
40 | 41 | from homeassistant.helpers.service_info.usb import UsbServiceInfo |
|
88 | 89 | CONF_ADDON_LR_S2_AUTHENTICATED_KEY: CONF_LR_S2_AUTHENTICATED_KEY, |
89 | 90 | } |
90 | 91 |
|
| 92 | +CONF_ADDON_RF_REGION = "rf_region" |
| 93 | + |
91 | 94 | EXAMPLE_SERVER_URL = "ws://localhost:3000" |
92 | 95 | ON_SUPERVISOR_SCHEMA = vol.Schema({vol.Optional(CONF_USE_ADDON, default=True): bool}) |
93 | 96 | MIN_MIGRATION_SDK_VERSION = AwesomeVersion("6.61") |
|
103 | 106 | "#how-to-migrate-from-one-adapter-to-a-new-adapter-using-z-wave-js-ui" |
104 | 107 | ) |
105 | 108 |
|
| 109 | +RF_REGIONS = [ |
| 110 | + "Australia/New Zealand", |
| 111 | + "China", |
| 112 | + "Europe", |
| 113 | + "Hong Kong", |
| 114 | + "India", |
| 115 | + "Israel", |
| 116 | + "Japan", |
| 117 | + "Korea", |
| 118 | + "Russia", |
| 119 | + "USA", |
| 120 | +] |
| 121 | + |
106 | 122 |
|
107 | 123 | def get_manual_schema(user_input: dict[str, Any]) -> vol.Schema: |
108 | 124 | """Return a schema for the manual step.""" |
@@ -195,10 +211,12 @@ def __init__(self) -> None: |
195 | 211 | self.backup_data: bytes | None = None |
196 | 212 | self.backup_filepath: Path | None = None |
197 | 213 | self.use_addon = False |
| 214 | + self._addon_config_updates: dict[str, Any] = {} |
198 | 215 | self._migrating = False |
199 | 216 | self._reconfigure_config_entry: ZwaveJSConfigEntry | None = None |
200 | 217 | self._usb_discovery = False |
201 | 218 | self._recommended_install = False |
| 219 | + self._rf_region: str | None = None |
202 | 220 |
|
203 | 221 | async def async_step_install_addon( |
204 | 222 | self, user_input: dict[str, Any] | None = None |
@@ -236,6 +254,21 @@ async def async_step_start_addon( |
236 | 254 | self, user_input: dict[str, Any] | None = None |
237 | 255 | ) -> ConfigFlowResult: |
238 | 256 | """Start Z-Wave JS add-on.""" |
| 257 | + if self.hass.config.country is None and ( |
| 258 | + not self._rf_region or self._rf_region == "Automatic" |
| 259 | + ): |
| 260 | + # If the country is not set, we need to check the RF region add-on config. |
| 261 | + addon_info = await self._async_get_addon_info() |
| 262 | + rf_region: str | None = addon_info.options.get(CONF_ADDON_RF_REGION) |
| 263 | + self._rf_region = rf_region |
| 264 | + if rf_region is None or rf_region == "Automatic": |
| 265 | + # If the RF region is not set, we need to ask the user to select it. |
| 266 | + return await self.async_step_rf_region() |
| 267 | + if config_updates := self._addon_config_updates: |
| 268 | + # If we have updates to the add-on config, set them before starting the add-on. |
| 269 | + self._addon_config_updates = {} |
| 270 | + await self._async_set_addon_config(config_updates) |
| 271 | + |
239 | 272 | if not self.start_task: |
240 | 273 | self.start_task = self.hass.async_create_task(self._async_start_addon()) |
241 | 274 |
|
@@ -629,6 +662,33 @@ async def async_step_intent_custom( |
629 | 662 | return await self.async_step_on_supervisor({CONF_USE_ADDON: True}) |
630 | 663 | return await self.async_step_on_supervisor() |
631 | 664 |
|
| 665 | + async def async_step_rf_region( |
| 666 | + self, user_input: dict[str, Any] | None = None |
| 667 | + ) -> ConfigFlowResult: |
| 668 | + """Handle RF region selection step.""" |
| 669 | + if user_input is not None: |
| 670 | + # Store the selected RF region |
| 671 | + self._addon_config_updates[CONF_ADDON_RF_REGION] = self._rf_region = ( |
| 672 | + user_input["rf_region"] |
| 673 | + ) |
| 674 | + return await self.async_step_start_addon() |
| 675 | + |
| 676 | + schema = vol.Schema( |
| 677 | + { |
| 678 | + vol.Required("rf_region"): selector.SelectSelector( |
| 679 | + selector.SelectSelectorConfig( |
| 680 | + options=RF_REGIONS, |
| 681 | + mode=selector.SelectSelectorMode.DROPDOWN, |
| 682 | + ) |
| 683 | + ), |
| 684 | + } |
| 685 | + ) |
| 686 | + |
| 687 | + return self.async_show_form( |
| 688 | + step_id="rf_region", |
| 689 | + data_schema=schema, |
| 690 | + ) |
| 691 | + |
632 | 692 | async def async_step_on_supervisor( |
633 | 693 | self, user_input: dict[str, Any] | None = None |
634 | 694 | ) -> ConfigFlowResult: |
@@ -728,7 +788,7 @@ async def async_step_network_type( |
728 | 788 | CONF_ADDON_LR_S2_AUTHENTICATED_KEY: self.lr_s2_authenticated_key, |
729 | 789 | } |
730 | 790 |
|
731 | | - await self._async_set_addon_config(addon_config_updates) |
| 791 | + self._addon_config_updates = addon_config_updates |
732 | 792 | return await self.async_step_start_addon() |
733 | 793 |
|
734 | 794 | # Network already exists, go to security keys step |
@@ -799,7 +859,7 @@ async def async_step_configure_security_keys( |
799 | 859 | CONF_ADDON_LR_S2_AUTHENTICATED_KEY: self.lr_s2_authenticated_key, |
800 | 860 | } |
801 | 861 |
|
802 | | - await self._async_set_addon_config(addon_config_updates) |
| 862 | + self._addon_config_updates = addon_config_updates |
803 | 863 | return await self.async_step_start_addon() |
804 | 864 |
|
805 | 865 | data_schema = vol.Schema( |
@@ -1004,7 +1064,7 @@ async def async_step_instruct_unplug( |
1004 | 1064 | if user_input is not None: |
1005 | 1065 | if self.usb_path: |
1006 | 1066 | # USB discovery was used, so the device is already known. |
1007 | | - await self._async_set_addon_config({CONF_ADDON_DEVICE: self.usb_path}) |
| 1067 | + self._addon_config_updates[CONF_ADDON_DEVICE] = self.usb_path |
1008 | 1068 | return await self.async_step_start_addon() |
1009 | 1069 | # Now that the old controller is gone, we can scan for serial ports again |
1010 | 1070 | return await self.async_step_choose_serial_port() |
@@ -1136,6 +1196,8 @@ async def async_step_configure_addon_reconfigure( |
1136 | 1196 | CONF_ADDON_LR_S2_AUTHENTICATED_KEY: self.lr_s2_authenticated_key, |
1137 | 1197 | } |
1138 | 1198 |
|
| 1199 | + addon_config_updates = self._addon_config_updates | addon_config_updates |
| 1200 | + self._addon_config_updates = {} |
1139 | 1201 | await self._async_set_addon_config(addon_config_updates) |
1140 | 1202 |
|
1141 | 1203 | if addon_info.state == AddonState.RUNNING and not self.restart_addon: |
@@ -1207,7 +1269,7 @@ async def async_step_choose_serial_port( |
1207 | 1269 | """Choose a serial port.""" |
1208 | 1270 | if user_input is not None: |
1209 | 1271 | self.usb_path = user_input[CONF_USB_PATH] |
1210 | | - await self._async_set_addon_config({CONF_ADDON_DEVICE: self.usb_path}) |
| 1272 | + self._addon_config_updates[CONF_ADDON_DEVICE] = self.usb_path |
1211 | 1273 | return await self.async_step_start_addon() |
1212 | 1274 |
|
1213 | 1275 | try: |
|
0 commit comments