命令行传感器和模板的使用之在 Home Assistant 中监控树莓派的 CPU 温度,内存等信息

背景介绍

引言

我们知道在 Home Assistant 中,sensor 平台的作用就是获取各种数据,但是有时候我们想要的设备或特殊的数据,HA 并没有指定的platform支持,因此 HA 给我们提供了一个强大的 Command line Sensor(命令行传感器)平台。它可以通过指定的命令获取数据,也就意味着几乎可以接入 HA 任何种类的(包括具体的和抽象的)传感器。 下面本文就带你一步步手撸一个自己的传感器出来~
command line sensor

运行环境

树莓派 3B+ 在 Docker 下安装 Hassio,使用 Samba add-on,在 VS Code 中使用 Home Assistant Config Helper 插件编辑 YAML 文件。

如何获取硬件信息

这里以 epsilon1 的帖子为参考,修改了一部分以适应 HA 的要求,运行环境为 Python3。不同的平台(这里是树莓派),可能相应的需要做出一些修改。

  • 注意: 在 Docker 内、外运行相同的命令,如获取 CPU 和内存使用情况,会得到不同的结果(没有学习过 Docker,直觉认为在 Docker 内外还是有差异的),因此以下脚本中注释了用户空间占用 CPU 百分比的信息。
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(重点)

废话不多说,下面就来看看这个命令行传感器如何配置吧!完整配置信息请参考官方文档 Command line Sensor ,下面摘录一部分作主要说明。

CPU 温度示例(★)

许多关于硬件的信息可以由 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

注意事项

  • 获取命令的 command 直接将载荷数据 输出、打印出来 即可,即类似于上面的 cat 命令;或者 Python 的 print 函数,可以看到在上一节获取硬件信息的脚本中,最后是一行打印函数 print(json.dumps(RaspiInfo))。至于这里为什么要用 json.dumps() 我们后面再介绍。
  • 若使用 value_template 提取数据,则在模板表达式中使用 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 数据(★)

好了,当你大致熟悉了这个命令行传感器怎么配置后,我们再来介绍它剩下的一个强大的功能:(可选)json_attributes。在这个配置选项下,我们定义一系列字典的键(Key),这样命令行传感器就能根据这些键名,从命令传回的 JSON 字典数据中提取键对应的值,并将其设置为传感器的属性。这样一来,我们就能一次性传回多个数值了,非常方便。

  • 注意:传回的字典一定要是符合标准 JSON 格式的,所以在上面的脚本中,最后一行利用了 Python 库函数 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

注意事项

  • 当执行外部脚本时,脚本的存放路径显得格外重要。如果是在 Docker 下安装的 Hassio,脚本路径应该写为 command: "python3 /config/scripts/queryRaspi.py",而不能用绝对路径 command: python3 "/usr/share/hassio/homeassistant/scripts/queryRaspi.py" ,会出现找不到文件或目录的错误
    文档说明
    SambaSamba
  • 而其他方式安装的 HA,我没有验证过,配置中应该就是写脚本的绝对路径,至少官方文档中示例写的就是绝对路径(如 command: 'python3 /home/pi/.homeassistant/scripts/datetime.py'),大家试一下会不会报错吧。
  • 事实上,在我这种安装环境下(Docker + Hassio),在 Samba 中看到的 config 目录下的内容,和 Hassio 配置文件的默认路径 /usr/share/hassio/homeassistant 下的内容是一样的。两种路径拥有相同内容
  • 因此,现在就把上面查询树莓派各种信息的 Python 脚本保存到 config 目录下(也就是 /usr/share/hassio/homeassistant/scripts/queryRaspi.py
    文件路径

阶段成果

至此,重新启动 Home Assistant 服务后(你也可以在后面所有配置完成后再重启),我们将在 开发者工具-状态 里看到我们定义的一个命令行传感器实体。
实体状态

  • 可以看到实体名称就是我们定义的 RaspInfo 的小写 raspinfo;相应的,若取名为 Rasp Info,实体名称就会变为 rasp_info
  • 状态(States)栏已经获得了脚本命令正确的返回值,并且属性(Attributes)栏里已经成功将字典里的键(Key)解析为这个实体的属性。

以上都没有问题的话,我们继续往下看。

Template Sensor(重点)

虽然上面的命令行传感器已经能够将(一整项)状态数据显示在主页了,但是该怎么把各项数据单独作为传感器实体显示出来呢?事实上 template 平台支持我们定义一个从其它实体获取值的传感器,也就是 Template Sensor ,而这正是我们想要的功能(利用命令行传感器的各个属性值)。

下面就来看看这个基于模板的传感器如何配置吧!完整配置信息请参考官方文档 Template Sensor

  • 注:这一部分主要涉及的是模板(template)的使用,这里不作赘述,可以参考文档 Templating

配置

在配置文件的 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 服务后(你也可以在后面所有配置完成后再重启),我们将在 开发者工具-状态 里看到所有刚刚创建的传感器的单独实体。

  • 若在前端主页出现实体不可用的警告或者玄学问题,可以尝试重新启动 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 !

未来工作

  • 完整阅读文档,了解所有配置(有个印象,方便查阅)
  • 对着文档,修改传感器图标使得更加美观
  • … … …

通过 ESPHome 在 OLED 上显示

待填坑

结语

不知不觉写了好长时间将近九千个字(符),太长不看系列。希望自己把问题描述的足够清楚了,在这里也只是抛砖引玉,有了这一遍流程,大家就已经可以自己动手开发自己想要的各类“传感器”了,别忘了来分享喔。

  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在Node-RED使用Home Assistant组件和在Home Assistant使用Node-RED插件有一些区别。这两种方法都可以实现Home Assistant与Node-RED之间的集成,但具体的实现方式和功能略有不同。 1. 在Node-RED使用Home Assistant组件: - 使用Home Assistant组件可以在Node-RED直接与Home Assistant进行通信和控制。你可以使用Home Assistant节点来读取和写入Home Assistant实体的状态,执行服务调用,接收事件以及发送命令。 - Node-RED提供了丰富的节点和工具,使你能够轻松地构建自定义的自动化逻辑和工作流程,并与Home Assistant的设备、传感器和服务进行交互。 2. 在Home Assistant使用Node-RED插件: - 使用Node-RED插件可以将Node-RED嵌入到Home Assistant的界面,以便直接在Home Assistant编辑和管理Node-RED的工作流程。 - 通过将Node-RED集成到Home Assistant,你可以利用Home Assistant的实体和服务来触发和控制Node-RED的流程。你可以使用Home Assistant的触发器(如状态变化、时间等)来启动Node-RED流程,并通过调用Home Assistant服务来与设备进行交互。 - 这种方式更适合那些已经熟悉Home Assistant界面和配置的用户,可以更方便地在Home Assistant管理和监控Node-RED的工作流程。 总的来说,选择使用哪种方法取决于你的需求和个人偏好。如果你更喜欢在Node-RED构建和管理自动化逻辑,那么使用Home Assistant组件可能更适合你。如果你已经习惯了Home Assistant的界面并且想要在一个统一的界面管理所有的自动化和服务,那么使用Node-RED插件可能更适合你。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值