Alert2 - a new alerting component

Great set of related features and great thoughts, I think there is validity to the generacism of templates but as you said it’s not simple to write. There might be some ways to accomplish most I’ll put some thought into the problem as well.

I’ve also been accumulating a few features I think would be tremendously useful, I’ll get more over next day or two.

EDIT (deletion): thought I had problems with unavailable/undefined that I may not be, looking futher

And thank you on friendly_name that is definitely a problem

Apologies for the delay here. Great work on the generators! Everything seems to be working great from what I can tell. After catching up on some of the conversation here, I would love to see configuration reloading happen. That’d make iterating a lot easier for me. Definitely most interested in this.

I can think of two other, but really not important, features if you don’t mind the unsolicited feedback. Feel free to ignore them as it may be my niche use case

  • I’d love for alert activities (firing/acked/snoozed) to end up in the event stream which would help make automations off the back of alerts easier to work with.
  • it’d be cool if one could specify that an notifier supports actionable notifications and it’d auto populate an ack, snooze for an hour, snooze for an amount of time as actions. It’d be up to the end user to handle this (or since they end up in the event stream at least for HA Mobile notifications so I’m pretty sure that the integration could handle that case)
1 Like

A few updates. First, I just released Alert2 v1.7.1 and Alert2 UI v1.5.4. Changes:

  • YAML reload. You can now reload your Alert2 config without restarting HA. This deletes all alerts and generators and then reloads the config, including defaults. Reloading does not affect the HA startup-related config parameters notifier_startup_grace_secs and defer_startup_notifications.
  • friendly_name now takes a template and tracks template changes.
  • Merge @cerebrate’s PR (Thanks!) to make time abbreviations more standards-compliant (i.e., “m” → “min”)
  • UI more-info dialog now shows time in friendlier local-time format rather than ISO.
  • Update tests and docs. Also, did a substantial refactor of template change-tracking code.

I’d love anyone’s thoughts on the following:

An interesting use case

The use case is a “front_door_open” alert. Say you have delay_on_secs set to a few seconds to not trigger on routine openings. Imagine two things happen. First, someone wants to prop the door open for a while. Second, later, the temperature drops and so the door being open is more of a problem.

The question is how to alert on this. You could imagine the user snoozing the alert when they’re going to prop open the door. You could also imagine an automation triggering when the temperature drops to reset and unsnooze the alert, allowing it to fire.

But if you unsnooze the alert and it starts firing again, you don’t have any information about why it started firing again. E.g., maybe the snooze interval happened to expire.

And creating a second alert, front_door_open_cold seems a bit klunky, and a bit confusing to have two distinct alerts about the front door being open.

Two possible solutions

First, I could add a service call to send an custom notification message, so the temperature automation could manually send an alert notification that the temp dropped. The disadvantage is that that info would appear only in one notification and not in the UI or subsequent reminders.

Alternatively, I could introduce two attributes:

  • priority. A float. Affects how the alert’s displayed in the UI. Available as a template variable for notification messages.
  • circumstances. A string. Surfaces in the UI, maybe shown below each alert name. And available as a variable for notification messages.

Then when the temperature drops, you could raise the alert priority and set the circumstances to indicate that the temp dropped.

Adding these two attributes seems like perhaps too much complexity and maybe not a perfect semantic fit, so I have mixed feelings on it.

Other thoughts?

@woodersayer , thanks for the followup. Good suggestion regarding event stream. I’m not super knowledgable about actionable notifications. I though you could add some fields to data in a notification and that triggered some buttons in the mobile app - could you flesh out a bit more how you envision it working?

-Josh

@redstone99 Thanks for the latest release, I’ve been running it for about 24 hours and it seems the friendly_name dynamic template has resolved a number of issues. I’ll continue to monitor.

I’ve been thinking about some of the features/capabilities that would be useful next and along the lines of what has been requested from others as well. Here’s some suggestions that I have:

Product Level Features

These are the features I think the overall product needs without yet identifying which component they belong in or how they would be designed:

  1. “Staged” alerting. The ability to have an alert fire in one or more stages. These could be further conditions/triggers (e.g. a low temperature alert goes below freezing now, a door open has too much of a temperature drop, etc.), additional time passing since the alert fired (e.g., escalate the group of people notified if the first group didn’t respond or fire a critical notification or phone call now instead of a regular notification), or even an external service triggering further action on the alert. I’m seeing enough overlap here that I think there is a single generic feature that solves the overall problem.

  2. Ability to send display information to the UI. I’d like the UI to be displaying current information about an alert (e.g. the current temperature of a low temperature warning). Typically my workflow is: get a notification (e.g. low temperature warning), then remember where in my dashboard that paticular sensor is, and go check it’s current value to know how bad the situation is. Allowing an updating current value to be shown for the alert in the UI would have utility for both my use case and it seems like the open door case.

  3. UI grouping/sorting/filtering. The UI would benefit from having the ability to set groups, sorts, and include/exclude filters. This would allow critical alerts to be shown first and other alerts to be put into groups (e.g. snoozed but not acked). Additionally, sorting of alerts to allow most important to be user defined and shown first (e.g. by a priority, last fired time, on/off, etc). Filters would allow different alert2 groups of alerts to be shown in different dashboard areas (e.g. user alerts vs. system level alerts), which could be via tags (like scheduler-card) or other fields.

  4. UI icons/filtering. There would be benefit to having different icon and color schemes for different alerts and statuses. I think this still requires some thought., e.g. can an alert itself specify the color it wants to be when alerted, or the icon? Is it better if the icon follows statuses like on/off/snoozed/unacked/etc., or something about the alert itself like a high priority fire alarm that needs immediate response (e.g. red, blinking, special icon, etc.). I’m leaning towards the latter, but theres a lot to think about to not get locked into an implementation too quickly.

  5. Handling of unavailable, unknown, and undefined states. Writing in checks for these into conditions becomes tedious, but alerts can fail non-gracefully without checks (e.g. casting to float or int in condition). However, you don’t always want to swallow these (I actually have an alert that explicitly alerts if a critical sensor is in one of those states for too long).

I think 1 through 3 seem to have the most immediate utility from what I’m seeing on the threads and my needs and having used other alerting/monitoring systems.

Possible Implementation for #1 - Staged Alerts

I’ll address #1 and #2 for now as I think they are immensely useful. A possible configuration could be to add a “stage” key items for an alert. I am uncertain if this works broadly for trigger alerts as I can’t conceptualize how you’d implement a stage outside of having a condition except for one particular (useful) use case, a user does not ack a trigger alert within a certain time period (so raise escalation level for example):

Here’s a possible configuration (in this example using a threshold alert):

alert2:
  alerts:
    - domain: system
      generator_name: disk_space_low
      generator: "{{ states.sensor|selectattr('entity_id','match','(.*)system_monitor_disk_usage')|map(attribute='entity_id')|list }}"
      name: "{{ genRaw }}_disk_space_low"
      friendly_name: "{{ state_attr(genRaw,'friendly_name') }} disk space low"
      threshold:
        value: "{{ states(genRaw)|float }}"
        maximum: 80
        hysteresis: 5
      message: "Usage: {{ states(genRaw) }}%"
      escalation_stages:
        1:
          stage_name: "Over 95% utilization, critically low" 
          threshold:
            value: "{{ states(genRaw)|float }}"
            maximum: 95
            hysteresis: 5
          message: "Usage: {{ states(genRaw) }}%"
          notifier: all_admins
        2:
          stage_name: "Over 95% utilization, response required" 
          message: "Critically high usage: {{ states(genRaw) }}%"
          delay_on_secs: 900
          notifier: all_admins_mobile_critical_notification

Where each escalation_stage can fire after the prior stage if the new condition is met. An open question would be if you can fall back “up” the stages as conditions are unmet or you can only progress “down” stages and just exit the entire condition when the original alert condition is met. For simplicity I think the latter is least error prone and most understandable for users and will have most straightforward code.

This solves both my escalation path and I think a second stage condition would solve the door_open, now it’s cold, problem as well with a single design.

I think there could be utility to also allow a service call to change stage but I don’t actually think that’s required for the use cases described given the design above but curious if that’s accurate.

It’s also a little unclear to me at present how stage should be best represented in notifications and the UI. It’s yet another field to try to combine together with the other fields. I don’t know if stage_name is a good idea above, perhaps the stage really just gets writen by the user in “message”. But the UI should be showing what stage you are in, so there’s usefulness in a stage name that the UI shows (to indicate the alert is escalating) - and a requirement from the open_door case. I think there’s utility in both stage_name and message, but some thinking of how they get combined to the user for notifications and UI display.

“Present” Values Display in UI

I’d love it if there was a field, perhaps “display_value” or “display_message” that specified a template that the UI rendered as a current value next to the alert. In my example above that could be the current disk space utilization, so in the UI I know the alert both fired and where the current value is (a value of 81% is different than 94%, but I really want to alert at 80%).

E.g.:

          display_message: "Usage: {{ states(genRaw) }}%"

It’s unclear to me if this was overloaded with your circumstances idea, it seemed like it may be?

Implementation in the UI of the above two features will be some display refactoring so it might make sense to think of the UI overall in terms of the other icon/color/sorting/grouping/fitlering items as well (and any other UI features).

Anyway, there are my current thoughts wanted to get them down!

1 Like

@tman98 thanks for the detailed thoughts! I like the idea of adding extra info to what’s displayed in the alert UI. At some point we should collect together all the feature / improvement ideas in a list somewhere. Maybe in a github evergreen discussion or just a markdown file in the repo or something.

The staged alerting idea is interesting design point. It suggests a sequential ordering, and the passage of time as a factor in progressing through the ordering. That makes sense as circumstance progress in severity. I could also imagine a change in circumstances that’s not necessarily sequential - say the front-door is propped open, it becomes cold (circumstance 1) and separately, someone leaves the house for vacation (circumstance 2) or separately it becomes hot (circumstance 3). Those don’t seem necessarily sequentially related to me.

And thanks for the concrete syntax suggestion for staging. I like the config fields in a stage being similar to (identical to?) the fields in an alert config. delay_on_secs is a close match semantically for capturing the passage of time, though it original meant delaying a transition from off->on, and here it means a delay in the triggering of a stage.

Hmm, fascinating stuff to consider. I think we’re circling around something good.

At present, I’m looking through the code to hopefully better integrate Alert2 with HA, like supporting assocating alert entities with devices, some kind of UI editing ability, and maybe helpers. Along the way I may throw in the ability to do a “dry run” of an alert or generator, to see what it’d do before actually creating it. Will see how involved this all is.

Josh

Non-sequential escalation stages could be logical - I think there might be usefulness for either so perhaps indicating a stage number or no-number to either enforce sequencing or to allow for non-sequential staging. We’d have to determine what happens if two stages were “on” at the same time for an alert, what would that mean and how would it be displayed.

I was thinking keeping as many names as similar as possible will be the easiest to program into the yaml.

A dry run is a great idea!

Josh, quick question on implementation. I noticed (happily) if you restart Alert2 and the configuration does not specify an alert that was previously active, Alert2 looks like it turns it off. For example, if I remove a particular alert or modify a generator and the new config no longer is creating that alert, when I restart the alert is gone.

I was wondering how this was implemented, because what’s interesting is if I have alert entities coming from a remote instance via Remote Home Assistant, the master instance does not seem to touch them. It seems that if your code was scanning
“alert2.” entities, it would pick up remote entities created by remote Alert2 components and then try to turn them off or otherwise remove them which would screw up the remote Alert2 instance that had created them. This is not happening which is good, but I’m trying to figure out if that’s coincidence or a specific fact of implementation (that is unaware of remote home assistant) is keeping the master Alert2 instance from touching entities coming from remote Alert2 instances.

Hi. First, I just released v1.7.3 which:

  1. Makes condition options for event alerts
  2. Fixes a bug where trigger blocks were not being initialized correctly and so sometimes wouldn’t trigger when they’re supposed to.

To answer your question: Alert2 internally maintains a list of alert2 entities that it created. If remote HA is adding alert2 entities, the Alert2 backend isn’t aware of it. “reload” first shuts down those native Alert2 alerts (i.e., turns off reminder timers, removes them from HA, etc), and then reprocesses the YAML config as if HA had restarted. So any alerts spec’d in the config are created anew. Does that answer your question?
-J

Btw, as I’m working on editing alerts in the UI, I just noticed that Alert2 swallows certain type errors in the condition field and convert them to “False”, which isn’t great. E.g., if your condition returns “foo”, that becomes False.

(the mock in my unittest didn’t accurately reflect the real HA internals in this regard. Will fix that, too). I think I’m going to change it so it is an error if condition renders to something that isn’t “truthy” (i.e., “true”, “on”, “yes”, positive numbers and the opposites) unless someone objects. I don’t like the idea that you may miss alerts because a condition has some type error in it that makes it become False all the time.

EDIT: I’ll probably put an explainer in the error message saying that condition got more strict so people aren’t wondering why they may be getting new errors.

EDIT2: This change will mean that the empty string, which used to mean “False”, will now cause an error to fire.

Btw, gotta say, even though I have only a little done in the UI work, it’s neat to be able to play with alert definitions and get instant feedback. Makes it easier to experiment.

J

Sweet. Great release! I’m home alone for the next week couple of days so I’ll have a some extra time to dedicate to alerting.

In regards to the suggestion of using the data field that’s exactly what I’m doing currently and it absolutely works. The suggestion is specifically to try to be “DRY” when writing alerts. For example, I have a bin which I store 3D printer filament that is to be humidity controlled. I have an alert that fires after the humidity rises above 20% for 5 minutes.

    - domain: humidity
      name: ams_humidity
      friendly_name: "AMS Humidity"
      condition: "sensor.filament_humidity"
      title: "AMS Filament Humidity Alert"
      message: "AMS humidity has gone above 15% humidity. It's at {{ states('sensor.filament_humidity')}}%."
      delay_on_secs: 600
      done_message: "AMS humidity has gone below the threshold. At, {{states('sensor.filament_humidity')}}"
      data:
        group: "GroupTag.ams_humdity_group"
        tag: "NotificationTag.ams_humditiy_tag"
        url: "/dashboard-home/management"
        actions:
          - action: "ACK_AMS_HUMIDITY"
            title: "Ack"
          - action: "SNOOZE_AMS_1_HOUR"
            title: "Snooze for 1 Hour"
          - action: "SNOOZE_FOR_1_DAY"
            title: "Snooze for 1 day"
      threshold:
        value: "sensor.filament_humidity"
        maximum: 15
        hysteresis: 5
      notifier: rich

When this alert fires I’m sent a notification that allows me to acknowledge the alert or snooze to it for 1 hour. Focusing only on an action being clicked, an event is sent into the event stream where the event is mobile_app_notification_action with the action equal to whatever you set and then the alert has to be read from the event stream and then actioned. A quick example of a pyscript notification action handlers:

@event_trigger("mobile_app_notification_action", "action =='ACK_AMS_HUMIDITY'")
def ack_ams_humidity(**kwargs):
    alert2.ack(entity_id="alert2.humidity_ams_humidity")

@event_trigger("mobile_app_notification_action", "action =='SNOOZE_AMS_1_HOUR'")
def snooze_1_hour_ams_humidity(**kwargs):
...

@event_trigger("mobile_app_notification_action", "action ==''SNOOZE_AMS_1_DAY")
def snooze_1_day_ams_humidity(**kwargs):
...

Ideally, for every alert I create that I want to be able to ack or snooze from a notification I have to include details in alert configuration which will largely be the same for all alerts as well as implement the handling logic for them. I mind implementing the event handlers less as I’m not sure this is something the integration can do but being able to have actions automatically be added would be ideal. I figure something like the following:

alert2:
  defaults:
     actions:
         - action: "SNOOZE_{{alert_name}}_1_hour"
            title: Snooze for 1 hour
         ...
  alerts:
      ...
        data:
           group: "GroupTag.ams_humdity_group"
            tag: "NotificationTag.ams_humditiy_tag"
            url: "/dashboard-home/management"

Where the “actions” are not overridden so the default would be added. Ideally, if alert2 could listen for and handle these that’d also be awesome but that may not be feasible as I’m not familiar with that side of Home Assistant.

Another “nice to have” feature would be to show alerts where the condition has passed but we are waiting on the length of time to pass before the alert is actually triggered. IE: “Pending alerts”.

Some other thoughts on what has been mentioned in this post:

  • I really am excited for UI. Instant feedback is great and hopefully will open alerting to more people
  • I like the idea of an staged alerting/escalation policy for alerts to increase severity.
  • Making the alerts more UI friendly is also pretty exciting!

As always, I appreciate the work you’re doing!

EDIT:
I had a thought about how to handle the snoozing and acking of alerts. I’ll update here with the result of that. Likely to be some time later this week.

@woodersayer That’s awesome you have actionable alerts working. I agree I’d love those too for sure! Being able to ack/snooze/disable etc. from the alert itself on the phone is amazing. Seems like alert2 could handle the action returns for sure by listening to the event stream and just having a YAML configuration option for specific actions to take.

Ironically, this seems remarkably overloaded with the concept of external triggers and/or service calls (see GitHub issue thread Trigger based alert doesn't fire · Issue #7 · redstone99/hass-alert2 · GitHub that also has possible connection between stages/escalation and a separate trigger and/or service call manual deactivation (or deescalation) as an option) to deactivate an alert if you just expanded the set of actions that can occur on a specific event/service call for an alert.

I think there’s a set of interrelated features here that are pointing to a particular architecture for ways to interact with a fired alert and I think there’s an elegant solution to get all of them through a good design/configuration.

Will revert as I noodle on it

Josh - thanks for the explanation on alert handling on restart, that makes sense. Does mean on a crash I think there could be alerts that didn’t shut down properly - may mean a cleanup call is necessary in the future but in this remote home assistant example there’s some entity name prefixing that would have to be applied. I view as a low priority item just wanted to note before closing out that topic.

I know there are a few interspersed conversations here, but as we’re tossing around product feature suggestions, I have some thoughts now on unavailable states to try to get everything written down.

I think, similar to the “availability” option in YAML templates (Template - Home Assistant), an availability option for Alerts would be valuable.

Nearly every one of my alerts is written like this at present:

    - domain: temperature
      generator_name: very_low_indoor_temperature
      generator: "{{ expand('sensor.very_low_building_temperature_alert_group')|map(attribute='entity_id')|list }}"
      name: "{{ genRaw }}_is_low"
      friendly_name: "{{ state_attr(genRaw,'friendly_name') }} is low temp"
      condition: "{{ states(genRaw) != 'unundefined' and  states(genRaw) != 'unavailable' and states(genRaw)|float < states('input_number.indoor_building_very_low_temperature_alert_value')|float }}"
      delay_on_secs: 600
      message: "Low temp of {{ states(genRaw)|float }}"
      reminder_frequency_mins: 30

Where I check for availability of the entity in the condition to prevent exceptions/failures of the alert (e.g. the cast to float).

Note that threshold alerts still fail though and throw exceptions as there’s no way to specify availability.

I then have a giant single generator that enumerates over all the groups I care about to check availability and report an error for unavailable entities:

    - domain: critical
      generator_name: entity_unavailable
      generator: "{% from 'entity_name_state.jinja' import expand_with_remote -%}{{ expand_with_remote(
        'sensor.freezer_temperature_alert_group' ~ ',' ~
        'sensor.fridge_temperature_alert_group' ~ ',' ~
        'sensor.indoor_building_temperature_alert_group' ~ ',' ~
        'sensor.very_low_building_temperature_alert_group' ~ ',' ~
        'binary_sensor.leak_detected_alert_group' ~ ',' ~
        'binary_sensor.smoke_detected_alert_group' ~ ',' ~
        'binary_sensor.carbon_monoxide_detected_alert_group' ~ ',' ~
        'binary_sensor.unexpected_occupancy_detected_alert_group' ~ ',' ~
        'switch.switch_availability_group' ~ ',' ~
        'binary_sensor.occupancy_detected_group') }}"
      name: "{{ genRaw }}_entity_unavailable"
      friendly_name: "Entity unavailable: {{ state_attr(genRaw,'friendly_name') }}"
      condition: "{{ states(genRaw) == 'undefined' or states(genRaw) == 'unavailable' or states(genRaw) == 'unknown' }}"
      delay_on_secs: 60
      message: "Entity state: {{ states(genRaw) }}"
      notifier: all_devices
      reminder_frequency_mins: 1440

where expand_with_remote is a template macro that is able to expand multiple groups and groups that come from remote home assistant and make one list.

It would be a lot better to combine these. This would clean up conditions by removing the necessity of checking for entity availability. It would also make threshold alerts protected against exceptions from unavailable entities.

I suggest adding an availability template option to an alert’s YAML at a minimum. If this is true, the alert will not fire.

I mentally went down the path of thinking maybe there should be something like an “availbility_action” that would be “none” or “alert” and allow the alert to fire in some special case if it was unavailable (e.g. availability evaluated to ‘false’). But this leads down a whole series of implementation path questions, what is the “state” of an unavailable alert (e.g. is there now a third state to on/off but you can’t overload this name as ‘unavailable’ as that’s already in use by HA for the alert entity itself being unavailable), how do you notify (do you use the alert’s main notifier or some new special one which then creates a whole bunch of new config options we wouldn’t want). My feeling is that’s a thorny route - so I think if you use the availability template, you still need to create a separate alert to alert on unavailable entities should you desire to have those alerts. But at least the availability template would stop alerts from failing and throwing exceptions.

Reference: Macro for Expanding Remote Home Assistant Groups Locally in Alert2

To provide my macro I’m using in the YAML above, if you’re using Remote Home Assistant and want to work with groups replicated from remote instances in integrations like Alert2, you’ll notice some unique challenges. Groups from remote instances are reflected locally as single entity sensors, with their member entities moved into the entities attribute. This happens because the entity IDs on the local instance are prefixed (e.g., remote_), rendering the original group invalid locally.

To allow for expansion of these groups into their individual entities (with the correct local prefixes), I created a Jinja2 macro. This macro:

  1. Iterates through the entities in a local group and the entities attribute of each remote group.
  2. Adds the appropriate remote prefix to each remote entity ID.
  3. Expands nested groups (both local and remote) to resolve all endpoint entity IDs.

This means you can input a list of groups (local or remote, including nested ones), and the macro will return a fully expanded list of local entity IDs reflecting the original remote group members.


Macro Usage:

Use the macro as shown in the example below, passing a comma-separated string of group entity IDs to expand.

  • Input: A comma-delimited list of groups.
  • Output: A complete list of expanded entity IDs, with correct prefixes applied to reflect the local instance.

Example:

{{ expand_with_remote('group.local_group,group.remote_group') }}

Macro:

{%- macro expand_with_remote(entities) -%}
  {%- set ns = namespace(b1 = false) -%}
  [
  {%- for entity in entities.split(',') -%}
    {%- set entity_list = expand(entity) -%}
    {%- for o in entity_list -%}
      {%- if 'entity_id' in o.attributes %}
        {%- set prefix = (o.entity_id.split('.')[1]).split('_')[0] -%}
        {%- for o2 in o.attributes.entity_id -%}
          {%- if ns.b1 -%}
            ,
          {%- endif -%}
          {%- set ns.b1 = true -%}
          '{{ o2.split('.')[0] }}.{{ prefix }}_{{ o2.split('.')[1] }}'
        {%- endfor -%}
      {%- else -%}
        {%- if ns.b1 -%}
          ,
        {%- endif -%}
        {%- set ns.b1 = true -%}
        '{{- o.entity_id -}}'
      {%- endif -%}
    {%- endfor -%}
  {%- endfor -%}
  ]
{%- endmacro -%}

@woodersayer - good thoughts and suggestions. Adding a default for data makes sense, as does showing pending alerts. For pending alerts, I’d probably add an attribute to the alert indicating the pending state, and then a config switch in the UI to show the pending ones or not.

Making it easier to have alert2 management actions in notifications sounds like a good idea as well. Makes sense to me to have Alert2 watch the event stream for some set of predefined events. Do you have suggestions for what a good set might be? The action specs can’t take a parameter can they? Like instead of hard-coding SNOOZE_FOR_1_DAY, could you have the action be SNOOZE_FOR with a time parameter? I’m not super familiar with actions.

@tman98, I’m glad you’re giving the unknown/unavail issue some thought! I agree that triggering secondary alerts/notifications from within an alert might be rather complex/problematic. Also, what to do about alerts that reference multiple entities, any one of which might be unavailable. Some possibilities:

  • adding a function/filter to make it easier to detect entity availability issues in templates.
  • add a generator function that expands to the list of all entities referenced in alert templates. Might make it easier to set up alerting on unavailable entities.
  • Expose a variable last_value to threshold value templates to make it easier for them to specify policies to handle unavailable entities (e.g., fallback to the previous value).

I’m coming around more to staged alerts. Here are my recent thoughts on them:

  1. Expressing staging (or “circumstances”) is about notifications and display of the alert, not so much about whether it’s firing or not. So it makes sense to me to be able to alter any notification/display parameters of an alert in each stage.
  2. My inclination would be to declare that stages are mutually exclusive. You can’t be in two stages at the same time.
  3. Stages are ordered. The ordering may be related to display format/priority, but that’s not required.
  4. Stages are entered via some trigger/condition specification. Optionally, when an alert changes stage (or just advances in stage), the reminder/snooze status is reset. It’d be as if the alert just started firing after being off.

Oh and relatedly, it makes sense to me to add a display_message template parameter that is shown in the UI below the alert name. That can also be changed in stages.

EDIT: @tman98 - did you mention that Alert2 looses the last few minutes of alert history after HA restart? I was just looking at the state restore code as part of the UI work and it looks like it should write out most state when HA shuts down. I can test and see what’s up, but wondered if you remembered what tended to get lost on restart.

-Josh

Hello over here, @redstone99 !

I thought I’d post here on my general list of use cases and desires for future directions, rather than flood a whole bunch of feature request issues into the GitHub, and to let everyone comment.

Right now, I’ve just moved over to Alert2 from HA’s built in Alert, given that the latter has been frozen and may be deprecated (per here). And, let me say up front, I’m already pleased with the extra capabilities I’m getting from it, but it does mean that I’ve got a few feature requests based on making sure I can replicate some of the behaviors of Alert that we’ve got accustomed to here:

  • Alerts that don’t notify immediately (i.e., like the old skip_first option); this is, for example, like door and window open alerts where I don’t want an announcement every time someone goes in and out, but (in cases where the door is deliberately left open) I would like to be able to ack the alert immediately, meaning it should fire straight away. (This is the one I have a GitHub issue for.)

  • I’d like to have the option to hear the stop notification for acked condition alerts.

(To turn this into a use case, if I leave the door open deliberately, I ack the alert so I won’t be reminded. But if someone else closes the door, I’d like to know when that happens. Likewise, if I ack an overheating alert, I’d like to know if the situation resolves itself so I can stop trying to resolve it manually. That sort of case.)

This may actually be a request to have alerts unack when they go on->off, rather than off->on, although that would only apply to condition alerts and not event alerts. I recognize that that would be a possibly breaking change, so maybe as an option?

  • I have a couple of UI requests too. The first one is to make it easier to differentiate active and inactive (condition) alerts. I think one good step for that would be to apply an active color to active alert icons, similar to the state color in entity cards, and/or gray them out. Another one would be to sort “off” condition alerts into a separate section, as is currently done for acked, snoozed, and disabled alerts, and sort them to the very bottom.

I’m not sure how to best handle event alerts in this respect, though? (Unless the alert2.manual_turn_off action suggested here is implemented, of course.)

  • The other is that alongside the current custom card, which works well I find as a sort of “Master Alarm” panel, it would be good to have a custom alert2-row that works like multiple-entity-row; basically, providing the special functionality of the alert row displayed in the custom card in a package that could be dropped into any entities card, or auto-entities card.

This would make it a lot easier to set up, say, room-specific alert cards that provide all the alert functionality. I’ve got a couple of dozen pages in my Home Assistant UI, so it’d be handy to not need to flip back and forth to manage alerts.

So, y’know. Just a few small things. :grin:

Thanks for the great integration!

We’re sort of spanning here and two GitHub issues (Trigger based alert doesn't fire · Issue #7 · redstone99/hass-alert2 · GitHub and [feature] Allow alerts to fire but not notify on first firing · Issue #5 · redstone99/hass-alert2 · GitHub). I think this thread is the best place to discuss core architectural topics in order to keep coordinated in once organized location.

I tend to agree with @DonLuigi on Trigger based alert doesn't fire · Issue #7 · redstone99/hass-alert2 · GitHub (restating some of his thoughts here):

I think it’s valuable to step back to determine, What is an alert2 alert in the abstract? As @DonLuigi said, it is really just tracking that “something” has occurred that we care about (alert fired); then that that something may still be occurring (alert active/on); and finally that that something has ended (alert off and completion fired).

That abstraction is generic and usable across any of the ways of activating and deactivating alerts.

From a concept perspective:

  • An alert could be activated by an event, condition, service call, or something else in the future.

  • An alert can either stop immediately (single shot fired, which is the subset @DonLuigi described for an event notification alert, which in an even more generic abstraction is just an “immediate deactivation”) or stay active until expliictly deactivated.

  • Then an alert can deactivated via any number of mechanisms, e.g. a condition going false, an event, a service call, a cancellation by the user (e.g. button or actionable notification), etc.

But it’s all generically the same concept and I believe should be a single implementation as well. That creates a simpler and smaller code base with fewer lines of code and fewer tests that achieve more coverage.

One small nuance is the single event-based one-shot alert (immediate deactivation)‘s state today is the time it fired whereas “on/off” alerts’ state are the on/off state. Not sure if that semantic is critical or not but that could be implemented with a single special case if we beleive it is an important differentiation.

I do see strong value from a usability perspective in creating certain alert types/clases for configuration purposes (making it easier to write, read, and debug configuration YAML), for example:

  • event based alert (takes only an event and/or condition to be true for firing a one-shot alert with immediate deactivation)
  • condition alert (takes only a condition)
  • latched alert (event/service call with optional condition on and event/service call with (a separate most likely) condition off)

Other alert types can then be created in the future strictly in the configuration code section of the codebase, setting the appropriate activation/deactivation states of the generic implementation.

This also allows staging to then be built as a second abstraction layer over the alert, and I believe the above will simplify that code as well.

I’m not convinced staging is strictly a notification concept yet. I think there is a potential refinement of the alert state that is useful, but again an abstraction on top of the alert. For example, one set of stages might be to increase the size of the notification group or go from normal notifications to critical, or potentially send SMS messages, if the alert stays active for too long.This would be notification level staging.

But another might be to increase the notification criticality if the condition gets worse for example. Let’s say we have a fridge is getting cold (e.g. under 37 degrees F) alert. But if it goes under freezing we want to both escalate the notification but also a “substate” of the alert may also now be true (fridge is now freezing). I think there’s value in tracking a further state of the alert. This “substate” change could really just possibly be captured as just a refinement of the message and display_message as you said @redstone but I wanted to note that staging may be based on time, state changes, etc. and is worth of tracking. State changes should certainly go into history as well.

@tman98, great thoughts. I agree with I think all of it. Yeah, I’m not sure how to best handle event alerts (that immediately deactivate), both architecturally as well as in the UI.

@cerebrate - thanks for the ideas! Getting an “off” notification even after having ack’d the alert is an interesting feature. I wonder if it’s a form of staged alert, but probably simpler just to have a flag to specify that acking applies only to reminders, not the “off” notification.

I’m accumulating all the feature requests in a list. I can put it online if there’s a good place. I should add that there are a lot of them. I expect that the rate and scope of new feature requests will start to level out as the project matures. Coding help welcome!

-Josh

For myself, the current semantics make sense to me insofar as one-shot alerts behave like HA button/input_button objects, also one-shots, whereas condition alerts (and presumably latched event alerts) behave like switch/input_boolean objects, state-wise, which matches up intuitively.


I have also been thinking about staged alerts, and wondering if it might be a good idea to separate the notions behind them into two concepts which seem to me to have different semantics: call them severity and sub-alerts, perhaps.

Severity, as I see it, scales linearly, and every stage is a strict subset of the one before it. It’s possible to either advance to a new stage or revert to one before it (although this latter capability may not be used). Possibilities include:

“disk 80% full”, “disk 90% full”, “disk 95% full”, “out of disk space”
“overheating (5°)”, “overheating (10°)”, “overheating (critical)”
“alert”, “alert for > 15 minutes”, “alert for > 1 hour”

and so forth, where each one implies the previous is, or at least was, true.

Whereas sub-alerts I’m conceptualizing as alerts that are relevant because the primary alert is true, but which aren’t necessarily related to each other, and can change state independently.

So here, to use my standard example, we have:

“door is left open”

  • “door is left open AND it’s cold outside”
  • “door is left open AND it’s nighttime”
  • “door is left open AND activity is detected outside”

where the sub-alerts have different and unrelated conditions, but are all conditioned on the parent alert being “on”.

The former seems to be where staging is converging per here, but the latter seems like valuable functionality for the sort of use we talked about on GitHub here.

And conveniently, this latter is attainable right now by defining a condition alert whose conditions include a reference to the “parent” alert as well as its “actual” condition, so as a feature request it would just imply some syntactic sugar in the YAML and a cleaner display of them in the UI.

(Sorry if I’ve been recapitulating the already known, but I wanted to get this clear in my own head.)


…that was where I was going to leave it, but I stopped to get a coffee and now I have a new feature request or pair of them to add, courtesy of my lovely wife.

They’re both about snoozing, and partly my fault because I’d implemented a “snooze” feature for some of our alerts manually back under Alert. :slight_smile:

The first of them is just that the name of the snooze feature is confusing if you haven’t read the Alert2 docs, because the snooze everyone’s familiar with is the alarm-clock kind, and that kind of snooze starts sounding the alarm again when it expires. Whereas the Alert2 snooze doesn’t; the snoozed alert stays acked when the snooze expires, and so the notifications for an already-on alert don’t come back.

So, maybe that could use a rename to make its semantics more obvious to HA-users who aren’t also the HA-implementors?

The other one is for a notification snooze that would have identical semantics to an alarm-snooze, i.e., act like acking the alert and then automatically unacking it again when the snooze period expires?

(This latter is effectively what I set up for our “Clean Laundry Ready” alert using a timer and a couple of automations, so that she could flip the “Busy now; remind me in a couple of hours” switch and defer notifications for that long. This is of course just as easy to implement now with the ack and unack actions, which I’m going to do right now, but it seems like a generalizable enough request that it’s worth mentioning as a possible feature.)

Assuming the path that is that Alert2 is listening to the event stream AND sending the notifications, the user could simply configure the snooze length when creating the “data” field. A rough idea could be as follows:

alert2:
  defaults:
     ack_on_notification_click: true     # This can be done by setting the HA URL to 
     actions:
         - action: snooze 
            length: 1h
         - action: snooze
            length: 1w
  alerts:
      - domain: humidity
        name: bin_humidity
      ...
        data:
           group: "GroupTag.ams_humdity_group"
           tag: "NotificationTag.ams_humditiy_tag"
           url: "/dashboard-home/management"

In this above example:

  • The unique action identifier could be built programmatically for each alert as we know each alert will have a unique domain and name (I believe this is an existing requirement but I may be mistaken).
  • We would also know the default lengths of time the user wants
  • This still leaves the user in control of determining what works best for them.
  • This also makes it more easily extensible in the future as this would abstract away the action generation from the user

So the “actions” that get appended to the notifier service call could be converted into something like this:
humdity.bin_humidity|snooze_1_week
Where the pipe represents some delimiter to make it easier on the integration side to determine which part is the name of the alert and what is the actual action selected by the user.

This enters the event stream, the integration would listen to mobile_app_notification_action events for the interaction from the HA Companion app and then handle any which has action == <some action we expect to see from an alert notification>. This would seem to be the easiest to implement. That being said arbitrary input is supported by the HA Companion apps and for what it’s worth, I’m coming at this from a user perspective as I’ve not read too far into the development docs of HA. Here is a link to the docs talking about how automatons are intended to be used to handle this. To quote these docs, this what a mobile_app_notification_action event looks like is this:

{
    "event_type": "mobile_app_notification_action",
    "data": {
        "action": "OPEN_<context_id_here>",
        // will be present:
        // - when `REPLY` is used as the action identifier
        // - when `behavior` is set to `textInput`
        "reply_text": "Reply from user",
        // iOS-only, will be included if sent in the notification
        "action_data": {
          "entity_id": "light.test",
          "my_custom_data": "foo_bar"
        },
        // Android users can also expect to see all data fields sent with the notification in this response such as the "tag"
        "tag": "TEST"
    },
    "origin": "REMOTE",
    "time_fired": "2020-02-02T04:45:05.550251+00:00",
    "context": {
        "id": "abc123",
        "parent_id": null,
        "user_id": "123abc"
    }
}

In the above example, if REPLY is one of the actions and that is what this event is, then reply That is to say, arbitrary input is supported for alerts and the data is pretty easy to get into the alert. but the problem now becomes parsing the input from the user. One could allow pretty non specific snoozing (an untested regex could look like this [1-9][0-9]+[smhdwy]`), to allow the user to be more precise allow for them to mix these values (IE: 1w3dh), or one could require the user enter a parse-able date format that is included in the alert (IE: YYYY-MM-DDTHH:MM).
There will be errors because this is user input, so I see a couple of ways of handling when a reply contains an parse-able value:

  • Send the user notifications until they get it right (potentially eating into their 500 daily allotment from Nabu Casa)
  • Send them a singular follow up notification with a URL that the user can specify which takes them to a page where they can handle snooze/disabling/acking via the UI.

While I could handle arbitrary input on my own, I’ve made the decision not to as I find the for all of my alerts so far I’ve not needed anything really different than acking, snoozing for an hour, or snoozing for a day. If I want anything more, I can go to the UI to be more exact which I can do rather easily by including a URL as part of the notification definition.

tl;dr yes, actions do support arbitrary input and I intentionally don’t use them as I’ve found what appears to be a sweet spot for me (1 hour and 1 day) but I would love to avoid repeated configuration. Let me know if the above was worth your time and/or you have anything else I can help answer

A quick aside which I learned while answering you (link), apparently you can call services with URL handler so the default action when clicking a url could be acking it. Neat!

Wow great thoughts both! I think you’re on to some clever abstractions… going to keep thinking.

Just as a side note, for what it’s worth, I’m thoroughly enjoying this component’s budding community. Some really clever minds are getting involved here (@cerebrate
and @woodersayer) on top of an open minded and really great architect and author in @redstone99. Great ideas are being formed. It’s not always the case the discussions are so constructive and focused principally on building great tech in some of the HA communities (instead of defending turf), so it’s a very enjoyable breath of fresh air. I love opening my browser each day to see if there’s a new message :slight_smile: ! Thanks all.

2 Likes