🔔 Actionable notifications for Android

Did you find a solution?

I’m getting a similar error in the HA logs:

(‘trigger_entity’, None)]): Entity IDs can not be None for dictionary value @ data[‘entity_id’]. Got None

But I do have a valid trigger entity specified, using an input boolean, and the automation does correctly trigger and run.

Upvote for adding the capability send to an individual device OR a group of devices!

I don’t this is possible with the current setup, but i’m looking for a way for the notification to clear once the boolean has been cleared. For example i have a garage door and i want this mobile notification to appear when it is opened. However if i manually close the garage door (or use my garage door opener), once the door is closed, i am looking for this notification to be automatically cleared as this is no longer needed. I think the workaround would be to use the tag and clear the notification from another automation.

not a workaround, thats how you do it.

Yes I did actually!

  • I started by converting into a script instead of automation
  • This led to a world of hurt :slight_smile: I ran into two main problems:
    • the script needed to handle an unknown number of actions (1-3)
    • the script needed to handle arbitrary actions without knowing their parameters beforehand

You can find my struggles and the main error I encountered here
The workaround was a combination:

  • A script to allow the user to define the buttons and arbitrary actions
  • A python script to accept any number of arbitrary actions and execute the chosen one (see here on how to setup python scripts in HA)
  • BONUS: I also added context.id to prevent multiple notifications from interfering with one another

Here’s the end product, trimmed down for legibility:

# /config/scripts.yaml

actionable_notification:
  # ...
  fields:
    # ...
    action_1_title:
      name: 'Button 1: name'
      description: Name of the first button
      required: true
      default: ''
      selector:
        text:
    action_1_uri:
      name: 'Button 1: URI (Optional)'
      description: Optional URI for the first button
      default: ''
      selector:
        text:
    action_1_action:
      name: 'Button 1: service call(s)'
      description: Service(s) to run when the first button is clicked
      required: true
      default: []
      selector:
        action:

    # actions 2 and 3 are optional
    action_2_title:
      name: 'Button 2 (Optional): name'
      description: Name of the second button
      selector:
        text:
    action_2_uri:
      name: 'Button 2 (Optional): URI (Optional)'
      description: Optional URI for the second button
      selector:
        text:
    action_2_action:
      name: 'Button 2 (Optional): service call(s)'
      description: Service(s) to run when the second button is clicked
      required: true
      default: []
      selector:
        action:
    # ... action 3 is same as 2

  mode: single

  sequence:
  - variables:
      title: '{{ notification_title if notification_title is defined else "" }}'
      message: '{{ notification_message if notification_message is defined else ""}}'
      action_1:
        action: '{{ "action1" ~ context.id }}'
        title: '{{ action_1_title }}'
        uri: '{{ action_1_uri if action_1_uri is defined else "" }}'
      action_2:
        action: '{{ "action2" ~ context.id }}'
        title: '{{ action_2_title if action_2_title is defined else "" }}'
        uri: '{{ action_2_uri if action_2_uri is defined else "" }}'
      # action_3...

  # Send actionable notification
  - service: '{{ notify_service }}'
    data:
      title: '{{ title }}'
      message: '{{ message }}'
      data:
        tag: '{{ title }}'
        persistent: '{{ persistent_notification if persistent_notification is defined
          else false }}'
        actions: >
          {% set actions_raw = [action_1, action_2, action_3] %}
          {% set actions = namespace(data = []) %}
          {% for action in actions_raw %}
            {% if action["title"]|string|length %}
              {% set actions.data = actions.data + [action] %}
            {% endif %}
          {% endfor %}
          {{ actions.data }}

  # Wait for the user to select an action
  - wait_for_trigger:
    - platform: event
      event_type: mobile_app_notification_action
    - platform: event
      event_type: mobile_app_notification_cleared

  # Check that we have a chosen action
  - condition: template
    value_template: '{{ wait.trigger.event.data.action is defined }}'

  # Send the actions and the choice to python script
  - service: python_script.actionable_notifications_execute
    data:
      actions: >
        {{ [
          action_1_action,
          action_2_action if action_2_action is defined else [],
          action_3_action if action_3_action is defined else []
        ] }}
      chosen: '{{ wait.trigger.event.data.action }}'
      event: '{{ wait.trigger.event }}'
      context_id: '{{ context.id }}'
# /config/python_scripts/services.yaml

actionable_notifications_execute:
  name: Execute actionable notifications
  description: Execute the chosen actions from a list presented in a notification
  fields:
    actions:
      description: The potential actions to execute
    chosen:
      description: The chosen action ("action[num]")
    context_id:
      description: The (automatically-generated) notification context ID. Prevents confusion with other notifications' events.
# /config/python_scripts/actionable_notifications_execute.py

def get_param(service):
  if "data" in service:
    return service["data"]
  if "target" in service:
    return service["target"]
  return null

actions = data.get("actions")
chosen = data.get("chosen")
context_id = data.get("context_id")
index = int(chosen.replace(context_id, '')[-1]) - 1

for service in actions[index]:
  service_name = service.pop("service")
  domain, name = service_name.split(".")
  param = get_param(service)
  hass.services.call(domain, name, param)

1 Like

This is an awesome feature, glad I found this. I only have a couple smart bulbs but love the idea of getting a notification if my lights turn on (while I am not in my home zone), and being able to turn them off through the notification, which shows up correctly on my smart watch!

@dshokouhi If you use the alert integration you don’t need automations to send or clear the notification.

alert:
  garage_door_open:
    name: "Garage Door Open"
    title: "Garage Door Open"
    message: "The garage door is open."
    done_message: clear_notification
    entity_id: cover.garage_door_opener
    state: open
    repeat: 60
    notifiers: mobile
4 Likes

Thank you !

Is there any way to auto-dismiss this notification once the condition has resolved? (e.g. on the garage door scenario, when someone manually closes the garage door)

i dont understand what im missing here. Im only seeing a notification in the HA companion app and its only showing the name of the message and its just showing the yaml for the button and the action i am trying to use. I cant get any notifictions on my phone period,

Anyway to include an attachment to the notification, for example:

       service: notify.mobile_app_<your_device_id_here>
        data:
            message: "Something happened at home!"
            data:
            # an example of an absolute url
                image: "https://github.com/home-assistant/assets/blob/6a407898bd8ae80eb83634ffddb0d5ebdde95957/logo/logo.png?raw=true"
1 Like

This is super cool! Because the notification actions are an android standard y can click them from my SmartWatch (garmin). This will greatly reduce my usage of the phone!

Thanks to @vorion for creating this Blueprint
I have modified the one that is now built-in Home assistant (I am not sure what is different aside from being a script and the in the OP is a automation)

The changes are:

  • The target is now the name of a notify service, so you would enter: “notify.‘device/group name’”.
    For example: notify.mobile_app_oneplus or notify.phones_group
    Please note that the input is not validated, so make sure the spelling is correct.

  • Clearing the notification will trigger the Dismiss Action

  • Actioning or clearing the notification from one device will remove the notification from all other devices.

  • Added an option for timeout, after the time is done the Dismiss Action will be triggered, and the notification will be cleared.

blueprint:
  name: Confirmable Notification
  description: >-
    A script that sends an actionable notification with a confirmation before
    running the specified action.
  domain: script
  source_url: https://github.com/home-assistant/core/blob/919f4dd719ac2551ca63a93780852bba1aadd7b0/homeassistant/components/script/blueprints/confirmable_notification.yaml
  input:
    notify_device:
      name: Notification service
      description: Notification service name (ex. Notify.mobile_app_....). Note that device/s needs to run the official Home Assistant app to receive notifications.
      selector:
        text:
    title:
      name: "Title"
      description: "The title of the button shown in the notification."
      default: ""
      selector:
        text:
    message:
      name: "Message"
      description: "The message body"
      selector:
        text:
    confirm_text:
      name: "Confirmation Text"
      description: "Text to show on the confirmation button"
      default: "Confirm"
      selector:
        text:
    confirm_action:
      name: "Confirmation Action"
      description: "Action to run when notification is confirmed"
      default: []
      selector:
        action:
    dismiss_text:
      name: "Dismiss Text"
      description: "Text to show on the dismiss button"
      default: "Dismiss"
      selector:
        text:
    dismiss_action:
      name: "Dismiss Action"
      description: "Action to run when notification is dismissed"
      default: []
      selector:
        action:
    tag:
      name: "Notification Tag"
      description: "notification tag for updating and dismissing the notification"
      default: {}
      selector:
        text:
    timeout:
        name: "Timeout duration"
        default: {}
        selector:
          duration:
mode: restart

sequence:
  - alias: "Set up variables"
    variables:
      action_confirm: "{{ 'CONFIRM_' ~ context.id }}"
      action_dismiss: "{{ 'DISMISS_' ~ context.id }}"
  - alias: "Send notification"
    service: !input notify_device
    data:
      message: !input message 
      title: !input title
      data:
        actions:
          - action: "{{ action_confirm }}"
            title:  !input confirm_text
          - action: "{{ action_dismiss }}"
            title:  !input dismiss_text
        tag: !input tag
  - alias: "Awaiting response"
    wait_for_trigger:
      - platform: event
        event_type: mobile_app_notification_action
        event_data:
          action: "{{ action_confirm }}"
      - platform: event
        event_type: mobile_app_notification_action
        event_data:
          action: "{{ action_dismiss }}"
      - platform: event
        event_type: mobile_app_notification_cleared
    timeout: !input timeout
  - choose:
      - conditions: '{{ wait.trigger.event.event_type == "mobile_app_notification_cleared" }}' 
        sequence: 
          - service: !input notify_device
            data:
              message: clear_notification
              data:
                tag: !input tag
          - choose:
            default: !input dismiss_action
      - conditions: "{{ wait.trigger.event.data.action == action_confirm }}"
        sequence: 
          - service: !input notify_device
            data:
              message: clear_notification
              data:
                tag: !input tag
          - choose:
            default: !input confirm_action
      - conditions: "{{ wait.trigger.event.data.action == action_dismiss }}"
        sequence: 
          - service: !input notify_device
            data:
              message: clear_notification
              data:
                tag: !input tag
          - choose:
            default: !input dismiss_action
      - conditions: "{{ wait.remaining == 0}}"
        sequence: 
          - service: !input notify_device
            data:
              message: clear_notification
              data:
                tag: !input tag
          - choose:
            default: !input dismiss_action

Mentioning those who asked for this ability
@EvlLprchn @sacredshapes @tanderson1992 @frelev @jesc @rlyons20

5 Likes

I keep getting this error when trying to run the automation.
Error: Unable to find notify service for webhook ID

check if your notify service didnt change

Any chance anyone know how to get the Notification Channel working with this blueprint? I’ve modified it a bunch of different ways and I cannot get it to work. I feel like what I have here looks right, but I’m no expert.

blueprint:
  name: Test2
  description: 'Send actionable notifications to an Android device
    '
  domain: automation
  input:
    notify_device:
      name: Device to notify
      description: Device needs to run the official Home Assistant app to receive
        notifications
      selector:
        device:
          integration: mobile_app
          multiple: false
    trigger_entity:
      name: Trigger entity
      description: Send the notification when this boolean turns on
      selector:
        entity:
          domain: input_boolean
          multiple: false
    notification_title:
      name: Notification title (Optional)
      description: The title of the notification
      default: ''
    notification_message:
      name: Notification message (Optional)
      description: The message of the notification
      default: ''
    notification_tag:
      name: Notification tag (Optional)
      description: The tag of the notification
      default: ''
    notification_channel:
      name: Notification channel (Optional)
      description: The channel of the notification
      default: ''
    notification_timeout:
      name: Notification timeout (Optional)
      description: Length of time the notification is displayed
      default: ''
    persistent_notification:
      name: Create persistent notification?
      description: Persistent notifications cannot be dimissed by swiping away
      default: false
      selector:
        boolean: {}
    action_1_title:
      name: First action name
      description: Name of the first button
      default: ''
    action_1_uri:
      name: URI for action 1 (Optional)
      description: Optional URI for the first action
      default: ''
    first_action:
      name: Action 1
      description: Action to run when the first action is clicked
      default: []
      selector:
        action: {}
    action_2_title:
      name: Second action name
      description: Name of the second button
      default: ''
    action_2_uri:
      name: URI for action 1 (Optional)
      description: Optional URI for the second action
      default: ''
    second_action:
      name: Action 2
      description: Action to run when the second action is clicked"
      default: []
      selector:
        action: {}
    action_3_title:
      name: Third action name
      description: Name of the third button
      default: ''
    action_3_uri:
      name: URI for action 3 (Optional)
      description: Optional URI for the third action
      default: ''
    third_action:
      name: Action 3
      description: Action to run when the third action is clicked
      default: []
      selector:
        action: {}
  source_url: https://community.home-assistant.io/t/actionable-notifications-for-android/256773
mode: restart
max_exceeded: silent
variables:
  notify_device: !input 'notify_device'
  trigger_entity: !input 'trigger_entity'
  notification_title: !input 'notification_title'
  notification_message: !input 'notification_message'
  notification_tag: !input 'notification_tag'
  notification_channel: !input 'notification_channel'
  notification_timeout: !input 'notification_timeout'
  persistent_notification: !input 'persistent_notification'
  action_1_title: !input 'action_1_title'
  action_1_uri: !input 'action_1_uri'
  first_action: !input 'first_action'
  action_2_title: !input 'action_2_title'
  action_2_uri: !input 'action_2_uri'
  second_action: !input 'second_action'
  action_3_title: !input 'action_3_title'
  action_3_uri: !input 'action_3_uri'
  third_action: !input 'third_action'
trigger:
  platform: state
  entity_id: !input 'trigger_entity'
  from: 'off'
  to: 'on'
action:
- service: input_boolean.turn_off
  entity_id: !input 'trigger_entity'
- domain: mobile_app
  type: notify
  device_id: !input 'notify_device'
  title: '{{ notification_title }}'
  message: '{{ notification_message }}'
  data:
    tag: '{{ notification_tag }}'
    timeout: '{{ notification_timeout }}'
    persistent: '{{ persistent_notification }}'
    data:
      channel: '{{ notification_channel }}'
    actions: "{% set titles = [action_1_title, action_2_title, action_3_title] %}\
      \ {% set uris = [action_1_uri, action_2_uri, action_3_uri] %} {% set actions\
      \ = namespace(data = []) %}\n{% for title in titles %}\n  {% if title|length\
      \ %}\n    {% set uri = uris[loop.index - 1] %}\n    {% set action_name = \"\
      action\" + loop.index|string %}\n    {% set action = {\n      \"action\": \"\
      URI\" if uri|length else action_name,\n      \"title\": title,\n      \"uri\"\
      : uri \n      }\n    %}\n    {% set actions.data = actions.data + [action] %}\n\
      \  {% endif %}\n{% endfor %} {{ actions.data }}\n"
- wait_for_trigger:
    platform: event
    event_type: mobile_app_notification_action
- choose:
  - conditions: '{{ wait.trigger.event.data.action == ''action1'' }}'
    sequence: !input 'first_action'
  - conditions: '{{ wait.trigger.event.data.action == ''action2'' }}'
    sequence: !input 'second_action'
  - conditions: '{{ wait.trigger.event.data.action == ''action3'' }}'
    sequence: !input 'third_action'

1 Like

ditch the extra data line and move channel back in line with persistent and actions.

-face palms- I swear I tried that and it didn’t work… But it totally just worked. :clap: Thanks!