- id: pfv_plant_ups_on_battery alias: PFV plant - UPS on battery triggers: - trigger: state entity_id: - sensor.tsys1_ups_status - sensor.tsys1_triplite_status conditions: - condition: template value_template: '{{ ''On Battery'' in states(trigger.entity_id) }}' actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: POWER OUTAGE url: /lovelace-pfv-server-room/ups message: '{{ state_attr(trigger.entity_id, ''friendly_name'') }} lost utility power and is ON BATTERY at {{ states(''sensor.'' ~ trigger.entity_id.split(''.'')[1] | replace(''_status'', ''_battery_charge'')) }}% charge.' mode: single - id: pfv_plant_ups_battery_low alias: PFV plant - UPS battery low triggers: - trigger: numeric_state entity_id: - sensor.tsys1_ups_battery_charge - sensor.tsys1_triplite_battery_charge below: 40 conditions: - condition: template value_template: '{{ ''On Battery'' in states(trigger.entity_id | replace(''_battery_charge'', ''_status'')) }}' actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: UPS BATTERY LOW url: /lovelace-pfv-server-room/ups message: '{{ trigger.entity_id }} at {{ states(trigger.entity_id) }}% while on battery. Start graceful shutdown of VMs before hypervisors (#455 ordering).' mode: single - id: pfv_plant_ups_comm_lost alias: PFV plant - UPS communication lost triggers: - trigger: state entity_id: - sensor.tsys1_ups_status - sensor.tsys1_triplite_status to: unavailable for: 00:05:00 actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: UPS COMMS LOST url: /lovelace-pfv-server-room/ups message: '{{ trigger.entity_id }} unreachable for 5 minutes (nut-server or network path down; tsys1 also hosts pfv-bms itself).' mode: single - id: pfv_plant_ups_runtime_low alias: PFV plant - UPS runtime low while on battery description: On battery and runtime burned below 10 min — the graceful shutdown window is closing. VMs before hypervisors per #455. triggers: - trigger: numeric_state entity_id: sensor.pfv_ups_runtime_minutes below: 10 conditions: - condition: template value_template: "{{ states('sensor.tsys1_ups_status') not in ['Online', 'unknown', 'unavailable'] }}" actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: UPS RUNTIME LOW url: /lovelace-pfv-server-room/ups message: On battery {{ states('sensor.pfv_ups_runtime_minutes') }} min left — start graceful shutdown now (#455 ordering). mode: single - id: pfv_plant_ups_power_restored alias: PFV plant - utility power restored triggers: - trigger: state entity_id: - sensor.tsys1_ups_status - sensor.tsys1_triplite_status conditions: - condition: template value_template: "{{ trigger.from_state is not none and 'On Battery' in trigger.from_state.state\n \ and 'On Battery' not in states(trigger.entity_id) }}" actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: Power restored url: /lovelace-pfv-server-room/ups message: '{{ state_attr(trigger.entity_id, ''friendly_name'') }} is back ONLINE.' mode: single - id: pfv_plant_high_temperature alias: PFV plant - high temperature triggers: - trigger: numeric_state entity_id: - sensor.pfv_tsys3_nvme_temperature - sensor.pfv_tsys5_nvme_temperature above: 150 - trigger: numeric_state entity_id: - sensor.pfv_tsys4_dimm_18_temperature - sensor.pfv_tsys4_dimm_19_temperature - sensor.pfv_tsys4_dimm_1a_temperature - sensor.pfv_tsys4_dimm_1b_temperature above: 140 - trigger: numeric_state entity_id: - sensor.pfv_tsys1_drive_temperature - sensor.pfv_tsys4_drive_0_0_temperature - sensor.pfv_tsys4_drive_0_10_temperature - sensor.pfv_tsys4_drive_1_0_temperature - sensor.pfv_tsys4_drive_1_10_temperature - sensor.pfv_tsys5_drive_1_0_temperature - sensor.pfv_tsys5_drive_4_10_temperature - sensor.pfv_tsys5_drive_4_20_temperature - sensor.pfv_tsys5_drive_4_30_temperature - sensor.pfv_tsys9_drive_temperature above: 140 - trigger: numeric_state entity_id: - sensor.pfv_tsys3_gpu_temperature - sensor.pfv_jetson_gpu_temperature above: 185 - trigger: numeric_state entity_id: - sensor.pfv_tsys3_pch_temperature - sensor.pfv_tsys9_pch_temperature above: 160 # CPU-SoC silicon tier: idle silicon routinely exceeds the # ambient 104F threshold (subopi3 SoC idles at ~117F); 176F = 80C # pre-throttle territory for Pi-Jetson SoCs and server CPUs [#733] - trigger: numeric_state entity_id: - sensor.pfv_tsys3_cpu_temperature - sensor.pfv_tsys6_cpu_temperature - sensor.pfv_tsys7_cpu_temperature - sensor.pfv_tsys9_cpu_temperature - sensor.pfv_tsys7_drac_cpu1 - sensor.pfv_tsys7_drac_cpu2 - sensor.pfv_jetson_temperature - sensor.pfv_svrpi_temperature - sensor.pfv_subopi3_temperature - sensor.pfv_subopi_dev_3_temperature - sensor.pfv_subopi_dev_4_temperature above: 176 - trigger: numeric_state entity_id: - sensor.pfv_artroom_temperature - sensor.pfv_garage_temperature - sensor.pfv_tsys1_rack_temperature - sensor.pfv_tsys4_ambient_temperature - sensor.pfv_tsys5_ambient_temperature - sensor.pfv_tsys6_drac_ambient - sensor.pfv_tsys7_drac_inlet - sensor.pfv_tsys7_drac_exhaust above: 104 actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: HIGH TEMPERATURE url: /lovelace-pfv-server-room/temps message: '{{ trigger.entity_id }} is {{ states(trigger.entity_id) }}°F (class threshold exceeded). Check cooling/airflow.' mode: single - id: pfv_plant_sensor_watchdog alias: PFV plant - sensor watchdog (unavailable sensors) description: HA is the environmental brain (#344) — a silent sensor is an outage. Re-alert suppressed by 4h cooldown via last_notified input_text if present. triggers: - trigger: time_pattern minutes: /30 actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: SENSOR WATCHDOG url: /lovelace-pfv-server-room/overview message: >- {% set fleet = states.sensor | selectattr('entity_id', 'match', 'sensor\.pfv_') | list %} {% set dead = fleet | selectattr('state', 'in', ['unavailable', 'unknown']) | list %} {% if dead | length > 0 %} {{ dead | length }} of {{ fleet | length }} fleet sensors silent: {{ dead | map(attribute='entity_id') | join(', ') }} {% else %} all {{ fleet | length }} fleet sensors OK {% endif %} mode: single - id: pfv_plant_temp_rising_fast alias: PFV plant - temperature rising fast (rate-of-change) description: Catches dead AC minutes before the 104F threshold trips. triggers: - trigger: state entity_id: - binary_sensor.server_room_temp_rising - binary_sensor.tsys6_ambient_rising - binary_sensor.tsys7_inlet_rising - binary_sensor.garage_temp_rising to: "on" for: minutes: 2 actions: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: TEMP RISING FAST url: /lovelace-pfv-server-room/temps message: '{{ trigger.entity_id }} climbing ~10F/15min — check cooling before the 104F threshold. (rate-of-change early warning)' # Deploy pipeline [#734]: gitea repo webhook (release pushes) -> forced pull # -> minimal reload. Core restarts ONLY when configuration.yaml or a # packages platform-sensor file changed; everything else reloads with no # bounce. The git_pull add-on's auto_restart is disabled - this webhook # owns apply timing (no more 5-min-timer surprise restarts). - id: pfv_deploy_git_webhook alias: PFV deploy - git push to pull + minimal reload description: >- Gitea webhook on release pushes. Forces a git pull now, then homeassistant.reload_all unless files that require a core restart changed. Replaces the git_pull add-on timer auto-restart [#734]. mode: queued max_exceeded: silent triggers: - trigger: webhook webhook_id: !secret deploy_webhook_id allowed_methods: - POST local_only: false conditions: [] actions: - if: - condition: template value_template: "{{ trigger.json.ref | default('') != 'refs/heads/release' }}" then: - stop: "deploy webhook: non-release ref {{ trigger.json.ref | default('') }} ignored" - variables: changed_files: >- {{ (trigger.json.commits | default([]) | map(attribute='added') | flatten | list) + (trigger.json.commits | default([]) | map(attribute='removed') | flatten | list) + (trigger.json.commits | default([]) | map(attribute='modified') | flatten | list) }} need_restart: >- {{ changed_files | select('match', '^(configuration\.yaml|packages/.+)') | list | count > 0 }} push_message: >- Git push ({{ trigger.json.sender.login | default('unknown') }}): {{ trigger.json.commits | default([]) | map(attribute='message') | join(' | ') | truncate(120) }}. {{ 'Core restart required' if need_restart else 'Reload only - no core restart' }}. - action: persistent_notification.create data: title: Deploy started message: "{{ push_message }} Pulling now." - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: PFV deploy started message: "{{ push_message }}" - action: hassio.addon_restart data: addon: core_git_pull - delay: hours: 0 minutes: 0 seconds: 25 - if: - condition: template value_template: "{{ need_restart }}" then: - action: persistent_notification.create data: title: Deploy - restarting core message: "Pull done; restarting core for {{ changed_files | join(', ') }}. Back in ~1 min." - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: PFV deploy - core restarting message: "Pull done; restarting core for {{ changed_files | join(', ') }}." - delay: hours: 0 minutes: 0 seconds: 3 - action: homeassistant.restart else: - action: homeassistant.reload_all - action: persistent_notification.create data: title: Deploy complete message: "Pulled + reloaded YAML config at {{ now().strftime('%H:%M:%S') }} (no core restart). Files: {{ changed_files | join(', ') | truncate(180) }}" - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: PFV deploy complete message: "Pulled + reloaded YAML at {{ now().strftime('%H:%M:%S') }} - no core restart. Files: {{ changed_files | join(', ') | truncate(120) }}" # Deploy pipeline safety net [#734]: polls gitea release HEAD (rest sensor # in packages/deploy_pipeline.yaml) and applies pulls reload-only. The # gitea webhook is the fast path once gitea's SSRF allowlist permits # pfv-bms.knel.net; until then this net catches every push within 5 min # with NO core restart. Restarts for new platform sensors stay manual # (22222 shell) until the webhook path is live. - id: pfv_deploy_sha_watch alias: PFV deploy - gitea sha watch safety net description: >- Release HEAD sha changed -> pull + CORE RESTART. Interim deploy trigger while gitea webhook delivery is blocked by its SSRF host allowlist [#734]. Restart (not reload) is REQUIRED: automation reload loses webhook-trigger registration - found live 2026-09-03 (#345): after any reload-only deploy, webhook automations (doorman scan ingest, this pipeline's own fast path) silently stop firing while the endpoint still returns HTTP 200. Core restart re-registers them. Accepted trade-off: ~1 min HA outage per release deploy. mode: single max_exceeded: silent triggers: - trigger: state entity_id: sensor.pfv_deploy_gitea_release_head conditions: - condition: template value_template: >- {{ trigger.from_state is not none and trigger.from_state.state not in ['unknown', 'unavailable'] and trigger.to_state is not none and trigger.from_state.state != trigger.to_state.state }} actions: - action: hassio.addon_restart data: addon: core_git_pull - delay: hours: 0 minutes: 0 seconds: 20 - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: PFV deploy (sha watch) message: >- New release HEAD {{ states('sensor.pfv_deploy_gitea_release_head')[:7] }} pulled. Restarting HA core (webhook re-registration) - back in ~1 min. - action: homeassistant.restart - id: pfv_plant_temperature_recovered alias: PFV plant - temperature recovered description: >- Recovery twin of the high-temperature alert [#344 ask 2026-09-03]: notify when a sensor that was OVER its tier drops back below (fire-line minus 5F hysteresis) and HOLDS there for 10 minutes. from_state guard prevents spurious fires at HA restart; the tier map mirrors the high-temperature automation thresholds exactly. triggers: - trigger: numeric_state entity_id: - sensor.pfv_tsys3_nvme_temperature - sensor.pfv_tsys5_nvme_temperature below: 145 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_tsys4_dimm_18_temperature - sensor.pfv_tsys4_dimm_19_temperature - sensor.pfv_tsys4_dimm_1a_temperature - sensor.pfv_tsys4_dimm_1b_temperature below: 135 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_tsys1_drive_temperature - sensor.pfv_tsys4_drive_0_0_temperature - sensor.pfv_tsys4_drive_0_10_temperature - sensor.pfv_tsys4_drive_1_0_temperature - sensor.pfv_tsys4_drive_1_10_temperature - sensor.pfv_tsys5_drive_1_0_temperature - sensor.pfv_tsys5_drive_4_10_temperature - sensor.pfv_tsys5_drive_4_20_temperature - sensor.pfv_tsys5_drive_4_30_temperature - sensor.pfv_tsys9_drive_temperature below: 135 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_tsys3_gpu_temperature - sensor.pfv_jetson_gpu_temperature below: 180 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_tsys3_pch_temperature - sensor.pfv_tsys9_pch_temperature below: 155 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_tsys3_cpu_temperature - sensor.pfv_tsys6_cpu_temperature - sensor.pfv_tsys7_cpu_temperature - sensor.pfv_tsys9_cpu_temperature - sensor.pfv_tsys7_drac_cpu1 - sensor.pfv_tsys7_drac_cpu2 - sensor.pfv_jetson_temperature - sensor.pfv_svrpi_temperature - sensor.pfv_subopi3_temperature - sensor.pfv_subopi_dev_3_temperature - sensor.pfv_subopi_dev_4_temperature below: 171 for: 00:10:00 - trigger: numeric_state entity_id: - sensor.pfv_artroom_temperature - sensor.pfv_garage_temperature - sensor.pfv_tsys1_rack_temperature - sensor.pfv_tsys4_ambient_temperature - sensor.pfv_tsys5_ambient_temperature - sensor.pfv_tsys6_drac_ambient - sensor.pfv_tsys7_drac_inlet - sensor.pfv_tsys7_drac_exhaust below: 99 for: 00:10:00 actions: - variables: fire_lines: sensor.pfv_tsys3_nvme_temperature: 150 sensor.pfv_tsys5_nvme_temperature: 150 sensor.pfv_tsys4_dimm_18_temperature: 140 sensor.pfv_tsys4_dimm_19_temperature: 140 sensor.pfv_tsys4_dimm_1a_temperature: 140 sensor.pfv_tsys4_dimm_1b_temperature: 140 sensor.pfv_tsys1_drive_temperature: 140 sensor.pfv_tsys4_drive_0_0_temperature: 140 sensor.pfv_tsys4_drive_0_10_temperature: 140 sensor.pfv_tsys4_drive_1_0_temperature: 140 sensor.pfv_tsys4_drive_1_10_temperature: 140 sensor.pfv_tsys5_drive_1_0_temperature: 140 sensor.pfv_tsys5_drive_4_10_temperature: 140 sensor.pfv_tsys5_drive_4_20_temperature: 140 sensor.pfv_tsys5_drive_4_30_temperature: 140 sensor.pfv_tsys9_drive_temperature: 140 sensor.pfv_tsys3_gpu_temperature: 185 sensor.pfv_jetson_gpu_temperature: 185 sensor.pfv_tsys3_pch_temperature: 160 sensor.pfv_tsys9_pch_temperature: 160 sensor.pfv_tsys3_cpu_temperature: 176 sensor.pfv_tsys6_cpu_temperature: 176 sensor.pfv_tsys7_cpu_temperature: 176 sensor.pfv_tsys9_cpu_temperature: 176 sensor.pfv_tsys7_drac_cpu1: 176 sensor.pfv_tsys7_drac_cpu2: 176 sensor.pfv_jetson_temperature: 176 sensor.pfv_svrpi_temperature: 176 sensor.pfv_subopi3_temperature: 176 sensor.pfv_subopi_dev_3_temperature: 176 sensor.pfv_subopi_dev_4_temperature: 176 sensor.pfv_artroom_temperature: 104 sensor.pfv_garage_temperature: 104 sensor.pfv_tsys1_rack_temperature: 104 sensor.pfv_tsys4_ambient_temperature: 104 sensor.pfv_tsys5_ambient_temperature: 104 sensor.pfv_tsys6_drac_ambient: 104 sensor.pfv_tsys7_drac_inlet: 104 sensor.pfv_tsys7_drac_exhaust: 104 fire: "{{ fire_lines.get(trigger.entity_id, 0) | int }}" - condition: template value_template: >- {{ trigger.from_state is not none and trigger.from_state.state not in ['unavailable', 'unknown', 'none'] and trigger.from_state.state | float(-1) >= fire }} - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: TEMPERATURE RECOVERED url: /lovelace-pfv-server-room/temps message: >- {{ state_attr(trigger.entity_id, 'friendly_name') | default(trigger.entity_id) }} back to {{ states(trigger.entity_id) }}°F and holding — was {{ trigger.from_state.state }}°F when the alert cleared (tier fire line {{ fire }}°F). mode: single - id: pfv_watchdog_stale_entities alias: PFV watchdog - stale entity auto-heal description: > Detects silent poller wedges (2026-09-04: snmp tsys9 went 12h undetected; NUT APC 3h) and auto-heals config-entry platforms via homeassistant.reload_config_entry — no restart needed. Escalates to notify when reload does not recover. Auto core restart ONLY while input_boolean.pfv_watchdog_auto_restart is ON and entities stay stale — restart costs ~1 min downtime and re-registers webhooks (#345, #789). v1 notify repeats each cycle while stale (visible alarm); throttle in v2. mode: single max_exceeded: silent triggers: - trigger: time_pattern minutes: /5 variables: checks: - [sensor.pfv_tsys1_rack_temperature, 20] - [sensor.pfv_tsys1_drive_temperature, 30] - [sensor.pfv_tsys3_cpu_temperature, 20] - [sensor.pfv_tsys4_ambient_temperature, 20] - [sensor.pfv_tsys6_cpu_temperature, 20] - [sensor.pfv_tsys6_drac_ambient, 30] - [sensor.pfv_tsys7_cpu_temperature, 20] - [sensor.pfv_tsys7_drac_inlet, 30] - [sensor.pfv_tsys9_cpu_temperature, 20] - [sensor.pfv_tsys9_drive_temperature, 30] - [sensor.tsys1_ups_status, 15] - [sensor.tsys1_triplite_status, 15] - [sensor.pfv_deploy_gitea_release_head, 30] actions: - variables: stale_list: >- {% set ns = namespace(stale=[]) %} {% for pair in checks %} {% set s = states[pair[0]] %} {% if s is not none and s.last_updated is defined and (now() - s.last_updated).total_seconds() > pair[1] * 60 %} {% set ns.stale = ns.stale + [pair[0]] %} {% endif %} {% endfor %} {{ ns.stale }} - condition: template value_template: "{{ stale_list | length > 0 }}" - repeat: for_each: "{{ stale_list }}" sequence: - action: homeassistant.reload_config_entry data: entity_id: "{{ repeat.item }}" - delay: hours: 0 minutes: 2 seconds: 0 - variables: still_stale: >- {% set ns = namespace(stale=[]) %} {% for pair in checks %} {% set s = states[pair[0]] %} {% if s is not none and s.last_updated is defined and (now() - s.last_updated).total_seconds() > pair[1] * 60 %} {% set ns.stale = ns.stale + [pair[0]] %} {% endif %} {% endfor %} {{ ns.stale }} - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: WATCHDOG url: /lovelace-pfv-server-room/temps message: >- Stale after auto-reload: {{ still_stale | join(', ') }}. Auto-restart is {{ 'ON' if is_state('input_boolean.pfv_watchdog_auto_restart','on') else 'OFF (arm it on the watchdog switch if you want unattended restarts)' }}. - if: - condition: template value_template: "{{ is_state('input_boolean.pfv_watchdog_auto_restart','on') }}" then: - delay: hours: 0 minutes: 30 seconds: 0 - variables: hard_stale: >- {% set ns = namespace(stale=[]) %} {% for pair in checks %} {% set s = states[pair[0]] %} {% if s is not none and s.last_updated is defined and (now() - s.last_updated).total_seconds() > pair[1] * 60 %} {% set ns.stale = ns.stale + [pair[0]] %} {% endif %} {% endfor %} {{ ns.stale }} - if: - condition: template value_template: "{{ hard_stale | length > 0 }}" then: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: WATCHDOG — restarting core message: "Still stale after reload + 30 min: {{ hard_stale | join(', ') }}. Restarting HA core now." - action: homeassistant.restart - id: pfv_post_deploy_validation alias: PFV post-deploy validation description: > Runs after EVERY HA start (deploy restarts included): after a settle delay, verifies the critical sensor set actually materialized and is fresh. Catches bad deploys — missing templates, broken packages, wedged pollers — and pages with specifics instead of waiting for a human to notice (#778, #777). The watchdog then handles recovery. mode: single max_exceeded: silent triggers: - trigger: event event_type: homeassistant_start actions: - delay: hours: 0 minutes: 3 seconds: 0 - variables: required: - [sensor.pfv_tsys1_rack_temperature, 20] - [sensor.pfv_tsys9_cpu_temperature, 20] - [sensor.tsys1_ups_status, 15] - [sensor.tsys1_triplite_status, 15] - [sensor.pfv_ups_runtime_minutes, 30] - [sensor.pfv_tripp_lite_runtime_minutes, 30] - [sensor.pfv_deploy_gitea_release_head, 30] - [automation.pfv_watchdog_stale_entities, 0] - variables: bad_list: >- {% set ns = namespace(bad=[]) %} {% for pair in required %} {% set s = states[pair[0]] %} {% if s is none or s.state in ['unknown', 'unavailable', 'none'] %} {% set ns.bad = ns.bad + [pair[0] ~ ' (missing)'] %} {% elif pair[1] > 0 and s.last_updated is defined and (now() - s.last_updated).total_seconds() > pair[1] * 60 %} {% set ns.bad = ns.bad + [pair[0] ~ ' (stale)'] %} {% endif %} {% endfor %} {{ ns.bad }} - if: - condition: template value_template: "{{ bad_list | length > 0 }}" then: - action: notify.send_message target: entity_id: - notify.ultix_sidecar_new - notify.allthes_ipad data: title: POST-DEPLOY VALIDATION FAILED url: /lovelace-pfv-thermal message: >- After restart, these criticals are missing/stale: {{ bad_list | join(', ') }}. Watchdog will retry recovery; if this repeats, revert the last release (git revert + push). - action: persistent_notification.create data: title: POST-DEPLOY VALIDATION FAILED message: "Missing/stale: {{ bad_list | join(', ') }}" - id: pfv_kuma_heartbeat alias: PFV Kuma heartbeat (dead-man) description: > Pushes OK to the out-of-band Uptime Kuma every 5 minutes (#792). Kuma pages the founder directly if heartbeats stop — the alert path that works when HA itself is the failure. mode: single max_exceeded: silent triggers: - trigger: time_pattern minutes: /5 actions: - action: shell_command.kuma_ha_heartbeat