我们知道在 Home Assistant 中,sensor
平台的作用就是获取各种数据,但是有时候我们想要的设备或特殊的数据,HA 并没有指定的platform
支持,因此 HA 给我们提供了一个强大的 Command line Sensor(命令行传感器)平台。它可以通过指定的命令获取数据,也就意味着几乎可以接入 HA 任何种类的(包括具体的和抽象的)传感器。 下面本文就带你一步步手撸一个自己的传感器出来~
树莓派 3B+ 在 Docker 下安装 Hassio,使用 Samba
add-on,在 VS Code 中使用 Home Assistant Config Helper
插件编辑 YAML 文件。
这里以 epsilon1 的帖子为参考,修改了一部分以适应 HA 的要求,运行环境为 Python3。不同的平台(这里是树莓派),可能相应的需要做出一些修改。
import os
import json
# Return CPU temperature as a float
def getCPUtemperature():
f = os.popen("cat /sys/class/thermal/thermal_zone0/temp")
temp = int(f.readline().strip())/1000
return round(temp, 1)
# Return RAM information (unit=MB) in a list
# Index 0: total RAM
# Index 1: used RAM
# Index 2: free RAM
def getRAMinfo():
f = os.popen("free | awk '/Mem/ {print $2,$3,$4}'")
info = f.readline().split()
info = [round(int(i)/1024, 1) for i in info]
return info
'''
# Return % of CPU used by user as float
def getCPUinfo():
# Docker外部 info = os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()
# Docker内部 info = os.popen("top -n1 | awk '/CPU:/ {print $2}'").readline().strip()
if info:
return float(info)
else:
# 未获取到信息,返回默认错误值
return -1.0
'''
# Return information about disk space as a list (unit included)
# Index 0: total disk space
# Index 1: used disk space
# Index 2: remaining disk space
# Index 3: percentage of disk used
def getDiskinfo():
f = os.popen("df -h /")
info = f.readlines()[1].split()[1:5]
return info
if __name__ == '__main__':
RaspiInfo = {}
RaspiInfo['CPUtemp'] = getCPUtemperature()
RaspiInfo['RAMinfo'] = getRAMinfo()
RaspiInfo['DISKinfo'] = getDiskinfo()
#RaspiInfo['CPUuse'] = getCPUinfo()
# 必须转化为标准 JSON 格式备用,下文有解释
print(json.dumps(RaspiInfo))
运行打印出的数据示例:{"CPUtemp": 44.0, "RAMinfo": [874.5, 340.4, 37.7], "DISKinfo": ["15G", "8.5G", "5.3G", "62%"]}
废话不多说,下面就来看看这个命令行传感器如何配置吧!完整配置信息请参考官方文档 Command line Sensor ,下面摘录一部分作主要说明。
许多关于硬件的信息可以由 proc
文件系统获得,这里展示获取 CPU 温度的方法。
# configuration.yaml 示例,仅用于学习配置命令行传感器,并不是本次项目的配置文件
# 在 sensor 域下添加
sensor:
# 平台名,不用多说
- platform: command_line
# 添加传感器实体 entity 的名称,引用时为 sensor.cpu_temperature,可在 开发者工具-状态 内看到
name: CPU Temperature
# 用于获取温度数据的命令,注意单、双引号的使用
command: "cat /sys/class/thermal/thermal_zone0/temp"
#(可选)传感器数据的单位
unit_of_measurement: "°C"
#(可选)定义一个模板,从 command 传回的载荷数据(用 value 代替)中提取需要的值,
# 若未定义模板,则直接将 command 传回的数据作为传感器的值。
value_template: '{{ value | multiply(0.001) | round(1) }}'
#(可选)更新间隔,默认为 60s
scan_interval: 60
#(可选)命令执行超时设置,默认为 15s
command_timeout: 15
cat
命令;或者 Python 的 print
函数,可以看到在上一节获取硬件信息的脚本中,最后是一行打印函数 print(json.dumps(RaspiInfo))
。至于这里为什么要用 json.dumps()
我们后面再介绍。value
代替命令输出的载荷数据,而变量 value_json
则可以代替经 JSON 格式解析后的数据,具体的使用请参考文档 Processing incoming data。下面再通过几个例子感受一下上面说的内容:
# configuration.yaml entry 示例
sensor:
- platform: command_line
name: badlogin
command: "grep -c 'Login attempt' /home/hass/.homeassistant/home-assistant.log"
使用 Python 的 requests 库,通过 HTTP 获取指定 URL 的内容作为传感器的数值。
可以学习一下这里的 python3 -c "xxxxx"
通过命令行方式执行 Python 脚本的方式。
sensor:
- platform: command_line
command: python3 -c "import requests; print(requests.get('http://remote-host/sensor_data.txt').text)"
name: File value
同样可以执行外部的脚本,如下:
sensor:
- platform: command_line
name: Brightness
command: "python3 /path/to/script/arest-value.py"
好了,当你大致熟悉了这个命令行传感器怎么配置后,我们再来介绍它剩下的一个强大的功能:(可选)json_attributes
。在这个配置选项下,我们定义一系列字典的键(Key),这样命令行传感器就能根据这些键名,从命令传回的 JSON 字典数据中提取键对应的值,并将其设置为传感器的属性。这样一来,我们就能一次性传回多个数值了,非常方便。
json.dumps()
对字典进行 JSON 格式的编码。最后打印出的数据示例如:{"CPUtemp": 44.0, "RAMinfo": [874.5, 340.4, 37.7], "DISKinfo": ["15G", "8.5G", "5.3G", "62%"]}
根据以上字典内容,我们在配置文件的 sensor
域下添加:
# 我是在 configuration.yaml 中添加了一行 sensor: !include sensor.yaml
# 所以以下是 sensor.yaml 文件的内容
- platform: command_line
name: RaspInfo
scan_interval: 60
command: "python3 /config/scripts/queryRaspi.py" # 脚本路径问题参考下面注意事项
json_attributes: # 键名可为大小写
- RAMinfo
- DISKinfo
- CPUuse
- CPUtemp
command: "python3 /config/scripts/queryRaspi.py"
,而不能用绝对路径 command: python3 "/usr/share/hassio/homeassistant/scripts/queryRaspi.py"
,会出现找不到文件或目录的错误。command: 'python3 /home/pi/.homeassistant/scripts/datetime.py'
),大家试一下会不会报错吧。config
目录下的内容,和 Hassio 配置文件的默认路径 /usr/share/hassio/homeassistant
下的内容是一样的。config
目录下(也就是 /usr/share/hassio/homeassistant/scripts/queryRaspi.py
)至此,重新启动 Home Assistant 服务后(你也可以在后面所有配置完成后再重启),我们将在 开发者工具-状态 里看到我们定义的一个命令行传感器实体。
RaspInfo
的小写 raspinfo
;相应的,若取名为 Rasp Info
,实体名称就会变为 rasp_info
以上都没有问题的话,我们继续往下看。
虽然上面的命令行传感器已经能够将(一整项)状态数据显示在主页了,但是该怎么把各项数据单独作为传感器实体显示出来呢?事实上 template
平台支持我们定义一个从其它实体获取值的传感器,也就是 Template Sensor
,而这正是我们想要的功能(利用命令行传感器的各个属性值)。
下面就来看看这个基于模板的传感器如何配置吧!完整配置信息请参考官方文档 Template Sensor 。
在配置文件的 sensor
域下添加:
# 我是在 configuration.yaml 中添加了一行 sensor: !include sensor.yaml
# 所以以下是 sensor.yaml 文件的内容
# 平台名称
- platform: template
# 传感器列表
sensors:
# 实体名称:小写,下划线
cpu_temp:
# (可选)在前端显示的传感器昵称
friendly_name: "CPU Temperature"
# (可选)传感器数值的单位
unit_of_measurement: '℃'
#(必须)定义一个获取传感器状态(数值)的模板
# 这里就是获取上面定义的命令行传感器实体 sensor.raspinfo 的相应属性值,注意大小写
value_template: "{{state_attr('sensor.raspinfo', 'CPUtemp')}}"
# 以下配置类似,不再赘述
ram_total:
friendly_name: "RAM total"
unit_of_measurement: 'MB'
value_template: "{{state_attr('sensor.raspinfo', 'RAMinfo')[0]}}"
ram_used:
friendly_name: "RAM used"
unit_of_measurement: 'MB'
value_template: "{{state_attr('sensor.raspinfo', 'RAMinfo')[1]}}"
ram_free:
friendly_name: "RAM free"
unit_of_measurement: 'MB'
value_template: "{{state_attr('sensor.raspinfo', 'RAMinfo')[2]}}"
disk_total:
friendly_name: "DISK total"
value_template: "{{state_attr('sensor.raspinfo', 'DISKinfo')[0]}}"
disk_used:
friendly_name: "DISK used"
value_template: "{{state_attr('sensor.raspinfo', 'DISKinfo')[1]}}"
disk_left:
friendly_name: "DISK left"
value_template: "{{state_attr('sensor.raspinfo', 'DISKinfo')[2]}}"
disk_percentage:
friendly_name: "DISK percentage"
value_template: "{{state_attr('sensor.raspinfo', 'DISKinfo')[3]}}"
注意:这里配置的比较精简(足够用了,实在是太累了,不想再打字了,而且官方文档也很清晰),完整配置信息请参考官方文档 Template Sensor ,要学会模板(template)的使用。
至此,重新启动 Home Assistant 服务后(你也可以在后面所有配置完成后再重启),我们将在 开发者工具-状态 里看到所有刚刚创建的传感器的单独实体。
最后只需要简单的分组即可:
# 我是在 configuration.yaml 中添加了一行 group: !include groups.yaml
# 所以以下是 groups.yaml 文件的内容
default_view:
view: yes
icon: mdi:home
entities:
- group.raspinfo
raspinfo:
name: 树莓派
control: hidden
entities:
- sensor.cpu_temp
- sensor.ram_total
- sensor.ram_used
- sensor.ram_free
- sensor.disk_total
- sensor.disk_used
- sensor.disk_left
- sensor.disk_percentage
至此,重新启动 Home Assistant 服务后(若前面已经重启过,这里只需要重载分组即可),在前端面板便出现了各项传感器信息:
Bingo !
待填坑
不知不觉写了好长时间将近九千个字(符),太长不看系列。希望自己把问题描述的足够清楚了,在这里也只是抛砖引玉,有了这一遍流程,大家就已经可以自己动手开发自己想要的各类“传感器”了,别忘了来分享喔。