🔋 UPS Monitor via NUT – Battery, Status & Self-Test Notifications

:battery: [Blueprint] UPS Monitor via NUT – Battery, Status & Self-Test Notifications

This blueprint monitors a UPS device integrated via the NUT integration in Home Assistant.

It automatically sends notifications to your phone when:

  • :arrows_counterclockwise: UPS status changes (e.g., Online → On Battery)
  • :battery: UPS battery charge drops by a defined interval (default: every 10%)
  • :test_tube: UPS self-test result is not “Done and passed”

The automation includes battery voltage and charge % in the message when relevant.


:white_check_mark: Features

  • Uses status_data (e.g., OL, OB) for logic and status (e.g., Online) for human-readable messages
  • Configurable battery drop interval (e.g., every 10%)
  • Filters for correct sensors from the NUT integration
  • Sends notifications to your selected mobile app device
  • Blueprint is clean, reliable, and notification-ready

:toolbox: Requirements

To use this blueprint, you’ll need:

  • The NUT UPS integration
  • These entities exposed from your UPS:
    • sensor.nutdev1_status_data (e.g. OL / OB / LB)
    • sensor.nutdev1_status (e.g. Online / On Battery)
    • sensor.nutdev1_battery_charge
    • sensor.nutdev1_battery_voltage
    • sensor.nutdev1_self_test_result
  • At least one mobile_app device registered with Home Assistant (e.g. your phone)

:gear: Import This Blueprint

Open in Home Assistant


:speech_balloon: Example Notifications

  • UPS Monitor: UPS status changed: On Battery
  • UPS Monitor: Battery at 80%. Voltage: 12.3 V
  • UPS Monitor: Self-test result: Failed

Let me know if you have improvements or any ideas.

12 Likes

Thanks for putting this together.
I have a couple of units that don’t show the self-test as a sensor in HA. Can that be made optional in the blueprint?

2 Likes

I’d like that to.
So far I’m trying to use it with a different senor as a placeholder.

1 Like

Another ask would be a time delay on the notifications. I’ve noticed that the nut server running on some of my routers goes unavailable and then immediately shows up as available again. I know this may be more of a circumstantial or environmental issue but having a configurable delay would be nice.

1 Like

@kramttocs @EdnilH apologies for the delayed reply. I’ve updated the blueprint.

Please test it out and let me know whether it works as expected now.

2 Likes

No apology needed!

Thanks a lot for adding those. Imported, looks great, and will adjust/tweak it as I get alerts.

1 Like

Looks like it’s not happy with the Self-test Result Sensor field.

Can it still be made a ‘sensor’ field vs a free fill text?

Leaving it blank causes:

Message malformed: Entity is neither a valid entity ID nor a valid UUID for dictionary value @ data['entity_id']

Manually typing in a sensor like:

sensor.shop_router_ups_self_test_result

does work but open for typos.

Updated. Try it and let me know, please.

2 Likes

Looks like we are in business. Thanks!
Was able to add all my esphome nut servers and now will just wait to see how they alert.

Hopefully this will happen: Blueprint UI: Conditional visibility / disabling of inputs based on other selections · home-assistant · Discussion #2175 · GitHub

Few more asks :slight_smile: If you think it makes sense.

  1. Move the ‘Enable self-test monitoring’ toggle to be above the optional entity select input
  2. For ‘Debounce for battery notifications (seconds)’ add the word “Charge” just to make it clear what sensor it’s for. So ‘Debounce for battery charge notifications (seconds)’
  3. Add a Load sensor and check, along with a debounce
    This would be a lot like the ‘Charge’ (sensor, threshold, debounce) but would allow us to get alerted for things like if the UPS load is over 50% for more than 10 seconds.

Conditional visibility of inputs in blueprints would certainly help. I hope it will be implemented soon.

  1. Move the ‘Enable self-test monitoring’ toggle to be above the optional entity select input
  2. For ‘Debounce for battery notifications (seconds)’ add the word “Charge” just to make it clear what sensor it’s for. So ‘Debounce for battery charge notifications (seconds)’

I have implemented these two changes directly into the current gist. It’s straightforward and it makes sense.

Add a Load sensor and check, along with a debounce
This would be a lot like the ‘Charge’ (sensor, threshold, debounce) but would allow us to get alerted for things like if the UPS load is over 50% for more than 10 seconds.

This adds more functionality and more complexity, so I have created a new gist - so it can be tested separately. Honestly, I did not get to test it yet - but you can test it whenever you are ready: https://gist.githubusercontent.com/007hacky007/0c405dc1b9f4652afdb8ac6cce008d71/raw

Few points to note:

  • Load monitoring is off by default (enable_load_check: false).
  • Load sensor selection is optional (empty allowed) using the same “list input” pattern as self-test.
  • Notification is sent only when load stays above threshold for X seconds.
  • It does not attempt unit conversion - it assumes load is a percentage sensor (typical for NUT).
  • If the load sensor is unknown or unavailable, it does not satisfy “above threshold” and will not trigger.
1 Like

The two UI changes look great. I’ll have to test the other - appreciate you making that so quickly.

Realized the debounce for the status is half the battle - this is my fault for not thinking it through and I haven’t done any research yet to see if there is a good solution. I should have known better as I have the same situation for another device (my well pump) I monitor via automation.

The scenario is, for example:

Debounce: 60s

  1. Status is Online
  2. It’s Online for 1 hr
  3. Status goes unavailable for 30s due to network, NUT server, what not
  4. The flake is self-resolved and Status goes back to Online
  5. The debounce took care of it alerting for ‘unavailable’
  6. The problem is that one it is Online for 60s, it will send an alert

Again, this is my fault as I should thought of this before even asking. On the bright side, with the debounce it cut the alerts in half :smiley:

I guess it needs to, on change:

  1. Store the old status as X, new status as Y
  2. If the status changes for LESS than the debounce value, ignore it
  3. If the status changes for MORE than the debounce value AND the Y=X, ignore it. If Y != X, alert

I know there is the to_state and from_state attributes but the middle ‘unavailable’ state throws a wrench in that.

This is getting much more complex, just to handle some flakiness so I don’t know that it’s worth it tbh. I think I’d leave it as is unless more people comment about it.

Thank you! This works very well for me now.

1 Like

Hi, may I kindly ask to set the notifications to “high priority” so that they pop-up immediately on the phone?

As I understand, the ‘data’ part has to be added for Android phones:

- domain: mobile_app
  type: notify
  device_id: !input notify_device
  message: '{{ notify_message }}'
  data:
    priority: high
    ttl: 0

Good idea. I’ve implemented it. Please test it here before I’ll update it in the main/production blueprint and let me know whether it works as expected:

Open in Home Assistant

1 Like

Works fine, thanks a lot! Just as a remark, this only works for Android phones, but that’s fine for me as I don’t own any iOS devices.

Just tested with my iPhone and it works fine.

My only wish is that it could hit multiple phones at the same time.

@NathanR try this version

Open in Home Assistant

Let me know whether it works as expected.

This looks great but im having an issue when i try to save:

Message malformed: Unknown device ‘{{ repeat.item }}’

I switched to yaml to configure but I didn’t see errors jump out. Device had an identifier and ghere was only one.