From 04e942992b4338a82fbb1cd462a0b84aa1180321 Mon Sep 17 00:00:00 2001 From: impressionyang Date: Thu, 16 Apr 2026 13:51:37 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20OptionsFlow=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E8=A1=A8=E5=8D=95=E6=98=BE=E7=A4=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:集成配置选项面板中字体不显示 修复内容: - 移除 vol.Coerce 包装器,直接使用 int/bool 类型 - 添加错误处理和显示 - 修复 self._hass 为 self.hass (OptionsFlow 中通过属性访问) - 添加实际操作调用(扫描、配网、绑定、分组) - 添加错误时返回上一步的逻辑 修改的方法: - async_step_poll_config: 简化类型定义 - async_step_prov_action: 添加错误处理 - async_step_start_scan: 添加实际调用和错误处理 - async_step_stop_prov: 添加实际调用和错误处理 - async_step_bind_appkey: 添加实际调用和错误处理 - async_step_add_to_group: 添加实际调用和错误处理 - async_step_remove_from_group: 添加实际调用和错误处理 --- .../sigmesh_gateway/config_flow.py | 100 +++++++++++++++--- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/custom_components/sigmesh_gateway/config_flow.py b/custom_components/sigmesh_gateway/config_flow.py index 8b9062f..477f1d6 100644 --- a/custom_components/sigmesh_gateway/config_flow.py +++ b/custom_components/sigmesh_gateway/config_flow.py @@ -180,7 +180,7 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): vol.Required( "poll_interval", default=self.config_entry.options.get("poll_interval", 30), - ): vol.Coerce(int), + ): int, } ), ) @@ -189,14 +189,17 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): self, user_input: dict[str, Any] | None = None ) -> FlowResult: """配网操作选择.""" + errors = {} + if user_input is not None: - self._prov_action = user_input.get("action") - if self._prov_action == "start_scan": + action = user_input.get("action") + if action == "start_scan": return await self.async_step_start_scan() - elif self._prov_action == "stop_prov": + elif action == "stop_prov": return await self.async_step_stop_prov() - elif self._prov_action == "bind_appkey": + elif action == "bind_appkey": return await self.async_step_bind_appkey() + errors["base"] = "无效的操作" return self.async_show_form( step_id="prov_action", @@ -213,6 +216,7 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ), } ), + errors=errors, ) async def async_step_start_scan( @@ -220,7 +224,14 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ) -> FlowResult: """开始扫描设备.""" if user_input is not None: - # TODO: 调用配网管理器开始扫描 + # 调用配网管理器开始扫描 + try: + for coordinator in self.hass.data.get(DOMAIN, {}).values(): + if hasattr(coordinator, 'start_scanning'): + await coordinator.start_scanning() + except Exception as e: + self._errors["base"] = str(e) + return await self.async_step_prov_action() return self.async_create_entry(title="", data={}) return self.async_show_form( @@ -231,6 +242,7 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): vol.Required("confirm"): bool, } ), + errors=self._errors, ) async def async_step_stop_prov( @@ -238,7 +250,14 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ) -> FlowResult: """停止配网.""" if user_input is not None: - # TODO: 调用配网管理器停止配网 + # 调用配网管理器停止配网 + try: + for coordinator in self.hass.data.get(DOMAIN, {}).values(): + if hasattr(coordinator, 'stop_provisioning'): + await coordinator.stop_provisioning() + except Exception as e: + self._errors["base"] = str(e) + return await self.async_step_prov_action() return self.async_create_entry(title="", data={}) return self.async_show_form( @@ -248,6 +267,7 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): vol.Required("confirm"): bool, } ), + errors=self._errors, ) async def async_step_bind_appkey( @@ -255,7 +275,16 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ) -> FlowResult: """绑定 App Key.""" if user_input is not None: - # TODO: 调用配网管理器绑定 App Key + # 调用配网管理器绑定 App Key + try: + device_address = user_input.get("device_address") + element_address = user_input.get("element_address", 0) + for coordinator in self.hass.data.get(DOMAIN, {}).values(): + if hasattr(coordinator, 'bind_app_key'): + await coordinator.bind_app_key(device_address, element_address) + except Exception as e: + self._errors["base"] = str(e) + return await self.async_step_prov_action() return self.async_create_entry(title="", data={}) return self.async_show_form( @@ -263,9 +292,10 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): data_schema=vol.Schema( { vol.Required("device_address"): str, - vol.Required("element_address", default=0): vol.Coerce(int), + vol.Required("element_address", default=0): int, } ), + errors=self._errors, ) async def async_step_group_config( @@ -300,7 +330,26 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ) -> FlowResult: """添加设备到组.""" if user_input is not None: - # TODO: 调用配网管理器添加设备到组 + # 调用配网管理器添加设备到组 + try: + target_address = user_input.get("target_address") + element_address = user_input.get("element_address", 0) + group_address = user_input.get("group_address") + model_id = user_input.get("model_id", 4352) + is_sig = user_input.get("is_sig", True) + + # 解析组地址 + if isinstance(group_address, str): + group_address = int(group_address, 16) + + for coordinator in self.hass.data.get(DOMAIN, {}).values(): + if hasattr(coordinator, 'add_device_to_group'): + await coordinator.add_device_to_group( + target_address, element_address, group_address, model_id, is_sig + ) + except Exception as e: + self._errors["base"] = str(e) + return await self.async_step_group_config() return self.async_create_entry(title="", data={}) return self.async_show_form( @@ -308,15 +357,16 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): data_schema=vol.Schema( { vol.Required("target_address"): str, - vol.Required("element_address", default=0): vol.Coerce(int), + vol.Required("element_address", default=0): int, vol.Required("group_address", default=hex(DEFAULT_GROUP_ADDRESS_START)): str, - vol.Required("model_id", default=4352): vol.Coerce(int), # 默认 0x1100 + vol.Required("model_id", default=4352): int, vol.Required("is_sig", default=True): bool, } ), description_placeholders={ "default_group": hex(DEFAULT_GROUP_ADDRESS_START), }, + errors=self._errors, ) async def async_step_remove_from_group( @@ -324,7 +374,26 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): ) -> FlowResult: """从组中移除设备.""" if user_input is not None: - # TODO: 调用配网管理器移除设备 + # 调用配网管理器移除设备 + try: + target_address = user_input.get("target_address") + element_address = user_input.get("element_address", 0) + group_address = user_input.get("group_address") + model_id = user_input.get("model_id", 4352) + is_sig = user_input.get("is_sig", True) + + # 解析组地址 + if isinstance(group_address, str): + group_address = int(group_address, 16) + + for coordinator in self.hass.data.get(DOMAIN, {}).values(): + if hasattr(coordinator, 'remove_device_from_group'): + await coordinator.remove_device_from_group( + target_address, element_address, group_address, model_id, is_sig + ) + except Exception as e: + self._errors["base"] = str(e) + return await self.async_step_group_config() return self.async_create_entry(title="", data={}) return self.async_show_form( @@ -332,10 +401,11 @@ class SigMeshGatewayOptionsFlow(config_entries.OptionsFlow): data_schema=vol.Schema( { vol.Required("target_address"): str, - vol.Required("element_address", default=0): vol.Coerce(int), + vol.Required("element_address", default=0): int, vol.Required("group_address", default=hex(DEFAULT_GROUP_ADDRESS_START)): str, - vol.Required("model_id", default=4352): vol.Coerce(int), + vol.Required("model_id", default=4352): int, vol.Required("is_sig", default=True): bool, } ), + errors=self._errors, )