Home Assistant Lovelace 仪表盘实战:从零搭生产级 UI + 视图/卡片组织 + 卡片模组复用 + 5 个真实坑
适用场景:HA 设备一多,默认仪表盘开始"摊大饼",想把首页做成真正顺手的生产级控制台。一句话结论:用 yaml 模式(
ui-lovelace.yaml)做版本管理,按空间/场景分视图,用 tile + glance + entities 打底,card-mod 与 template 做样式复用,最后避开我在一线踩过的 5 个坑。
1. 从"能用"到"好用":我为什么重写整个仪表盘
上个月有位客户跟我抱怨:"打开 HA 首页,找厨房灯的开关要滑三屏。"我登进去一看——好家伙,47 个实体全摊在一个视图里,温度、开关、摄像头、天气预报混成一锅粥。这就是绝大多数 HA 用户的常态:设备越多,默认仪表盘越乱,最后干脆不看它了。
我做了五年智能家居运维,被问得最多的其实不是"自动化怎么配",而是"主页怎么这么难用"。仪表盘(Lovelace)是 HA 唯一每天都要看的界面,它烂了,再聪明的自动化也白搭。
我给自己定的标准是三条:
- 首屏 3 秒内能找到并操作最常用的设备(灯、空调、门锁);
- 一屏一主题,看环境就环境、看能源就能源,绝不混装;
- 配置可版本管理、可复用,升级 HA 或换硬件时不推倒重来。
按这三条,我把客户的仪表盘从 1 个视图重构成 6 个视图,首屏只留 9 个高频设备。他反馈:"现在进门一划就能开灯。"这就对了。
2. Lovelace 两种模式:storage 和 yaml 怎么选
Lovelace 有两种工作模式,很多人分不清,这是所有 UI 坑的总源头。
| 特性 | storage 模式(默认) | yaml 模式 |
|---|---|---|
| 配置存哪 | .storage/lovelace |
ui-lovelace.yaml |
| 能不能用 UI 编辑器 | 能 | 不能(只读,按钮变灰) |
| 版本管理 / git | 难(JSON 散在 .storage) | 容易(一个纯 YAML 文件) |
| 模板 / 变量 | 几乎不可用 | 完整支持 |
复用片段(!include) |
不可用 | 可用 |
| 我推荐给谁 | 纯小白、临时调试 | 生产环境、多设备、多人维护 |
2.1 怎么切成 yaml 模式
在 configuration.yaml 里加这一段,重启 HA:
重启后,http://<HA>:8123/config/lovelace/dashboards 会出现一个叫 YAML 模式 的仪表盘入口,编辑它的内容就是编辑 ui-lovelace.yaml。UI 右上角的编辑按钮会消失——这是正常的,不是 bug。
2.2 我从 storage 切 yaml 时踩的第一个坑
坑:切换后原来的仪表盘内容"消失"了。 其实不是消失,是 storage 和 yaml 是两套互不迁移的配置。我当时的处理:
- 切模式之前,在 UI 里点右上角三个点 → 编辑 → 右下角三点 → 原始配置编辑器,把整段 YAML 复制出来;
- 把复制的内容粘进新建的
ui-lovelace.yaml; - 再改
configuration.yaml加mode: yaml; - 重启后核对,确认无误才删
.storage/lovelace的备份(建议先打包整个.storage/目录)。
一句话:先导出,再切换,备份 .storage。 切错了能秒回滚,切对了再清理。
3. 视图(views)怎么组织:先分空间、再分场景
视图就是仪表盘顶部的"页签"。组织原则很简单:把操作频率作为第一优先级,把功能相关性作为第二优先级。
我的生产配置习惯是 5-6 个视图:
| 视图 | 路径 | 用途 | 放什么 |
|---|---|---|---|
| 概览 | overview |
默认首页 | 高频灯/空调/门锁,tile + glance |
| 环境 | climate |
温湿度、空气质量 | entities + history 趋势 |
| 能源 | energy |
电量、光伏、峰谷 | energy 卡 + history |
| 影音 | media |
电视/音响/投影 | media 卡 + 场景快捷 |
| 安防 | security |
门磁、摄像头、报警 | glance + camera + 布防开关 |
| 系统 | system |
主机状态、备份 | entities + 状态徽章 |
3.1 视图骨架怎么写
# ui-lovelace.yaml 顶部
title: 我家智能中枢
views:
- title: 概览
path: overview # 地址栏友好名,别用中文
icon: mdi:home # 页签图标
theme: default # 可覆盖主题
# 新版的 sections 布局:按区域分块,天然自适应移动端
sections:
- type: grid
cards:
- type: tile
entity: light.kitchen
- type: grid
cards:
- type: glance
entities: [...]
注意:
path建议全小写英文,title用中文。path一旦定下就别频繁改,否则收藏的书签全失效——这是我在客户家踩过的第 4 个坑(详见第 6 节)。
3.2 每个视图都设一个"默认视图"开关
生产环境多个人共用时,我建议明确首屏:在概览视图加 show_in_sidebar: true,并把 default_view 指到它。这样重启后不会落到"最近一次浏览"的奇怪位置。
3.3 给视图加主题和背景
生产环境我习惯给不同功能区配不同主题色,用 theme 和 background 就能区分"安防红调、能源绿调",用户一眼知道自己在哪个区。
- title: 安防
path: security
icon: mdi:shield-home
theme: red # 引用 /config/themes 下定义的主题
background: "radial-gradient(circle at top, #2b0000 0%, #000 70%)"
themes.yaml 里对应的主题定义:
主题在
themes:里定义(如themes.yaml),theme: red引用其键名。背景用 CSS 渐变,别用整图,移动端加载更快。
4. 常用卡片逐个上手:entities / glance / tile / history / weather / media
卡片是仪表盘的基本积木。下面这六类覆盖了我日常部署的 90% 场景,每类给一个真实片段。
4.1 entities:最通用的"列表 + 控制"
点一行能开关、能弹出更多信息,适合做设备清单。
- type: entities
title: 客厅设备
entities:
- entity: light.living_room
name: 主灯
icon: mdi:floor-lamp
- entity: switch.fan
name: 风扇
tap_action:
action: more-info # 点这一行弹详细面板
- entity: climate.living_room
name: 空调
4.2 glance:一屏只读状态速览
只显示状态不操作,适合"门磁、窗磁、人体感应"这类只看不点的一堆实体。
- type: glance
title: 门窗状态
columns: 4 # 一行 4 个
show_name: true
show_state: true
entities:
- entity: binary_sensor.door_front
name: 大门
- entity: binary_sensor.door_back
name: 后门
- entity: binary_sensor.window_living
name: 客厅窗
- entity: binary_sensor.window_bedroom
name: 卧室窗
4.3 tile:新一代"单设备控制大卡"
2023 年后 HA 主推的 tile 卡片,把状态、操作、跳转集成在一个大方块上,我把它当"首屏主力"。
- type: tile
entity: light.kitchen
icon: mdi:ceiling-light
name: 厨房灯
tap_action:
action: toggle # 点卡片本体 = 开关
hold_action:
action: more-info # 长按 = 详情
# 副按钮:亮度/色温快捷
features:
- type: light-brightness
tile 卡还能用 state_color 让状态直接"上色",比如空调制冷时蓝色、制热时橙色,扫一眼就懂。
- type: tile
entity: climate.living_room
name: 客厅空调
state_color: true # 跟随实体状态上色
icon: mdi:air-conditioner
tap_action:
action: more-info
4.4 history:看趋势,不看快照
排查"晚上室温到底几点开始降"这类问题,history 卡比数字香。
- type: history-graph
title: 24 小时室温
hours_to_show: 24
refresh_interval: 0 # 0 = 不自动刷新,靠事件推送
entities:
- entity: sensor.bedroom_temperature
name: 卧室
- entity: sensor.living_temperature
name: 客厅
4.5 weather:天气,别自己造轮子
配好 weather 集成(如和风天气、Met.no)后,直接引用 weather 实体即可。
4.6 media:影音控制
电视、音响、投影用 media 卡,播放状态、进度、音量一卡搞定。
4.7 conditional:按条件"有则显示,无则隐藏"
安防这类场景里,很多卡片只在特定条件下才有意义。conditional 卡片让"条件不满足就整卡隐藏",避免首页堆满没用的东西。
# 只在"布防中"显示一键撤防按钮
- type: conditional
conditions:
- condition: state
entity: alarm_control_panel.home
state: armed_home
card:
type: tile
entity: alarm_control_panel.home
name: 一键撤防
tap_action:
action: toggle
注意:
conditional只是"前端隐藏",不会阻止实体本身运行。想让自动化真正生效,得靠自动化里的 condition,别指望卡片。
4.8 markdown:放说明、放链接、放自定义内容
运维页我常用 markdown 卡放"值班信息"、"最近一次备份时间",或内嵌一个说明。
- type: markdown
title: 系统信息
content: |
最近备份:**{{ states('sensor.last_backup') }}**
主机温度:{{ states('sensor.host_temperature') }}℃
> 有问题联系值班群:运维-智能家居
我自己的经验:首屏不要超过 3 种卡片类型、10 个实体。 一旦超过,用户就会开始"找"而不是"用"。宁可多分一个视图,也别堆一个页面。
5. 卡片模组:card-mod 与 template 的复用
设备一多,卡片就重复。我不用"复制粘贴 20 遍"这种办法,而是做卡片模组,改一处全站生效。
5.1 card-mod:统一改样式
card-mod 是 HACS 里最常用的自定义卡片之一,它给任何卡片注入 style。我的典型用法是给所有 tile 卡统一圆角、统一高度,并让"异常状态"变红。
# 依赖:HACS 安装 card-mod 自定义卡片,并在 resources 注册
# 下面这个 tile 卡,温度 > 30℃ 时整卡红色边框
- type: tile
entity: sensor.bedroom_temperature
name: 卧室温度
card_mod:
style: |
ha-card {
border-radius: 16px;
{% if states('sensor.bedroom_temperature') | float > 30 %}
border: 2px solid red;
{% endif %}
}
card-mod 的
style: |是模板,能读states(),所以卡片会随着状态实时变色。这是我最喜欢的能力。
5.2 template:一个卡片,多种状态长相
用 template 自定义卡片,根据实体状态动态渲染内容、图标、甚至跳转目标。
- type: custom:template-card
card:
type: tile
entity: cover.garage_door
name: 车库门
style: | # 用模板控制图标与颜色
ha-card {
--tile-icon-color: {% if is_state('cover.garage_door', 'open') %}orange{% else %}green{% endif %};
}
5.3 复用片段:!include 把重复抽出去
把"环境一组"和"安防一组"这种常驻片段抽成独立文件,用 !include 拉进来,维护就只改一处。
# ui-lovelace.yaml
views:
- title: 概览
cards: !include cards/overview.yaml # 片段在 cards/overview.yaml
- title: 环境
cards: !include cards/environment.yaml
cards/overview.yaml 长这样:
# cards/overview.yaml —— 被 !include 引用的片段,无需 views 包裹
- type: tile
entity: light.kitchen
name: 厨房灯
- type: glance
title: 门窗
entities:
- binary_sensor.door_front
- binary_sensor.window_living
这个
!include是 yaml 模式的专属红利,storage 模式做不到。这也是我推荐生产环境用 yaml 模式的核心理由。
5.4 给片段传参:template-card 的 variables
!include 只能整体拉入,想"同一张卡复用 N 次、每次实体不同",我用 template-card 的 variables 传参。把"门磁卡"做成一个模板,传入不同实体即可复用。
# 模板定义(放 cards/door-card.yaml,用 !include 拉入)
type: custom:template-card
card:
type: tile
entity: "{{ door_entity }}" # 变量
name: "{{ door_name }}"
icon: "{{ 'mdi:door-open' if is_state(door_entity,'on') else 'mdi:door-closed' }}"
card_mod:
style: |
ha-card {
--tile-icon-color: {{ 'red' if is_state(door_entity,'on') else 'green' }};
}
# ui-lovelace.yaml 里调用两次,传不同变量
- type: custom:template-card
variables:
door_entity: binary_sensor.door_front
door_name: 大门
- type: custom:template-card
variables:
door_entity: binary_sensor.door_back
door_name: 后门
这样"门磁卡"的样式、逻辑只写一次,以后想统一改颜色,只动模板一处。这也是"卡片模组"最完整的形态:样式 + 逻辑 + 数据三分离。
6. 我遇到过的 5 个真实坑(附处理办法)
下面五个坑,每一个都在客户现场真实发生过。排障思路比报错本身值钱。
坑 1:YAML 语法——用 Tab 缩进,整页崩
有次我给客户改 ui-lovelace.yaml,粘了一段从网页复制的内容,缩进是 Tab 不是空格。保存后整个仪表盘直接白屏,HA 日志提示 YAML parsing error。
处理:YAML 铁律——只用空格,不用 Tab。缩进层级建议 2 空格,同一层级必须对齐。另一个高频雷是字符串里带冒号或井号:
# 错:冒号后跟空格被当成键值分隔
name: 客厅: 主灯
# 对:整个串用引号包起来
name: "客厅: 主灯"
# 错:# 后面被当注释吞掉
title: 报警 #1
# 对:
title: "报警 #1"
模板字符串里也容易翻车——{{ states('sensor.x') > 10 }} 里的 > 在 YAML 里是"折叠标量"符号,建议整个模板用引号包住:
排查工具:配置校验页 /config/server_control 或 ha core check;编辑器装 YAML lint 插件能省一半时间。
坑 2:权限——家庭成员看不到卡片
有个用户反馈"老婆登录后看不到安防视图"。我查了下,是他给安防视图加了 user 权限白名单,但只加了 admin 组,普通用户被排除。
处理:在视图上显式控制可见性,或检查用户组实体过滤。
另一个隐藏权限坑:实体级权限。如果用户组在 configuration.yaml 里配了 entities 白名单,那卡片引用的实体不在名单内就会"隐形",看起来像卡片没渲染。用管理员登录,在开发者工具 → States 确认实体真实存在且状态正常,再倒查权限。
坑 3:刷新——模板卡片不更新,改了配置不生效
最气人的坑:模板卡片的数字永远停在旧值。原因通常是没有正确订阅状态——模板里写了字面量,或者用 states() 但实体名写错。
处理:模板卡片里让 HA "订阅"你关心的实体。推荐 states('sensor.x') 或 this.entity:
- type: custom:template-card
card:
type: markdown
content: "室温 {{ states('sensor.living_temperature') }}℃"
只要 states('sensor.living_temperature') 被引用,HA 就会在它变化时重算卡片。千万别把状态写死在 content 里,那永远不更新。
改完 ui-lovelace.yaml 也要注意:yaml 模式改文件后要重载前端,否则浏览器拿着旧 JS 不放。我在客户家经常直接 Ctrl+F5 强刷。如果还旧,进开发者工具 → 应用 → 清除站点数据再刷新。
坑 4:实体 ID 变化——改个名,全站变 unknown
客户把 sensor.water_temperature 改名成 sensor.bath_water_temp,没同步仪表盘。结果概览上一整排卡片全显示 unknown。
处理:改名后全局搜一遍旧 ID。
我自己的习惯:所有卡片引用的实体 ID 只用一次定义,能少写就少写。比如用 !include 片段集中管理实体清单,改 ID 只动一处。另外 HA 在开发者工具 → 统计 页有"实体被引用位置"检索,能一键定位哪些自动化/仪表盘还引用旧 ID。
坑 5:自定义卡片白屏——resources 没加载对
装了 HACS 的自定义卡片(card-mod、template-card、mini-media-player 等),必须先在 Lovelace 资源里注册 JS 地址,否则卡片区域直接空白或报 custom element not defined。
处理:在 configuration.yaml 注册 lovelace: resources,或直接在仪表盘 → 资源 页添加。常见错误是 url 写错、或 HACS 更新后缓存了旧 JS。
# configuration.yaml
lovelace:
mode: yaml
resources:
- url: /hacsfiles/card-mod/card-mod.js
type: module
- url: /hacsfiles/template-card/template-card.js
type: module
白屏时先开浏览器开发者工具 → Console,看到 Failed to load module script 或 Failed to resolve module specifier,就是 URL 问题;看到 SyntaxError 就是 JS 版本不匹配(HACS 刚更新过),强刷缓存或重装该卡片。
7. 一份完整的生产配置示例
下面是我给一个"两室一厅 + 车库"客户落地、并稳定跑了半年的 ui-lovelace.yaml(节选主干)。它体现了前面所有原则:yaml 模式、分视图、tile 打底、card-mod 统一风格、!include 抽片段。
# ============================================================
# ui-lovelace.yaml —— 生产级 Lovelace 配置
# 启用:configuration.yaml 里加
# lovelace:
# mode: yaml
# ============================================================
title: 我的家
views:
# ---------- 视图 1:概览(默认首页) ----------
- title: 概览
path: overview
icon: mdi:home
show_in_sidebar: true
sections:
# 区块 1:最常用灯,tile 大卡
- type: grid
cards:
- type: tile
entity: light.kitchen
icon: mdi:ceiling-light
name: 厨房灯
tap_action:
action: toggle
- type: tile
entity: light.living_room
icon: mdi:floor-lamp
name: 客厅灯
tap_action:
action: toggle
- type: tile
entity: climate.bedroom
name: 卧室空调
tap_action:
action: more-info
# 区块 2:门窗只看不点
- type: grid
cards:
- type: glance
title: 门窗状态
columns: 4
entities:
- entity: binary_sensor.door_front
name: 大门
- entity: binary_sensor.window_living
name: 客厅窗
- entity: binary_sensor.window_bedroom
name: 卧室窗
- entity: binary_sensor.door_garage
name: 车库门
# 区块 3:快捷开关列表
- type: grid
cards:
- type: entities
title: 快捷开关
entities:
- entity: switch.water_heater
name: 热水器
- entity: switch.garden_light
name: 庭院灯
- entity: fan.living_room
name: 客厅风扇
tap_action:
action: more-info
# ---------- 视图 2:环境 ----------
- title: 环境
path: climate
icon: mdi:thermometer
cards:
- type: entities
title: 室内外温湿度
entities:
- entity: sensor.living_temperature
name: 客厅
- entity: sensor.bedroom_temperature
name: 卧室
- entity: sensor.outdoor_temperature
name: 室外
- entity: sensor.air_quality
name: PM2.5
- type: history-graph
title: 24 小时温度曲线
hours_to_show: 24
refresh_interval: 0
entities:
- sensor.living_temperature
- sensor.bedroom_temperature
- sensor.outdoor_temperature
- type: weather
entity: weather.my_home
show_forecast: true
forecast_type: daily
# ---------- 视图 3:能源 ----------
- title: 能源
path: energy
icon: mdi:flash
cards:
- type: energy-usage-graph
title: 实时功率
- type: energy-solar-graph
title: 光伏发电
- type: energy-gas-graph
title: 燃气用量
# ---------- 视图 4:影音 ----------
- title: 影音
path: media
icon: mdi:movie
cards:
- type: media-control
entity: media_player.living_tv
name: 客厅电视
- type: entities
title: 播放设备
entities:
- entity: media_player.speaker
name: 智能音箱
- entity: media_player.projector
name: 投影仪
# ---------- 视图 5:安防 ----------
- title: 安防
path: security
icon: mdi:shield-home
visibility:
- user: admin
- user: family
cards:
- type: tile
entity: alarm_control_panel.home
name: 一键布防
tap_action:
action: more-info
- type: glance
title: 传感器
columns: 3
entities:
- entity: binary_sensor.motion_living
name: 客厅移动
- entity: binary_sensor.motion_garage
name: 车库移动
- entity: binary_sensor.leak_kitchen
name: 厨房漏水
# 用 card-mod 给"漏水"传感器加红色警示态
- type: entities
title: 环境告警
entities:
- entity: binary_sensor.leak_kitchen
card_mod:
style: |
ha-entity-row {
{% if is_state('binary_sensor.leak_kitchen','on') %}
color: red; font-weight: bold;
{% endif %}
}
# ---------- 视图 6:系统(运维专用) ----------
- title: 系统
path: system
icon: mdi:cog
cards:
- type: entities
title: 主机状态
entities:
- entity: sensor.host_temperature
name: 主机温度
- entity: sensor.disk_used_percent
name: 磁盘占用
- entity: sensor.memory_used_percent
name: 内存占用
- entity: sensor.uptime
name: 运行时长
- type: markdown
title: 运维信息
content: |
- 最近备份:**{{ states('sensor.last_backup') }}**
- HA 版本:{{ states('sensor.ha_version') }}
- 配置模式:yaml(ui-lovelace.yaml)
- type: conditional
conditions:
- condition: numeric_state
entity: sensor.disk_used_percent
above: 90
card:
type: markdown
content: |
⚠️ **磁盘占用超 90%**,请尽快清理或扩容!
这份配置我建议直接按需复制,把实体 ID 换成你自己的,path 保持英文、title 随意中文。切 yaml 模式后保存、重载前端即可。
8. 性能与排障:白屏、不刷新、缓存
8.1 仪表盘变慢、打开卡顿
常见原因三个,按优先级排查:
- 模板卡片滥用:一个视图里几十个
template卡,每个都触发重算,前端会卡。用state绑定或减少模板,能合并就合并。 - history-graph 卡太多:历史查询重。把
hours_to_show收小,或用refresh_interval拉长。 - 太多实体同时加载:首屏塞 40+ 实体,WebSocket 推送压力大。拆视图、用
sections懒加载。
8.2 白屏三板斧
遇到整页白屏,按顺序做:
- 强刷:
Ctrl+F5,清掉旧 JS。 - 看 Console:开发者工具 → Console,十有八九是 resources 里的自定义卡片没加载(坑 5)。
- 看日志:HA 日志(
/config/home-assistant.log)搜lovelace或frontend,YAML 解析错误会直接点名。
8.3 改配置不生效
yaml 模式下改完文件,记得重载前端:设置 → 系统 → 右上角三点 → 重载 YAML。只改 ui-lovelace.yaml 时,其实前端刷新就够,不需要重启 HA。如果改的是 configuration.yaml(比如 resources),必须重启。
8.4 生产部署三件套
- 备份:改任何 UI 配置前,先备份
.storage/lovelace(storage 模式)或ui-lovelace.yaml(yaml 模式); - 版本化:把
ui-lovelace.yaml放进 git,commit message 写清楚改了什么,出问题git diff秒定位; - 灰度:大改仪表盘先在测试实例上验证,再上生产。我在客户家从不直接在生产上做 30 行的重构。
8.5 移动端适配:grid_options 与 view_layout
手机访问是仪表盘最常见的场景。新版 sections 布局自带响应式堆叠,但老的卡片式布局要靠 view_layout / grid_options 显式控制列宽。我的做法是:桌面双列,手机单列。
如果你的 HA 版本还支持 view_layout(旧版),可以这样精确控制:
# 需要 custom-lovelace 的 view-layout 支持时
cards:
- type: tile
entity: light.kitchen
view_layout:
grid-area: sidebar # 固定到侧边区域
移动端优化的核心是减少首屏实体数 + 让卡片自适应。我实测:手机单屏能舒服显示 6-8 个 tile 卡,超过就开始滑屏,交互体验直线下降。宁可拆视图,别硬挤。
9. 常见问题 FAQ
Q:为什么我改了 ui-lovelace.yaml 但页面没变化?
A:yaml 模式改完要刷新前端。Ctrl+F5 强刷;若改了 configuration.yaml 的 lovelace.resources,需重启 HA。
Q:如何把一个视图默认展示给所有人?
A:在概览视图设 show_in_sidebar: true,并在 views 里把它排第一,或设 default_view。
Q:tile 卡和 entities 卡怎么选? A:单个高频设备、要"点一下就能开关"的用 tile;一堆设备要列表管理、带跳转详情的用 entities。首屏推荐 tile,二级页推荐 entities。
Q:自定义卡片必须装 HACS 吗?
A:card-mod、template-card 这类一般走 HACS 安装,装完要在 lovelace.resources 注册 JS。不注册就会白屏/报错。
Q:手机端仪表盘很挤怎么办?
A:用 sections 布局(新版),卡片会自动堆叠;或给卡片加 view_layout / grid_options 控制列宽。别用 columns 写死。
把仪表盘当成"每天都要用的工具"而不是"配置好的装饰品",你会发现 HA 的体验完全不一样。上面这些配置和坑,我都在真实项目里趟过。你现在要做的,就是切到 yaml 模式,把那份生产配置拷回去,换上你自己的实体 ID——然后记得先备份。