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檔
再取出含有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