#:########################################################################################:#
# 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)
          }}
