Home Assistant:使用 InfluxDB 收集传感器数据
Home Assistant (HA) 是一款功能强大的物联网 (IoT) 设备及其传感器管理解决方案。它有助于简化数据采集,并提供用户友好的家庭自动化功能。在默认配置下,HA 会将所有状态变化存储在其内部的 SQLite 数据库中。然而,对于物联网开发人员来说,使用和处理时序数据库(例如 InfluxDB)才是常态。那么,我们能否也使用 HA 将传感器数据存储在时序数据库中呢?简而言之:可以。详细来说:可以,但 HA 对如何以及保存哪些数据有明确的、不可配置的约定,因此请仔细查看相关细节……
本文是一份完整的 Home Assistant 时间序列数据库功能设置、结构和使用指南。您将了解如何启用 HA 将数据写入自定义 InfluxDB,查看数据结构示例,并学习如何使用聚合和保留策略自定义存储的数据。
本文的技术背景是 Home Assistant 2022.11 和 ESPHome 2022.11.3,但也应该适用于更新的版本。
本文最初发表于我的博客admantium.com。
为 Home Assistant 配置 InfluxDB
在开始之前,我们先回顾一下。当您收集传感器数据并运行 Home Assistant 实例时,实际上有两种选择。第一种选择是为每个开发板显式配置一个 MQTT 连接,并为每个要记录的传感器数据配置一个 MQTT 发布器。但顾名思义,这需要为所有开发板和所有传感器分别配置。第二种选择,也是本文将要探讨的,是自动将 Home Assistant 注册到 InfluxDB 的每个状态更新镜像到 InfluxDB。这不仅可以避免上述问题,还可以标准化测量数据,并仅记录所有传感器或基于状态的实体。
要启用 InfluxDB 连接,官方文档说明需要将以下
设置添加到 Home Assistant 安装目录下的 configuration.yaml 文件中。为了便于理解,我们将其分为两部分:连接设置,用于指定主机名、端口和数据库名称;以及测量设置,用于定义测量值的命名方式、使用的标签以及数据库中应包含或排除的实体。
influxdb:
### Connection Setting ###
api_version: 2
ssl: false
host: influxdb
port: 8086
bucket: home_assistant
### measurements setup ###
tags:
source: ha
tags_attributes:
- friendly_name
default_measurement: units
exclude:
entities:
- zone.home
domains:
- persistent_notification
- person
include:
domains:
- sensor
- binary_sensor
- sun
entities:
- weather.home
然后你需要重启 Home Assistant 进程或服务。就我而言,这是一个需要重新启用的 Docker 容器。
> docker-compose restart home_assistant
> docker-compose logs -f home_assistant
为确保配置正确应用,请检查日志文件:
home_assistant | 2022-01-16 12:15:04 ERROR (MainThread) [homeassistant.config] Invalid config for [influxdb]: token and bucket are required when api_version is 2 for dictionary value @ data['influxdb']. Got OrderedDict([('api_version', 2), ('ssl', False), ('host', 'influxdb'), ('port', 8086), ('bucket', 'home_assistant'), ('tags', OrderedDict([('source', 'ha')])), ('tags_attributes', ['friendly_name']), ('default_measurement', 'units')]). (See /config/configuration.yaml, line 14). Please check the docs at https://www.home-assistant.io/integrations/influxdb
home_assistant | 2022-01-16 12:15:04 ERROR (MainThread) [homeassistant.setup] Setup failed for influxdb: Invalid config.
如果看到此信息,说明您运行的 InfluxDB 版本低于 2.0,因此需要按如下方式更改连接设置:
influxdb:
host: influxdb
port: 8086
database: home_assistant
username: ''
password: ''
ssl: false
verify_ssl: false
max_retries: 3
default_measurement: state
从现在开始,指定的 InfluxDB 数据库/存储桶将填充记录的值。
测量数据库概述
我们来看看这些数据的结构。使用你喜欢的工具连接到 InfluxDB 并进行探索。
> show measurements
name: measurements
name
----
%
IAQ
V
dBm
h
hPa
m
ms
ppm
s
state
°C
Ω
>
第一个令人惊讶的地方是这些测量单位的名称:它们本身就是被测量的单位!让我们先来了解一下它们的含义。
| 测量名称 | 单元 | 解释 |
|---|---|---|
| % | 百分比 | 电池电量百分比 |
| 室内空气质量 | 空气质量指数 | 由 BME680 计算得出 |
| V | 伏特 | 电池电压水平 |
| 分贝米 | 分贝毫瓦 | 无线连接强度 |
| h | 小时 | 及时报告的测量和状态变化 |
| 百帕 | 赫克托帕斯卡 | 来自 BME680 传感器的气压 |
| 米 | 分钟 | 记录我的电路板动态睡眠时间的设置 |
| 每百万 | 每百万个粒子 | 测量二氧化碳颗粒的数量 |
| 状态 | 杂项 | 本次测量会记录所有传感器的所有状态变化。 |
| 摄氏度 | 摄氏度 | 温度测量 |
| Ω | 电阻 | BME680传感器的电阻测量值用于计算室内空气质量(IAQ)。 |
好的,我们来研究一下测量表本身的结构。首先,我们来看一下数值的测量,然后再看一下状态的测量。
测量数据库的结构
这些测量方法本身的结构非常相似:
> select * from "dBm" LIMIT 10
name: dBm
time device_class_str domain entity_id friendly_name friendly_name_str state_class_str value
---- ---------------- ------ --------- ------------- ----------------- --------------- -----
1642857893213061120 signal_strength sensor wifi_signal_esp8266_01 826601 WiFi Signal esp8266-01 measurement -68
1642857986913826048 signal_strength sensor wifi_signal_esp8266_01 826601 WiFi Signal esp8266-01 measurement -69
1642858046926774016 signal_strength sensor wifi_signal_esp8266_01 826601 WiFi Signal esp8266-01 measurement -71
1642858106919809024 signal_strength sensor wifi_signal_esp8266_01 826601 WiFi Signal esp8266-01 measurement -70
表格列内容如下:
| 钥匙 | 类型 | 描述 |
|---|---|---|
| 时间 | 时代 | 测量时间戳 |
| 设备类字符串 | 细绳 | 例如,“°C”表示温度,“dBm”表示信号强度。 |
| 领域 | 细绳 | 领域构成价值的逻辑结构或起源,例如“传感器”或“光”。 |
| 实体 ID | 细绳 | 实体的ID |
| 友好名称 | 整数 | friendl_name_str 的内部 ID |
| friendly_name_str | 细绳 | 用户可配置的设备备用名称,可用于代替其内部 ID |
| icon_str | 细绳 | 指定 HA 仪表板分配给此值的图标名称 |
| state_class_str | 细绳 | 数据的来源,这里总是“测量”。 |
| 价值 | * | 具体测量值 |
州数据库的结构
这个特殊的数据库会跟踪您 Home Assistant 安装中的所有状态变化。它的结构取决于您集成的实体数量——传感器越多,数据库中的列就越多。
这是我刚开始使用 Home Assistant 时的数据库:
> select * from state limit 1
name: state
time access_token access_token_str device_class_str domain editable entity_id entity_id_str entity_picture_str friendly_name friendly_name_str icon_str id latitude longitude newest_version_str passive radius release_notes_str state supported_color_modes_str supported_features value
---- ------------ ---------------- ---------------- ------ -------- --------- ------------- ------------------ ------------- ----------------- -------- -- -------- --------- ------------------ ------- ------ ----------------- ----- ------------------------- ------------------ -----
1642332817702238976 scene new_scene ['camera.esp32camera', 'light.esp32_camera_light'] New Scene 1636879982536 scening
这是撰写本文时的状态,当时新增了温度传感器、运动传感器和 LED 灯。
select * from "state" Limit 1
name: state
time access_token access_token_str azimuth brightness color_mode_str current device_class_str domain editable effect_list_str effect_str elevation entity_id entity_id_str entity_picture_str friendly_name friendly_name_str hs_color_str icon_str id initial_str last_triggered last_triggered_str latitude longitude max message_str min mode_str newest_version_str next_dawn next_dawn_str next_dusk next_dusk_str next_midnight next_midnight_str next_noon next_noon_str next_rising next_rising_str next_setting next_setting_str passive pattern_str radius release_notes_str rgb_color rgb_color_str rising state step supported_color_modes_str supported_features title_str value xy_color_str
---- ------------ ---------------- ------- ---------- -------------- ------- ---------------- ------ -------- --------------- ---------- --------- --------- ------------- ------------------ ------------- ----------------- ------------ -------- -- ----------- -------------- ------------------ -------- --------- --- ----------- --- -------- ------------------ --------- ------------- --------- ------------- ------------- ----------------- --------- ------------- ----------- --------------- ------------ ---------------- ------- ----------- ------ ----------------- --------- ------------- ------ ----- ---- ------------------------- ------------------ --------- ----- ------------
1642332817702238976 scene new_scene ['camera.esp32camera', 'light.esp32_camera_light'] New Scene 1636879982536 scening
如您所见,这些值很多,但其中大多数仅在非常特定的状态更改时才会被记录。让我们通过一个具体的例子来理解它们:将 LED 灯设置为“开”。
| 姓名 | 状态 | 描述 |
|---|---|---|
| 标签 | ||
| 时间(UTC) | 1644753700955780000 | 状态变更时间戳 |
| 访问令牌 | ||
| access_token_str | ||
| 方位角 | ||
| 亮度 | 31 | 此LED的亮度值 |
| color_mode_str | RGB | 表示颜色寻址方式的字符串 |
| 当前的 | ||
| 设备类字符串 | ||
| 领域 | 光 | 领域之光 |
| 可编辑 | ||
| effect_list_str | ['无', '彩虹', '脉冲'] | 为 LED 配置的效果名称 |
| effect_str | 没有任何 | |
| 海拔 | ||
| 实体 ID | rgb_led_ring | 实体 ID |
| entity_id_str | ||
| entity_picture_str | ||
| 友好名称 | ||
| friendly_name_str | RGB LED环 | 给出的友好名称 |
| hs_color_str | (14.717,62.353) | 色调和饱和度值 |
| icon_str | ||
| ID | ||
| initial_str | ||
| 上次触发 | ||
| last_triggered_str | ||
| 纬度 | ||
| 经度 | ||
| 最大限度 | ||
| 消息字符串 | ||
| 最小 | ||
| mode_str | ||
| 最新版本字符串 | ||
| 下一个道 | ||
| next_dawn_str | ||
| 下一个黄昏 | ||
| 下一个黄昏 | ||
| 下一个午夜 | ||
| next_midnight_str | ||
| 下一个中午 | ||
| next_noon_str | ||
| 下一个崛起 | ||
| 下一个上升的 | ||
| 下一个设置 | ||
| next_setting_str | ||
| 被动的 | ||
| pattern_str | ||
| 半径 | ||
| 发行说明字符串 | ||
| RGB颜色 | 25513596 | 配置的 RGB 颜色简写 |
| rgb_color_str | (255、135、96) | 配置的 RGB 颜色的长表示法 |
| 上升 | ||
| 状态 | 在 | 有效的状态变化 |
| 步 | ||
| supported_color_modes_str | ['rgb'] | 针对此 LED 的颜色模式 |
| 支持的功能 | 44 | 功能的内部 ID |
| 标题字符串 | ||
| 价值 | 1 | 表示状态变化的布尔值 |
| xy_color_str | (0.552,0.346) | xy 色彩 |
有了这些理解,让我们将数据可视化。
Grafana传感器测量仪表盘
InfluxDB 数据的可视化给我们带来了一个有趣的难题。一方面,Home Assistant 会为其数据库中收集的所有数据提供传感器可视化功能。这很方便,而且无需任何配置。另一方面,你也可以将任何 InfluxDB 数据添加到 Home Assistant 的仪表盘卡片中¹。但是,既然默认的可视化功能已经开箱即用,你还有必要这样做吗?
对于我其他的 InfluxDB 数据(主要是来自我的 Linux 工作站和 Raspberry Pi 的硬件指标),我已经使用 Grafana 仪表盘进行可视化。因此,我想添加一个新的 Grafana 仪表盘来可视化存储在 InfluxDB 中的 Home Assistant 传感器数据。
第一个图表只需几分钟即可设置完成:
- 配置 InfluxDB Home Assistant 数据库。在 Grafana 主视图中,转到“配置”=>“数据源”,然后单击“新建数据源”。在此处,输入 InfluxDB 服务器的 URL 和端口,并在“数据库”字段中输入
home_assistant - 创建一个新的仪表盘,例如命名为“家庭助手传感器”。
- 在仪表盘中创建一个新面板:选择 Home Assistant InfluxDB 数据源,此时会显示一个功能丰富的查询编辑器界面。在这里,选择您感兴趣的指标及其平均值。
这样,您将获得一个图表。但您可能会遇到同一时间戳和数据出现多个重复值的情况。这种情况发生在您为同一实体配置了多个集成时,例如同时使用 ESPHome API 和 MQTT 集成读取温度数据。
让我们考虑以下示例:从同一个传感器进行多次温度测量,但entity_id测量值不同。
name time (UTC) device_class_str domain entity_id friendly_name friendly_name_str state_class_str value
°C 1644341442651680000 temperature sensor bme680_temperature 680 BME680 Temperature measurement 8.6
°C 1644341442671660000 temperature sensor bme680_temperature_2 680
BME680 Temperature measurement 8.6
°C 1644343135338740000 temperature sensor bme680_temperature_2 680 BME680 Temperature measurement 8.9
解决数据重复问题有多种方法。一方面,您可以从数据库中删除时间戳相同但实体 ID 不同的条目。另一方面,您可以使用自定义保留策略,根据需要筛选和聚合数据。更简单的方法是,如果您只关注数据可视化,可以使用自定义SELECT语句将多个数据点合并为平均值。
在撰写本文时,我仍在向 Home Assistant 添加新的设备和实体,因此无法排除出现更多重复授权的可能性。所以,我选择了最简单的解决方案,创建了一个自定义查询,对 10 分钟时间跨度内的数据取平均值。查询语句如下:
SELECT mean("value")
FROM "°C"
WHERE ("entity_id" = 'bme680_temperature' OR "entity_id" = 'bme680_temperature_2')
GROUP BY time(10m) fill(previous)
查询检查器按要求返回了值:
通过类似的查询,我可以将收集到的所有温度和湿度数据汇总到这些图表中:
我对这个结果很满意。
结论
Home Assistant 会收集所有已配置设备的状态变化和传感器数据。但您可以通过配置对 InfluxDB 实例的访问,获取这些数据的额外副本,以时间序列数据库条目的形式存储。此数据库完全是额外的,Home Assistant 会将所有数据存储在其自身的数据库和已配置的 InfluxDB 中。现在,您可以开始读取和可视化这些数据了。
为了帮助您入门,本文还探讨了 Home Assistant 如何存储数据:传感器数据被收集到以测量值命名的表中,例如 `<summary>`、`<state>`V或dBm` °C<state>`,状态变化则被记录在state测量值中。您已经了解了表列及其含义。最后,我还展示了如何基于这些测量值创建 Grafana 仪表板,并解决了 Home Assistant 为多个已配置实体存储类似测量值时可能出现的重复数据问题。
脚注
-
如果您想直接在 Home Assistant中可视化 InfluxDB 数据,请阅读这篇分步指南。↩

