UniFi UPS Tower integration with Home Assistant
NUT, notifications, dashboard
After setting up my UniFi UPS Tower with Home Assistant and fine-tuning notifications,
I wanted to share a stable, working configuration for anyone using UniFi UPS devices.
Tested setup
- UniFi UPS Tower 1000VA 230V – firmware 1.4.12
- UDM-SE connected via NUT client port
- Home Assistant 2025.10.x (Yellow / CM5)
- iPhone 15 Pro with critical notifications
- All devices on LAN 192.168.233.x
Stable for 24 h with no false triggers
Tested with real power outage simulation (5 min runtime)
How to set it up (step-by-step)
-
Enable the NUT server on your UniFi UPS Tower
- Open the UPS Tower web interface (you can find its IP in UniFi Controller).
- Navigate to Settings → Network → NUT Server.
- Enable the NUT server.
- Set a simple device name, e.g.
UPS(this name is used in all NUT commands). - Save the settings and reboot the UPS if necessary.
-
Find the UPS IP address
- In UniFi Controller → Devices → UPS Tower → Network tab.
- Example:
your_ups_ip
-
Verify that the NUT service is reachable
- From a terminal on your computer: (example nc -vz 192.168.1.44 3493)
You should see something like:nc -vz your_ups_ip 3493Connection to your_ups_ip port 3493 [tcp/nut] succeeded!
- From a terminal on your computer: (example nc -vz 192.168.1.44 3493)
-
List available UPS variables
- Test communication with:
Example output:echo -e "LIST VAR UPS\n" | nc your_ups_ip 3493VAR "UPS" "battery.charge" 91 VAR "UPS" "ups.status" "OL CHRG" VAR "UPS" "battery.runtime" 3649
- Test communication with:
-
Add the sensors in Home Assistant
- Copy the YAML block below into your
configuration.yamlundercommand_line:
or place it in a separate file, e.g.sensors/ups.yaml.
- Copy the YAML block below into your
-
Reload the configuration
- In Home Assistant go to:
Settings → Developer Tools → YAML → Reload Command Line Entities
(or simply restart Home Assistant once).
- In Home Assistant go to:
-
Add the automation
- Paste the automation YAML (see below) under
Settings → Automations → YAML mode
to receive critical iOS notifications when the UPS changes state.
- Paste the automation YAML (see below) under
-
Test the setup
- Simulate a short power outage by unplugging the UPS input.
- Wait ~25–30 seconds for the updated readings and the notification to appear.
-
Add a dashboard card
- Use the provided Mushroom dashboard example below.
- Adjust entity names as needed to match your setup.
Configuration (command_line sensors)
Copy the following YAML into your configuration.yaml under command_line:
or into a separate file such as sensors/ups.yaml.
command_line:
- sensor:
name: "UPS Battery Charge"
command: "echo -e 'GET VAR UPS battery.charge\\n' | nc your_ups_ip 3493 | awk '{print $4}'"
unit_of_measurement: "%"
value_template: "{{ value | float(0) }}"
scan_interval: 20
- sensor:
name: "UPS Runtime"
command: "echo -e 'GET VAR UPS battery.runtime\\n' | nc your_ups_ip 3493 | awk '{print $4/60}'"
unit_of_measurement: "min"
value_template: "{{ (value | float(0)) | round(0) }}"
scan_interval: 20
- sensor:
name: "UPS Input Voltage"
command: "echo -e 'GET VAR UPS input.voltage\\n' | nc your_ups_ip 3493 | awk '{print $4}'"
unit_of_measurement: "V"
value_template: "{{ value | float(0) }}"
scan_interval: 20
- sensor:
name: "UPS Output Power"
command: "echo -e 'GET VAR UPS output.power\\n' | nc your_ups_ip 3493 | awk '{print $4}'"
unit_of_measurement: "W"
value_template: "{{ value | float(0) }}"
scan_interval: 20
- sensor:
name: "UPS Load"
command: "echo -e 'GET VAR UPS ups.load\\n' | nc your_ups_ip 3493 | awk '{print $4}'"
unit_of_measurement: "%"
value_template: "{{ value | float(0) }}"
scan_interval: 20
- sensor:
name: "UPS Status Short"
command: "echo -e 'GET VAR UPS ups.status\\n' | nc your_ups_ip 3493 | awk '{print $4}' | tr -d '\"'"
value_template: >-
{% set v = value | trim %}
{% if v in ['unknown', '', 'unavailable'] %}
{{ states('sensor.ups_status_short') }}
{% else %}
{{ v }}
{% endif %}
scan_interval: 20
- sensor:
name: "UPS Status"
command: "echo -e 'LIST VAR UPS\\n' | nc your_ups_ip 3493 | grep 'ups.status' | awk '{for (i=4; i<=NF; i++) printf $i \" \"; print \"\"}' | tr -d '\"'"
value_template: >-
{% set v = value | trim %}
{% if v in ['unknown', '', 'unavailable'] %}
{{ states('sensor.ups_status') }}
{% else %}
{{ v }}
{% endif %}
scan_interval: 20
Automation – Critical Power Notifications
Example notifications
(real screenshots from the test setup)
This automation sends iOS critical push notifications whenever the UPS switches
between line power and battery mode.
It includes a 30-second delay to ensure the sensors have updated values.
alias: UPS – Status change notifications (critical + delay)
description: >
Sends iOS critical notifications when the UPS switches between line and battery.
Includes a 30s delay for reliable sensor refresh.
triggers:
- entity_id: sensor.ups_status_short
to: OB
trigger: state
- entity_id: sensor.ups_status_short
to: OL
trigger: state
actions:
- choose:
- conditions:
- condition: state
entity_id: sensor.ups_status_short
state: OB
sequence:
- delay: "00:00:30"
- service: notify.mobile_app_karoly_iphone_15_pro
data:
title: ⚡ Power outage – UPS on battery
message: >
The UPS has switched to battery mode.
Battery: {{ states('sensor.ups_battery_charge') }}%
Runtime: {{ states('sensor.ups_runtime') }} minutes.
data:
push:
sound:
name: default
critical: 1
volume: 1
- service: logbook.log
data:
name: UPS
message: Switched to battery mode (OB)
entity_id: sensor.ups_status_short
- conditions:
- condition: state
entity_id: sensor.ups_status_short
state: OL
sequence:
- delay: "00:00:30"
- service: notify.mobile_app_karoly_iphone_15_pro
data:
title: 🔌 Power restored – UPS back on line
message: >
The UPS is now back on mains power.
Status: {{ states('sensor.ups_status') }}
Battery: {{ states('sensor.ups_battery_charge') }}%
data:
push:
sound:
name: default
critical: 1
volume: 0.7
- service: logbook.log
data:
name: UPS
message: Returned to line mode (OL)
entity_id: sensor.ups_status_short
mode: single
Tip:
Make sure your iPhone notifications are configured to allow Critical Alerts
for the Home Assistant app — otherwise the push won’t bypass Silent/DND mode.
Example Dashboard View (Mushroom)
Below is a simple, clean dashboard card setup using Mushroom (legacy) cards
to display key UPS information — status, power, charge, load, voltage, and runtime.
You can freely adjust colors or entity names as needed.
Here’s how the UPS status overview looks in Home Assistant
using Mushroom legacy cards and the stack-in-card layout:
type: custom:stack-in-card
mode: vertical
cards:
- type: custom:mushroom-title-card
title: 🧠 UniFi UPS Tower – Status Overview
subtitle: Power state, charge, runtime, load
alignment: center
- type: horizontal-stack
cards:
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_status
primary: UPS Status
secondary: "{{ states('sensor.ups_status') }}"
icon: mdi:power
icon_color: green
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_battery_charge
primary: Battery
secondary: "{{ states('sensor.ups_battery_charge') }} %"
icon: mdi:battery
icon_color: green
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_output_power
primary: Power
secondary: "{{ states('sensor.ups_output_power') }} W"
icon: mdi:flash
icon_color: yellow
- type: horizontal-stack
cards:
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_load
primary: Load
secondary: "{{ states('sensor.ups_load') }} %"
icon: mdi:gauge
icon_color: green
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_input_voltage
primary: Input Voltage
secondary: "{{ states('sensor.ups_input_voltage') }} V"
icon: mdi:power-plug
icon_color: green
- type: custom:mushroom-legacy-template-card
entity: sensor.ups_runtime
primary: Runtime
secondary: "{{ states('sensor.ups_runtime') }} min"
icon: mdi:timer
icon_color: blue
Tip:
If you use Swipe Card, you can easily include this view as part of
your Power or Network dashboard for quick UPS monitoring.
Notes & Tips
- Delay (30 s) is important for reliable sensor updates
- Works without NUT integration — uses only raw nc command
- No false triggers after reconnect
- Tested with 5-minute real outage
- Stable 24h continuous operation
Feedback and improvements welcome — happy to answer any questions! ![]()


