配置流(Config Flow)入门
说实话,我刚接触 Home Assistant 插件开发时,最头疼的就是配置流。那时候我写了个简单的传感器插件,每次配置都要手动改 configuration.yaml,用户反馈说「这也太不友好了」。嗯,确实如此。配置流就是来解决这个问题的。
配置流的概念
配置流是什么?说白了,它是一个让用户通过 UI 界面完成插件配置的机制。你想想看,如果每次装个插件都要去改 YAML 文件,重启 HA,那体验也太差了。配置流让用户可以在「设置 → 设备与服务 → 添加集成」的界面里,一步步完成配置。
我个人习惯把配置流理解成一个「向导」。它引导用户输入必要的信息,比如 API Key、IP 地址、用户名密码等。配置流会验证这些信息是否正确,然后把它们安全地存储起来。
核心要点:配置流是用户与你的插件交互的第一个界面。第一印象很重要,所以配置流的体验一定要做好。
配置流的生命周期
配置流不是一次性跑完就完事了。它有完整的生命周期。我在项目中遇到过不少新手,以为配置流只是「填表单 → 保存」这么简单,结果踩了不少坑。
配置流的生命周期包含以下几个阶段:
- 初始化阶段:用户点击「添加集成」,HA 调用你的配置流入口
- 用户输入阶段:你定义的表单一步步展示给用户
- 验证阶段:用户提交数据后,你进行校验(比如测试连接)
- 创建阶段:验证通过后,创建配置条目并存储
- 重配置阶段:用户后续可以修改配置
- 删除阶段:用户移除集成时触发
为什么会这样设计?因为配置流需要处理各种边界情况。比如用户输错了密码怎么办?网络超时怎么办?这些都需要在生命周期里妥善处理。
创建第一个配置流
好,理论说完了,咱们动手写一个。我会创建一个最简单的配置流,让用户输入一个 API Key。
首先,你需要在插件目录下创建 config_flow.py 文件。这是配置流的入口文件。
# config_flow.py
from homeassistant import config_entries
from homeassistant.core import callback
import voluptuous as vol
class MyCustomConfigFlow(config_entries.ConfigFlow, domain="my_custom"):
"""我的第一个配置流"""
VERSION = 1
async def async_step_user(self, user_input=None):
"""用户手动添加时的第一步"""
errors = {}
if user_input is not None:
# 验证用户输入
api_key = user_input.get("api_key")
if not api_key or len(api_key) < 10:
errors["api_key"] = "API Key 长度至少为10个字符"
else:
# 验证通过,创建配置条目
return self.async_create_entry(
title="我的自定义集成",
data=user_input
)
# 显示表单
return self.async_show_form(
step_id="user",
data_schema=vol.Schema({
vol.Required("api_key"): str,
vol.Optional("name", default="我的设备"): str,
}),
errors=errors,
)
这段代码看起来不多,但包含了配置流的核心逻辑。我来拆解一下:
async_step_user是配置流的默认入口。用户点击添加集成时,HA 会调用这个方法user_input参数接收用户提交的表单数据。第一次调用时是Nonevoluptuous库用来定义表单结构。我习惯用它,因为语法简洁async_create_entry是创建配置条目的关键方法。调用它后,配置数据就存到 HA 的配置存储里了
小技巧:配置流的 VERSION 字段很重要。如果你后续修改了配置结构,记得升级版本号。我曾经因为忘了改版本号,导致用户升级后配置丢失,被吐槽了好久。
注册配置流
光有 config_flow.py 还不够,你得告诉 HA 你的插件支持配置流。在 __init__.py 里加上配置流的引用:
# __init__.py
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
DOMAIN = "my_custom"
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""通过配置流设置插件"""
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][entry.entry_id] = entry.data
# 这里可以加载你的平台(传感器、开关等)
await hass.config_entries.async_forward_entry_setups(entry, ["sensor"])
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""卸载配置条目"""
await hass.config_entries.async_forward_entry_unload(entry, ["sensor"])
return True
然后在 manifest.json 里声明配置流支持:
{
"domain": "my_custom",
"name": "我的自定义集成",
"version": "1.0.0",
"config_flow": true,
"requirements": [],
"dependencies": [],
"codeowners": ["@your_github"]
}
注意 "config_flow": true 这一行。少了它,HA 就不会在 UI 里显示你的集成。
配置流的进阶用法
基础的配置流写完了,但实际项目中往往需要更复杂的交互。我分享几个常用的模式:
多步骤配置流
有时候一个表单不够用。比如你要先让用户选择设备类型,再根据类型展示不同的配置项。这时候可以用多步骤:
class MyCustomConfigFlow(config_entries.ConfigFlow, domain="my_custom"):
async def async_step_user(self, user_input=None):
"""第一步:选择设备类型"""
if user_input is not None:
self.device_type = user_input["device_type"]
# 根据类型跳转到不同步骤
if self.device_type == "sensor":
return await self.async_step_sensor_config()
else:
return await self.async_step_switch_config()
return self.async_show_form(
step_id="user",
data_schema=vol.Schema({
vol.Required("device_type"): vol.In(["sensor", "switch"]),
}),
)
async def async_step_sensor_config(self, user_input=None):
"""第二步:传感器配置"""
if user_input is not None:
return self.async_create_entry(
title="传感器设备",
data={**user_input, "device_type": "sensor"}
)
return self.async_show_form(
step_id="sensor_config",
data_schema=vol.Schema({
vol.Required("sensor_type"): str,
vol.Optional("unit", default="°C"): str,
}),
)
注意:多步骤配置流里,记得用 self 变量保存中间状态。我之前犯过错误,在步骤之间用局部变量传数据,结果异步调用时数据丢了。嗯,血的教训。
配置选项流
用户安装完集成后,可能想修改配置。这时候需要选项流(Options Flow)。它和配置流很像,但入口不同:
@staticmethod
@callback
def async_get_options_flow(config_entry):
return OptionsFlowHandler(config_entry)
class OptionsFlowHandler(config_entries.OptionsFlow):
"""选项流处理"""
async def async_step_init(self, user_input=None):
"""选项流入口"""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
return self.async_show_form(
step_id="init",
data_schema=vol.Schema({
vol.Optional(
"api_key",
default=self.config_entry.data.get("api_key")
): str,
}),
)
选项流让用户可以随时修改配置,不用重新安装集成。这个功能我建议每个插件都加上,用户体验会好很多。
配置流的调试技巧
写配置流时难免遇到问题。我分享几个调试方法:
| 问题 | 排查方法 | 常见原因 |
|---|---|---|
| 配置流不显示 | 检查 manifest.json 的 config_flow 字段 | 忘记设置 config_flow: true |
| 表单提交后没反应 | 查看 HA 的日志(设置 → 系统 → 日志) | 验证逻辑抛异常了 |
| 配置数据没保存 | 检查 async_create_entry 是否被调用 | 验证条件没满足,没走到创建步骤 |
| 多步骤跳转失败 | 确认 self 变量是否正确保存了状态 | 异步上下文导致变量丢失 |
调试小技巧:我习惯在配置流里加 _LOGGER.debug 日志。比如在 async_step_user 里打印 user_input 的内容。这样能清楚看到用户提交了什么数据,验证逻辑有没有走对。
总结
配置流是 Home Assistant 插件开发的核心技能。它让用户通过 UI 完成配置,大大提升了使用体验。从初始化到创建条目,再到选项流和删除,每个阶段都有它的意义。
我个人建议,刚开始写配置流时,先从一个简单的单步骤表单入手。跑通了再尝试多步骤和选项流。别一上来就想搞复杂的,容易把自己绕进去。
嗯,配置流的内容就讲到这里。记住,好的配置流能让用户对你的插件第一印象加分不少。花点心思在设计上,值得的。