home-assistant · git:20261027.6562616 · 2026-10-27 · sha256 aad8c590d0113fba
home-assistant git:20261027.6562616A
Immutable. This exact content never changes and is served at /api/v1/blob/aad8c590d0113fba.
---
name: home-assistant
description: "Use when automating a smart home with Home Assistant 2026.10 — configuration.yaml and automations.yaml, triggers/conditions/actions YAML, REST API /api/states and /api/services, WebSocket subscribe_events, long-lived access tokens, Docker container installs; also for 'Configuration invalid' after a YAML edit, 401 from the API, template errors, and entities stuck 'unavailable'. Open-source home automation that runs locally."
tags:
- home-assistant
- iot
- automation
- smart-home
- yaml
- rest-api
- websocket
- docker
- python
- mqtt
---
> **项目地址:** <https://github.com/home-assistant/core>
>
> **官方文档:** <https://www.home-assistant.io/docs/>
>
> **开发者文档:** <https://developers.home-assistant.io/>
>
> **最新版本:** 2026.10.4(GitHub Releases 与 Docker 镜像 tag 一致,截至 2026-10)
>
> **安装形态:** Home Assistant OS / Supervised / Container / Core(pip)
>
> **许可证:** Apache-2.0
## 概述
Home Assistant 是一个本地优先的开源家庭自动化平台。它把上千种设备与云服务统一成「实体(entity)」,再通过状态机、自动化规则、脚本与仪表盘把它们编排起来。数据与逻辑都跑在你自己的机器上,不依赖厂商云。
对脚本与自动化最关键的几层:
- **实体与状态**:每个设备暴露为 `domain.name`(如 `light.study`),状态 + 属性构成当前值
- **服务(service/action)**:`light.turn_on`、`climate.set_temperature` 这类可调用动作,是自动化与 API 的执行单位
- **自动化与脚本**:YAML 或 UI 定义的 `triggers/conditions/actions` 三段式规则
- **REST API**:`/api/*`,用长期访问令牌鉴权,适合外部程序读写状态、触发服务
- **WebSocket API**:`/api/websocket`,支持实时订阅事件、订阅触发器、批量取状态
- **模板(Jinja2)**:`{{ states('sensor.x') }}` 在自动化与 `/api/template` 中计算动态值
## 环境准备
### 方式一:Home Assistant OS(推荐给家庭用户)
在 Raspberry Pi / NUC / 虚拟机上刷写官方镜像,得到受管系统(含 Supervised、Add-ons、备份)。安装入口见 <https://www.home-assistant.io/installation/>。首次启动后浏览器访问 `http://<ip>:8123` 完成引导。
### 方式二:Docker Container
```bash
docker run -d \
--name homeassistant \
--restart=unless-stopped \
--privileged \
--network=host \
-e TZ=Asia/Shanghai \
-v /path/to/config:/config \
-v /run/dbus:/run/dbus:ro \
ghcr.io/home-assistant/home-assistant:stable
```
要点:
- `-v /path/to/config:/config` 必须持久化,否则升级即丢配置;
- `--network=host` 让设备发现(mDNS/SSDP)正常工作,端口直接是 8123;
- 需要直通 USB 设备(Zigbee/Z-Wave 棒)时加 `--device /dev/ttyUSB0:/dev/ttyUSB0`;
- 关机给足时间:`docker run --stop-timeout 60`,否则容易损坏数据库。
```yaml
# compose.yaml
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host
privileged: true
stop_grace_period: 60s
environment:
TZ: Asia/Shanghai
volumes:
- ./config:/config
- /run/dbus:/run/dbus:ro
```
### 方式三:Core(pip,仅开发/调试)
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install homeassistant==2026.10.4
hass --config ./config --debug
```
Core 不含 Supervisor 与 Add-ons,适合读源码、改集成、跑测试。
### 验证
```bash
# 容器形态
docker logs -f homeassistant | head -40
# 配置检查(容器内)
docker exec -it homeassistant python -m homeassistant --script check_config -c /config
# API 存活探测(需要长期令牌)
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8123/api/
```
最后一条应返回 `{"message":"API running."}`。
## 核心接口
### 目录与文件
| 路径 | 作用 |
|------|------|
| `configuration.yaml` | 主配置入口,集成、模板、HTTP 等 |
| `automations.yaml` | UI 生成的自动化(**不要手改**,UI 会覆写) |
| `scripts.yaml` / `scenes.yaml` | 脚本与场景 |
| `secrets.yaml` | 密钥,用 `!secret` 标签引用 |
| `.storage/` | 注册表与运行时数据(实体、设备、区域),**不要手改** |
| `home-assistant.log` | 运行日志(也可从 `/api/error_log` 取) |
### configuration.yaml 基础
```yaml
# 基础配置
homeassistant:
name: Home
unit_system: metric
time_zone: Asia/Shanghai
country: CN
currency: CNY
language: zh-Hans
# UI 管理的自动化以 include 方式接入
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
# 拆分配置(推荐:按功能放到 packages/)
homeassistant:
packages: !include_dir_named packages
```
```yaml
# packages/lighting.yaml —— 一个文件描述一整套相关配置
input_boolean:
hallway_night_mode:
name: Hallway night mode
template:
- sensor:
- name: "Living room average temperature"
unit_of_measurement: "°C"
state: >
{{ ((states('sensor.living_room_temp_1') | float(0)
+ states('sensor.living_room_temp_2') | float(0)) / 2) | round(1) }}
```
### 自动化结构(triggers / conditions / actions)
新版写法用复数键 `triggers` / `conditions` / `actions`(旧的单数形式仍在兼容范围内,但新代码应写复数):
```yaml
automation:
- id: "hallway_motion_light"
alias: 走廊有人自动开灯
description: 夜间检测到移动时开灯,2 分钟无移动后关闭
mode: restart
max_exceeded: silent
triggers:
- trigger: state
entity_id: binary_sensor.hallway_motion
from: "off"
to: "on"
for: "00:00:05"
conditions:
- condition: numeric_state
entity_id: sensor.outdoor_illuminance
below: 30
- condition: state
entity_id: input_boolean.hallway_night_mode
state: "on"
actions:
- action: light.turn_on
target:
entity_id: light.hallway
data:
brightness_pct: 40
- wait_for_trigger:
- trigger: state
entity_id: binary_sensor.hallway_motion
to: "off"
for: "00:02:00"
timeout: "00:10:00"
- action: light.turn_off
target:
entity_id: light.hallway
```
自动化内联写在 `configuration.yaml` 时用带标签的块(可多组):
```yaml
automation: !include automations.yaml
automation kitchen:
- triggers:
- trigger: time
at: "06:30:00"
actions:
- action: light.turn_on
target:
entity_id: light.kitchen
```
### REST API
所有请求带 `Authorization: Bearer <long-lived-token>`。令牌在网页界面 **个人资料 → 安全 → 长期访问令牌** 处创建。
| 端点 | 方法 | 用途 |
|------|------|------|
| `/api/` | GET | 健康检查 |
| `/api/config` | GET | 当前配置(版本、单位、时区等) |
| `/api/states` | GET | 全部实体状态 |
| `/api/states/<entity_id>` | GET / POST | 读 / 直接写状态 |
| `/api/services` | GET | 可用服务清单 |
| `/api/services/<domain>/<service>` | POST | 调用服务(核心动作) |
| `/api/events` / `/api/events/<event_type>` | GET / POST | 读事件总线 / 触发自定义事件 |
| `/api/template` | POST | 渲染 Jinja2 模板 |
| `/api/history/period/<timestamp>` | GET | 历史状态 |
| `/api/logbook/<timestamp>` | GET | 日志簿 |
| `/api/error_log` | GET | 文本日志 |
| `/api/config/core/check_config` | POST | 校验配置 |
| `/api/intent/handle` | POST | 走意图识别(语音助手同路径) |
| `/api/calendars` | GET | 日历事件 |
```bash
# 读一个实体的状态
curl -s -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
http://localhost:8123/api/states/light.hallway
# 调用服务:开灯并设置亮度
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"entity_id":"light.hallway","brightness_pct":40}' \
http://localhost:8123/api/services/light/turn_on
# 渲染模板
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"template":"{{ states("sensor.outdoor_illuminance") }} lx"}' \
http://localhost:8123/api/template
```
状态码含义:200/201 成功;400 请求体不合法;401 令牌缺失或失效;404 实体/端点不存在;405 方法用错。
### WebSocket API
连接 `ws://<host>:8123/api/websocket`,走「先认证、后命令」两阶段:
1. 服务器发 `{"type":"auth_required"}`
2. 客户端发 `{"type":"auth","access_token":"..."}`
3. 服务器回 `{"type":"auth_ok",...}`(失败为 `auth_invalid`)
4. 之后每条命令带唯一的 `id`,响应以 `{"type":"result","id":N,...}` 返回;事件推送为 `{"type":"event",...}`
常用命令:`get_states`、`get_config`、`get_services`、`get_panels`、`call_service`、`subscribe_events`、`unsubscribe_events`、`subscribe_trigger`、`fire_event`、`validate_config`、`ping`。
```python
import asyncio, json, websockets
async def main(token: str):
async with websockets.connect("ws://localhost:8123/api/websocket") as ws:
print(json.loads(await ws.recv())) # auth_required
await ws.send(json.dumps({"type": "auth", "access_token": token}))
print(json.loads(await ws.recv())) # auth_ok
await ws.send(json.dumps({"id": 1, "type": "get_states"}))
while True:
msg = json.loads(await ws.recv())
if msg.get("id") == 1 and msg.get("type") == "result":
print("entities:", len(msg["result"]))
break
# 订阅状态变化事件
await ws.send(json.dumps({"id": 2, "type": "subscribe_events",
"event_type": "state_changed"}))
print(json.loads(await ws.recv())) # result: success
print(json.loads(await ws.recv())) # 第一条 state_changed
asyncio.run(main("YOUR_LONG_LIVED_TOKEN"))
```
WebSocket 适合「要实时、要少轮询」的场景;REST 适合一次性读写。
## 典型工作流:外部传感器 → 自动写入状态 → 自动化响应 → 验收
输入:一台跑 Python 的边缘设备,每 30 秒读一次光照度;目标是把数据写进 Home Assistant,让「夜间自动开灯」自动化能用到它。
**步骤 1:创建长期访问令牌**
浏览器进入 `http://<ha>:8123/profile` → **安全** → **长期访问令牌** → 创建,复制整个令牌(只显示一次)。
```bash
export HA_URL="http://localhost:8123"
export TOKEN="<粘贴长期访问令牌>"
curl -s -H "Authorization: Bearer $TOKEN" "$HA_URL/api/" # 期望 {"message":"API running."}
```
**步骤 2:把传感器数值写成实体状态**
```python
import os, time, random, requests
HA = os.environ["HA_URL"]; TOKEN = os.environ["TOKEN"]
HEAD = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
def push_illuminance(lux: float) -> None:
r = requests.post(
f"{HA}/api/states/sensor.balcony_illuminance",
headers=HEAD,
json={"state": round(lux, 1),
"attributes": {"unit_of_measurement": "lx",
"friendly_name": "Balcony illuminance",
"device_class": "illuminance"}},
timeout=10,
)
r.raise_for_status()
if __name__ == "__main__":
while True:
push_illuminance(random.uniform(5, 200)) # 换成真实读数
time.sleep(30)
```
关键点:用固定 `entity_id`(`sensor.balcony_illuminance`)反复 POST,Home Assistant 会更新同一实体而不是新建。Python 里用 f-string 拼 URL 时,注意别让 Jinja 的 `{{ }}` 与 f-string 的花括号互相干扰。
**步骤 3:让自动化消费该实体**
把前面的「走廊有人自动开灯」自动化里 `sensor.outdoor_illuminance` 换成 `sensor.balcony_illuminance`,保存后重新加载自动化(**开发者工具 → YAML → 重新加载自动化**)。
**步骤 4:验证链路**
```bash
# 实体是否已出现、值是否为最新
curl -s -H "Authorization: Bearer $TOKEN" "$HA_URL/api/states/sensor.balcony_illuminance" | python -m json.tool
# 手动触发一次自动化所依赖的服务,确认执行侧正常
curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"entity_id":"light.hallway"}' "$HA_URL/api/services/light/toggle"
```
看 **设置 → 系统 → 日志** 或 `/api/error_log`,确认自动化被触发且没有模板错误。
**步骤 5:收尾**
- 把令牌与 URL 放进环境变量或 `secrets.yaml`,不要提交到仓库;
- 想长期可靠就用 MQTT 或专用集成,直接 POST 状态属于「外部状态注入」,重启后实体状态可能丢失。
## 最佳实践
1. **配置用 `packages` 拆分**:一个功能一个 YAML 文件,避免 `configuration.yaml` 变成千行巨石。
2. **UI 生成的 `automations.yaml` 不要手改**:UI 会整体覆写;要手写就用带标签的 `automation <name>:` 块放到自己的文件。
3. **改完配置先校验**:`python -m homeassistant --script check_config -c /config`,或 POST `/api/config/core/check_config`,再考虑重启。
4. **优先 reload 而不是 restart**:自动化、模板、脚本、input_* 都支持热重载,重启会打断正在跑的自动化。
5. **模板里一律给默认值**:`states('sensor.x') | float(0)`、`| default('unknown')`,实体缺失时避免整条自动化报错。
6. **自动化设 `mode`**:`single`(默认,丢弃重叠)、`restart`(取消旧跑新的)、`queued`(排队)、`parallel`(并行),按语义选。
7. **密钥走 `secrets.yaml`**:用 `!secret` 引用,避免把令牌写进配置或截图。
8. **容器务必持久化 `/config` 并设置停容器超时**:`--stop-timeout 60` / `stop_grace_period: 60s`,否则 SQLite 可能损坏。
## 常见问题
| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 启动后提示 **Configuration invalid** | YAML 语法或集成键值错 | 看通知里的具体文件与行号;跑 `check_config` 定位;常见是缩进用了 Tab 或 `:` 后少空格 |
| REST 调用返回 401 | 令牌缺失、过期或复制不全 | 重新在个人资料页创建长期令牌,确认请求头是 `Bearer <token>`(注意空格) |
| 调用服务返回 400 | 请求体字段名与服务不匹配 | 先 GET `/api/services` 看该服务的字段,再按示例 POST;注意 `entity_id` 与 `target` 的区别 |
| 实体显示 **unavailable** | 集成未加载、设备离线或重启中 | 看 `home-assistant.log`;在 **设置 → 设备与服务** 里重载对应集成 |
| 自动化不触发 | 触发器条件不满足,或自动化被关闭 | 打开自动化的 **追踪(Traces)** 看每一步;确认 `initial_state` 与 UI 上的开关状态 |
| 模板报 `TypeError` / `ValueError` | 实体不存在或值不是数字 | 用 `| float(0)`、`| int(0)`、`| default(...)` 兜底;先用 `/api/template` 单独试算 |
| 升级后集成报错 | 破坏性变更或自定义集成不兼容 | 先读版本发布说明的 Breaking Changes;回滚镜像 tag 到上一个版本 |
| 容器重启后配置全没了 | 没挂载 `/config` 卷 | 停容器,重新以 `-v <host>:/config` 启动;以后先确认卷再升级 |
## AI 使用建议
- **先探版本与形态**:`GET /api/config` 拿 `version` 与 `location_name`;容器内 `docker exec` 跑命令比在宿主机猜路径可靠。
- **改 YAML 前必备份**:`cp configuration.yaml configuration.yaml.bak`,改完先 `check_config`,通过后再 reload/restart。
- **令牌不落盘**:用环境变量传 `TOKEN`,示例里的 `<粘贴长期访问令牌>` 必须替换;不要把令牌写进脚本或报告。
- **验证产物**:写状态后回读 `/api/states/<entity_id>` 核对值与属性;触发服务后看日志或追踪,确认动作真的执行,而不是只看 200。
- **写操作确认**:`POST /api/states` 会覆盖实体状态(重启后可能丢失),`homeassistant.restart` 会中断所有自动化;执行前向用户确认。
## 相关技能
- **node-red** — 另一种低代码自动化编排,常与 HA 通过 MQTT/HTTP 互通:[../node-red/SKILL.md](../node-red/SKILL.md)
- **esphome** — 给 HA 提供原生 API 的 ESP 固件框架:[../esphome/SKILL.md](../esphome/SKILL.md)
- **ke3036-keyes-pico** — 用 MicroPython 直接产出传感器数据:[../ke3036-keyes-pico/SKILL.md](../ke3036-keyes-pico/SKILL.md)
- **ollama** — 本地大模型,可被 HA 的对话助手调用:[../../ai/ollama/SKILL.md](../../ai/ollama/SKILL.md)
## 相关资源
- 官方文档:<https://www.home-assistant.io/docs/>
- 开发者文档(REST / WebSocket / 集成开发):<https://developers.home-assistant.io/>
- 自动化 YAML 参考:<https://www.home-assistant.io/docs/automation/yaml/>
- 模板函数参考:<https://www.home-assistant.io/docs/configuration/templating/>
- 安装方式对比:<https://www.home-assistant.io/installation/>