Unifi Integration: LTE Failover event

I’ve recently added a Unifi LTE router as failover and I need to get an event or a trigger in Home Assistant in order to know when network communication is in failover and be able to automate some tasks.

this is the device: https://store.ui.com/collections/unifi-accessories/products/unifi-lte

And the option in the Unifi-OS console to be warned

I have a similar setup, but using WAN/WAN2 with a 4G modem on WAN2 instead of a dedicated Unify LTE device. However, I never thought of using the build-in notification system, so I’ll be monitoring this thread as well.

In any case, here is my current setup, it might be a start or a source of inspiration using another approach;

I first have a command line sensor:

- platform: command_line
  unique_id: "usg_load_balance_status"
  name: "USG load balance status"
  command: ssh admin@<usg lan ip> -q -i /config/id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PubkeyAcceptedKeyTypes=+ssh-rsa "vbash -ic 'show load-balance status'" | grep "interface\|carrier\|status\|gateway\|weight"
  value_template: "{{ '[{\"' + value.replace(' ', '').replace('\n',',').replace(',interface:', '\ninterface:').replace(',', '\",\"').replace(':', '\":\"').replace('\n', '\"},{\"') + '\"}]' }}"
  unit_of_measurement: ''
  scan_interval: 30

Then I have a bunch of template sensors, each further processing the response data

- unique_id: usg_eth0_all_states
  name: "USG eth0 all states"
  state: >-
    {% set entries = states('sensor.usg_load_balance_status') | from_json() %}
    {% for entry in entries %}
     {% if entry['interface'] == 'eth0' %}
       {{ entry | to_json() }}
     {% endif %}
    {% endfor %}
  availability: "{{ states('sensor.usg_load_balance_status') != 'Unknown' }}"
  unit_of_measurement: ''
- unique_id: usg_eth2_all_states
  name: "USG eth2 all states"
  state: >-
    {% set entries = states('sensor.usg_load_balance_status') | from_json() %}
    {% for entry in entries %}
     {% if entry['interface'] == 'eth2' %}
       {{ entry | to_json() }}
     {% endif %}
    {% endfor %}
  availability: "{{ states('sensor.usg_load_balance_status') != 'Unknown' }}"
  unit_of_measurement: ''

- unique_id: usg_wan
  name: "USG WAN"
  state: "{{ (states('sensor.usg_eth0_all_states') | from_json())['status'] }}"
  availability: "{{ states('sensor.usg_load_balance_status') != 'Unknown' }}"
  unit_of_measurement: ''
  attributes:
    gateway: "{{ (states('sensor.usg_eth0_all_states') | from_json())['gateway'] }}"
    weight: "{{ (states('sensor.usg_eth0_all_states') | from_json())['weight'] }}"
    carrier: "{{ (states('sensor.usg_eth0_all_states') | from_json())['carrier'] }}"
- unique_id: usg_wan2
  name: "USG WAN2"
  state: "{{ (states('sensor.usg_eth2_all_states') | from_json())['status'] }}"
  availability: "{{ states('sensor.usg_load_balance_status') != 'Unknown' }}"
  unit_of_measurement: ''
  attributes:
    gateway: "{{ (states('sensor.usg_eth2_all_states') | from_json())['gateway'] }}"
    weight: "{{ (states('sensor.usg_eth2_all_states') | from_json())['weight'] }}"
    carrier: "{{ (states('sensor.usg_eth2_all_states') | from_json())['carrier'] }}"

- unique_id: internet_source
  name: "Internet source"
  state: >-
    {% if states('sensor.usg_wan') == 'active' %}
      cable
    {% elif states('sensor.usg_wan2') == 'active' %}
      lte
    {% else %}
      unknown
    {% endif %}
  availability: "{{ states('sensor.usg_wan') != 'Unknown' }}"
  unit_of_measurement: ''
2 Likes

Don’t forget to vote then :wink:

1 Like

This is brilliant! Got it working after a few tries.
Thanks a lot.

1 Like

Update:

Removing the “unit of measurement” on the command line sensor, and also the template sensors solved the issue.


This has been working great since my last post, but after upgrade to I think 2023.5, this error message started appearing:

ValueError: Sensor sensor.usg_eth0_all_states has device class None, state class None unit and suggested precision None thus indicating it has a numeric value; however, it has the non-numeric value: {"interface":"eth0","carrier":"up","status":"active","gateway":"192.168.100.1","weight":"100%"} (<class 'homeassistant.helpers.template.gen_result_wrapper.<locals>.Wrapper'>)

I tried to remove the “unit of measurement”, but that did not help. Any ideas?
I can see that the ssh command runs and collects the data, but the issue is with the formatting I think.

Edit:

Seems related to this:

Unfortunately, this doesn’t seem to work on UDM Pros with newer firmware. There is no vbash command anymore. Does anyone have a suggestion for a workaround?

Thank you very much. It was the only way I found to monitor my PPPoE connections (I have dual WAN) and generate alerts and alarms on the home assistant. However, from time to time I need to resend the encryption key to the USG (which allows passwordless ssh). Any way to avoid this?

Since my USG broken down I also have an UDM pro now, and no way (yet) to load the failover state from the device itself.

I eventually figured out a workaround, which is basically having my LTE router maintain a dynamic domain (so updating an A record with its public IP), Then I have the DNS IP integration resolve the public IP, and the IP address of the LTE router’s domain. If they are different, I know that HA is using my cable connection to access the internet, if they are equal, I know that HA is using my LTE connection.

Since the LTE switches IP address often, there might be a delay in detection if my internet would fail over at the moment my LTE router just got a new IP address, but yeah, it is what it is.

1 Like

Sorry for the re-up. I found another way if one of your WANs has a static IP address.
I have a COX ONT (static IP) with a Google Fi 4g failover (Static Ip to 4g modem)

Under Diagnostic the first entry in Unifi plugin should be the name of your router. This entity has the current IP address of the active WAN under attributes. I use this info to toggle the modem’s power via a ZigBee adapter. Since I have static IPs all around it helps, but If you have just one it should work pretty reliably.

alias: cox ont
description: ""
trigger:
  - platform: state
    entity_id:
      - device_tracker.dream_machine_special_edition
    attribute: ip
    from: xxx.xxx.xxx.xxx
    to: 192.168.8.139
    for:
      hours: 0
      minutes: 2
      seconds: 0
condition: []
action:
  - service: switch.turn_off
    metadata: {}
    data: {}
    target:
      device_id: 7e6c7acd5c59778d5832728
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - service: switch.turn_on
    metadata: {}
    data: {}
    target:
      device_id: 7e6c7acd5c59778d5832
  - delay:
      hours: 0
      minutes: 5
      seconds: 0
      milliseconds: 0
mode: single

1 Like

That’s a great find, thanks for sharing!

1 Like