Question
How to Monitor OpenWRT Stats in Home Assistant via SNMP?
Answer
Step 1: Install SNMP on OpenWRT
SSH into your OpenWRT router and install the SNMP daemon:
opkg update
opkg install snmpd
Enable and start the service:
/etc/init.d/snmpd enable
/etc/init.d/snmpd start
Step 2: Add sensors to Home Assistant
Add the following configuration to your Home Assistant configuration.yaml. Replace 192.168.1.1 with your router's IP address.
What this monitors:
- CPU usage (per-core and overall)
- Memory usage
- WAN bandwidth (download/upload in Mbps)
- LAN bandwidth (download/upload in Mbps)
- Total data transferred (GB)
- WAN status (up/down)
- System uptime and load average
# ============================================
# OPENWRT ROUTER SNMP MONITORING
# TUF-AX4200 at 192.168.1.1
# ============================================
sensor:
# ============================================
# RAW SNMP COUNTERS - 64-BIT (HIGH CAPACITY)
# ============================================
# WAN interface (index 3 = eth1) - 64-bit counters
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 30
name: "Router WAN RX Bytes Raw"
baseoid: 1.3.6.1.2.1.31.1.1.1.6.3
accept_errors: true
unit_of_measurement: 'B'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 30
name: "Router WAN TX Bytes Raw"
baseoid: 1.3.6.1.2.1.31.1.1.1.10.3
accept_errors: true
unit_of_measurement: 'B'
# LAN interface (index 9 = br-lan) - 64-bit counters
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 30
name: "Router LAN RX Bytes Raw"
baseoid: 1.3.6.1.2.1.31.1.1.1.6.9
accept_errors: true
unit_of_measurement: 'B'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 30
name: "Router LAN TX Bytes Raw"
baseoid: 1.3.6.1.2.1.31.1.1.1.10.9
accept_errors: true
unit_of_measurement: 'B'
# ============================================
# SYSTEM METRICS
# ============================================
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
name: "Router Uptime Raw"
baseoid: 1.3.6.1.2.1.1.3.0
accept_errors: true
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
name: "Router WAN Status Raw"
baseoid: 1.3.6.1.2.1.2.2.1.8.3
accept_errors: true
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
name: "Router Load Average"
baseoid: 1.3.6.1.4.1.2021.10.1.3.1
accept_errors: true
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
name: "Router Memory Total"
baseoid: 1.3.6.1.4.1.2021.4.5.0
accept_errors: true
unit_of_measurement: 'KB'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
name: "Router Memory Free"
baseoid: 1.3.6.1.4.1.2021.4.6.0
accept_errors: true
unit_of_measurement: 'KB'
# ============================================
# CPU METRICS (PER-CORE)
# ============================================
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 10
name: "Router CPU Core 0"
baseoid: 1.3.6.1.2.1.25.3.3.1.2.196608
accept_errors: true
unit_of_measurement: '%'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 10
name: "Router CPU Core 1"
baseoid: 1.3.6.1.2.1.25.3.3.1.2.196609
accept_errors: true
unit_of_measurement: '%'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 10
name: "Router CPU Core 2"
baseoid: 1.3.6.1.2.1.25.3.3.1.2.196610
accept_errors: true
unit_of_measurement: '%'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 10
name: "Router CPU Core 3"
baseoid: 1.3.6.1.2.1.25.3.3.1.2.196611
accept_errors: true
unit_of_measurement: '%'
- platform: snmp
host: 192.168.1.1
community: public
version: '2c'
scan_interval: 10
name: "Router CPU Idle"
baseoid: 1.3.6.1.4.1.2021.11.11.0
accept_errors: true
unit_of_measurement: '%'
# ============================================
# CALCULATE RATES (bytes per second)
# ============================================
- platform: derivative
source: sensor.router_wan_rx_bytes_raw
name: "Router WAN RX Rate"
unit_time: s
time_window: "00:00:30"
unit: B/s
- platform: derivative
source: sensor.router_wan_tx_bytes_raw
name: "Router WAN TX Rate"
unit_time: s
time_window: "00:00:30"
unit: B/s
- platform: derivative
source: sensor.router_lan_rx_bytes_raw
name: "Router LAN RX Rate"
unit_time: s
time_window: "00:00:30"
unit: B/s
- platform: derivative
source: sensor.router_lan_tx_bytes_raw
name: "Router LAN TX Rate"
unit_time: s
time_window: "00:00:30"
unit: B/s
# ============================================
# MODERN TEMPLATE SYNTAX - FIXED
# ============================================
template:
- sensor:
# BANDWIDTH SENSORS - CORRECTED (RX=Download, TX=Upload)
- name: "Router WAN Download"
unique_id: router_wan_download
unit_of_measurement: "Mbps"
icon: mdi:download-network
state: >
{% set rate = states('sensor.router_wan_rx_rate') | float(0) %}
{% set mbps = ((rate * 8) / 1000000) | round(2) %}
{{ [mbps, 0] | max }}
availability: >
{{ states('sensor.router_wan_rx_rate') not in ['unknown', 'unavailable', 'none'] }}
- name: "Router WAN Upload"
unique_id: router_wan_upload
unit_of_measurement: "Mbps"
icon: mdi:upload-network
state: >
{% set rate = states('sensor.router_wan_tx_rate') | float(0) %}
{% set mbps = ((rate * 8) / 1000000) | round(2) %}
{{ [mbps, 0] | max }}
availability: >
{{ states('sensor.router_wan_tx_rate') not in ['unknown', 'unavailable', 'none'] }}
- name: "Router LAN Download"
unique_id: router_lan_download
unit_of_measurement: "Mbps"
icon: mdi:download
state: >
{% set rate = states('sensor.router_lan_rx_rate') | float(0) %}
{% set mbps = ((rate * 8) / 1000000) | round(2) %}
{{ [mbps, 0] | max }}
- name: "Router LAN Upload"
unique_id: router_lan_upload
unit_of_measurement: "Mbps"
icon: mdi:upload
state: >
{% set rate = states('sensor.router_lan_tx_rate') | float(0) %}
{% set mbps = ((rate * 8) / 1000000) | round(2) %}
{{ [mbps, 0] | max }}
# CPU SENSORS
- name: "Router CPU Usage"
unique_id: router_cpu_usage
unit_of_measurement: "%"
icon: mdi:cpu-64-bit
state: >
{% set idle = states('sensor.router_cpu_idle') | float(0) %}
{{ (100 - idle) | round(1) }}
availability: >
{{ states('sensor.router_cpu_idle') not in ['unknown', 'unavailable', 'none'] }}
# SYSTEM SENSORS
- name: "Router Uptime"
unique_id: router_uptime
icon: mdi:clock-outline
state: >
{% set timeticks = states('sensor.router_uptime_raw') | float(0) %}
{% set seconds = (timeticks / 100) | int %}
{% set days = (seconds / 86400) | int %}
{% set hours = ((seconds % 86400) / 3600) | int %}
{% set minutes = ((seconds % 3600) / 60) | int %}
{% if days > 0 %}
{{ days }}d {{ hours }}h {{ minutes }}m
{% elif hours > 0 %}
{{ hours }}h {{ minutes }}m
{% else %}
{{ minutes }}m
{% endif %}
- name: "Router WAN Total Download"
unique_id: router_wan_total_download
unit_of_measurement: "GB"
icon: mdi:download-network
state: >
{% set bytes = states('sensor.router_wan_rx_bytes_raw') | float(0) %}
{{ (bytes / 1000000000) | round(3) }}
- name: "Router WAN Total Upload"
unique_id: router_wan_total_upload
unit_of_measurement: "GB"
icon: mdi:upload-network
state: >
{% set bytes = states('sensor.router_wan_tx_bytes_raw') | float(0) %}
{{ (bytes / 1000000000) | round(3) }}
- name: "Router Memory Usage"
unique_id: router_memory_usage
unit_of_measurement: "%"
icon: mdi:memory
state: >
{% set total = states('sensor.router_memory_total') | float(0) %}
{% set free = states('sensor.router_memory_free') | float(0) %}
{% if total > 0 %}
{{ (((total - free) / total) * 100) | round(1) }}
{% else %}
0
{% endif %}
- name: "Router WAN Status"
unique_id: router_wan_status
icon: >
{% if states('sensor.router_wan_status_raw') == '1' %}
mdi:check-network
{% else %}
mdi:close-network
{% endif %}
state: >
{% if states('sensor.router_wan_status_raw') == '1' %}
Up
{% elif states('sensor.router_wan_status_raw') == '2' %}
Down
{% else %}
Unknown
{% endif %}
Important notes
- Replace
192.168.1.1with your router's IP address throughout the configuration - Interface indices may vary by router. On the TUF-AX4200, WAN (eth1) is index 3 and br-lan is index 9. Use
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.2.2.1.2to find your interface indices - CPU core OIDs (196608, 196609, etc.) may differ on your router. Adjust or remove cores based on your CPU
- The SNMP community string defaults to
public. For security, consider changing it in/etc/config/snmpd - Restart Home Assistant after adding the configuration