因篇幅關係,拆成以下幾篇易於閱讀。
- 透過Home Assistant實做魚缸的監控與輔助管理之一:系統概要
- 透過Home Assistant實做魚缸的監控與輔助管理之二:感應器與ESP32
- 透過Home Assistant實做魚缸的監控與輔助管理之三:實現輔助管理 (本文)
- 透過Home Assistant實做魚缸的監控與輔助管理之四:操作介面
本篇文章來記錄一下在Home Assistant中的各種sensor、script與automation,以及自訂義的timer、input_number與input_boolean,開始之前先講三個前提。
前提一:在Home Assistant裡,我有將configuration.yaml中的各種區塊獨立出來,這樣比較方便管理。
automation: !include automations.yaml
binary_sensor: !include binary_sensor.yaml
input_boolean: !include input_boolean.yaml
input_number: !include input_number.yaml
mqtt: !include mqtt.yaml
script: !include scripts.yaml
sensor: !include sensor.yaml
sql: !include sql.yaml
timer: !include timer.yaml
前提二:需要紀錄的事項會透過notify.notify_line_aquarium(快要停止服務了)把訊息發送到line上,以及透過script.aquarium_logger將訊息寫入文字檔裡,文字檔可轉成網頁並放在lovelace中,詳細介紹可以參考Home Assistant中利用iframe card將文字檔內容嵌入lovelace的方法。
雖然是在automation中用到notify.send_message就可以,但因為寫入檔案的訊息前面我都會加上日期時間戳記,所以獨立出一個script.aquarium_logger統一處理日期時間戳記,可以省去不少維護的麻煩,其中{{ msg }}是從automation或script中帶過來的變數。
script.yaml
aquarium_logger:
alias: Aquarium_Logger
sequence:
- action: notify.send_message
target:
entity_id: notify.aquarium
data:
message: "{{ now().strftime('%Y/%m/%d %H:%M:%S') }} → {{ msg }}"
前提三:篇幅的關係,操作介面的東西擺在另一篇文章中,本文中如果有看起來很累贅的sensor或其他東西,可能是在操作介面中會用到,也有可能是我寫程式的當下頭腦不清楚。另外本文的索引如下
水溫相關
水溫原始值
以下二個MQTT sensor是從ESP32發佈的topic中取得的資料原始值
mqtt.yaml
- name: Aquarium_MainTank_WaterTemperature
state_topic: "aquarium/maintank/water_temperature"
value_template: "{{ value }}"
unit_of_measurement: "°C"
- name: Aquarium_Bucket_WaterTemperature
state_topic: "aquarium/bucket/water_temperature"
value_template: "{{ value }}"
unit_of_measurement: "°C"
水溫改寫
如果ESP32收不到來自DS18B20水溫線的資料,溫度會顯示-127°C,在長時間的溫度追蹤裡會將這種資料移除,並配合automation做警示。
sensor.yaml
- platform: template
sensors:
aquarium_maintank_watertemperature_rendering:
friendly_name: Aquarium_MainTank_WaterTemperature_Rendering
value_template: >-
{% if states('sensor.aquarium_maintank_watertemperature') | float != -127 %}
{{ states('sensor.aquarium_maintank_watertemperature') }}
{% endif %}
unit_of_measurement: "°C"
- platform: template
sensors:
aquarium_bucket_watertemperature_rendering:
friendly_name: Aquarium_Bucket_WaterTemperature_Rendering
value_template: >-
{% if states('sensor.aquarium_bucket_watertemperature') | float != -127 %}
{{ states('sensor.aquarium_bucket_watertemperature') }}
{% endif %}
unit_of_measurement: "°C"
水溫線異常警報
automation.yaml
- alias: Aquarium:Invalid_WaterTemperature_Alarm
triggers:
- trigger: template
value_template: "{{ states('sensor.aquarium_maintank_watertemperature') | int == -127 or states('sensor.aquarium_bucket_watertemperature') | int == -127 }}"
actions:
- variables:
message: >
{% if trigger.entity_id == "sensor.aquarium_maintank_watertemperature" %} 主缸水溫線異常。
{% elif trigger.entity_id == "sensor.aquarium_bucket_watertemperature" %} 補水桶水溫線異常。
{% else %} 請檢查水溫線。
{% endif %}
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
主缸水溫異常警報
利用二個input_number定義出正常水溫的上下限
input_number.yaml
aquarium_maintank_watertemperature_max:
name: Aquarium_MainTank_WaterTemperature_Max
min: 26
max: 35
step: 0.5
unit_of_measurement: "°C"
aquarium_maintank_watertemperature_min:
name: Aquarium_MainTank_WaterTemperature_Min
min: 17
max: 26
step: 0.5
unit_of_measurement: "°C"
當水溫超出上限或低於下限時啟動binary_sensor
binary_sensor.yaml
- platform: template
sensors:
aquarium_watertemperature_alarm:
friendly_name: Aquarium_WaterTemperature_Alarm
value_template: >
{{ states('sensor.aquarium_maintank_watertemperature_rendering') | float(default=0) > states('input_number.aquarium_maintank_watertemperature_max') | float(default=0) or states('sensor.aquarium_maintank_watertemperature_rendering') | float(default=0) <= states('input_number.aquarium_maintank_watertemperature_min') | float(default=0) }}
當水溫超出上下限的第五分鐘會發佈第一條警報,之後每半小時檢查一次,若還是超出上下限就再發一條警報,避免水溫在界限附近可能會頻繁地收到太多警報。
automation.yaml
- alias: Aquarium:WaterTemperature_Alarm
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_watertemperature_alarm
from: "off"
to: "on"
for:
minutes: 5
conditions:
- condition: template
value_template: "{{ states('sensor.aquarium_maintank_watertemperature_rendering') != 'unavailable' }}"
actions:
- alias: repeat
repeat:
while:
- condition: state
entity_id: binary_sensor.aquarium_watertemperature_alarm
state: "on"
sequence:
- action: notify.notify_line_aquarium
data:
message: >
水溫超出上下限,目前為{{ states('sensor.aquarium_maintank_watertemperature_rendering') }}。
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: >
水溫超出上下限,目前為{{ states('sensor.aquarium_maintank_watertemperature_rendering') }}。
- delay:
minutes: 30
mode: restart
主缸過去一小時溫差過大警報
金魚是冷水魚,不怕高溫低溫,但怕溫度急遽地改變,所以監測主缸水溫一小時內的變化。這個沒有現成的sensor平台可以處理,只能從資料庫裡查詢最大值與最小值後相減。
sql.yaml
- name: Aquarium_MainTank_WaterTemperature_1HR_Range
query: >
SELECT
MAX(CAST(states.state AS DECIMAL(5,2))) - MIN(CAST(states.state AS DECIMAL(5,2))) AS result
FROM
states
INNER JOIN states_meta ON
states.metadata_id = states_meta.metadata_id
WHERE
states_meta.entity_id = 'sensor.aquarium_maintank_watertemperature_rendering'
AND FROM_UNIXTIME(last_updated_ts) >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND states.state != 'unavailable'
AND states.state != 'unknown';
column: "result"
unit_of_measurement: "°C"
給一個input_number當警示的上限,溫差是取差值的絕對值且愈小愈好,所以這個沒有下限。
input_number.yaml
aquarium_maintank_watertemperature_1hr_range_max:
name: Aquarium_MainTank_WaterTemperature_1HR_Range_Max
min: 0
max: 5
step: 0.1
unit_of_measurement: "°C"
若溫差超過上限,則binary_sensor為on。
binary_sensor.yaml
- platform: template
sensors:
aquarium_maintank_watertemperature_1hr_range_alarm:
friendly_name: Aquarium_MainTank_WaterTemperature_1HR_Range_Alarm
value_template: >
{{ (states('sensor.aquarium_maintank_watertemperature_1hr_range') | float(default=0) | abs) > (states('input_number.aquarium_maintank_watertemperature_1hr_range_max') | float(default=0)) }}
一樣是發警報,再依情況看要怎麼處置。
automation.yaml
- alias: Aquarium:MainTank_WaterTemperature_1HR_Range_Alarm
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_maintank_watertemperature_1hr_range_alarm
from: "off"
to: "on"
for:
minutes: 5
actions:
- variables:
message: 主缸一小時溫差過大。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
主缸與補水桶溫差過大警報
一樣是溫度急遽地改變的問題,所以自動補水或手動補水前需要確認主缸與補水桶間的溫差,這在後面補水相關再提,其他的與前面邏輯雷同。
sensor.yaml
- platform: template
sensors:
aquarium_watertemperature_gap:
value_template: >
{{ (states('sensor.aquarium_maintank_watertemperature_rendering') | float - states('sensor.aquarium_bucket_watertemperature_rendering') | float) | round(2) }}
unit_of_measurement: "°C"
binary_sensor.yaml
- platform: template
sensors:
aquarium_watertemperature_gap_alarm:
friendly_name: Aquarium_WaterTemperature_Gap_Alarm
value_template: >
{{ states('sensor.aquarium_watertemperature_gap') | float(default=0) > states('input_number.aquarium_watertemperature_gap_max') | float(default=0) }}
automation.yaml
- alias: Aquarium:WaterTemperature_Gap_Alarm
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_watertemperature_gap_alarm
from: "off"
to: "on"
for:
minutes: 5
actions:
- variables:
message: 主缸與補水桶的溫差過大。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
pH值相關
pH校正參數
ESP32可以從pH模組得到pH探棒的電壓值,做完電壓值對pH值的校正後,電壓值才能轉為pH值。校正的參數可以寫在ESP32中,但這樣每校一次都需要做ESP32的更新,這樣有點麻煩,我的做法是把參數放在Home Assistant的input_number中,當參數改變時會發佈MQTT的訊息,ESP32再去更新校正的參數即可。
input_number.yaml
aquarium_ph_slope:
name: Aquarium_pH_Slope
min: -10
max: 0
step: 0.0001
aquarium_ph_intercept:
name: Aquarium_pH_Intercept
min: -100
max: 100
step: 0.0001
automation.yaml
- alias: Aquarium:Update_pH_Calibration_Slope
triggers:
- trigger: state
entity_id: input_number.aquarium_ph_slope
for:
seconds: 5
actions:
- action: mqtt.publish
data:
topic: "aquarium/others/ph_slope"
payload: "{{ states('input_number.aquarium_ph_slope') }}"
qos: 1
retain: true
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: >
pH校正斜率從{{ trigger.from_state.state }}更改至{{ trigger.to_state.state }}
- alias: Aquarium:Update_pH_Calibration_Intercept
triggers:
- trigger: state
entity_id: input_number.aquarium_ph_intercept
for:
seconds: 5
actions:
- action: mqtt.publish
data:
topic: "aquarium/others/ph_intercept"
payload: "{{ states('input_number.aquarium_ph_intercept') }}"
qos: 1
retain: true
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: >
pH校正截距從{{ trigger.from_state.state }}更改至{{ trigger.to_state.state }}
pH原始值
pH值本身沒有單位,但若不給個空白單位,在Home Assistant中的歷史資料不會以折線圖表示。
mqtt.yaml
- name: Aquarium_MainTank_PH
state_topic: "aquarium/maintank/ph"
value_template: "{{ value }}"
unit_of_measurement: ""
pH資料改寫
這個pH模組我用起來覺得讀值不太穩定,雖然在ESP32中已經做過多點取樣平均的動作,但還是偶爾會看到奇異點的出現。原始值拉進來後我做一個合理性的改寫,先取得過去一小時的平均值與標準差,這個只能用SQL來做。
sql.yaml
- name: Aquarium_pH_Average_1HR
query: >
SELECT
CAST(AVG(states.state) AS DECIMAL(5,2)) AS result
FROM
states
INNER JOIN states_meta ON
states.metadata_id = states_meta.metadata_id
WHERE
states_meta.entity_id = 'sensor.aquarium_maintank_ph'
AND FROM_UNIXTIME(last_updated_ts) >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND states.state != 'unavailable'
AND states.state != 'unknown';
column: "result"
unit_of_measurement: ""
- name: Aquarium_pH_StandDev_1HR
query: >
SELECT
CAST(STDDEV(states.state) AS DECIMAL(5,2)) AS result
FROM
states
INNER JOIN states_meta ON
states.metadata_id = states_meta.metadata_id
WHERE
states_meta.entity_id = 'sensor.aquarium_maintank_ph'
AND FROM_UNIXTIME(last_updated_ts) >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND states.state != 'unavailable'
AND states.state != 'unknown';
column: "result"
unit_of_measurement: ""
再將原始讀值超過平均值加減三倍標準差的值給排除,這裡用template sensor來做。
sensor.yaml
- platform: template
sensors:
aquarium_maintank_ph_rendering:
friendly_name: Aquarium_MainTank_pH_Rendering
value_template: >
{% set ph_value = states('sensor.aquarium_maintank_ph') | float %}
{% set avg = states('sensor.aquarium_ph_average_1hr') | float %}
{% set stddev = states('sensor.aquarium_ph_standdev_1hr') | float %}
{% set upper_bound = avg + 3 * stddev %}
{% set lower_bound = avg - 3 * stddev %}
{% if ph_value >= lower_bound and ph_value <= upper_bound %}
{{ ph_value }}
{% else %}
{{ avg }}
{% endif %}
unit_of_measurement: ""
這樣資料會比較收斂一些。
pH警報
警報的部分,與溫度警報基本上雷同,不多贅述。
input_number.yaml
aquarium_ph_max:
name: Aquarium_pH_Max
min: 0
max: 14
step: 0.1
aquarium_ph_min:
name: Aquarium_pH_Min
min: 0
max: 14
step: 0.1
binary_sensor.yaml
- platform: template
sensors:
aquarium_ph_alarm:
friendly_name: Aquarium_pH_Alarm
value_template: >
{{ states('sensor.aquarium_maintank_ph_rendering') | float(default=0) > states('input_number.aquarium_ph_max') | float(default=0) or states('sensor.aquarium_maintank_ph_rendering') | float(default=0) <= states('input_number.aquarium_ph_min') | float(default=0) }}
automation.yaml
- alias: Aquarium:pH_Alarm
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_ph_alarm
from: "off"
to: "on"
for:
minutes: 5
conditions:
- condition: template
value_template: "{{ states('sensor.aquarium_maintank_ph_rendering') != 'unavailable' }}"
actions:
- alias: repeat
repeat:
while:
- condition: state
entity_id: binary_sensor.aquarium_ph_alarm
state: "on"
sequence:
- action: notify.notify_line_aquarium
data:
message: >
pH超出上下限,目前為{{ states('sensor.aquarium_maintank_ph_rendering') }}。
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: >
pH超出上下限,目前為{{ states('sensor.aquarium_maintank_ph_rendering') }}。
- delay:
minutes: 30
mode: restart
TDS值相關
TDS原始值
mqtt.yaml
- name: Aquarium_MainTank_TDS
state_topic: "aquarium/maintank/tds"
value_template: "{{ value }}"
unit_of_measurement: "ppm"
TDS改寫
同pH,有做合理性的改寫。
sql.yaml
- name: Aquarium_TDS_Average_1HR
query: >
SELECT
CAST(AVG(states.state) AS DECIMAL(5,2)) AS result
FROM
states
INNER JOIN states_meta ON
states.metadata_id = states_meta.metadata_id
WHERE
states_meta.entity_id = 'sensor.aquarium_maintank_tds'
AND FROM_UNIXTIME(last_updated_ts) >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND states.state != 'unavailable'
AND states.state != 'unknown';
column: "result"
unit_of_measurement: "ppm"
- name: Aquarium_TDS_StandDev_1HR
query: >
SELECT
CAST(STDDEV(states.state) AS DECIMAL(5,2)) AS result
FROM
states
INNER JOIN states_meta ON
states.metadata_id = states_meta.metadata_id
WHERE
states_meta.entity_id = 'sensor.aquarium_maintank_tds'
AND FROM_UNIXTIME(last_updated_ts) >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND states.state != 'unavailable'
AND states.state != 'unknown';
column: "result"
unit_of_measurement: "ppm"
sensor.yaml
- platform: template
sensors:
aquarium_maintank_tds_rendering:
friendly_name: Aquarium_MainTank_TDS_Rendering
value_template: >-
{% set tds_value = states('sensor.aquarium_maintank_tds') | float %}
{% set avg = states('sensor.aquarium_tds_average_1hr') | float %}
{% set stddev = states('sensor.aquarium_tds_standdev_1hr') | float %}
{% set upper_bound = avg + 3 * stddev %}
{% set lower_bound = avg - 3 * stddev %}
{% if tds_value >= lower_bound and tds_value <= upper_bound %}
{{ tds_value }}
{% else %}
{{ avg }}
{% endif %}
unit_of_measurement: "ppm"
TDS警報
input_number.yaml
aquarium_tds_max:
name: Aquarium_TDS_Max
min: 100
max: 300
step: 5
unit_of_measurement: "ppm"
aquarium_tds_min:
name: Aquarium_TDS_Min
min: 100
max: 300
step: 5
unit_of_measurement: "ppm"
binary_sensor.yaml
- platform: template
sensors:
aquarium_tds_alarm:
friendly_name: Aquarium_TDS_Alarm
value_template: >
{{ states('sensor.aquarium_maintank_tds_rendering') | float(default=0) > states('input_number.aquarium_tds_max') | float(default=0) or states('sensor.aquarium_maintank_tds_rendering') | float(default=0) <= states('input_number.aquarium_tds_min') | float(default=0) }}
automation.yaml
- alias: Aquarium:TDS_Alarm
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_tds_alarm
from: "off"
to: "on"
for:
minutes: 5
conditions:
- condition: template
value_template: "{{ states('sensor.aquarium_maintank_tds_rendering') != 'unavailable' }}"
actions:
- alias: repeat
repeat:
while:
- condition: state
entity_id: binary_sensor.aquarium_tds_alarm
state: "on"
sequence:
- action: notify.notify_line_aquarium
data:
message: >
TDS超出上下限,目前為{{ states('sensor.aquarium_maintank_tds_rendering') }}。
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: >
TDS超出上下限,目前為{{ states('sensor.aquarium_maintank_tds_rendering') }}。
- delay:
minutes: 30
mode: restart
控制器狀態
家裡的路由器是Mikrotik,Home Assistant HACS中有對應的integration可以使用,該integration中有監測裝置是否離線的功能。因為監測資料都是ESP32來的,如果斷線或是無線網路不穩定,可能會有疑慮。
automation.yaml
- alias: Aquarium:Controller_Offline
triggers:
- trigger: state
entity_id:
- device_tracker.093_a340
- device_tracker.094_ebdc
from: "home"
to: "not_home"
for:
minutes: 3
actions:
- variables:
message: >
{% if trigger.entity_id == "device_tracker.093_a340" %} 主控制器離線。
{% elif trigger.entity_id == "device_tracker.094_ebdc" %} 副控制器離線。
{% else %} 未知的控制器狀態變化。
{% endif %}
- alias: repeat
repeat:
while:
- condition: template
value_template: "{{ states('sdevice_tracker.093_a340') == 'not_home' or states('sdevice_tracker.094_ebdc') == 'not_home' }}"
sequence:
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
- delay:
minutes: 30
mode: restart
維護模式
一個簡單的input_boolean,使用者可以自行開啟關閉。
input_boolean.yaml
aquarium_maintenance:
name: Aquarium_Maintenance
我的魚缸有個上蓋,上蓋邊緣跟主缸有一個門窗感應器來判斷上蓋有沒有被拿起,當上蓋拿起來的時候通常就是要維護的時候,所以會自動觸發維護模式。
automation.yaml
- alias: Aquarium:Maintenance_AutoOn
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_tankcover_contactsensor_contact
from: "off"
to: "on"
for:
seconds: 3
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- action: input_boolean.turn_on
entity_id: input_boolean.aquarium_maintenance
mode: queued
- alias: Aquarium:Maintenance_AutoOff
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_tankcover_contactsensor_contact
from: "on"
to: "off"
for:
seconds: 3
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "on"
actions:
- action: input_boolean.turn_off
entity_id: input_boolean.aquarium_maintenance
mode: queued
維護模式觸發後,會把魚缸燈和加熱棒關掉,並且開啟該區域的照明燈方便作業並停用該區域的燈光自動化。
automation.yaml
- alias: Aquarium:Maintenance_Mode_On
triggers:
- trigger: state
entity_id: input_boolean.aquarium_maintenance
from: "off"
to: "on"
actions:
- variables:
message: 維護模式開啟。
- action: switch.turn_off
entity_id:
- switch.gosund_powerstrip_aquarium_switch1
- switch.gosund_powerstrip_aquarium_switch4
- action: input_boolean.turn_off
entity_id: input_boolean.light_automation_restaurant
- action: light.turn_on
entity_id:
- light.restaurant
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: queued
- alias: Aquarium:Maintenance_Mode_Off
triggers:
- trigger: state
entity_id: input_boolean.aquarium_maintenance
from: "on"
to: "off"
actions:
- variables:
message: 維護模式關閉。
- action: input_boolean.turn_on
entity_id: input_boolean.light_automation_restaurant
- action: light.turn_off
entity_id:
- light.restaurant
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: queued
設備相關
燈光(延長線第一格)
燈光在非維護模式下,14:00開燈到22:00。
automation.yaml
- alias: Aquarium:Light_AutoOn
triggers:
- trigger: time
at: "14:00:00"
conditions:
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch1
state: "off"
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- action: switch.turn_on
data: {}
entity_id: switch.gosund_powerstrip_aquarium_switch1
mode: queued
- alias: Aquarium:Light_AutoOff
triggers:
- trigger: time
at: "22:00:00"
conditions:
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch1
state: "on"
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- action: switch.turn_off
data: {}
entity_id: switch.gosund_powerstrip_aquarium_switch1
mode: queued
補水馬達(延長線第二格)
補水馬達在補水桶水位過低時,應該被切斷電源。
automation.yaml
- alias: Aquarium:RefillWater_Pump_TurnOff_When_WaterLowLevel
triggers:
- trigger: state
entity_id: input_number.aquarium_bucket_waterlevel
from: "2"
to: "1"
actions:
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch2
mode: queued
沉水馬達(延長線第三格)
沉水馬達在沉馬格水位過低時,應該被切斷電源。
automation.yaml
- alias: Aquarium:Submersible_Pump_TurnOff_When_WaterLowLevel
triggers:
- trigger: state
entity_id: input_number.aquarium_pumptank_waterlevel
from: "0.5"
to: "0"
actions:
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch3
mode: queued
另外還做了停止後自動延遲啟動的功能,可以用在餵食或簡單的換棉。先來個倒數計時器
timer.yaml
submersible_pump_duration:
name: Submersible_Pump_Duration
用腳本啟動這個功能,當沉水馬達是啟動的狀態下,會開始倒數指定的時間並將沉水馬達關掉,當沉水馬達是關閉的狀態下,會直接停止計時器,並將沉水馬達的電源打開。
script.yaml
aquarium_pump_delay:
alias: Aquarium_Pump_Delay
sequence:
- choose:
- conditions:
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch3
state: "on"
sequence:
- action: timer.start
target:
entity_id: timer.submersible_pump_duration
data:
duration: >
00:{{ '%02d' | format(states('input_number.submersible_pump_duration') | int) }}:00
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch3
- conditions:
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch3
state: "off"
sequence:
- action: timer.finish
target:
entity_id: timer.submersible_pump_duration
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch3
當計時器結束後就打開沉馬的電源
automation.yaml
- alias: Aquarium:Submersible_Pump_Delay_Start
triggers:
- trigger: event
event_type: timer.finished
event_data:
entity_id: timer.submersible_pump_duration
actions:
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch3
mode: queued
加溫棒(延長線第四格)
冷水魚會用到加溫棒的機會不大,買著防身而已,我買的加溫棒有自帶控制器,這樣等於是雙重保險。先用input_number建立加溫棒啟動跟停止的上下限
input_number.yaml
aquarium_heater_on_threshold:
name: Aquarium_Heater_On_Threshold
min: 20
max: 26
step: 0.5
unit_of_measurement: "°C"
aquarium_heater_off_threshold:
name: Aquarium_Heater_Off_Threshold
min: 23
max: 29
step: 0.5
unit_of_measurement: "°C"
低於下限時啟動,高於上限時停止。
automation.yaml
- alias: Aquarium:Heater_TurnOn
triggers:
- trigger: numeric_state
entity_id: sensor.aquarium_maintank_watertemperature_rendering
below: input_number.aquarium_heater_on_threshold
for:
minutes: 1
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch4
state: "off"
actions:
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch4
mode: queued
- alias: Aquarium:Heater_TurnOff
triggers:
- trigger: numeric_state
entity_id: sensor.aquarium_maintank_watertemperature_rendering
above: input_number.aquarium_heater_off_threshold
for:
minutes: 1
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch4
state: "on"
actions:
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch4
mode: queued
打氣機(延長線第五格)
自帶電池的不斷電打氣機,控制了開關也沒用,除非電池沒電不然不會停止。
降溫風扇(延長線第六格)
跟加溫棒邏輯相同,先建立上下限
input_number.yaml
aquarium_fan_on_threshold:
name: Aquarium_Fan_On_Threshold
min: 26
max: 32
step: 0.5
unit_of_measurement: "°C"
aquarium_fan_off_threshold:
name: Aquarium_Fan_Off_Threshold
min: 23
max: 29
step: 0.5
unit_of_measurement: "°C"
然後自動控制
automation.yaml
- alias: Aquarium:Fan_TurnOn
triggers:
- trigger: numeric_state
entity_id: sensor.aquarium_maintank_watertemperature_rendering
above: input_number.aquarium_fan_on_threshold
for:
minutes: 1
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch6
state: "off"
actions:
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch6
mode: queued
- alias: Aquarium:Fan_TurnOff
triggers:
- trigger: numeric_state
entity_id: sensor.aquarium_maintank_watertemperature_rendering
below: input_number.aquarium_fan_off_threshold
for:
minutes: 1
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
- condition: state
entity_id: switch.gosund_powerstrip_aquarium_switch6
state: "on"
actions:
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch6
mode: queued
實體開關
這條延長線很奇怪,除了延長線總開關外沒有控制單一插座的實體開關,如果我要手動開關插座就一定得拿手機操作,所以後來補了一個無線開關來控制燈光和風扇。
automation.yaml
- alias: Aquarium:Button_Single
triggers:
- trigger: state
entity_id: sensor.aquarium_control_wirelessbutton_action
to: "single"
actions:
- action: switch.toggle
data: {}
entity_id: switch.gosund_powerstrip_aquarium_switch1
mode: queued
- alias: Aquarium:Button_Hold
triggers:
- trigger: state
entity_id: sensor.aquarium_control_wirelessbutton_action
to: "hold"
actions:
- action: switch.toggle
data: {}
entity_id: switch.gosund_powerstrip_aquarium_switch6
mode: queued
插座狀態
除了燈光外,其他五個插座若意外地啟動或關閉都有可能出事,所以也警報一下。
automation.yaml
- alias: Aquarium:Device_StatusOn_Monitor
triggers:
- trigger: state
entity_id:
- switch.gosund_powerstrip_aquarium_switch2
- switch.gosund_powerstrip_aquarium_switch3
- switch.gosund_powerstrip_aquarium_switch4
- switch.gosund_powerstrip_aquarium_switch5
- switch.gosund_powerstrip_aquarium_switch6
from: "off"
to: "on"
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- variables:
message: >
{% if trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch2" %} 開始補水。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch3" %} 沉水馬達電源開啟。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch4" %} 加溫棒電源開啟。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch5" %} 打氣機電源開啟。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch6" %} 風扇電源開啟。
{% else %} 未知的設備狀態變化。
{% endif %}
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: queued
- alias: Aquarium:Device_StatusOff_Monitor
triggers:
- trigger: state
entity_id:
- switch.gosund_powerstrip_aquarium_switch2
- switch.gosund_powerstrip_aquarium_switch3
- switch.gosund_powerstrip_aquarium_switch4
- switch.gosund_powerstrip_aquarium_switch5
- switch.gosund_powerstrip_aquarium_switch6
from: "on"
to: "off"
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- variables:
message: >
{% if trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch2" %} 停止補水。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch3" %} 沉水馬達電源關閉。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch4" %} 加溫棒電源關閉。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch5" %} 打氣機電源關閉。
{% elif trigger.entity_id == "switch.gosund_powerstrip_aquarium_switch6" %} 風扇電源關閉。
{% else %} 未知的設備狀態變化。
{% endif %}
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: queued
設備失效監控
可以從插座功率跟插座開關狀態去監控設備是否失效,比如說沉水馬達正常情況功耗是35W,但在沉馬水達的插座為開的情況下,只有18W的輸出,那表示應該發生什麼事需要檢查了。但這條延長線並沒有針對單一插座做功耗監控,只有整條延長線的總功耗,雖然這樣判斷上就比較模糊一點,但還是可以做。
先計算功耗目標值,初始值設為0,再慢慢依照插座開關狀態往上加。
sensor.yaml
- platform: template
sensors:
aquarium_power_target:
value_template: >
{% set power = 0 %}
{% if states('switch.gosund_powerstrip_aquarium_switch1') == "on" %}
{% set power = power + 20.6 %}
{% endif %}
{% if states('switch.gosund_powerstrip_aquarium_switch2') == "on" %}
{% set power = power + 25 %}
{% endif %}
{% if states('switch.gosund_powerstrip_aquarium_switch3') == "on" %}
{% set power = power + 32 %}
{% endif %}
{% if states('switch.gosund_powerstrip_aquarium_switch4') == "on" %}
{% set power = power + 200 %}
{% endif %}
{% if states('switch.gosund_powerstrip_aquarium_switch5') == "on" %}
{% set power = power + 3 %}
{% endif %}
{% if states('switch.gosund_powerstrip_aquarium_switch6') == "on" %}
{% set power = power + 3 %}
{% endif %}
{{ power }}
比較實際功耗與目標功耗,若「實際功耗超出1.05倍目標功耗」或是「實際功耗低於0.95倍目標功耗」那就可能有什麼問題。
binary_sensor.yaml
- platform: template
sensors:
aquarium_power_check:
value_template: >
{{ states('sensor.gosund_powerstrip_aquarium_power') | float(default=0) <= (states('sensor.aquarium_power_target') | float(default=1))*0.95 or states('sensor.gosund_powerstrip_aquarium_power') | float(default=1) >= (states('sensor.aquarium_power_target') | float(default=0))*1.05 }}
automation.yaml
- alias: Aquarium:Device_Power_Monitor_Fail
triggers:
- trigger: state
entity_id: binary_sensor.aquarium_power_check
from: "off"
to: "on"
for:
minutes: 5
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- variables:
message: >
設備功耗異常,功耗目標值為{{ states('sensor.aquarium_power_target') }},實際值為{{ states('sensor.gosund_powerstrip_aquarium_power') }}。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: queued
自動補水
目標是要在該補水的時候判斷能不能補水,該補水的時機點是
- 背濾沉馬格水位太低,沉馬抽不到水。
- 背濾濾材格水位太低,水流沒經過濾材。
第二點會比第一點早發生,而如果第一點發生了,會直接把沉馬給停了避免沉馬損壞,所以觸發補水時機點用第二點來做。
補水前要先判斷適不適合補水,如果有以下情況也不適合補水
- 主缸水位太高,那可能是棉塞住了,補了只會更高。
- 補水桶水位太低,沒水可以補。
所以先來一個判斷水位的配套,這在之前的在Home Assistant中利用動態圖片來呈現魚缸水位的變化一文中有提到。
input_number.yaml
aquarium_bucket_waterlevel:
name: Aquarium_Bucket_Waterlevel
min: -1
max: 2
step: 0.5
aquarium_maintank_waterlevel:
name: Aquarium_Maintank_Waterlevel
min: -1
max: 2
step: 0.5
aquarium_filtertank_waterlevel:
name: Aquarium_Filtertank_Waterlevel
min: -1
max: 2
step: 0.5
aquarium_pumptank_waterlevel:
name: Aquarium_Pumptank_Waterlevel
min: -1
max: 2
step: 0.5
automation.yaml
- alias: Aquarium:Water_Level_Rendering(Varied)
triggers:
- trigger: state
entity_id:
- sensor.aquarium_bucket_waterlevel
- sensor.aquarium_maintank_waterlevel
- sensor.aquarium_filtertank_waterlevel
- sensor.aquarium_pumptank_waterlevel
conditions:
- condition: template
value_template: "{{ trigger.from_state.state != 'unavailable' and trigger.to_state.state != 'unavailable' and trigger.from_state.state != trigger.to_state.state }}"
actions:
- action: input_number.set_value
target:
entity_id: >
{% if trigger.entity_id == "sensor.aquarium_bucket_waterlevel" %} input_number.aquarium_bucket_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_maintank_waterlevel" %} input_number.aquarium_maintank_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_filtertank_waterlevel" %} input_number.aquarium_filtertank_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_pumptank_waterlevel" %} input_number.aquarium_pumptank_waterlevel
{% else %} input_number.dummy_number
{% endif %}
data:
value: >
{% if trigger.entity_id == "sensor.aquarium_pumptank_waterlevel" %}
{% if trigger.from_state.state == '1' and trigger.to_state.state == '2' %} 1.5
{% elif trigger.from_state.state == '2' and trigger.to_state.state == '1' %} 1.5
{% elif trigger.from_state.state == '0' and trigger.to_state.state == '1' %} 0.5
{% elif trigger.from_state.state == '1' and trigger.to_state.state == '0' %} 0.5
{% else %} -1
{% endif %}
{% else %}
1
{% endif %}
mode: parallel
max: 30
- alias: Aquarium:Water_Level_Rendering(Stable)
triggers:
- trigger: state
entity_id:
- sensor.aquarium_bucket_waterlevel
- sensor.aquarium_maintank_waterlevel
- sensor.aquarium_filtertank_waterlevel
- sensor.aquarium_pumptank_waterlevel
for:
minutes: 2
conditions:
- condition: template
value_template: "{{ trigger.from_state.state != 'unavailable' and trigger.to_state.state != 'unavailable' and trigger.from_state.state != trigger.to_state.state }}"
actions:
- action: input_number.set_value
target:
entity_id: >
{% if trigger.entity_id == "sensor.aquarium_bucket_waterlevel" %} input_number.aquarium_bucket_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_maintank_waterlevel" %} input_number.aquarium_maintank_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_filtertank_waterlevel" %} input_number.aquarium_filtertank_waterlevel
{% elif trigger.entity_id == "sensor.aquarium_pumptank_waterlevel" %} input_number.aquarium_pumptank_waterlevel
{% else %} input_number.dummy_number
{% endif %}
data:
value: >
{% if trigger.entity_id == "sensor.aquarium_pumptank_waterlevel" %}
{% if trigger.from_state.state == '1' and trigger.to_state.state == '2' %} 2
{% elif trigger.from_state.state == '2' and trigger.to_state.state == '1' %} 1
{% elif trigger.from_state.state == '0' and trigger.to_state.state == '1' %} 1
{% elif trigger.from_state.state == '1' and trigger.to_state.state == '0' %} 0
{% else %} -1
{% endif %}
{% else %}
{% if trigger.from_state.state == '0' and trigger.to_state.state == '2' %} 2
{% elif trigger.from_state.state == '2' and trigger.to_state.state == '0' %} 0
{% else %} -1
{% endif %}
{% endif %}
mode: parallel
max: 30
再來是依據各種狀況來判斷補水狀態的sensor
sensor.yaml
- platform: template
sensors:
aquarium_tank_refill_condition:
friendly_name: Aquarium_Tank_Refill_Condition
value_template: >
{% if states('switch.gosund_powerstrip_aquarium_switch2') == "on" %}
補水中
{% elif states('input_boolean.aquarium_maintenance') == "on" %}
維護模式
{% elif states('sensor.aquarium_watertemperature_gap') | float < states('input_number.aquarium_water_refill_temperature_gap') | float and states('input_number.aquarium_pumptank_waterlevel') | int != 2 and states('input_number.aquarium_bucket_waterlevel') | int == 2 and states('input_number.aquarium_maintank_waterlevel') | int == 0 and states('input_boolean.aquarium_maintenance') == "off" and states('switch.gosund_powerstrip_aquarium_switch2') == "off" %}
待命中
{% elif states('sensor.aquarium_watertemperature_gap') | float >= states('input_number.aquarium_water_refill_temperature_gap') | float %}
補水桶溫差過大
{% elif states('sensor.aquarium_waterlevel_check') != "安全" %}
水位異常
{% endif %}
執行手動補水的腳本,若是要手動補水就單純執行這個腳本,但只有「待命中」和「維護模式」二種狀況下可以手動補水,補水量是由馬達啟動的時間來控制。自動補水則是從automation那邊延伸過來。
input_number.yaml
aquarium_water_refill_duration:
name: Aquarium_Water_Refill_Duration
min: 0
max: 20
step: 1
unit_of_measurement: "秒"
script.yaml
aquarium_maintank_manually_refill:
alias: Aquarium_MainTank_Manually_Refill
sequence:
- choose:
- conditions:
- condition: or
conditions:
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "待命中"
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "維護模式"
sequence:
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch2
- delay:
seconds: "{{ states('input_number.aquarium_water_refill_duration') | int }}"
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch2
自動補水的部分,寫二條automation,第一條是在滿足背濾濾材格水位太低時觸發,第二條則是固定時間的確認。第二條在彌補第一條的不足,否則若第一條因為某些原因沒有觸發(Home Assistant重新啟動之類的),那就都不會補水了。
另外actions中用到了choose,這裡用choose會比用conditions搭配template的if/else還來的簡單一點。
automation.yaml
- alias: Aquarium:Auto_Refill
triggers:
- trigger: template
value_template: "{{ states('input_number.aquarium_filtertank_waterlevel') | int == 0 }}"
conditions:
- condition: state
entity_id: device_tracker.093_a340
state: "home"
actions:
- choose:
- conditions:
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "待命中"
sequence:
- variables:
message: >
滿足待命時自動補水,12小時內已補過{{ states('sensor.aquarium_maintank_refill_count_12') }}次。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
- action: script.turn_on
data:
entity_id: script.aquarium_maintank_refill
- conditions:
- condition: or
conditions:
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "補水桶溫差過大"
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "水位異常"
sequence:
- variables:
message: >
自動補水條件未滿足,原因為{{ states('sensor.aquarium_tank_refill_condition') }}。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
- alias: Aquarium:Auto_Refill_Regular_Check
triggers:
- trigger: time_pattern
minutes: "/10"
conditions:
- condition: template
value_template: >
{{ states('input_number.aquarium_filtertank_waterlevel') | int == 0 and states('device_tracker.093_a340') == "home" and states('sensor.aquarium_tank_refill_condition') != "維護模式" }}
actions:
- choose:
- conditions:
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "待命中"
sequence:
- variables:
message: >
滿足待命時自動補水,12小時內已補過{{ states('sensor.aquarium_maintank_refill_count_12') }}次。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
- action: script.turn_on
data:
entity_id: script.aquarium_maintank_refill
- conditions:
- condition: or
conditions:
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "補水桶溫差過大"
- condition: state
entity_id: sensor.aquarium_tank_refill_condition
state: "水位異常"
sequence:
- variables:
message: >
自動補水條件未滿足,原因為{{ states('sensor.aquarium_tank_refill_condition') }}。
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
自動補水的腳本獨立出來的原因是
- 要計算過去12小時內補過幾次水,幾週跑下來大概都是補1次,如果有超過就要看一下是不是哪裡有問題。
- 可以省略補水條件的檢查,因為在automation中的condition已經檢查過。
script.yaml
aquarium_maintank_refill:
alias: Aquarium_MainTank_Refill
sequence:
- action: switch.turn_on
entity_id: switch.gosund_powerstrip_aquarium_switch2
- delay:
seconds: "{{ states('input_number.aquarium_water_refill_duration') | int }}"
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch2
sensor.yaml
- platform: history_stats
name: Aquarium_MainTank_Refill_Count_12
entity_id: script.aquarium_maintank_refill
state: "on"
type: count
start: "{{ as_timestamp(now()) - 12 * 60 * 60 }}"
end: "{{ now() }}"
最後再來一條停止自動補水的安全措施,避免意外地補水馬達沒有關閉造成水漫金山。用馬達持續啟動時間來做,分別在+2、+7與+15秒時觸發。
- alias: Aquarium:Tank_Stop_Refill
triggers:
- trigger: state
entity_id: device_tracker.093_a340
to: "not_home"
- trigger: state
entity_id: switch.gosund_powerstrip_aquarium_switch2
from: "off"
to: "on"
for:
seconds: "{{ states('input_number.aquarium_water_refill_duration') | int + 2 }}"
- trigger: state
entity_id: switch.gosund_powerstrip_aquarium_switch2
from: "off"
to: "on"
for:
seconds: "{{ states('input_number.aquarium_water_refill_duration') | int + 7 }}"
- trigger: state
entity_id: switch.gosund_powerstrip_aquarium_switch2
from: "off"
to: "on"
for:
seconds: "{{ states('input_number.aquarium_water_refill_duration') | int + 15 }}"
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- action: switch.turn_off
entity_id: switch.gosund_powerstrip_aquarium_switch2
mode: queued
水位相關
水位警報
- alias: Aquarium:Water_Level_Alarm
triggers:
- trigger: state
entity_id:
- input_number.aquarium_bucket_waterlevel
- input_number.aquarium_maintank_waterlevel
- input_number.aquarium_filtertank_waterlevel
- input_number.aquarium_pumptank_waterlevel
conditions:
- condition: state
entity_id: input_boolean.aquarium_maintenance
state: "off"
actions:
- variables:
message: >
{% if trigger.entity_id == "input_number.aquarium_bucket_waterlevel" %}
{% if trigger.to_state.state | float == 0 %}
補水桶水位過低。
{% elif trigger.to_state.state | float == 1 %}
補水桶水位在交界處。
{% elif trigger.to_state.state | float == 2 %}
補水桶水位正常。
{% else %}
檢查水位 {{ trigger.entity_id }} from {{ trigger.from_state.state }} to {{ trigger.to_state.state }}
{% endif %}
{% elif trigger.entity_id == "input_number.aquarium_maintank_waterlevel" %}
{% if trigger.to_state.state | float == 0 %}
主缸水位正常。
{% elif trigger.to_state.state | float == 1 %}
主缸水位在交界處。
{% elif trigger.to_state.state | float == 2 %}
主缸水位過高。
{% else %}
檢查水位 {{ trigger.entity_id }} from {{ trigger.from_state.state }} to {{ trigger.to_state.state }}
{% endif %}
{% elif trigger.entity_id == "input_number.aquarium_filtertank_waterlevel" %}
{% if trigger.to_state.state | float == 0 %}
過濾槽水位過低。
{% elif trigger.to_state.state | float == 1 %}
過濾槽水位在交界處。
{% elif trigger.to_state.state | float == 2 %}
過濾槽水位正常。
{% else %}
檢查水位 {{ trigger.entity_id }} from {{ trigger.from_state.state }} to {{ trigger.to_state.state }}
{% endif %}
{% elif trigger.entity_id == "input_number.aquarium_pumptank_waterlevel" %}
{% if trigger.to_state.state | float == 0 %}
沉馬格水位過低。
{% elif trigger.to_state.state | float == 0.5 %}
沉馬格水位在低水位交界處。
{% elif trigger.to_state.state | float == 1 %}
沉馬格水位正常。
{% elif trigger.to_state.state | float == 1.5 %}
沉馬格水位在高水位交界處。
{% elif trigger.to_state.state | float == 2 %}
沉馬格水位過高。
{% else %}
檢查水位 {{ trigger.entity_id }} from {{ trigger.from_state.state }} to {{ trigger.to_state.state }}
{% endif %}
{% else %}
請檢查水位。
{% endif %}
- action: notify.notify_line_aquarium
data:
message: "{{ message }}"
- action: script.turn_on
target:
entity_id: script.aquarium_logger
data:
variables:
msg: "{{ message }}"
mode: parallel
max: 30