various tidyups

This commit is contained in:
zorruno
2026-07-22 22:15:25 +12:00
parent b9e9c98f7e
commit 8fdcb128a3
15 changed files with 778 additions and 2030 deletions
@@ -9,7 +9,7 @@
# jobs_tracker_jobs.yaml
#
# VERSION:
# V2.3 2026-07-20
# V2.4 2026-07-21
#
# PURPOSE:
# Defines the job registry, MQTT Discovery entities, completion triggers and
@@ -41,6 +41,12 @@
# Complete
#
# VERSION HISTORY:
# V2.4 2026-07-21
# - Startup now waits for every retained job timestamp before refreshing.
# - Minute refreshes skip while retained MQTT state is not ready.
# - Restored stale event timestamps are no longer accepted as completions.
# - Discovery device firmware version updated to 2.4.
#
# V2.3 2026-07-20
# - All completion methods now obey the configured completion window.
# - Physical completion entities, Home Assistant discovery buttons and direct
@@ -360,7 +366,7 @@ script:
device_name: "Jobs Tracker"
device_manufacturer: "View Road Home Assistant"
device_model: "Shared household jobs tracker"
device_sw_version: "2.3"
device_sw_version: "2.4"
value_template_state: >-
{% raw %}{{ value_json.state | default('unknown') }}{% endraw %}
@@ -697,10 +703,23 @@ automation:
actions:
- action: script.jobs_tracker_publish_discovery
# Give Home Assistant a moment to process MQTT Discovery.
- delay: "00:00:10"
- variables:
jobs_tracker_jobs: *jobs_tracker_jobs
# Force retained state payloads onto each job topic.
# Do not refresh until every retained timestamp has returned from MQTT.
# Aborting on timeout protects valid retained data from being replaced by 0.
- wait_template: >-
{% set ns = namespace(ready=true) %}
{% for job in jobs_tracker_jobs %}
{% if not is_number(state_attr(job.state_entity, 'last_completed_ts')) %}
{% set ns.ready = false %}
{% endif %}
{% endfor %}
{{ ns.ready }}
timeout: "00:01:30"
continue_on_timeout: false
# Recalculate each job only after retained state is confirmed ready.
- action: script.jobs_tracker_dispatch
data:
update_all: true
@@ -711,25 +730,26 @@ automation:
mode: single
triggers:
- trigger: homeassistant
event: start
id: ha_start
- trigger: time_pattern
minutes: "/1"
id: tick
variables:
jobs_tracker_jobs: *jobs_tracker_jobs
conditions:
# Skip the minute tick until every retained timestamp is available.
- condition: template
value_template: >-
{% set ns = namespace(ready=true) %}
{% for job in jobs_tracker_jobs %}
{% if not is_number(state_attr(job.state_entity, 'last_completed_ts')) %}
{% set ns.ready = false %}
{% endif %}
{% endfor %}
{{ ns.ready }}
actions:
- if:
- condition: template
value_template: "{{ trigger.id == 'ha_start' }}"
then:
- action: script.jobs_tracker_publish_discovery
# Let retained MQTT Discovery and job state messages restore before
# the first refresh.
- delay: "00:01:30"
- action: script.jobs_tracker_dispatch
data:
update_all: true
@@ -747,9 +767,18 @@ automation:
conditions:
- condition: template
value_template: >-
{% set valid_state = trigger.to_state is not none
and trigger.to_state.state not in ['unknown', 'unavailable'] %}
{% set event_entity = trigger.entity_id.startswith('event.') %}
{% set event_ts = as_timestamp(trigger.to_state.state, 0)
if valid_state and event_entity else 0 %}
{% set event_age = as_timestamp(now()) - event_ts %}
{{
trigger.to_state is not none
and trigger.to_state.state not in ['unknown', 'unavailable']
valid_state
and (
not event_entity
or (event_ts > 0 and event_age >= 0 and event_age <= 30)
)
}}
actions:
@@ -9,7 +9,6 @@ automation:
members:
- switch.esp_centralstairs_top_relay_1_main_stair_lights
- switch.esp_centralstairs_bottom_relay_1_main_stair_lights_lower
- switch.esp_loungemiddleswitch_relay_3_downlights_north
sync_on_start: true
startup_delay: 5
+476
View File
@@ -0,0 +1,476 @@
#:########################################################################################:#
# Package: EdgeRouter SNMP Monitoring
# File: edgerouter_snmp.yaml
# Version: v1.0.1
# Date: 2026-07-21
#
# Purpose:
# Monitors the EdgeRouter X through read-only SNMPv2c after the previous EdgeOS
# integration became incompatible with EdgeOS v3.0.x. Provides traffic rates
# for the major physical interfaces and system health sensors for the router.
#
# Interfaces:
# - eth0 / ifIndex 4: WAN and Internet traffic.
# - eth1 / ifIndex 5: Home LAN traffic.
# - eth2 / ifIndex 6: Home Wireless traffic.
# - eth3 / ifIndex 7: Home Automation traffic.
# - eth4 / ifIndex 8: Secondary Home Automation traffic.
#
# Behaviour:
# - Polls 64-bit IF-MIB counters so totals remain reliable on busy interfaces.
# - Converts cumulative received/transmitted byte counters into kB/s rates.
# - Polls firmware, uptime, CPU idle, load averages, and memory counters.
# - Calculates memory usage from total, free, buffer, and cache values.
#
# Polling:
# - Traffic counters: Every 10 seconds.
# - Uptime, CPU, load, and memory: Every 60 seconds.
# - Firmware description: Every 300 seconds.
#
# Notes:
# - The SNMP community is stored in secrets.yaml and is never hardcoded here.
# - WAN traffic intentionally uses physical eth0 because hardware-offloaded
# traffic is under-reported by the logical pppoe0 and eth0.10 interfaces.
# - Received traffic on LAN interfaces is upload toward the router; transmitted
# traffic is download from the router toward clients on that interface.
# - SNMP, derivative, and template platforms create standalone entities rather
# than a combined Home Assistant device entry.
#
# Version History:
# - v1.0.1 (2026-07-21): Moved the EdgeRouter host address to secrets.yaml.
# - v1.0.0 (2026-07-21): Initial documented SNMP traffic and health package.
#:########################################################################################:#
sensor:
#:######################################################################################:#
# WAN TRAFFIC - eth0 / ifIndex 4
#:######################################################################################:#
# ifHCInOctets counts bytes received from the Internet. The physical interface
# is used so hardware-offloaded traffic is included in the total.
- platform: snmp
name: "EdgeRouter WAN Received Bytes"
unique_id: "edgerouter_wan_received_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.6.4
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# ifHCOutOctets counts bytes transmitted from the router to the Internet.
- platform: snmp
name: "EdgeRouter WAN Transmitted Bytes"
unique_id: "edgerouter_wan_transmitted_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.10.4
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Convert the cumulative received-byte counter into the WAN download rate.
- platform: derivative
name: "EdgeRouter WAN Download Rate"
unique_id: "edgerouter_wan_download_rate"
source: sensor.edgerouter_wan_received_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
# Convert the cumulative transmitted-byte counter into the WAN upload rate.
- platform: derivative
name: "EdgeRouter WAN Upload Rate"
unique_id: "edgerouter_wan_upload_rate"
source: sensor.edgerouter_wan_transmitted_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
#:######################################################################################:#
# HOME LAN TRAFFIC - eth1 / ifIndex 5
#:######################################################################################:#
# Bytes received by the router from Home LAN clients become the LAN upload rate.
- platform: snmp
name: "EdgeRouter Home LAN Received Bytes"
unique_id: "edgerouter_home_lan_received_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.6.5
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Bytes transmitted by the router to Home LAN clients become the LAN download rate.
- platform: snmp
name: "EdgeRouter Home LAN Transmitted Bytes"
unique_id: "edgerouter_home_lan_transmitted_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.10.5
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Derive the client-to-router upload rate from the received-byte counter.
- platform: derivative
name: "EdgeRouter Home LAN Upload Rate"
unique_id: "edgerouter_home_lan_upload_rate"
source: sensor.edgerouter_home_lan_received_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
# Derive the router-to-client download rate from the transmitted-byte counter.
- platform: derivative
name: "EdgeRouter Home LAN Download Rate"
unique_id: "edgerouter_home_lan_download_rate"
source: sensor.edgerouter_home_lan_transmitted_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
#:######################################################################################:#
# HOME WIRELESS TRAFFIC - eth2 / ifIndex 6
#:######################################################################################:#
# Bytes received by the router from the wireless network become its upload rate.
- platform: snmp
name: "EdgeRouter Home Wireless Received Bytes"
unique_id: "edgerouter_home_wireless_received_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.6.6
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Bytes transmitted by the router to the wireless network become its download rate.
- platform: snmp
name: "EdgeRouter Home Wireless Transmitted Bytes"
unique_id: "edgerouter_home_wireless_transmitted_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.10.6
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Derive the wireless-to-router upload rate from the received-byte counter.
- platform: derivative
name: "EdgeRouter Home Wireless Upload Rate"
unique_id: "edgerouter_home_wireless_upload_rate"
source: sensor.edgerouter_home_wireless_received_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
# Derive the router-to-wireless download rate from the transmitted-byte counter.
- platform: derivative
name: "EdgeRouter Home Wireless Download Rate"
unique_id: "edgerouter_home_wireless_download_rate"
source: sensor.edgerouter_home_wireless_transmitted_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
#:######################################################################################:#
# HOME AUTOMATION TRAFFIC - eth3 / ifIndex 7
#:######################################################################################:#
# Bytes received by the router from Home Automation become its upload rate.
- platform: snmp
name: "EdgeRouter Home Automation Received Bytes"
unique_id: "edgerouter_home_automation_received_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.6.7
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Bytes transmitted by the router to Home Automation become its download rate.
- platform: snmp
name: "EdgeRouter Home Automation Transmitted Bytes"
unique_id: "edgerouter_home_automation_transmitted_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.10.7
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Derive the Home Automation upload rate from the received-byte counter.
- platform: derivative
name: "EdgeRouter Home Automation Upload Rate"
unique_id: "edgerouter_home_automation_upload_rate"
source: sensor.edgerouter_home_automation_received_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
# Derive the Home Automation download rate from the transmitted-byte counter.
- platform: derivative
name: "EdgeRouter Home Automation Download Rate"
unique_id: "edgerouter_home_automation_download_rate"
source: sensor.edgerouter_home_automation_transmitted_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
#:######################################################################################:#
# SECONDARY HOME AUTOMATION TRAFFIC - eth4 / ifIndex 8
#:######################################################################################:#
# Bytes received by the router from this network become its upload rate.
- platform: snmp
name: "EdgeRouter Home Automation 2 Received Bytes"
unique_id: "edgerouter_home_automation_2_received_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.6.8
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Bytes transmitted by the router to this network become its download rate.
- platform: snmp
name: "EdgeRouter Home Automation 2 Transmitted Bytes"
unique_id: "edgerouter_home_automation_2_transmitted_bytes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.31.1.1.1.10.8
accept_errors: true
device_class: data_size
state_class: total_increasing
unit_of_measurement: "B"
scan_interval: 10
# Derive the secondary Home Automation upload rate from received bytes.
- platform: derivative
name: "EdgeRouter Home Automation 2 Upload Rate"
unique_id: "edgerouter_home_automation_2_upload_rate"
source: sensor.edgerouter_home_automation_2_received_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
# Derive the secondary Home Automation download rate from transmitted bytes.
- platform: derivative
name: "EdgeRouter Home Automation 2 Download Rate"
unique_id: "edgerouter_home_automation_2_download_rate"
source: sensor.edgerouter_home_automation_2_transmitted_bytes
unit_prefix: k
unit_time: s
round: 1
time_window: "00:00:30"
#:######################################################################################:#
# ROUTER IDENTITY AND UPTIME
#:######################################################################################:#
# sysDescr reports the installed EdgeOS firmware and build information.
- platform: snmp
name: "EdgeRouter Firmware"
unique_id: "edgerouter_firmware"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.1.1.0
accept_errors: true
scan_interval: 300
# hrSystemUptime is reported in hundredths of a second and converted to seconds.
- platform: snmp
name: "EdgeRouter Uptime"
unique_id: "edgerouter_uptime"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.2.1.25.1.1.0
accept_errors: true
device_class: duration
state_class: measurement
unit_of_measurement: "s"
value_template: "{{ ((value | default(0) | float(0)) / 100) | round(0) }}"
scan_interval: 60
#:######################################################################################:#
# CPU USAGE AND LOAD AVERAGES
#:######################################################################################:#
# UCD-SNMP reports CPU idle percentage, so usage is calculated as 100 - idle.
- platform: snmp
name: "EdgeRouter CPU Usage"
unique_id: "edgerouter_cpu_usage"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.11.11.0
accept_errors: true
state_class: measurement
unit_of_measurement: "%"
value_template: "{{ 100 - (value | default(100) | int(100)) }}"
scan_interval: 60
# One-minute load average from the UCD-SNMP load table.
- platform: snmp
name: "EdgeRouter Load 1 Minute"
unique_id: "edgerouter_load_1_minute"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.10.1.3.1
accept_errors: true
state_class: measurement
value_template: "{{ value | default(0) | float(0) }}"
scan_interval: 60
# Five-minute load average from the UCD-SNMP load table.
- platform: snmp
name: "EdgeRouter Load 5 Minutes"
unique_id: "edgerouter_load_5_minutes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.10.1.3.2
accept_errors: true
state_class: measurement
value_template: "{{ value | default(0) | float(0) }}"
scan_interval: 60
# Fifteen-minute load average from the UCD-SNMP load table.
- platform: snmp
name: "EdgeRouter Load 15 Minutes"
unique_id: "edgerouter_load_15_minutes"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.10.1.3.3
accept_errors: true
state_class: measurement
value_template: "{{ value | default(0) | float(0) }}"
scan_interval: 60
#:######################################################################################:#
# MEMORY COUNTERS
#:######################################################################################:#
# Total physical memory reported by UCD-SNMP in KiB.
- platform: snmp
name: "EdgeRouter Memory Total"
unique_id: "edgerouter_memory_total"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.4.5.0
accept_errors: true
device_class: data_size
state_class: measurement
unit_of_measurement: "KiB"
scan_interval: 60
# Currently free memory reported by UCD-SNMP in KiB.
- platform: snmp
name: "EdgeRouter Memory Free"
unique_id: "edgerouter_memory_free"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.4.6.0
accept_errors: true
device_class: data_size
state_class: measurement
unit_of_measurement: "KiB"
scan_interval: 60
# Memory allocated to buffers, excluded from calculated active usage.
- platform: snmp
name: "EdgeRouter Memory Buffers"
unique_id: "edgerouter_memory_buffers"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.4.14.0
accept_errors: true
device_class: data_size
state_class: measurement
unit_of_measurement: "KiB"
scan_interval: 60
# Memory allocated to cache, excluded from calculated active usage.
- platform: snmp
name: "EdgeRouter Memory Cached"
unique_id: "edgerouter_memory_cached"
host: !secret edgerouter_host
community: !secret edgerouter_snmp_community
version: 2c
baseoid: 1.3.6.1.4.1.2021.4.15.0
accept_errors: true
device_class: data_size
state_class: measurement
unit_of_measurement: "KiB"
scan_interval: 60
#:######################################################################################:#
# DERIVED MEMORY USAGE
#:######################################################################################:#
# Calculate active memory as total minus free, buffers, and cache. The template
# remains unavailable until every source counter has a valid state.
template:
- sensor:
- name: "EdgeRouter Memory Usage"
unique_id: "edgerouter_memory_usage"
unit_of_measurement: "%"
state_class: measurement
availability: >-
{{
has_value('sensor.edgerouter_memory_total')
and has_value('sensor.edgerouter_memory_free')
and has_value('sensor.edgerouter_memory_buffers')
and has_value('sensor.edgerouter_memory_cached')
}}
state: >-
{{
(
(
(states('sensor.edgerouter_memory_total') | float(0))
- (states('sensor.edgerouter_memory_free') | float(0))
- (states('sensor.edgerouter_memory_buffers') | float(0))
- (states('sensor.edgerouter_memory_cached') | float(0))
)
/ (states('sensor.edgerouter_memory_total') | float(1))
* 100
)
| round(1)
}}
+12 -7
View File
@@ -4,22 +4,27 @@ template:
unique_id: internet_downtraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
{{ state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Received)') | float(0) }}
availability: "{{ has_value('sensor.edgerouter_wan_download_rate') }}"
state: "{{ states('sensor.edgerouter_wan_download_rate') | float(0) }}"
- name: "Internet Upload Traffic"
unique_id: internet_uptraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
{{ state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Sent)') | float(0) }}
availability: "{{ has_value('sensor.edgerouter_wan_upload_rate') }}"
state: "{{ states('sensor.edgerouter_wan_upload_rate') | float(0) }}"
- name: "Internet Total Traffic"
unique_id: internet_totaltraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
availability: >-
{{
(state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Received)') | float(0))
+ (state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Sent)') | float(0))
has_value('sensor.edgerouter_wan_download_rate')
and has_value('sensor.edgerouter_wan_upload_rate')
}}
state: >-
{{
(states('sensor.edgerouter_wan_download_rate') | float(0))
+ (states('sensor.edgerouter_wan_upload_rate') | float(0))
}}
+25
View File
@@ -0,0 +1,25 @@
template:
- sensor:
- name: "Internet Download Traffic"
unique_id: internet_downtraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
{{ state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Received)') | float(0) }}
- name: "Internet Upload Traffic"
unique_id: internet_uptraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
{{ state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Sent)') | float(0) }}
- name: "Internet Total Traffic"
unique_id: internet_totaltraffic
unit_of_measurement: "kB/s"
state_class: measurement
state: >
{{
(state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Received)') | float(0))
+ (state_attr('binary_sensor.edgeos_interface_pppoe0', 'KBytes/ps (Sent)') | float(0))
}}
+46 -14
View File
@@ -1,3 +1,28 @@
#:########################################################################################:#
# Package: Pet Feeding and Jobs Timing
# File: pet_feeding_and_jobs.yaml
# Version: v1.1.0
# Date: 2026-07-21
#
# Purpose:
# Provides legacy MQTT pet activity sensors and Jobs-derived timing sensors for
# the Lounge dog-feeding and depooping gauges.
#
# Behaviour:
# - Dog feeding reports the newest valid morning or evening completion time.
# - Dog depooping reports the weekly Jobs completion time.
# - Invalid or unrestored Jobs attributes make a timing sensor unavailable
# instead of exposing a numeric sentinel value.
#
# Version History:
# - v1.1.0 (2026-07-21): Reject invalid Jobs timing attributes and remove the
# 999999-hour fallback from the dog-feeding gauge source.
# - v1.0.0 (2026-07-21): Added Jobs-derived dog timing sensors for P010.
#:########################################################################################:#
#:######################################################################################:#
# LEGACY MQTT PET ACTIVITY AND TIMING SENSORS
#:######################################################################################:#
mqtt:
sensor:
- unique_id: dog_fed_activity
@@ -25,6 +50,9 @@ mqtt:
state_topic: "viewroad-tele/petfeeding/hoursSinceDePooped"
unit_of_measurement: "Hours"
#:######################################################################################:#
# JOBS-DERIVED LOUNGE GAUGE SENSORS
#:######################################################################################:#
template:
- sensor:
- name: "Jobs Tracker Hours Since Dog Fed"
@@ -34,19 +62,21 @@ template:
unit_of_measurement: "h"
icon: "mdi:dog-side"
availability: >-
{{
state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') is not none
or state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') is not none
}}
{% set morning = state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') %}
{% set evening = state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') %}
{{ is_number(morning) or is_number(evening) }}
state: >-
{{
[
state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') | float(999999),
state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') | float(999999)
]
| min
| round(0)
}}
{% set morning = state_attr('sensor.jobs_tracker_dog_feeding_morning', 'hours_since_completed') %}
{% set evening = state_attr('sensor.jobs_tracker_dog_feeding_evening', 'hours_since_completed') %}
{% if is_number(morning) and is_number(evening) %}
{{ [morning | float(0), evening | float(0)] | min | round(0) }}
{% elif is_number(morning) %}
{{ morning | float(0) | round(0) }}
{% elif is_number(evening) %}
{{ evening | float(0) | round(0) }}
{% else %}
{{ none }}
{% endif %}
- name: "Jobs Tracker Hours Since Dog Depooped"
unique_id: "jobs_tracker_hours_since_dog_depooped"
@@ -55,6 +85,8 @@ template:
unit_of_measurement: "h"
icon: "mdi:emoticon-poop"
availability: >-
{{ state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') is not none }}
{% set hours = state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') %}
{{ is_number(hours) }}
state: >-
{{ state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') | float(none) }}
{% set hours = state_attr('sensor.jobs_tracker_dog_depooping', 'hours_since_completed') %}
{{ hours | float(0) if is_number(hours) else none }}