Home Assistant

💡 快速導航

Home Assistant 是我家智慧裝置的控制與自動化中樞。它不只是把不同品牌的設備集中到同一個 Dashboard,而是把「人在不在家、現在幾點、設備狀態如何」組合成可以長期維護的生活流程。

我把 Home Assistant 跑在 OMV 的 Docker 環境,讓 OMV 負責運算與容器管理,設定資料則透過持久化掛載保存。這也延續整套 Home Lab 的分層原則:TrueNAS 管資料,OMV 管服務。


🎯 我為什麼用它

不想每個品牌都開一個 App

家裡的燈、空調、空氣清淨機、攝影機、電視和感測器來自不同品牌。若只使用原廠 App,每個設備都各自運作,很難做跨品牌聯動。

Home Assistant 把它們整理成統一的 entity,讓我可以用相同方式控制、監看與自動化。

自動化要依照生活情境,而不是單一排程

固定時間開燈很容易,但真正好用的自動化會同時考慮:

  • 家裡是否有人
  • 現在是白天還是晚上
  • 電視、空調或空氣清淨機目前是否運作
  • 空氣品質是否真的允許關閉清淨機
  • 動作失敗時是否還能手動控制

優先在本地完成控制

能走區網、Bluetooth、MQTT 或本地 API 的設備,我會優先使用本地整合。即使外網或原廠雲端暫時異常,核心控制和多數自動化仍能繼續運作。


🧱 我的架構

flowchart TD
    U[手機 / 平板 / 瀏覽器] --> RP[反向代理 / HTTPS]
    RP --> HA[Home Assistant<br/>OMV / Docker]
    SSO[OpenID SSO] --> HA

    LAN[區網探索 / Bluetooth / MQTT] --> HA
    HA --> IOT[燈光 / 空調 / 清淨機 / 感測器]
    HA --> CAM[攝影機 / Frigate]
    HA --> MEDIA[電視 / Cast / Plex]
    HA --> INFRA[OpenWrt / OMV]
    HA --> DATA[(Config / Backup)]

部署摘要

項目目前做法原因
運行主機OMV集中承載 Home Lab 的 Docker 服務
部署方式Docker Compose設定可追蹤,升級與回滾流程一致
版本策略固定 image tag避免 latest 在重建時意外跨版本
盤點時版本Home Assistant Core 2026.8.2本文記錄的是這個版本的實際狀態
網路network_mode: host讓 mDNS、裝置探索與區網整合較直接
設定資料Host path 掛載到 /config容器重建後仍保留設定與歷史資料
Bluetooth掛載 Host D-Bus讓 Home Assistant 使用主機的 Bluetooth stack
對外入口反向代理 + HTTPS + OpenID SSO統一入口,不直接公開原始服務端口
備份每週完整備份 + 升級前備份同時處理日常故障與版本升級風險

Docker Compose 摘要

以下是移除私人路徑與環境資訊後的核心配置:

services:
  homeassistant:
    container_name: homeassistant
    image: homeassistant/home-assistant:2026.8.2
    environment:
      - TZ=<your-timezone>
    volumes:
      - <config-path>:/config
      - ./patches/luci/device_tracker.py:/usr/src/homeassistant/homeassistant/components/luci/device_tracker.py:ro
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    restart: unless-stopped
    privileged: true
    cap_add:
      - NET_ADMIN
    network_mode: host

Warning

host network、privileged: true 與 NET_ADMIN 是我目前為了區網探索、Bluetooth 和既有整合採用的配置,不代表每個環境都需要。它們會擴大容器權限,部署時應逐項確認並盡量縮小權限範圍。


🔌 裝置與整合

我的重點不是追求整合數量,而是把每天真的會互相影響的設備放進同一套狀態模型。

類別目前使用的整合與設備
燈光與開關TP-Link / Tapo、Tuya / LocalTuya、Xiaomi、Govee、SwitchBot、ESPHome
空調與環境Resideo / Honeywell Home T6 Pro、Blueair、Qingping、天氣與空氣品質資料
影音設備Android TV、Apple TV、Google Cast、Plex
攝影機Tapo、Frigate、go2rtc
PresenceHome Assistant Companion App、Bluetooth / iBeacon、OpenWrt LuCI
Home LabOpenMediaVault、MQTT、網路設備狀態
UIHACS、Mushroom、UI Lovelace Minimalist

Dashboard 目前依用途分成 Home、Lights、Devices 與 Network 等頁面。首頁只放每天需要確認的狀態;詳細控制和診斷資訊則拆到其他頁面,避免所有 entity 都塞在同一張 Dashboard。

我也建立了 template sensors,集中顯示目前開啟的燈、開關和異常感測器數量。這比逐個巡視設備更適合當作家庭狀態摘要。


❄️ 空調與溫控

家中的冷氣與暖氣由 Resideo(Honeywell Home)T6 Pro thermostat 控制。Home Assistant 透過內建的 HomeKit Controller 在區網內連接 thermostat,不需要經過原廠雲端才能讀取狀態或下達指令。

Home Assistant → HomeKit Controller → T6 Pro Thermostat → HVAC

在 Dashboard 的 thermostat card 中,我可以直接查看目前溫度、調整目標溫度,並切換 cool、heat 和 off 模式。相同的 climate entity 也提供給 automation 使用,因此手動控制與自動節能不需要維護兩套狀態。

目前的空調自動化

自動化條件動作
Cooling Midnight Off每天凌晨 1:00,且 HVAC 仍在 cool 模式將 HVAC mode 設為 off
Away HVAC Off主要 Presence 離家 10 分鐘,且 HVAC 在 cool 或 heat 模式將 HVAC mode 設為 off

凌晨自動關閉是一道避免冷氣整夜運作的安全網;離家延遲則用來過濾手機短暫斷線,避免一離線就立刻關機。

Note

目前 Away HVAC Off 仍由單一主要 Presence 觸發。多人家庭更完整的做法應改成「所有成員都離家」後再關閉空調,避免家中仍有人時被誤關。


⚡ 我每天真的用到的自動化

情境Trigger / ConditionAction
離家攝影機模式家中成員都離開一段時間關閉隱私模式並啟用需要的監控功能
回家攝影機模式成員回到家恢復攝影機隱私模式
空調午夜關閉凌晨 1:00,且空調仍在製冷關閉 HVAC
空調離家節能主要 Presence 離家 10 分鐘,且冷氣或暖氣仍在運作關閉 HVAC
電視情境燈電視開啟或關閉,再判斷日出/日落開啟合適的電視牆燈,關機時關燈
空氣清淨機固定時段或成員離家,並檢查空氣品質開關清淨機,避免空氣差時過早關閉
NFC 快捷操作掃描已註冊的 NFC tag執行關燈等常用動作
每週備份每週六凌晨建立壓縮完整備份並保留 14 天

我的自動化原則

  1. 先確認狀態,再執行動作:避免設備已經關閉時重複呼叫。
  2. 離家判斷要有緩衝時間:手機短暫斷線不應立即觸發整套 away automation。
  3. 多人家庭要看整體 Presence:一個人離開,不代表家裡沒人。
  4. 保留手動控制:自動化失效時,原本的開關或 App 仍能使用。
  5. 高風險動作要另外保護:門鎖等操作不能只依賴可複製的 tag,還要考慮手機解鎖、通知與實體安全。

📍 Presence Detection:最值得記錄的坑

Presence 是攝影機隱私模式、空調節能和離家流程的共同基礎。一旦誤判,後面的自動化即使寫得完全正確,結果仍然會錯。

問題:OpenWrt 的 reachable 不是穩定的「人在家」訊號

我使用 OpenWrt LuCI tracker 觀察手機是否連在家中網路。實際上,OpenWrt neighbor table 的 reachable flag 可能短暫變成 false,即使手機仍在家中 Wi-Fi。

原本的 LuCI integration 還有另一個邊界情況:若已註冊的手機沒有出現在第一次 only_reachable=True 掃描中,對應 tracker entity 可能根本不會建立,後續輪詢也無法讓它恢復。

我的處理方式

flowchart LR
    R[OpenWrt LuCI] --> RAW[Raw device tracker]
    RAW --> PATCH[本地 LuCI patch]
    PATCH --> SMOOTH[Template tracker<br/>3-8 分鐘 debounce]
    SMOOTH --> PERSON[Person entity]
    PERSON --> AUTO[家庭自動化]

我保留 only_reachable=True,避免把舊 ARP 紀錄誤認為還在家;同時用一個版本綁定的本地 patch,讓已經註冊過的裝置即使第一次掃描缺席,也會先建立為 not_home,之後可在 30 秒輪詢中恢復。

Raw tracker 之上再加一層 template tracker:

  • 回到 home 時立即更新
  • 變成 not_home 時等待 3-8 分鐘
  • 等待期間若重新連線,就不觸發離家流程

概念化設定如下,實際 entity ID 已隱藏:

template:
  - trigger:
      - platform: state
        entity_id: device_tracker.<phone>
        to: "home"
      - platform: state
        entity_id: device_tracker.<phone>
        to: "not_home"
        for: "00:05:00"
    device_tracker:
      - name: phone_smoothed
        in_zones: >-
          {{ ['zone.home'] if states('device_tracker.<phone>') == 'home' else [] }}

Important

這個 patch 直接覆蓋 Home Assistant image 內的 LuCI module,因此每次升級 Home Assistant 都必須先和新版 upstream 檔案比較。若官方已修正,就應移除 patch,而不是永久維護自己的 fork。


🖥️ Dashboard 的定位

Dashboard 是控制與觀察介面,不應成為自動化邏輯本身。

這是目前掛在牆上的 Home Assistant WebUI。硬體本身是一台便宜的 Android 平板,主要用途是把家庭常用控制、溫濕度、空氣品質和空調狀態固定展示在一個隨手可看的位置。

  • Home:家庭摘要、Presence、天氣和常用控制
  • Lights:依房間整理燈光與群組
  • Devices:空調、清淨機、掃地機器人與影音設備
  • Network:Home Lab 和網路設備狀態

我使用 HACS 安裝部分前端元件,並搭配 Mushroom 與 UI Lovelace Minimalist。UI 可以慢慢調整,但 entity 命名、area 分類與 automation 邏輯要先穩定,否則 Dashboard 做得再漂亮也很難維護。


💾 備份與還原

目前由 Auto Backup automation 在每週六凌晨建立壓縮完整備份,保留 14 天;每次升級前再額外建立一份手動備份。

我會保護的內容

  • configuration.yaml 與拆分出去的 YAML 設定
  • .storage 內的 integration、entity registry 和 Dashboard 設定
  • automations.yaml、scripts.yaml 與 scenes.yaml
  • custom_components、themes 與前端資源
  • secrets 與憑證,但不放進公開文件或公開 repository
  • Recorder database;它是歷史資料,不應是唯一可用的設定備份

還原順序

  1. 停止 Home Assistant container。
  2. 保留故障現場的 config 副本,避免直接覆蓋唯一線索。
  3. 還原最後一份確認可用的設定與備份。
  4. 使用原本固定的 image tag 啟動,不要在還原時同時升級。
  5. 檢查登入、核心 integration、Presence、攝影機隱私模式與空調控制。
  6. 確認無誤後,再處理版本升級或歷史資料。

我曾留下過損壞的 SQLite Recorder database,這提醒我:備份設定、備份歷史資料和實際做還原演練,是三件不同的事。


⬆️ 升級流程

Home Assistant 更新很快,而我的環境還有 HACS integrations 與 LuCI 本地 patch,所以我不使用 latest 自動追版。

升級前

  1. 閱讀 release notes,特別注意 deprecated integrations 與 YAML breaking changes。
  2. 建立完整備份,並記錄目前可回滾的 image tag。
  3. 確認 HACS custom integrations 支援目標版本。
  4. 比較新版 LuCI device_tracker.py 與本地 patch。
  5. 執行 docker compose config --quiet,先排除 Compose 結構或環境變數錯誤。
  6. 使用 Home Assistant 的 configuration check 驗證設定。

升級後

  1. 確認 container 正常啟動,檢查 error log。
  2. 重新載入 LuCI,確認 raw 與 smoothed trackers 都能恢復。
  3. 測試離家/回家、攝影機隱私、空調、燈光與 TTS。
  4. 確認 Dashboard 和 HACS cards 沒有前端錯誤。
  5. 確認下一次排程備份可以正常建立。

若核心功能失敗,我會先回滾 image tag 和設定,而不是在壞掉的 production instance 上連續嘗試多個變更。


🔐 安全與隱私

  • 對外存取統一經過 HTTPS 反向代理,不直接公開 Home Assistant 原始端口。
  • OpenID SSO 是登入便利層,不能取代 Home Assistant 權限、強密碼與 MFA。
  • API key、client secret、精確位置、內網 IP、device ID 和 tag ID 都不應出現在公開筆記。
  • YAML 需要憑證時使用 !secret,並確保 secrets 與 .env 不會進入公開 Git repository。
  • privileged、NET_ADMIN 與 host network 都要定期檢查是否仍有必要。
  • 攝影機自動化預設以家庭隱私為優先;任何異常都應能手動切回隱私模式。

🧯 我踩過的坑

1. 把 Presence 當成絕對真相

Wi-Fi tracker、Bluetooth 和手機 App 都可能短暫離線。真正穩定的 Presence 需要 debounce、多人條件和失敗時的安全預設。

2. 太早建立複雜自動化

如果一開始就把十幾個條件塞進同一條 automation,後面任何 entity 改名都可能牽一髮動全身。先做 2-3 個每天一定會用到的流程,比一次完成「全屋自動化」可靠。

3. Custom integration 和 patch 都有維護成本

HACS 很方便,但每多一個 custom component,就多一個可能在升級後壞掉的相依項目。本地 patch 更要綁定測試版本並留下移除條件。

4. 只做備份,不做還原測試

看到 backup file 不代表它一定可用。至少要知道如何用固定版本啟動、還原 config,並驗證最重要的幾條 automation。

5. UI 整理不能取代 entity 整理

Dashboard 卡片可以隨時重做,但混亂的命名、area 和 device 關係會直接增加所有自動化的維護成本。


如果你也要這樣做

  1. 先整理 area、device 和 entity 命名規則。
  2. 選 2-3 個每天都會用到、失敗風險低的情境開始。
  3. 為離家判斷加上延遲,並保留手動控制方式。
  4. 在增加 custom integrations 前,先建立備份與還原流程。
  5. 穩定運作一段時間後,再加入跨品牌與多人 Presence 自動化。

Home Assistant 最有價值的地方,不是 Dashboard 上有多少按鈕,而是讓設備在正確的時間完成正確的事,同時在出錯時仍然可理解、可維護、可回復。

回到 Home Lab 總覽