创建实验室预览功能
Home Assistant 实验室提供了一种标准化方式,用于发布预览功能,让用户可以在这些功能成为正式标准之前选择启用。本文介绍如何向实验室添加新的预览功能。
什么是实验室预览功能?
实验室预览功能已经过充分测试,其界面和设计会通过真实使用场景与用户反馈继续打磨,然后再成为 Home Assistant 的标准功能。这些功能具有以下特征:
- 可选:默认关闭,用户必须主动启用
- 经过充分测试:代码已可用于生产环境,而不是实验性或未完成的实现
- 可能发生变化:可能会有重大调整、增加新能力,或根据反馈被移除
- 可逆:可以随时关闭,无需重启
实验室的目的在于完善界面与设计,而不是测试 bug。这与 beta 测试不同;beta 测试关注的是即将发布的 Home Assistant 版本是否稳定。
何时使用实验室
实验室适用于:
- 重大 UI 变更或重设计
- 重要的架构变化
- 最终设计和实现会明显受到用户反馈影响的功能
实验室不适用于:
- 本应作为标准功能存在的配置选项(请改用集成选项或配置流程)
- 可以直接发布的小改动
- 不能在运行时切换的功能
- 存在严重 bug 或明显尚未完成的功能(这些应继续开发)
添加实验室预览功能
1. 在 manifest.json 中定义功能
将您的功能添加到集成的 manifest.json 中的 preview_features 部分:
{
"domain": "my_integration",
"name": "My Integration",
"preview_features": {
"my_preview_feature": {
"feedback_url": "https://community.home-assistant.io/t/...",
"learn_more_url": "https://www.home-assistant.io/integrations/my_integration",
"report_issue_url": "https://github.com/home-assistant/core/issues/new?template=bug_report.yml"
}
}
}
字段说明:
feedback_url:指向社区论坛主题、反馈表单或反馈讨论的链接
learn_more_url:该功能相关文档的链接
report_issue_url:指向 GitHub issue 报告页面的链接
所有字段都是可选的,但强烈建议提供,以便用户反馈和报告问题。
2. 添加翻译
将翻译添加到集成的 strings.json:
{
"preview_features": {
"my_preview_feature": {
"name": "My preview feature",
"description": "Enables the new preview feature that does X, Y, and Z.\n\nThis feature is stable but may change based on user feedback."
}
}
}
描述应当:
- 清楚说明该功能的作用
- 保持简洁,但信息充分
- 提及该功能未来是否可能继续扩展
- 可以使用 Markdown 格式(粗体、链接等)
自定义确认消息(可选)
您可以自定义用户启用或禁用该功能时看到的确认消息。如果功能存在用户需要注意的特定行为或后果,这会非常有用:
{
"preview_features": {
"my_preview_feature": {
"name": "My preview feature",
"description": "Enables the new preview feature that does X, Y, and Z.\n\n**Note:** Enabling this feature will migrate your configuration to a new format. The configuration will remain in the new format even if you disable the feature later.\n\nThis feature is stable but may change based on user feedback.",
"enable_confirmation": "This will migrate your existing configuration to the new format. You can disable the feature later, but the configuration will remain migrated.",
"disable_confirmation": "This will stop the new behavior, but your configuration will remain in the migrated format."
}
}
}
何时使用自定义确认:
- 功能会产生持久性变更(迁移、新实体等)
- 用户需要理解某些特定后果
- 功能会以不那么直观的方式与其他系统交互
- 您希望对启用/禁用后的行为建立明确预期
描述建议:
- 在描述中写明重要后果:用户应仅通过描述就能理解会发生什么,而不是只依赖确认弹窗
- 使用确认消息强调用户执行操作时需要注意的关键点
- 明确说明启用/禁用时会发生什么
- 保持信息简洁但充分
- 不要重复通用信息(用户已经看得到标准警告)
3. 实现功能
后端功能
对于后端功能,请在代码中检查标志:
from homeassistant.components.labs import async_is_preview_feature_enabled
from homeassistant.core import HomeAssistant
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up the integration."""
if async_is_preview_feature_enabled(hass, DOMAIN, "my_preview_feature"):
# Enable preview functionality
await setup_preview_feature(hass)
# Standard setup continues
return True
前端功能
对于前端功能,请在 TypeScript 中检查标志:
import { fetchLabFeatures } from "../../../data/labs";
const features = await fetchLabFeatures(this.hass);
const featureEnabled = features.find(
(f) => f.domain === "my_integration" && f.preview_feature === "my_preview_feature"
)?.enabled;
if (featureEnabled) {
// Load preview UI component
}
响应功能开关变更
使用 async_subscribe_preview_feature() 辅助函数订阅功能开关事件。监听器会接收事件数据作为参数,并支持异步协程函数:
from homeassistant.components.labs import (
EventLabsUpdatedData,
async_subscribe_preview_feature,
)
from homeassistant.core import HomeAssistant
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up the integration."""
async def _async_update_my_preview_feature(
event_data: EventLabsUpdatedData,
) -> None:
"""Enable or disable the preview feature based on current state."""
if event_data["enabled"]:
# Enable feature
await async_enable_my_feature(hass)
else:
# Disable feature
await async_disable_my_feature(hass)
# Subscribe to changes for this specific feature
entry.async_on_unload(
async_subscribe_preview_feature(
hass,
DOMAIN,
"my_preview_feature",
_async_update_my_preview_feature,
)
)
return True
async_subscribe_preview_feature() 会自动筛选当前域和当前功能的事件,并将包含 enabled 状态在内的事件数据直接传给监听器。
Info
对于更复杂的场景或存在多个预览功能的情况,您仍然可以直接使用更底层的 EVENT_LABS_UPDATED 事件。对于大多数用例,建议优先使用 async_subscribe_preview_feature(),因为它可以减少样板代码并提升可读性。
4. 必须支持运行时启用
关键要求:所有实验室预览功能都必须支持在运行时启用和禁用,且不需要重启 Home Assistant。
好的模式:
- 动态加载/卸载 UI 组件
- 在功能切换时创建/移除实体
- 启用/禁用后台任务
- 注册/注销事件监听器
不良模式:
- 更改 Core 的启动行为
- 修改仅在启动时加载的集成逻辑
- 从根本上改变系统初始化流程
- 要求修改
configuration.yaml
5. 建立反馈渠道
在发布功能之前,先建立合适的反馈渠道:
- 社区论坛:在 "Beta" 或 "Feature Requests" 分类中创建主题
- GitHub:可选地创建 discussion,或指定专门的反馈 issue
- 将这些链接填入功能定义中的
feedback_url
选择最适合您需求的渠道。社区论坛主题更适合公开讨论,而 GitHub 更适合技术反馈和问题跟踪。
6. 更新生成的文件
修改 manifest.json 后,运行:
python -m script.hassfest
这会用您的功能更新 homeassistant/generated/labs.py。
7. 记录功能
为预览功能补充文档:
- 更新集成文档页面,说明该实验室功能
- 解释当前预览的内容,以及您希望获得哪些反馈
- 提供清晰的启用说明
8. 创建 My Home Assistant 链接(可选)
您可以创建 "My Home Assistant" 链接,直接跳转到实验室中的对应功能。以下场景尤其适合使用:
- 宣布新预览功能的发行说明
- 带有明确行动引导的文档
- 希望用户轻松试用该功能的社区讨论
链接格式如下:
https://my.home-assistant.io/redirect/labs/?domain=<domain>&preview_feature=<feature_id>
例如:
https://my.home-assistant.io/redirect/labs/?domain=kitchen_sink&preview_feature=special_repair
当用户点击该链接时:
- 会被重定向到其 Home Assistant 实例中的实验室面板
- 页面会自动滚动到您的目标功能
- 功能卡片会高亮显示 3 秒以吸引注意
您可以在以下位置使用这些链接:
- 发行说明:例如“前往实验室面板试用新功能”
- 文档:添加 "My" 链接按钮,方便用户直接启用
- 社区论坛帖子:引导用户测试特定功能
Markdown 示例:
To try this new preview feature, visit {% my labs domain="kitchen_sink" preview_feature="special_repair" title="Labs" %}
and enable the "Special repair" feature.
完整示例:Kitchen Sink Special Repair
有关完整可运行示例,请参见 kitchen_sink 集成:
manifest.json:
{
"domain": "kitchen_sink",
"preview_features": {
"special_repair": {
"feedback_url": "https://community.home-assistant.io",
"learn_more_url": "https://www.home-assistant.io/integrations/kitchen_sink",
"report_issue_url": "https://github.com/home-assistant/core/issues/new"
}
}
}
strings.json:
{
"preview_features": {
"special_repair": {
"name": "Special repair",
"description": "Creates a **special repair issue** when enabled.\n\nThis demonstrates how lab features can interact with other Home Assistant integrations.",
"enable_confirmation": "This will create a special repair issue to demonstrate how preview features can interact with the repairs system. The repair will be removed when you disable this feature.",
"disable_confirmation": "This will remove the special repair issue that was created by this preview feature."
}
},
"issues": {
"special_repair": {
"title": "Special repair feature preview",
"description": "This is a special repair created by a preview feature! This demonstrates how lab features can interact with the Home Assistant repair system. You can disable this by turning off the kitchen sink special repair feature in Settings > System > Labs."
}
}
}
__init__.py:
from homeassistant.components.labs import (
EventLabsUpdatedData,
async_is_preview_feature_enabled,
async_subscribe_preview_feature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up the integration."""
async def _async_update_s