『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 14044|回复: 7

[基础教程] 命令行传感器和模板的使用之在HA中监控树莓派的CPU温度内存

[复制链接]

4

主题

67

帖子

515

积分

高级会员

Rank: 4

积分
515
金钱
448
HASS币
0
发表于 2019-10-22 14:45:28 | 显示全部楼层 |阅读模式
本帖最后由 AlanGreen 于 2019-10-24 20:55 编辑

背景介绍

引言

我们知道在 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 上显示

待填坑

战术总结

  • 一定要学会查看日志,根据报错信息对症下药
  • 不知不觉写了好长时间将近九千个字(符),太长不看系列。希望自己把问题描述的足够清楚了,在这里也只是抛砖引玉,有了这一遍流程,大家就已经可以自己动手开发自己想要的各类“传感器”了,别忘了来分享喔。对了,新人求回复。文章还发在 CSDN















评分

参与人数 1金钱 +20 收起 理由
咸味土豆 + 20 wow,像极了以前的M大,超级详细的解析。.

查看全部评分

回复

使用道具 举报

8

主题

736

帖子

4558

积分

论坛元老

Rank: 8Rank: 8

积分
4558
金钱
3817
HASS币
40
QQ
发表于 2019-10-22 14:53:06 | 显示全部楼层
本帖最后由 Aiden1 于 2019-10-22 14:54 编辑

沙发! 说到OLED显示,我先上几张我目前的做的效果图,要不一起研究一下?

时间

时间

余额

余额

温湿度

温湿度
回复

使用道具 举报

4

主题

67

帖子

515

积分

高级会员

Rank: 4

积分
515
金钱
448
HASS币
0
 楼主| 发表于 2019-10-22 14:54:27 | 显示全部楼层
Aiden1 发表于 2019-10-22 14:53
沙发! 说到OLED显示,我先上几张我目前的做的效果过,要不一起研究一下? ...

嘿嘿,不知道 ESPHome 配置的简不简单,有空看了再更新~
回复

使用道具 举报

8

主题

736

帖子

4558

积分

论坛元老

Rank: 8Rank: 8

积分
4558
金钱
3817
HASS币
40
QQ
发表于 2019-10-22 14:55:12 | 显示全部楼层
AlanGreen 发表于 2019-10-22 14:54
嘿嘿,不知道 ESPHome 配置的简不简单,有空看了再更新~

还可以,挺简单的
回复

使用道具 举报

1

主题

35

帖子

274

积分

中级会员

Rank: 3Rank: 3

积分
274
金钱
239
HASS币
0
发表于 2019-10-23 11:03:41 | 显示全部楼层
可以啊,学习学习
回复

使用道具 举报

4

主题

67

帖子

515

积分

高级会员

Rank: 4

积分
515
金钱
448
HASS币
0
 楼主| 发表于 2019-10-23 11:21:44 | 显示全部楼层

多谢支持~
回复

使用道具 举报

0

主题

12

帖子

45

积分

新手上路

Rank: 1

积分
45
金钱
33
HASS币
0
发表于 2020-5-16 16:04:29 | 显示全部楼层
对于小白有点复杂
回复

使用道具 举报

0

主题

36

帖子

343

积分

中级会员

Rank: 3Rank: 3

积分
343
金钱
306
HASS币
0
发表于 2021-2-16 19:52:10 | 显示全部楼层
太牛了,刚接触这个平台不久,功能也太强大了吧,把命令行都接入进来了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-16 21:26 , Processed in 0.185333 second(s), 35 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表