I have an EdgeRouter ERLite‑3 with two internet pipes, a primary via AT&T fiber and a secondary via Google Fi LTE on a Netgear modem. I initially setup the secondary LTE just because I had a modem laying around and Google Fi has free data sims, which was no extra cost. But this did save me some trouble while working from home when AT&T decided to be flaky a few times.
I’ve broken this up in to two parts. The first will be the failover status and notifications, and second will be HA pulling bandwidth info via SNMP.
Failover
I followed https://help.ui.com/hc/en-us/articles/205145990-EdgeRouter-WAN-Load-Balancing#3 to setup the dual WAN setup initially. My load-balance sections looks like the following. eth2 is the primary fiber, and eth1 is the secondary lte interface (note the failover-only option). I’m pinging cloudflare’s 1.1.1.1 to check for liveliness.
load-balance {
group wan-group {
exclude-local-dns disable
flush-on-active enable
gateway-update-interval 20
interface eth1 {
failover-only
route {
default
}
route-test {
count {
failure 3
success 3
}
initial-delay 60
interval 10
type {
ping {
target 1.1.1.1
}
}
}
}
interface eth2 {
route {
default
}
route-test {
count {
failure 3
success 3
}
initial-delay 60
interval 10
type {
ping {
target 1.1.1.1
}
}
}
}
lb-local enable
lb-local-metric-change enable
transition-script /config/scripts/wan_failover.sh
}
}
Whenever a failover transition occurs, the EdgeRouter will invoke the script with several arguments, and will do so for each interface. I have the script to invoke a webhook on HA which configures the status.
#!/bin/bash
curl --request POST --header "Content-Type: application/json" --data "{\"group\":\"$1\",\"interface\":\"$2\",\"status\":\"$3\"}" http://hass.home/api/webhook/wan_failover
input_text:
wan_status:
name: "WAN Status"
lte_status:
name: "LTE Status"
sensor:
- platform: template
sensors:
wan_status:
friendly_name: "WAN Status"
value_template: "{{ states('input_text.wan_status') | capitalize }}"
icon_template: >-
{% if is_state("input_text.wan_status", "active") %}
mdi:lan-connect
{% elif is_state("input_text.wan_status", "inactive") %}
mdi:lan-disconnect
{% else %}
mdi:lan-pending
{% endif %}
lte_status:
friendly_name: "LTE Status"
value_template: "{{ states('input_text.lte_status') | capitalize }}"
icon_template: >-
{% if is_state("input_text.lte_status", "active") %}
mdi:lan-connect
{% elif is_state("input_text.lte_status", "inactive") %}
mdi:lan-disconnect
{% else %}
mdi:lan-pending
{% endif %}
- alias: WAN Failover Webhook
description: ''
trigger:
- platform: webhook
webhook_id: wan_failover
condition: []
action:
- data_template:
entity_id: '{{ ''input_text.wan_status'' if trigger.json.interface == ''eth2'' else ''input_text.lte_status'' }}'
value: '{{ trigger.json.status }}'
service: input_text.set_value
- delay: 00:00:10
- data_template:
message: '{{ ''WAN'' if trigger.json.interface == ''eth2'' else ''LTE'' }} interface
is now {{ trigger.json.status }}'
title: WAN Failover
service: notify.pushover
mode: parallel
max: 10
The webhook will both set the input_text for wan/lte status, and also send me a notification. (although I can’t remember why I have a 10s delay between them ). Having this webhook to be in parallel mode is important, because edgerouter will invoke the transition-script once for each interface more or less at the same time.
Bandwidth
To query the bandwidth, I have SNMP enabled on the EdgeRouter and the following HA configuration.
sensor:
- platform: time_date
display_options:
- 'date_time'
- platform: snmp
name: wan_in
baseoid: 1.3.6.1.2.1.2.2.1.10.4
host: !secret zeus_hostname
version: !secret zeus_snmp_version
accept_errors: true
scan_interval: 10
- platform: snmp
name: wan_out
baseoid: 1.3.6.1.2.1.2.2.1.16.4
host: !secret zeus_hostname
version: !secret zeus_snmp_version
accept_errors: true
scan_interval: 10
- platform: derivative
name: wan_in_der
source: sensor.wan_in
unit_time: s
unit: B
- platform: derivative
name: wan_out_der
source: sensor.wan_out
unit_time: s
unit: B
- platform: template
sensors:
wan_in_mbps:
value_template: "{{ [((states('sensor.wan_in_der')|float*8)/1000000)|round(2),0]|max }}"
unit_of_measurement: 'Mbps'
friendly_name: "WAN In"
wan_out_mbps:
value_template: "{{ [((states('sensor.wan_out_der')|float*8)/1000000)|round(2),0]|max }}"
unit_of_measurement: 'Mbps'
friendly_name: "WAN Out"
- platform: snmp
name: lte_in
baseoid: 1.3.6.1.2.1.2.2.1.10.3
host: !secret zeus_hostname
version: !secret zeus_snmp_version
accept_errors: true
scan_interval: 10
- platform: snmp
name: lte_out
baseoid: 1.3.6.1.2.1.2.2.1.16.3
host: !secret zeus_hostname
version: !secret zeus_snmp_version
accept_errors: true
scan_interval: 10
- platform: derivative
name: lte_in_der
source: sensor.lte_in
unit_time: s
unit: B
- platform: derivative
name: lte_out_der
source: sensor.lte_out
unit_time: s
unit: B
- platform: template
sensors:
lte_in_mbps:
value_template: "{{ [((states('sensor.lte_in_der')|float*8)/1000000)|round(2),0]|max }}"
unit_of_measurement: 'Mbps'
friendly_name: "LTE In"
lte_out_mbps:
value_template: "{{ [((states('sensor.lte_out_der')|float*8)/1000000)|round(2),0]|max }}"
unit_of_measurement: 'Mbps'
friendly_name: "LTE Out"