Home Assistant Command Line Sensor的變數處理與單位轉換

Command line sensor

Command line在Home Assistant Core 2023.12之後已轉成整合(Integration)而非原本Sensor下的一個Platform,最常用的Command line sensor佈署的方式變成在configuration.yaml下

command_line:
  - sensor:
      command: SENSOR_COMMAND_1
  - sensor:
      command: SENSOR_COMMAND_2

Commad line sensor的部分我多用在資料爬蟲,爬unifi controller、爬高速公路路況、爬空汙資料、爬台股、爬伺服器狀況等等。同一個類別的資料,我會存成同一份檔案再去做資料處理,避免短時間內做多次爬取,可能會變拒絕連線的問題。

從Command line得到的結果稱為Payload,例如我將docker stats的結果存成DataDockerStatus.txt檔

docker stats

再取出含有wordpress的這一列(grep wordpress)裡的MEM USAGE部分

$ cat /config/data/DataDockerStatus.txt | grep wordpress | awk '{print $4}'
718.7MiB

這個Command下的Payload就是718.7MiB

要做資料處理,就會使用上value_template對Payload做處理,在value_template中Payload的變數為value,如果Payload是json格式,可以改用value_json比較好處理。

以上面這個為例,718.7MiB是字串而非數值,要將MiB抹掉並轉成浮點數,再掛個單位給它才是正確的做法,不然Home Assistant無法對字串畫出趨勢圖。

- sensor:
    name: WordPress_DockerMEM
    command: "cat /config/data/DataDockerStatus.txt | grep wordpress | awk '{print $4}'"
    value_template: >
      value.replace("MiB","") | float
    unit_of_measurement: "MB"

在此例value_template的運算中,value是718.7MiB,先用replace把”MiB”取代成””,再轉成浮點數,就會得到數字格式的718.7。

那再來看frigate與wordpress的MEM USAGE,一個單位是MiB,另一個是GiB,照上面那種做法會有二個問題。

  • 這二個sensor單位會不同,很難看,而且還要各別處理。
  • 萬一MEM USAGE從MiB跳到GiB或GiB跳到MiB,就會有抹不到的問題,即使用了二個replace把GiB和MiB都抹掉,得到的數字單位也不正確。

要解決這個問題,可以在value_template中用上if else,如果Payload字串含有MiB,抹去MiB後轉成浮點數,除以1024後再取到小數點下二位,就可以轉成以GiB為單位的值,反之,若是Payload字串中含有GiB,直接抹去GiB轉成浮點數即可。

- sensor:
    name: WordPress_DockerMEM
    command: "cat /config/data/DataDockerStatus.txt | grep wordpress | awk '{print $4}'"
    value_template: >
      {% if "MiB" in value %} {% set MEM = ((value.replace('MiB','') | float)/1024) | round(2) %}
      {% elif "GiB" in value %} {% set MEM = value.replace('GiB','') | float %}
      {% endif %}
      {{ MEM }}
    unit_of_measurement: "GB"
    scan_interval: 180
- sensor:
    name: Frigate_DockerMEM
    command: "cat /config/data/DataDockerStatus.txt | grep frigate | awk '{print $4}'"
    value_template: >
      {% if "MiB" in value %} {% set MEM = ((value.replace('MiB','') | float)/1024) | round(2) %}
      {% elif "GiB" in value %} {% set MEM = value.replace('GiB','') | float %}
      {% endif %}
      {{ MEM }}
    unit_of_measurement: "GB"
    scan_interval: 180

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端