Home Assistant Integration Patterns
Service Response Data Pattern
The Problem
By default, HA services are "fire-and-forget" and return empty arrays
[].
The Solution (HA 2023.7+)
Register service with
supports_response:
CODEBLOCK0
Call with ?return_response flag:
CODEBLOCK1
Response Handler
async def handle_get_full_config(hass: HomeAssistant, call: ServiceCall):
"""Handle the service call and return data."""
# ... your logic ...
return {"entities": entity_data, "automations": automation_data}
HTTP View vs Service: When to Use Each
| Use Case | Use | Don't Use |
|---|
| Return complex data | HTTP View | Service (without response support) |
| Fire-and-forget actions |
Service | HTTP View |
| Trigger automations | Service | HTTP View |
| Query state/config | HTTP View | Internal storage APIs |
HTTP View Pattern
For data retrieval APIs:
CODEBLOCK3
Critical: Avoid Internal APIs
Never use underscore-prefixed APIs — they're private and change between versions.
❌ Wrong:
CODEBLOCK4
✅ Right:
# Use public APIs only
from homeassistant.helpers.storage import Store
store = Store(hass, STORAGE_VERSION, STORAGE_KEY)
Storage Patterns
For Small Data (Settings, Cache)
CODEBLOCK6
For Large Data (History, Logs)
Use external database or file storage, not HA storage helpers.
Breaking Changes to Watch
| Change | Version | Migration |
|---|
| Conversation agents | 2025.x+ | Use async_process directly |
| Service response data |
2023.7+ | Add
supports_response param |
| Config entry migration | 2022.x+ | Use
async_migrate_entry |
Always check: https://www.home-assistant.io/blog/ for your target version range.
HACS Integration Structure
CODEBLOCK7
Minimal manifest.json
{
"domain": "your_domain",
"name": "Your Integration",
"codeowners": ["@yourusername"],
"config_flow": true,
"dependencies": [],
"requirements": [],
"version": "1.0.0"
}
Testing Checklist
- - [ ] Service calls return expected data (with
?return_response) - [ ] HTTP views accessible with auth token
- [ ] No underscore-prefixed API usage
- [ ] Storage persists across restarts
- [ ] Config flow creates config entry
- [ ] Error handling returns meaningful messages
Documentation Resources
- - Integration basics: INLINECODE7
- Service calls: INLINECODE8
- HTTP views: INLINECODE9
- Breaking changes:
home-assistant.io/blog/ (filter by version) - HACS guidelines: INLINECODE11
Lesson Learned
From HA-OpenClaw Bridge attempt:
"80% of our issues were discoverable with 30-60 minutes of upfront docs reading. We jumped straight to coding based on assumptions rather than reading how HA actually works."
Use skills/pre-coding-research/ methodology before starting.
Home Assistant 集成模式
服务响应数据模式
问题
默认情况下,HA 服务是即发即弃的,返回空数组 []。
解决方案(HA 2023.7+)
使用 supports_response 注册服务:
python
from homeassistant.helpers.service import SupportsResponse
hass.services.async_register(
domain,
getfullconfig,
handlegetfull_config,
schema=GETCONFIGSCHEMA,
supports_response=SupportsResponse.ONLY, # ← 关键参数
)
使用 ?return_response 标志调用:
bash
curl -X POST $HAURL/api/services/yourdomain/getfullconfig?return_response
响应处理器
python
async def handle
getfull_config(hass: HomeAssistant, call: ServiceCall):
处理服务调用并返回数据。
# ... 你的逻辑 ...
return {entities: entity
data, automations: automationdata}
HTTP 视图与服务:何时使用
| 使用场景 | 使用 | 不使用 |
|---|
| 返回复杂数据 | HTTP 视图 | 服务(无响应支持) |
| 即发即弃操作 |
服务 | HTTP 视图 |
| 触发自动化 | 服务 | HTTP 视图 |
| 查询状态/配置 | HTTP 视图 | 内部存储 API |
HTTP 视图模式
用于数据检索 API:
python
from homeassistant.components.http import HomeAssistantView
class OpenClawConfigView(HomeAssistantView):
用于检索配置的 HTTP 视图。
url = /api/openclaw/config
name = api:openclaw:config
requires_auth = True
async def get(self, request):
hass = request.app[hass]
config = await getconfigdata(hass)
return json_response(config)
在 async_setup 中注册:
hass.http.register_view(OpenClawConfigView())
关键:避免使用内部 API
切勿使用以下划线为前缀的 API——它们是私有的,会在版本之间发生变化。
❌ 错误:
python
storagecollection = hass.data[storage_collection]
✅ 正确:
python
仅使用公共 API
from homeassistant.helpers.storage import Store
store = Store(hass, STORAGE
VERSION, STORAGEKEY)
存储模式
适用于小数据(设置、缓存)
python
from homeassistant.helpers.storage import Store
STORAGEKEY = yourdomain.storage
STORAGE_VERSION = 1
store = Store(hass, STORAGEVERSION, STORAGEKEY)
保存
data = {entities: modified_entities}
await store.async_save(data)
加载
data = await store.async_load()
适用于大数据(历史记录、日志)
使用外部数据库或文件存储,而非 HA 存储助手。
需关注的破坏性变更
| 变更 | 版本 | 迁移方式 |
|---|
| 对话代理 | 2025.x+ | 直接使用 asyncprocess |
| 服务响应数据 |
2023.7+ | 添加 supportsresponse 参数 |
| 配置条目迁移 | 2022.x+ | 使用 async
migrateentry |
始终检查: https://www.home-assistant.io/blog/ 以了解你的目标版本范围。
HACS 集成结构
customcomponents/yourdomain/
├── init.py # asyncsetupentry
├── config_flow.py # UI 配置
├── manifest.json # 依赖项、版本
├── services.yaml # 服务定义
└── storage_services.py # 你的存储逻辑
最小化 manifest.json
json
{
domain: your_domain,
name: Your Integration,
codeowners: [@yourusername],
config_flow: true,
dependencies: [],
requirements: [],
version: 1.0.0
}
测试清单
- - [ ] 服务调用返回预期数据(使用 ?return_response)
- [ ] HTTP 视图可通过认证令牌访问
- [ ] 未使用以下划线为前缀的 API
- [ ] 存储数据在重启后持续存在
- [ ] 配置流创建配置条目
- [ ] 错误处理返回有意义的消息
文档资源
- - 集成基础:developers.home-assistant.io/docs/creatingintegrationindex
- 服务调用:developers.home-assistant.io/docs/dev101services
- HTTP 视图:developers.home-assistant.io/docs/api/webserver
- 破坏性变更:home-assistant.io/blog/(按版本筛选)
- HACS 指南:hacs.xyz/docs/publish/start
经验教训
来自 HA-OpenClaw 桥接尝试:
我们 80% 的问题本可以通过 30-60 分钟的前期文档阅读来发现。我们直接基于假设开始编码,而没有阅读 HA 的实际工作原理。
在开始之前使用 skills/pre-coding-research/ 方法论。