找回密碼
 立即註冊
惟家LINE群QRCODE
    查看: 0|回覆: 0

    把 HA 的長期數據丟到 InfluxDB + Grafana(完整步驟)

    [複製鏈接]

    !lvup!   100%

    363

    主題

    27

    回帖

    2200萬

    積分

    管理員

    積分
    22005752
    發表於 3 天前 | 顯示全部樓層 |閱讀模式
    HA 的 recorder 不適合存長期數據。
    想看「過去兩年的用電趨勢」,要把資料搬出去。



    為什麼不用 HA 自己存


    • recorder 的設計是「最近的詳細狀態」,不是時序資料庫
    • purge_keep_days 一過就刪掉
    • SQLite 查大量歷史資料很慢
    • HA 的歷史圖表功能有限(不能疊圖、不能做複雜計算)


    HA 的「長期統計」其實已經解決一部分

    先講清楚:有 state_class 的感測器會自動進 statistics 表
    每小時存一筆(最大/最小/平均),而且不受 purge_keep_days 影響

    所以如果你只是想看「用電量的月趨勢」,HA 內建就夠了。

    什麼時候才需要 InfluxDB + Grafana


    • 更細的解析度(每分鐘而不是每小時)
    • 複雜的查詢和計算
    • 把多個來源的資料疊在一起看
    • 漂亮的儀表板(Grafana 真的比較好看)
    • 存很多年


    架設 InfluxDB

    用前面那篇的 compose 檔就可以。重點設定:
    1.   influxdb:
    2.     image: influxdb:2
    3.     container_name: influxdb
    4.     restart: unless-stopped
    5.     ports:
    6.       - "8086:8086"
    7.     volumes:
    8.       - /volume1/docker/influxdb/data:/var/lib/influxdb2
    9.       - /volume1/docker/influxdb/config:/etc/influxdb2
    10.     environment:
    11.       - TZ=Asia/Taipei
    12.       - DOCKER_INFLUXDB_INIT_MODE=setup
    13.       - DOCKER_INFLUXDB_INIT_USERNAME=admin
    14.       - DOCKER_INFLUXDB_INIT_PASSWORD_FILE=/run/secrets/influx_pw
    15.       - DOCKER_INFLUXDB_INIT_ORG=home
    16.       - DOCKER_INFLUXDB_INIT_BUCKET=homeassistant
    17.       - DOCKER_INFLUXDB_INIT_RETENTION=520w    # 十年
    複製代碼

    起來之後到 http://NAS:8086,用 admin 登入。

    建立一個專用的 API Token

    Load Data → API Tokens → Generate API Token → Custom API Token


    • homeassistant bucket 給 Read + Write
    • 不要用 All Access Token
    • 產生後馬上複製(只顯示一次)




    HA 這邊的設定
    1. # configuration.yaml
    2. influxdb:
    3.   api_version: 2
    4.   ssl: false
    5.   host: 192.168.1.20
    6.   port: 8086
    7.   token: !secret influxdb_token
    8.   organization: home
    9.   bucket: homeassistant
    10.   tags:
    11.     source: ha
    12.   tags_attributes:
    13.     - friendly_name
    14.     - device_class
    15.   default_measurement: units
    16.   # 關鍵:只送你真的要長期保存的
    17.   include:
    18.     domains:
    19.       - sensor
    20.     entity_globs:
    21.       - sensor.*_energy
    22.       - sensor.*_power
    23.       - sensor.*_temperature
    24.       - sensor.*_humidity
    25.     entities:
    26.       - binary_sensor.front_door
    27.       - climate.living_room
    28.   exclude:
    29.     entity_globs:
    30.       - sensor.*_linkquality
    31.       - sensor.*_rssi
    32.       - sensor.*_battery_voltage
    33.       - sensor.*_last_seen
    34.       - sensor.date*
    35.       - sensor.time*
    複製代碼

    一定要用 include,不要全部送。

    全部送的後果


    • InfluxDB 長得很快(我試過一個月 8GB)
    • 網路流量增加
    • 查詢變慢
    • 而且九成的資料你永遠不會看


    我的原則:只送「會想看一年後趨勢」的東西。

    實際上大概是:溫度、濕度、用電量、功率、CO2、PM2.5。

    驗證有沒有進去
    1. # 在 InfluxDB 的 Data Explorer 裡
    2. from(bucket: "homeassistant")
    3.   |> range(start: -1h)
    4.   |> filter(fn: (r) => r["_measurement"] == "°C")
    5.   |> filter(fn: (r) => r["entity_id"] == "living_room_temperature")
    複製代碼

    注意:HA 送過去的 measurement 名稱是「單位」
    (°C、%、W、kWh),這是預設行為。

    想改成用實體名當 measurement
    1. influxdb:
    2.   override_measurement: state
    複製代碼

    但改了之後查詢語法會不一樣,而且已經存的資料不會變。
    一開始就決定好,不要中途改。



    Grafana 設定

    第一步:加資料來源

    Connections → Add new connection → InfluxDB


    • Query LanguageFlux(InfluxDB 2.x 用這個)
    • URLhttp://influxdb:8086(同一個 compose 網路的話用容器名)
    • Organization:home
    • Token:剛剛那個
    • Default Bucket:homeassistant


    第二步:做第一個圖表
    1. from(bucket: "homeassistant")
    2.   |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
    3.   |> filter(fn: (r) => r["_measurement"] == "°C")
    4.   |> filter(fn: (r) => r["_field"] == "value")
    5.   |> filter(fn: (r) => r["entity_id"] =~ /.*_temperature/)
    6.   |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
    7.   |> yield(name: "mean")
    複製代碼

    幾個實用的查詢

    每日用電量(長條圖)
    1. from(bucket: "homeassistant")
    2.   |> range(start: -30d)
    3.   |> filter(fn: (r) => r["entity_id"] == "total_energy")
    4.   |> filter(fn: (r) => r["_field"] == "value")
    5.   |> aggregateWindow(every: 1d, fn: max, createEmpty: false)
    6.   |> difference()
    複製代碼

    用 difference() 把「累計值」轉成「每日增量」
    這是累計型感測器最常用的處理。

    多個房間的溫度疊圖
    1. from(bucket: "homeassistant")
    2.   |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
    3.   |> filter(fn: (r) => r["_measurement"] == "°C")
    4.   |> filter(fn: (r) => contains(value: r["entity_id"],
    5.        set: ["living_room_temperature",
    6.              "bedroom_temperature",
    7.              "study_temperature"]))
    8.   |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
    複製代碼

    室內外溫差
    1. indoor = from(bucket: "homeassistant")
    2.   |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
    3.   |> filter(fn: (r) => r["entity_id"] == "living_room_temperature")
    4.   |> filter(fn: (r) => r["_field"] == "value")
    5.   |> aggregateWindow(every: 10m, fn: mean)
    6. outdoor = from(bucket: "homeassistant")
    7.   |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
    8.   |> filter(fn: (r) => r["entity_id"] == "outdoor_temperature")
    9.   |> filter(fn: (r) => r["_field"] == "value")
    10.   |> aggregateWindow(every: 10m, fn: mean)
    11. join(tables: {i: indoor, o: outdoor}, on: ["_time"])
    12.   |> map(fn: (r) => ({ _time: r._time, _value: r._value_i - r._value_o }))
    複製代碼

    這個圖很有意思 —— 可以看出冷氣的實際效率,
    以及哪些時段隔熱最差。

    把 Grafana 嵌回 HA
    1. # 儀表板 YAML
    2. type: iframe
    3. url: >
    4.   http://192.168.1.20:3000/d-solo/abc123/home?orgId=1&panelId=2&kiosk&theme=dark
    5. aspect_ratio: 50%
    複製代碼

    要先在 Grafana 允許嵌入
    1. environment:
    2.   - GF_SECURITY_ALLOW_EMBEDDING=true
    3.   - GF_AUTH_ANONYMOUS_ENABLED=true
    4.   - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer
    複製代碼

    開了匿名存取的話,一定要確認 Grafana 沒有對外開放。

    維運注意事項

    1. 磁碟會長

    設定保留期限(Retention Policy):

    Load Data → Buckets → 點那個 bucket → Settings → Retention

    我的設定


    • 原始資料保留 90 天
    • 另外建一個 bucket 存降取樣的資料,保留 十年


    降取樣(Downsampling):用 InfluxDB 的 Task 定期把
    原始資料聚合成每小時一筆,存到另一個 bucket。
    1. // InfluxDB Task
    2. option task = {name: "downsample_hourly", every: 1h}
    3. from(bucket: "homeassistant")
    4.   |> range(start: -2h)
    5.   |> filter(fn: (r) => r["_field"] == "value")
    6.   |> aggregateWindow(every: 1h, fn: mean, createEmpty: false)
    7.   |> to(bucket: "homeassistant_long", org: "home")
    複製代碼

    2. 備份
    1. docker exec influxdb influx backup /tmp/backup \
    2.   -t 你的token
    3. docker cp influxdb:/tmp/backup /volume1/backup/influx-$(date +%F)
    複製代碼

    Grafana 的儀表板也要備份
    可以用 Export JSON,存進 Git。

    3. 時區


    • 容器要設 TZ=Asia/Taipei
    • Grafana 的使用者偏好也要設時區
    • 不然圖表的 X 軸會差 8 小時


    ---

    老實講,這一套對大多數人來說是過度工程

    如果你只是想看用電趨勢,HA 內建的能源儀表板就很夠了

    值得裝 InfluxDB + Grafana 的情況:


    • 你真的會定期看數據做決策
    • 你想要很細的解析度
    • 你喜歡做圖表(這是正當理由)


    我自己裝了之後,最常看的其實只有兩張圖:
    每日用電長條圖室內外溫差

    其他做得很漂亮的圖表,大概一個月看一次。
    您需要登入後纔可以回帖 登入 | 立即註冊

    本版積分規則

    Archiver|手機版|惟家的智能論壇

    GMT+8, 2026-9-24 10:32 , Processed in 0.087134 second(s), 26 queries .

    快速回覆 返回頂部 返回列表