123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- blueprint:
- domain: script
- name: Notify user
- description: >-
- Notify a user
- input:
- notify_device:
- name: "Devices to notify"
- description: >-
- The name of the notify service, e.g service.mobile_app_x
- selector:
- object:
- index:
- name: Device index
- description: >-
- If called several times within same context, increase this for each.
- default:
- seconds: 0
- selector:
- number:
- min: 1
- max: 1000
- step: 1
- timeout:
- name: "Timeout"
- description: >-
- Timeout before notifications dissapear.
- selector:
- duration:
- # enable_days: true
- data:
- name: "Message data"
- description: "Equal to data field in the notify service"
- selector:
- object:
- # Scripts to run based on `data->actions` set in notify-service. E.g:
- # ```
- # data:
- # actions:
- # - action: ACTION_ANCHOR
- # title: This test
- # ```
- # with matching:
- # ```
- # action_scripts:
- # ACTION_ANCHOR: script...
- # ```
- # The format for `ACTION_ANCHOR` can be just a string, referencing a script,
- # or an object with the following format:
- # ```
- # ACTION_ANCHOR:
- # script: script..
- # variables:
- # var1: ....
- # ```
- action_scripts:
- name: Action scripts
- description: >-
- Read `action_scripts` comments within blueprint.
- selector:
- object:
- default: {}
-
- tts:
- name: "TTS"
- description: "Not used yet"
- selector:
- boolean:
- default: "{{ false }}"
- mode: parallel
- variables:
- input_notify_device: !input notify_device
- index: !input index
- ctx: "{{ this.context.id + '_' + input_notify_device ~ '_' ~ index }}" #
-
- input_timeout: !input timeout
- update_timeout: >-
- {% set seconds = 0 %}
- {% if input_timeout is iterable %}
- {% if 'seconds' in input_timeout %}
- {% set seconds = seconds + input_timeout.seconds|int %}
- {% endif %}
- {% if 'minutes' in input_timeout %}
- {% set seconds = seconds + (input_timeout.minutes|int * 60 * 60) %}
- {% endif %}
- {% if 'hours' in input_timeout %}
- {% set seconds = seconds + ((input_timeout.hours|int) * 60 * 60) %}
- {% endif %}
- {% if 'days' in input_timeout %}
- {% set seconds = seconds + ((input_timeout.days|int) * 60 * 60 * 24) %}
- {% endif %}
- {% elif input_timeout is not iterable %}
- {% set seconds = input_timeout|int %}
- {% endif %}
- {{ 0 if seconds == 0 else (now().timestamp() + seconds) }}
- input_data: !input data
- update_data: >-
- {% set data_data = (input_data.data.items() | list) if 'data' in input_data else [] %}
- {% if 'data' in input_data %}
- {% if 'actions' in input_data.data %}
- {% set action = namespace(entities=[]) %}
- {% for a in input_data.data.actions %}
- {% set update = {"action": ctx ~ '_' ~ a.action}.items() | list %}
- {% set current = a.items() | list | rejectattr(
- '0', 'eq', update | map(attribute='0') | list
- ) | list %}
- {% set action.entities = action.entities + [
- dict.from_keys(current + update)
- ] %}
- {% endfor %}
- {% set actions = { "actions": action.entities }.items() | list %}
- {% set data_data = dict.from_keys(data_data | rejectattr(
- '0', 'eq', actions | map(attribute='0') | list
- ) | list + actions).items() | list
- %}
- {% endif %}
- {% if 'group' not in input_data.data %}
- {% set add = { "group": "default-group" }.items() | list %}
- {% set data_data = dict.from_keys(data_data | rejectattr(
- '0', 'eq', add | map(attribute='0') | list
- ) | list + add).items() | list
- %}
- {% endif %}
- {% if (
- (
- 'alert_once' in input_data.data or
- 'actions' in input_data.data or
- 'persistent' in input_data.data
- ) and 'tag' not in input_data.data
- ) or (
- timeout != 0 and 'tag' not in input_data.data
- )
- %}
- {% set add = { "tag": "tag_" + ctx }.items() | list %}
- {% set data_data = dict.from_keys(data_data | rejectattr(
- '0', 'eq', add | map(attribute='0') | list
- ) | list + add).items() | list
- %}
- {% endif %}
- {% else %}
- {% if timeout != 0 %}
- {% set add = { "tag": "tag_" + ctx }.items() | list %}
- {% set data_data = dict.from_keys(data_data | rejectattr(
- '0', 'eq', add | map(attribute='0') | list
- ) | list + add).items() | list
- %}
- {% endif %}
- {% endif %}
-
- {% if data_data|length != 0 %}
- {% set data_data = {"data": dict.from_keys(data_data)}.items() | list %}
- {{ dict.from_keys((input_data.items() | list | rejectattr(
- '0', 'eq', data_data | map(attribute='0') | list
- ) | list) + data_data) }}
- {% else %}
- {{ input_data }}
- {% endif %}
- action_scripts: !input action_scripts
- action_handlers: >-
- {% set actions = namespace(handlers=[]) %}
- {% for ask in action_scripts.keys() %}
- {% set askc = ctx ~ '_' ~ ask %}
- {% for action in update_data.data.actions if askc == action.action %}
- {% set actions.handlers = actions.handlers + [(
- askc, action_scripts[ask]
- )] %}
- {% endfor %}
- {% endfor %}
- {{ dict.from_keys(actions.handlers) }}
- sequence:
- # - service: system_log.write
- # data:
- # level: warning
- # message: >-
- # Action handlers: {{ action_handlers }}
- # Timeout: {{ update_timeout }} seconds
- # Data: {{ update_data }}
-
- - alias: "Parallize event listeners and notification"
- parallel:
- - alias: "Listen for event if actions are given"
- if: "{{ action_handlers|length > 0 }}"
- then:
- - alias: "Loop for events until criterias are met"
- repeat:
- while: "{{ (update_timeout - now().timestamp() > 0) or update_timeout == 0 }}"
- sequence:
- - if: "{{ update_timeout == 0 }}"
- then:
- alias: "Wait for app event, without timeout"
- wait_for_trigger:
- - platform: event
- event_type:
- - mobile_app_notification_action
- - mobile_app_notification_cleared
- else:
- alias: "Wait for app event, with timeout"
- wait_for_trigger:
- - platform: event
- event_type:
- - mobile_app_notification_action
- - mobile_app_notification_cleared
- timeout: >-
- {{ update_timeout - now().timestamp() }}
- - if: "{{ wait.trigger is none }}"
- then:
- alias: "Reached timeout, stopping."
- stop: "Reached timeout, stopping."
-
- - variables:
- in_ctx: >-
- {% set in_ctx = namespace(bool=false) %}
- {% for key in wait.trigger.event.data.keys() if key.startswith('action') and key.endswith('key') %}
- {% if wait.trigger.event.data[key].startswith(ctx) %}
- {% set in_ctx.bool = true %}
- {% endif %}
- {% endfor %}
- {{ in_ctx.bool }}
- - alias: "Check if context matches or restart from top"
- condition: "{{ in_ctx }}"
- - if: >-
- {{
- wait.trigger.event.event_type.endswith('_cleared') or
- wait.trigger.event.data.action not in action_handlers.keys()
- }}
- then:
- - alias: "Cleared event within user context"
- event: custom_mobile_app_notification_action
- event_data:
- context: "{{ ctx }}"
- action: "cleared"
- - stop: "User cleared notification or choose an invalid option, stop listening for events."
- - event: custom_mobile_app_notification_action
- event_data:
- context: "{{ ctx }}"
- action: "{{ wait.trigger.event.data.action }}"
- - stop: "User acted within context, stop listening for further events."
- - alias: "Listen for forwarded events"
- if: "{{ action_handlers|length > 0 or update_timeout != 0 }}"
- then:
- - if: "{{ update_timeout == 0 }}"
- then:
- alias: "Wait for context event, without timeout"
- wait_for_trigger:
- - platform: event
- event_type: custom_mobile_app_notification_action
- event_data:
- context: "{{ ctx }}"
- else:
- alias: "Wait for context event, with timeout"
- wait_for_trigger:
- - platform: event
- event_type: custom_mobile_app_notification_action
- event_data:
- context: "{{ ctx }}"
- timeout: >-
- {{ update_timeout - now().timestamp() }}
- - alias: "Check if timed out and remove notification"
- if: "{{ wait.trigger == none }}"
- then:
- alias: "Clear notification, timeout reached."
- service: "{{ input_notify_device }}"
- data:
- message: "clear_notification"
- data:
- tag: "{{ data.data.tag }}"
- else:
- - variables:
- action: >-
- {% set action = wait.trigger.event.data.action %}
- {{ action_handlers[action] if action in action_handlers else false }}
- - alias: "Action is known or stop executing"
- condition: "{{ action is not false }}"
- - if: "{{ action is string or 'variables' not in action }}"
- then:
- service: script.turn_on
- target:
- entity_id: "{{ script }}"
- else:
- service: script.turn_on
- target:
- entity_id: "{{ action.script }}"
- data:
- variables: "{{ action.variables }}"
- - alias: Send message to device
- service: "{{ input_notify_device }}"
-
- data: >-
- {{ update_data }}
- # @ignore: Incorrect type. Expected "object"
|