diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3aa864b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +TODO.md diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a04b218 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "*.yaml": "home-assistant" + } +} \ No newline at end of file diff --git a/notifications.yaml b/notifications.yaml index e880626..3619c15 100644 --- a/notifications.yaml +++ b/notifications.yaml @@ -1,15 +1,15 @@ -mode: restart +mode: parallel blueprint: - name: 🔔 Notifications (Version 2.0.2 Beta) + name: 🔔 Notifications (Version 2.1.3) source_url: https://github.com/samuelthng/t-house-blueprints/blob/main/notifications.yaml homeassistant: - min_version: 2023.11.0 + min_version: 2024.06.0 domain: script author: samuelthng/t-house-blueprints description: >-

🔔 Notifications

- Version 2.0.2 Beta | 🔗 Github Link | 💬 Community Post + Version 2.1.3 | 🔗 Github Link | 💬 Community Post

@@ -17,23 +17,25 @@ blueprint: ### Features: - > 📲 Sends notification to [Home Assistant Companion](https://companion.home-assistant.io/) + > 📲 Sends notification to [Home Assistant Companion](https://companion.home-assistant.io/) - > 3️⃣ Up to 3 customisable, action buttons (Previously: ✅ Confirm and ❌ Dismiss Button) + > 3️⃣ Up to 3 customisable, action buttons (Previously: ✅ Confirm and ❌ Dismiss Button) - > ⌛️ Timeout actions with custom duration, fired if no option response received + > ⌛️ Timeout actions with custom duration, fired if no option response received - > 🧹 Clear notification after timeout + > 🧹 Clear notification after timeout and after response received - > 📸 Camera Snapshots + > 📸 Camera Snapshots - > 🔗 Custom Notification Link + > 🔗 Custom Notification Link - > 📜 Flexible [script fields](https://www.home-assistant.io/integrations/script/#fields) + > 📜 Flexible [script fields](https://www.home-assistant.io/integrations/script/#fields) - > 🍎 Supports iOS + > 🎯 Zone-based notification delivery - > 🤖 Supports Android + > 🍎 Supports iOS + + > 🤖 Supports Android Examples can be found [here](https://community.home-assistant.io/t/notification-with-confirm-dismiss-and-timeout/551552#example-usage-6) @@ -41,6 +43,28 @@ blueprint:
Expand/collapse changelog + + ### Version 2.1.3 + - Fixed: When `notify_device` is empty, automatically include all available mobile devices + + ### Version 2.1.2 + - Fixed: Support for multiple zones configuration + + ### Version 2.1.1 + - Added: Clear Notification if response received + + ### Version 2.1.0 + - Added zone-based message functionality + + ### Version 2.0.5 + - modify multiples devices => merge multi devices from samuelthng that I missed... + - added `notification_link` field + + ### Version 2.0.4 + - suppport notifications to multiples devices + + ### Version 2.0.3 + - collapse menus ability on main blueprint creation page, maybe more readable ### Version 2.0.2 Beta Multiple Device - *19 Jan 2023* - Added: Field for `notification_link`. [#26](https://github.com/samuelthng/t-house-blueprints/pull/26) (Thanks to [HNKNTA](https://github.com/HNKNTA)) @@ -116,651 +140,716 @@ blueprint: ############################## # Input: Notification Strategy ############################## - notify_device: - name: "📲 Device to notify" - description: >- - Device needs to run the official [Home Assistant Companion](https://companion.home-assistant.io/) app to receive notifications.

- ❔ Only used with `📲 Notification Strategy: Device`
- 👍🏻 `Device` is the preferred and default option. - default: "" - selector: - device: - filter: - - integration: mobile_app + target: + name: Notification target + icon: mdi:bullseye-arrow + description: Control who will receive the notification. + input: + notify_device: + name: "📲 Devices to notify" + description: >- + Can be overrided. + Devices needs to run the official [Home Assistant Companion](https://companion.home-assistant.io/) app to receive notifications.

+ default: [] + selector: + device: + multiple: true + filter: + - integration: mobile_app + target: + name: "🎯 Send the notification to" + description: Target of the notification. + default: send_to_all + selector: + select: + options: + - label: Everyone + value: send_to_all + - label: Everyone inside (a) zone(s) (Use the zone input below) + value: send_to_persons_in_zones + - label: Everyone outside (a) zone(s) (Use the zone input below) + value: send_to_persons_not_in_zones + zones: + name: Zones (Optional) + description: Only usefull if the Target of the notification was set to "Everyone inside (a) zone(s)" or "Everyone outside (a) zone(s)". + default: [] + selector: + entity: + multiple: true + filter: + - domain: zone ############################## # Input: Notification Content ############################## - title: - name: "🏷️ Title" - description: "The title of the notification. \n\n`Optional`\n" - default: "" - selector: - text: - subtitle: - name: "🏷️ Subtitle" - description: "The subtitle of the notification. \n\n`Optional`\n" - default: "" - selector: - text: - message: - name: "💬 Message" - description: "The message body to display on the notification. \n\n`🤖 Android`: You may add [HTML formatting](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#notification-message-html-formatting) to customise the look of the message." - selector: - text: - icon: - name: "🙂 Icon" - description: "Custom icon for this notification. \n\n`🤖 Android Only`, `Optional`" - default: "" - selector: + content: + name: Default content + description: Default content of the notification. + collapsed: false + input: + title: + name: "🏷️ Title" + description: "The title of the notification. \n\n`Optional` Can be overrided.\n" + default: "" + selector: + text: + subtitle: + name: "🏷️ Subtitle" + description: "The subtitle of the notification. \n\n`Optional` Can be overrided.\n" + default: "" + selector: + text: + message: + name: "💬 Message" + description: "The message body to display on the notification. \n\n`🤖 Android`: You may add [HTML formatting](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#notification-message-html-formatting) to customise the look of the message. Can be overrided." + default: "" + selector: + text: icon: - enable_icon_color: - name: "🎨 Use Icon Color" - description: "If disabled, uses default icon color. \n\n`🤖 Android Only`, `Optional`" - default: false - selector: - boolean: - icon_color: - name: "🎨 Icon Color" - description: "Custom icon color for this notification. \n\n`🤖 Android Only`, `Optional`" - default: [102, 186, 240] - selector: - color_rgb: + name: "🙂 Icon" + description: "Custom icon for this notification. \n\n`🤖 Android Only`, `Optional`" + default: "" + selector: + icon: + enable_icon_color: + name: "🎨 Use Icon Color" + description: "If disabled, uses default icon color. \n\n`🤖 Android Only`, `Optional`" + default: false + selector: + boolean: + icon_color: + name: "🎨 Icon Color" + description: "Custom icon color for this notification. \n\n`🤖 Android Only`, `Optional`" + default: [102, 186, 240] + selector: + color_rgb: ############################## # Input: Response Options ############################## - ## Option 1 - confirm_enabled: - name: "1️⃣ Option 1" - description: "Show or hide this option." - default: True - selector: - boolean: - - confirm_text: - name: "1️⃣ Option 1 - Title" - description: "Title to show on the first option." - default: "Option 1" - selector: - text: - - confirm_option_mode: - name: "1️⃣ Option 1 - Mode" - description: >- - Action mode for this option.

- If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

- -
- ❔ What is this? - - This option is only applicable to Android due to technical limitations. - - The android app can't sending events and open links on the device at the same time, using the same option. - - As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. - - This is due to: - - - The lack of events being sent when URI options are fired. - - The requirement to set the `action` parameter to `"URI"`. - -
- -  iOS: Ignore this, iOS will run both actions and links if they are set.

- `🤖 Android Only`, `Optional` - default: "" - selector: - select: - mode: dropdown - options: - - label: "" - value: "" - - label: Action(s) - value: action - - label: "Link (🤖 Android Only)" - value: uri - - confirm_action: - name: "1️⃣ Option 1 - Action(s)" - description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" - default: [] - selector: - action: - - confirm_uri: - name: "1️⃣ Option 1 - Link" - description: >- - Navigate to a link or app when this option is selected.
- -
- 🔗 Show Common Examples - - - To **open a Home Assistant view**, use relative links like these: - `/lovelace/my-dashboard` - `/config/dashboard` - `/developer-tools/template` - - - Use **launch a page in your default browser**, - select the appropriate `Link` option in modes and enter a URL here: - `https://example.com` - -

- -
- 🤖 Show Android Specific Examples - - - To **open an Application** on your device, for example: - `app://` - `app://io.homeassistant.companion.android` - - - To **view an Entity** on your Home Assistant setup: - `entityId:` - `entityId:sun.sun` - - - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): - `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` - - - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): - `deep-link://` - `deep-link://example://link/to/content` - - - To **see notification history**: - `settings://notification_history` - -

- -
-  Show iOS Specific Examples - - - Use **application-launching URLs** on your device - `tel:123456789` - `mailto:my@email.com` - -

- - ❔ Android: Used with `Mode: Link` options
- ❔ iOS: Leave empty to disable
- ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

- `Optional` - default: "" - selector: - text: - type: url - - confirm_icon: - name: "1️⃣ Option 1 - Icon" - description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" - default: "" - selector: - text: - prefix: "sfsymbols:" - - confirm_is_destructive: - name: "1️⃣ Option 1 - Destructive" - description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: - - confirm_authentication_required: - name: "1️⃣ Option 1 - Authentication Required" - description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: - - ## Option 2 - dismiss_enabled: - name: "2️⃣ Option 2" - description: "Show or hide this option." - default: True - selector: - boolean: - - dismiss_text: - name: "2️⃣ Option 2 - Title" - description: "Title to show on the first option." - default: "Option 2" - selector: - text: - - dismiss_option_mode: - name: "2️⃣ Option 2 - Mode" - description: >- - Action mode for this option.

- If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

- -
- ❔ What is this? - - This option is only applicable to Android due to technical limitations. - - The android app can't sending events and open links on the device at the same time, using the same option. - - As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. - - This is due to: - - - The lack of events being sent when URI options are fired. - - The requirement to set the `action` parameter to `"URI"`. - -
- -  iOS: Ignore this, iOS will run both actions and links if they are set.

- `🤖 Android Only`, `Optional` - default: "" - selector: - select: - mode: dropdown - options: - - label: "" - value: "" - - label: Action(s) - value: action - - label: "Link (🤖 Android Only)" - value: uri - - dismiss_action: - name: "2️⃣ Option 2 - Action(s)" - description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" - default: [] - selector: - action: - - dismiss_uri: - name: "2️⃣ Option 2 - Link" - description: >- - Navigate to a link or app when this option is selected.
- -
- 🔗 Show Common Examples - - - To **open a Home Assistant view**, use relative links like these: - `/lovelace/my-dashboard` - `/config/dashboard` - `/developer-tools/template` - - - Use **launch a page in your default browser**, - select the appropriate `Link` option in modes and enter a URL here: - `https://example.com` - -

- -
- 🤖 Show Android Specific Examples - - - To **open an Application** on your device, for example: - `app://` - `app://io.homeassistant.companion.android` - - - To **view an Entity** on your Home Assistant setup: - `entityId:` - `entityId:sun.sun` - - - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): - `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` - - - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): - `deep-link://` - `deep-link://example://link/to/content` - - - To **see notification history**: - `settings://notification_history` - -

- -
-  Show iOS Specific Examples - - - Use **application-launching URLs** on your device - `tel:123456789` - `mailto:my@email.com` - -

- - ❔ Android: Used with `Mode: Link` options
- ❔ iOS: Leave empty to disable
- ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

- `Optional` - default: "" - selector: - text: - type: url - - dismiss_icon: - name: "2️⃣ Option 2 - Icon" - description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" - default: "" - selector: - text: - prefix: "sfsymbols:" - - dismiss_is_destructive: - name: "2️⃣ Option 2 - Destructive" - description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: - - dismiss_authentication_required: - name: "2️⃣ Option 2 - Authentication Required" - description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: - - ## Option 3 - option_three_enabled: - name: "3️⃣ Option 3" - description: "Show or hide this option." - default: false - selector: - boolean: - - option_three_text: - name: "3️⃣ Option 3 - Title" - description: "Title to show on the first option." - default: "Option 3" - selector: - text: - - option_three_option_mode: - name: "3️⃣ Option 3 - Mode" - description: >- - Action mode for this option.

- If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

- -
- ❔ What is this? - - This option is only applicable to Android due to technical limitations. - - The android app can't sending events and open links on the device at the same time, using the same option. - - As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. - - This is due to: - - - The lack of events being sent when URI options are fired. - - The requirement to set the `action` parameter to `"URI"`. - -
- -  iOS: Ignore this, iOS will run both actions and links if they are set.

- `🤖 Android Only`, `Optional` - default: "" - selector: - select: - mode: dropdown - options: - - label: "" - value: "" - - label: Action(s) - value: action - - label: "Link (🤖 Android Only)" - value: uri - - option_three_action: - name: "3️⃣ Option 3 - Action(s)" - description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" - default: [] - selector: - action: - - option_three_uri: - name: "3️⃣ Option 3 - Link" - description: >- - Navigate to a link or app when this option is selected.
- -
- 🔗 Show Common Examples - - - To **open a Home Assistant view**, use relative links like these: - `/lovelace/my-dashboard` - `/config/dashboard` - `/developer-tools/template` - - - Use **launch a page in your default browser**, - select the appropriate `Link` option in modes and enter a URL here: - `https://example.com` - -

- -
- 🤖 Show Android Specific Examples - - - To **open an Application** on your device, for example: - `app://` - `app://io.homeassistant.companion.android` - - - To **view an Entity** on your Home Assistant setup: - `entityId:` - `entityId:sun.sun` - - - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): - `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` - - - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): - `deep-link://` - `deep-link://example://link/to/content` - - - To **see notification history**: - `settings://notification_history` - -

- -
-  Show iOS Specific Examples - - - Use **application-launching URLs** on your device - `tel:123456789` - `mailto:my@email.com` - -

- - ❔ Android: Used with `Mode: Link` options
- ❔ iOS: Leave empty to disable
- ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

- `Optional` - default: "" - selector: - text: - type: url - - option_three_icon: - name: "3️⃣ Option 3 - Icon" - description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" - default: "" - selector: - text: - prefix: "sfsymbols:" - - option_three_is_destructive: - name: "3️⃣ Option 3 - Destructive" - description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: - - option_three_authentication_required: - name: "3️⃣ Option 3 - Authentication Required" - description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" - default: false - selector: - boolean: + option1: ## Option 1 + name: Option 1 + collapsed: true + input: + confirm_enabled: + name: "1️⃣ Option 1" + description: "Show or hide this option. Can be overrided." + default: False + selector: + boolean: + + confirm_text: + name: "1️⃣ Option 1 - Title" + description: "Title to show on the first option." + default: "Option 1" + selector: + text: + + confirm_option_mode: + name: "1️⃣ Option 1 - Mode" + description: >- + Action mode for this option.

+ If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

+ +
+ ❔ What is this? + + This option is only applicable to Android due to technical limitations. + + The android app can't sending events and open links on the device at the same time, using the same option. + + As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. + + This is due to: + + - The lack of events being sent when URI options are fired. + - The requirement to set the `action` parameter to `"URI"`. + +
+ +  iOS: Ignore this, iOS will run both actions and links if they are set.

+ `🤖 Android Only`, `Optional` + default: "" + selector: + select: + mode: dropdown + options: + - label: "" + value: "" + - label: Action(s) + value: action + - label: "Link (🤖 Android Only)" + value: uri + + confirm_action: + name: "1️⃣ Option 1 - Action(s)" + description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" + default: [] + selector: + action: + + confirm_uri: + name: "1️⃣ Option 1 - Link" + description: >- + Navigate to a link or app when this option is selected.
+ +
+ 🔗 Show Common Examples + + - To **open a Home Assistant view**, use relative links like these: + `/lovelace/my-dashboard` + `/config/dashboard` + `/developer-tools/template` + + - Use **launch a page in your default browser**, + select the appropriate `Link` option in modes and enter a URL here: + `https://example.com` + +

+ +
+ 🤖 Show Android Specific Examples + + - To **open an Application** on your device, for example: + `app://` + `app://io.homeassistant.companion.android` + + - To **view an Entity** on your Home Assistant setup: + `entityId:` + `entityId:sun.sun` + + - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): + `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` + + - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): + `deep-link://` + `deep-link://example://link/to/content` + + - To **see notification history**: + `settings://notification_history` + +

+ +
+  Show iOS Specific Examples + + - Use **application-launching URLs** on your device + `tel:123456789` + `mailto:my@email.com` + +

+ + ❔ Android: Used with `Mode: Link` options
+ ❔ iOS: Leave empty to disable
+ ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

+ `Optional` + default: "" + selector: + text: + type: url + + confirm_icon: + name: "1️⃣ Option 1 - Icon" + description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" + default: "" + selector: + text: + prefix: "sfsymbols:" + + confirm_is_destructive: + name: "1️⃣ Option 1 - Destructive" + description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: + + confirm_authentication_required: + name: "1️⃣ Option 1 - Authentication Required" + description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: + + option2: ## Option 2 + name: Option 2 + collapsed: true + input: + dismiss_enabled: + name: "2️⃣ Option 2" + description: "Show or hide this option. Can be overrided." + default: False + selector: + boolean: + + dismiss_text: + name: "2️⃣ Option 2 - Title" + description: "Title to show on the first option." + default: "Option 2" + selector: + text: + + dismiss_option_mode: + name: "2️⃣ Option 2 - Mode" + description: >- + Action mode for this option.

+ If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

+ +
+ ❔ What is this? + + This option is only applicable to Android due to technical limitations. + + The android app can't sending events and open links on the device at the same time, using the same option. + + As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. + + This is due to: + + - The lack of events being sent when URI options are fired. + - The requirement to set the `action` parameter to `"URI"`. + +
+ +  iOS: Ignore this, iOS will run both actions and links if they are set.

+ `🤖 Android Only`, `Optional` + default: "" + selector: + select: + mode: dropdown + options: + - label: "" + value: "" + - label: Action(s) + value: action + - label: "Link (🤖 Android Only)" + value: uri + + dismiss_action: + name: "2️⃣ Option 2 - Action(s)" + description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" + default: [] + selector: + action: + + dismiss_uri: + name: "2️⃣ Option 2 - Link" + description: >- + Navigate to a link or app when this option is selected.
+ +
+ 🔗 Show Common Examples + + - To **open a Home Assistant view**, use relative links like these: + `/lovelace/my-dashboard` + `/config/dashboard` + `/developer-tools/template` + + - Use **launch a page in your default browser**, + select the appropriate `Link` option in modes and enter a URL here: + `https://example.com` + +

+ +
+ 🤖 Show Android Specific Examples + + - To **open an Application** on your device, for example: + `app://` + `app://io.homeassistant.companion.android` + + - To **view an Entity** on your Home Assistant setup: + `entityId:` + `entityId:sun.sun` + + - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): + `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` + + - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): + `deep-link://` + `deep-link://example://link/to/content` + + - To **see notification history**: + `settings://notification_history` + +

+ +
+  Show iOS Specific Examples + + - Use **application-launching URLs** on your device + `tel:123456789` + `mailto:my@email.com` + +

+ + ❔ Android: Used with `Mode: Link` options
+ ❔ iOS: Leave empty to disable
+ ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

+ `Optional` + default: "" + selector: + text: + type: url + + dismiss_icon: + name: "2️⃣ Option 2 - Icon" + description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" + default: "" + selector: + text: + prefix: "sfsymbols:" + + dismiss_is_destructive: + name: "2️⃣ Option 2 - Destructive" + description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: + + dismiss_authentication_required: + name: "2️⃣ Option 2 - Authentication Required" + description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: + + option3: ## Option 3 + name: Option 3 + collapsed: true + input: + option_three_enabled: + name: "3️⃣ Option 3" + description: "Show or hide this option. Can be overrided." + default: False + selector: + boolean: + + option_three_text: + name: "3️⃣ Option 3 - Title" + description: "Title to show on the first option." + default: "Option 3" + selector: + text: + + option_three_option_mode: + name: "3️⃣ Option 3 - Mode" + description: >- + Action mode for this option.

+ If you need this option to do nothing, pick `Mode: Action(s)` here and leave the `Action(s)` input empty for this option.

+ +
+ ❔ What is this? + + This option is only applicable to Android due to technical limitations. + + The android app can't sending events and open links on the device at the same time, using the same option. + + As such, options on the android app can only be either a link, or an action on Home Assistant. Not both. + + This is due to: + + - The lack of events being sent when URI options are fired. + - The requirement to set the `action` parameter to `"URI"`. + +
+ +  iOS: Ignore this, iOS will run both actions and links if they are set.

+ `🤖 Android Only`, `Optional` + default: "" + selector: + select: + mode: dropdown + options: + - label: "" + value: "" + - label: Action(s) + value: action + - label: "Link (🤖 Android Only)" + value: uri + + option_three_action: + name: "3️⃣ Option 3 - Action(s)" + description: "Action(s) to run when this option is selected.\n\n❔ Used with `Mode: Action(s)` option\n❔ Script stops after actions are run\n❔ Leave empty to do nothing\n\n`Optional`" + default: [] + selector: + action: + + option_three_uri: + name: "3️⃣ Option 3 - Link" + description: >- + Navigate to a link or app when this option is selected.
+ +
+ 🔗 Show Common Examples + + - To **open a Home Assistant view**, use relative links like these: + `/lovelace/my-dashboard` + `/config/dashboard` + `/developer-tools/template` + + - Use **launch a page in your default browser**, + select the appropriate `Link` option in modes and enter a URL here: + `https://example.com` + +

+ +
+ 🤖 Show Android Specific Examples + + - To **open an Application** on your device, for example: + `app://` + `app://io.homeassistant.companion.android` + + - To **view an Entity** on your Home Assistant setup: + `entityId:` + `entityId:sun.sun` + + - To use [**Intent scheme URIs**](https://developer.chrome.com/docs/multidevice/android/intents/#syntax): + `intent://scan/#Intent;scheme=zxing;package=com.my.pkg;end` + + - To use [**Deep links**](https://developer.android.com/training/app-links#deep-links): + `deep-link://` + `deep-link://example://link/to/content` + + - To **see notification history**: + `settings://notification_history` + +

+ +
+  Show iOS Specific Examples + + - Use **application-launching URLs** on your device + `tel:123456789` + `mailto:my@email.com` + +

+ + ❔ Android: Used with `Mode: Link` options
+ ❔ iOS: Leave empty to disable
+ ⚠️ Android: Using this option **WILL NOT STOP** timeout countdown. Please triple check actions that will be run in `Timeout Action(s)`.

+ `Optional` + default: "" + selector: + text: + type: url + + option_three_icon: + name: "3️⃣ Option 3 - Icon" + description: "Custom icon to show on this option. \n\nPlease refer to the [documentation here](https://companion.home-assistant.io/docs/notifications/actionable-notifications#icon-values). \nThere are many reference pages out there, feel use a [search engine](https://www.google.com/search?q=sfsymbols+reference+list)! \n\n` iOS Only`, `Optional`" + default: "" + selector: + text: + prefix: "sfsymbols:" + + option_three_is_destructive: + name: "3️⃣ Option 3 - Destructive" + description: "Set the action's title to be red, indicating a destructive action. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: + + option_three_authentication_required: + name: "3️⃣ Option 3 - Authentication Required" + description: "Require device to be unlocked to use this option. \n\n` iOS Only`, `Optional`" + default: false + selector: + boolean: ############################## # Input: Timeout Options ############################## - enable_timeout: - name: "⌛️ Enable Timeout" - description: "Require script to stop listening after the set duration.

👍🏻 Recommended to enable.
⚠️ If disabled, script will wait for response indefinitely until the next time it is triggered." - default: true # Default `true` for backward compatibility. - selector: - boolean: - timeout: - name: "⌛️ Timeout Duration" - description: "Amount of time to wait for an action response before firing timeout action. \n\n👍🏻 Recommended: ≥1 minute, to allow notifications to be sent. \nDefault: 15 minutes. \n" - default: - hours: 0 - minutes: 15 - seconds: 0 - selector: - duration: - enable_day: false - run_timeout_actions: - name: "⌛️ Enable Timeout Action(s)" - description: "Run timeout actions upon a timeout event.

👍🏻 Recommended to enable.
⚠️ If disabled, script will timeout without executing any timeout actions." - default: true # Default `true` for backward compatibility. - selector: - boolean: - timeout_action: - name: "⌛️ Timeout Action(s)" - description: "Action to run when notification response is timed out. \n\n❔ Leave empty if no actions should be run \n\n⚠️ Android Users: Note, URI options do not stop the timeout countdown. This action could be run after pressing the URI option.\n❔ Android Users: Workaround for the above, you may disable `⌛️ Run timeout action(s) when notification cleared` and manually clear the notification after selecting your URI option. \n\n`Optional`" - default: [] - selector: - action: - swipe_away_as_timeout: - name: "⌛️ Run timeout action(s) when notification cleared" - description: "If enabled, swiping the notification away will immediately trigger timeout actions. \n\n`🤖 Android Only`" - default: false - selector: - boolean: - clear_on_timeout: - name: "🧹 Clear notification on timeout" - description: "Dismiss the notification after action selection times out." - default: false - selector: - boolean: - persist: - name: "🚩 Persistent Notification" - description: "Prevents notifications from being swiped away by accident. \n\n❔ This option blocks `⌛️ Run timeout action(s) when notification cleared` \n\n`🤖 Android Only`" - default: false - selector: - boolean: + timeoutoption: ## Timeout Options + name: Timout Options + collapsed: true + input: + enable_timeout: + name: "⌛️ Enable Timeout" + description: "Require script to stop listening after the set duration. Can be overrided.

👍🏻 Recommended to enable.
⚠️ If disabled, script will wait for response indefinitely until the next time it is triggered." + default: true # Default `true` for backward compatibility. + selector: + boolean: + timeout: + name: "⌛️ Timeout Duration" + description: "Amount of time to wait for an action response before firing timeout action. \n\n👍🏻 Recommended: ≥1 minute, to allow notifications to be sent. \nDefault: 15 minutes. Can be overrided.\n" + default: + hours: 0 + minutes: 15 + seconds: 0 + selector: + duration: + enable_day: false + run_timeout_actions: + name: "⌛️ Enable Timeout Action(s)" + description: "Run timeout actions upon a timeout event.

👍🏻 Recommended to enable.
⚠️ If disabled, script will timeout without executing any timeout actions. Can be overrided." + default: true # Default `true` for backward compatibility. + selector: + boolean: + timeout_action: + name: "⌛️ Timeout Action(s)" + description: "Action to run when notification response is timed out. Can be overrided. \n\n❔ Leave empty if no actions should be run \n\n⚠️ Android Users: Note, URI options do not stop the timeout countdown. This action could be run after pressing the URI option.\n❔ Android Users: Workaround for the above, you may disable `⌛️ Run timeout action(s) when notification cleared` and manually clear the notification after selecting your URI option. \n\n`Optional`" + default: [] + selector: + action: + swipe_away_as_timeout: + name: "⌛️ Run timeout action(s) when notification cleared" + description: "If enabled, swiping the notification away will immediately trigger timeout actions. \n\n`🤖 Android Only`" + default: false + selector: + boolean: + clear_on_timeout: + name: "🧹 Clear notification on timeout" + description: "Dismiss the notification after action selection times out." + default: false + selector: + boolean: + clear_on_response: + name: "🧹 Clear notifications on response" + description: "Clear notifications on all devices when any device responds to the notification." + default: false + selector: + boolean: + persist: + name: "🚩 Persistent Notification" + description: "Prevents notifications from being swiped away by accident. \n\n❔ This option blocks `⌛️ Run timeout action(s) when notification cleared` \n\n`🤖 Android Only`" + default: false + selector: + boolean: ############################## # Input: Notification Link ############################## - notification_link: - name: "🔗 Notification Link" - description: "Link to navigate to upon clicking the notification. \n\n Examples: \n - Home Assistant relative links: `/config/updates` or `/lovelace/home` \n - Apps: `app://` \n - Entity `More Info` Panel: `entityId:` \n - Deep links: `deep-link://` \n\nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#opening-a-url) for more information and options. \n\n`Optional`" - default: "" - selector: - text: + notiflink: + name: Notification Link + collapsed: true + input: + notification_link: + name: "🔗 Notification Link" + description: "Link to navigate to upon clicking the notification. Can be overrided. \n\n Examples: \n - Home Assistant relative links: `/config/updates` or `/lovelace/home` \n - Apps: `app://` \n - Entity `More Info` Panel: `entityId:` \n - Deep links: `deep-link://` \n\nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#opening-a-url) for more information and options. \n\n`Optional`" + default: "" + selector: + text: ############################## # Input: Attachments ############################## - attachment_type: - name: "📸 Attachment Type" - description: > - Choose to send an attachment along with the notification.
- - `Optional` - default: "none" - selector: - select: - options: - - label: "None" - value: "none" - - label: "Camera" - value: "camera_entity" - attachment_camera_entity: - name: "📸 Attachment: Camera Entity" - description: >- - Camera Entity to display snapshots of on the notification.
- - Please note, iOS and Android have differing vehaviours, as specified in the documentation. - See the links below for more information. - -
 Camera Stream🤖 Automatic Snapshots

- - ❔ Only used with `Attachment Type: Camera` - default: "" - selector: - entity: - filter: - - domain: "camera" + attachments: + name: Attachments + collapsed: true + input: + attachment_type: + name: "📸 Attachment Type" + description: > + Choose to send an attachment along with the notification.
+ + `Optional` Can be overrided. + default: "none" + selector: + select: + options: + - label: "None" + value: "none" + - label: "Camera" + value: "camera_entity" + attachment_camera_entity: + name: "📸 Attachment: Camera Entity" + description: >- + Camera Entity to display snapshots of on the notification.
+ + Please note, iOS and Android have differing vehaviours, as specified in the documentation. + See the links below for more information. + +
 Camera Stream🤖 Automatic Snapshots

+ + ❔ Only used with `Attachment Type: Camera` + Can be overrided. + default: "" + selector: + entity: + filter: + - domain: "camera" ############################## # Input: Misc Inputs ############################## - car_ui: - name: "🚘 Show on Android Auto" - description: "Display notification on Android Auto interface. \n\n`🤖 Android Only`" - default: false - selector: - boolean: - tag: - name: "🔖 Tag" - description: "Used to uniquely identify the notification. \n\nUse tag if you are using this script with other notification services. \nLeave empty otherwise. \n\nExample: `my_awesome_notification_for_device_X` \n\n👍🏻 Recommended to leave empty\n\n`Optional`" - default: "" - selector: - text: - group: - name: "📣 Notification Group ID" - description: "Used for grouping different notifications together visually. \n\n⚠️ iOS critical notifications do no support grouping. \nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#grouping) for more information. \n\n`Optional`" - default: "" - selector: - text: - channel: - name: "📣 Notification Channel" - description: "Defines the channel, to be used with Importance. \nRelates to the importance of the notification. \n\n`🤖 Android Only`, `Optional`" - default: "General" - selector: - text: - importance: - name: "❕ Notification Channel Importance" - description: "See [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#notification-channel-importance) for more information. \n\n`🤖 Android Only`" - default: default - selector: - select: - options: - - label: "Urgent (Makes a sound with heads-up notification)" - value: high - - label: "Default (Makes a sound)" - value: default - - label: "Silent (Makes no sound)" - value: low - - label: "Low (Makes no sound, doesn't appear in status bar)" - value: min - android_high_priority: - name: "❕ High Priority Mode" - description: "Workaround to ensure notifications are delivered in timely fashion. This will override the Notification Channel Importance with `importance: high`, and set `ttl: 0`. \n\n`🤖 Android Only`" - default: true - selector: - boolean: - interruption_level: - name: "❕ Interruption Level" - description: "See [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#interruption-level) for more information. \n\n` iOS Only`" - default: active - selector: - select: - options: - - label: "Silent (Makes no sound, does not wake screen)" - value: passive - - label: "Default" - value: active - - label: "Important (Overrides Focus)" - value: time-sensitive - - label: "Critical (Overrides Focus and Mute, restricted features)" - value: critical - visibility: - name: "🔏 Notification Lockscreen Visibility" - description: "Show or hide notification content on the lockscreen. \nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#notification-sensitivity--lock-screen-visibility) for more information. \n\nDefault: `Private` \n\n`🤖 Android Only`" - default: "private" - selector: - select: - options: - - label: "Public: Always show content." - value: public - - label: "Private: Show content based on phone settings." - value: private - - label: "Secret: Always hide content on the lockscreen." - value: secret + miscinput: + name: Other options + collapsed: true + input: + car_ui: + name: "🚘 Show on Android Auto" + description: "Display notification on Android Auto interface. \n\n`🤖 Android Only`" + default: false + selector: + boolean: + tag: + name: "🔖 Tag" + description: "Used to uniquely identify the notification. \n\nUse tag if you are using this script with other notification services. \nLeave empty otherwise. \n\nExample: `my_awesome_notification_for_device_X` \n\n👍🏻 Recommended to leave empty\n\n`Optional`" + default: "" + selector: + text: + group: + name: "📣 Notification Group ID" + description: "Used for grouping different notifications together visually. \n\n⚠️ iOS critical notifications do no support grouping. \nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#grouping) for more information. \n\n`Optional`" + default: "" + selector: + text: + channel: + name: "📣 Notification Channel" + description: "Defines the channel, to be used with Importance. \nRelates to the importance of the notification. \n\n`🤖 Android Only`, `Optional`" + default: "General" + selector: + text: + importance: + name: "❕ Notification Channel Importance" + description: "See [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#notification-channel-importance) for more information. \n\n`🤖 Android Only`" + default: default + selector: + select: + options: + - label: "Urgent (Makes a sound with heads-up notification)" + value: high + - label: "Default (Makes a sound)" + value: default + - label: "Silent (Makes no sound)" + value: low + - label: "Low (Makes no sound, doesn't appear in status bar)" + value: min + android_high_priority: + name: "❕ High Priority Mode" + description: "Workaround to ensure notifications are delivered in timely fashion. This will override the Notification Channel Importance with `importance: high`, and set `ttl: 0`. \n\n`🤖 Android Only`" + default: true + selector: + boolean: + interruption_level: + name: "❕ Interruption Level" + description: "See [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic/#interruption-level) for more information. \n\n` iOS Only`" + default: active + selector: + select: + options: + - label: "Silent (Makes no sound, does not wake screen)" + value: passive + - label: "Default" + value: active + - label: "Important (Overrides Focus)" + value: time-sensitive + - label: "Critical (Overrides Focus and Mute, restricted features)" + value: critical + visibility: + name: "🔏 Notification Lockscreen Visibility" + description: "Show or hide notification content on the lockscreen. \nSee [documentation](https://companion.home-assistant.io/docs/notifications/notifications-basic?_highlight=tag#notification-sensitivity--lock-screen-visibility) for more information. \n\nDefault: `Private` \n\n`🤖 Android Only`" + default: "private" + selector: + select: + options: + - label: "Public: Always show content." + value: public + - label: "Private: Show content based on phone settings." + value: private + - label: "Secret: Always hide content on the lockscreen." + value: secret ############################## # Fields @@ -772,6 +861,7 @@ fields: default: !input notify_device selector: device: + multiple: true filter: - integration: mobile_app field_title: @@ -906,9 +996,23 @@ fields: # selector: # action: + field_persist: + name: "🚩 Persistent Notification" + description: "Override persistent Notification. \n\n❔ This option blocks `⌛️ Run timeout action(s) when notification cleared` \n\n`🤖 Android Only`" + default: false + selector: + boolean: + + field_clear_on_response: + name: "🧹 Clear notifications on response" + description: "Override clearing notifications on all devices when any device responds to the notification." + example: !input clear_on_response + selector: + boolean: + sequence: ############################## - # Setup Variables + # Setup commons Variables ############################## - alias: Basic Notification Content variables: @@ -943,7 +1047,8 @@ sequence: channel: !input channel visibility: !input visibility importance: !input importance - persist: !input persist + script_persist: !input persist + persist: "{{ iif(field_persist is defined, field_persist, script_persist) }}" # chronometer: !input chronometer # Unlikely to support, depends on template flexibility # alert_once: !input alert_once car_ui: !input car_ui @@ -975,6 +1080,9 @@ sequence: script_run_timeout_actions: !input run_timeout_actions run_timeout_actions: "{{ iif(field_run_timeout_actions is defined, field_run_timeout_actions, script_run_timeout_actions) }}" swipe_away_as_timeout: !input swipe_away_as_timeout + # [Clear on response] + script_clear_on_response: !input clear_on_response + clear_on_response: "{{ iif(field_clear_on_response is defined, field_clear_on_response, script_clear_on_response) }}" - alias: Attachments variables: @@ -1001,9 +1109,87 @@ sequence: - alias: Device Configuration variables: script_notify_device: !input notify_device - notify_device: "{{ iif(field_notify_device is defined, field_notify_device, script_notify_device) }}" + notify_device: >- + {% if (field_notify_device is defined and field_notify_device|length > 0) %} + {{ field_notify_device }} + {% elif (script_notify_device is defined and script_notify_device|length > 0) %} + {{ script_notify_device }} + {% else %} + {% set devices = namespace(data=[]) %} + {% for entity in integration_entities('mobile_app') %} + {% if entity.startswith('device_tracker.') %} + {% set device_id = device_id(entity) %} + {% if device_id %} + {% set devices.data = devices.data + [device_id] %} + {% endif %} + {% endif %} + {% endfor %} + {{ devices.data }} + {% endif %} + target: !input target + zones: !input zones + + - alias: Zone-based Device Filtering + variables: + filtered_devices: > + {% set final_devices = namespace(data = []) %} + {% if target == 'send_to_all' or not zones %} + {% set final_devices.data = notify_device %} + {% elif target in ['send_to_persons_in_zones', 'send_to_persons_not_in_zones'] %} + {% for device in notify_device %} + {% set tracker_id = 'device_tracker.' + device_attr(device,'name')|slugify %} + {% set device_state = states(tracker_id)|lower %} + {% set in_any_zone = false %} + {% for zone in zones %} + {% set zone_name = zone.split('.')[1]|lower %} + {% if device_state == zone_name %} + {% set in_any_zone = true %} + {% break %} + {% endif %} + {% endfor %} + {% if (target == 'send_to_persons_in_zones' and in_any_zone) or (target == 'send_to_persons_not_in_zones' and not in_any_zone) %} + {% set final_devices.data = final_devices.data + [device] %} + {% endif %} + {% endfor %} + {% endif %} + {{ final_devices.data }} + + # debug_info: > + # {% set debug = namespace(messages=[]) %} + # {% set debug.messages = debug.messages + ['Target mode: ' ~ target] %} + # {% set debug.messages = debug.messages + ['Zones is string: ' ~ (zones is string)] %} + # {% set debug.messages = debug.messages + ['Zones is sequence: ' ~ (zones is sequence)] %} + # {% set debug.messages = debug.messages + ['Zones raw: ' ~ zones] %} + # {% set debug.messages = debug.messages + ['Zone name: ' ~ zones[0].split('.')[1]|lower] %} + # {% set debug.messages = debug.messages + ['Input devices count: ' ~ notify_device|length] %} + # {% for device in notify_device %} + # {% set device_name = device_attr(device,'name') %} + # {% set tracker_id = 'device_tracker.' + device_name|slugify %} + # {% set device_state = states(tracker_id)|lower %} + # {% set zone_name = zones[0].split('.')[1]|lower %} + # {% set debug.messages = debug.messages + ['Device: ' ~ device_name ~ ' | Tracker: ' ~ tracker_id ~ ' | State: ' ~ states(tracker_id) ~ ' | Zone match: ' ~ zone_name ~ '(' ~ (device_state == zone_name) ~ ')'] %} + # {% endfor %} + # {% set zone_name = zones[0].split('.')[1]|lower %} + # {% set debug.messages = debug.messages + ['Zone: ' ~ zones[0] ~ ' | Name: ' ~ zone_name ~ ' | State: ' ~ states(zones[0])] %} + # {% set debug.messages = debug.messages + ['Filtered devices: ' ~ (filtered_devices|list|length) ~ ' devices'] %} + # {% for device in filtered_devices %} + # {% set debug.messages = debug.messages + ['Filtered device: ' ~ device_attr(device,'name')] %} + # {% endfor %} + # {% set debug.messages = debug.messages + ['Notify services: ' ~ notify_service|join(', ')] %} + # {{ debug.messages|join(' | ') }} + notify_service: >- - {{ "notify.mobile_app_{id}".format(id=device_attr(notify_device,'name')|slugify) }} + {% set devices = namespace(data = [])%} + {% for device in filtered_devices %} + {% set devices.data = devices.data + ["notify.mobile_app_{id}".format(id=device_attr(device,'name')|slugify)] %} + {% endfor %} + {{ devices.data }} + + + # - service: persistent_notification.create + # data: + # title: "Zone Filtering Debug Info" + # message: "{{ debug_info }}" - alias: Option 1 variables: @@ -1121,49 +1307,69 @@ sequence: variables: options: >- {{ [option_one, option_two, option_three] | selectattr('enabled') | list }} - expect_response: "{{ enable_timeout or option_one_enabled or option_two_enabled or option_three_enabled }}" # If there's no timeout nor options, then no point waiting. Stop script. # Build OS specific notification payloads. notification_data: >- - {% set apple_device = 'APPLE' in (device_attr(notify_device, "manufacturer")|upper) %} - {% set payload = namespace(data={ 'apple_device': apple_device }) %} - {% if payload.data.apple_device %} - {# iOS #} - {% set push = namespace(d={}) %} - {% set payload.data = dict(payload.data, **{ 'subtitle': subtitle }) %} - {% set push.d = dict(push.d, **{ 'interruption-level': interruption_level }) %} - {% if notification_link|length %}{% set payload.data = dict(payload.data, **{ 'url': notification_link }) %}{% endif %} - {% if attachment_type == 'camera_entity' %}{% set payload.data = dict(payload.data, **{ 'entity_id': attachment_camera_entity }) %}{% endif %} - {% set payload.data = dict(payload.data, **{ 'push': push.d }) %} - {% else %} - {# Android #} - {% set payload.data = dict(payload.data, **{ 'subject': subtitle }) %} - {% set payload.data = dict(payload.data, **{ 'visibility': visibility }) %} - {% set payload.data = dict(payload.data, **{ 'importance': importance }) %} - {% if android_high_priority %}{% set payload.data = dict(payload.data, **{ 'priority': 'high', 'ttl': 0 }) %}{% endif %} - {% if notification_link|length %}{% set payload.data = dict(payload.data, **{ 'clickAction': notification_link }) %}{% endif %} - {% if attachment_type == 'camera_entity' and (media_url|length) %}{% set payload.data = dict(payload.data, **{ 'image': media_url }) %}{% endif %} - {% if notification_icon|length %}{% set payload.data = dict(payload.data, **{ 'notification_icon': notification_icon }) %}{% endif %} - {% if enable_icon_color %}{% set payload.data = dict(payload.data, **{ 'color': icon_color_hex }) %}{% endif %} - {% if enable_timeout and clear_on_timeout %}{% set payload.data = dict(payload.data, **{ 'timeout': timeout_seconds }) %}{% endif %} - {% if channel|length %}{% set payload.data = dict(payload.data, **{ 'channel': channel }) %}{% endif %} - {% if persist %}{% set payload.data = dict(payload.data, **{ 'persistent': persist }) %}{% endif %} - {% if car_ui %}{% set payload.data = dict(payload.data, **{ 'car_ui': car_ui }) %}{% endif %} - {% endif %} - {# Common #} - {% set payload.data = dict(payload.data, **{ 'actions': options }) %} - {% set payload.data = dict(payload.data, **{ 'tag': tag }) %} - {% if group|length %}{% set payload.data = dict(payload.data, **{ 'group': group }) %}{% endif %} - {{ payload.data }} + {% set notifications = namespace(data=[])%} + {% set memo = namespace(data={})%} + {% for device in notify_device %} + {% set apple_device = 'APPLE' in (device_attr(device, "manufacturer")|upper) %} + {% set memo_key = 'APPLE' if apple_device else 'ANDROID' %} + {% if not memo_key in memo.data %} + {# If OS payload not built yet, evaluate it. #} + {% set payload = namespace(data={ 'apple_device': apple_device }) %} + {% if payload.data.apple_device %} + {# iOS #} + {% set push = namespace(d={}) %} + {% set payload.data = dict(payload.data, **{ 'subtitle': subtitle }) %} + {% set push.d = dict(push.d, **{ 'interruption-level': interruption_level }) %} + {% if notification_link|length %}{% set payload.data = dict(payload.data, **{ 'url': notification_link }) %}{% endif %} + {% if attachment_type == 'camera_entity' %}{% set payload.data = dict(payload.data, **{ 'entity_id': attachment_camera_entity }) %}{% endif %} + {% set payload.data = dict(payload.data, **{ 'push': push.d }) %} + {% else %} + {# Android #} + {% set payload.data = dict(payload.data, **{ 'subject': subtitle }) %} + {% set payload.data = dict(payload.data, **{ 'visibility': visibility }) %} + {% set payload.data = dict(payload.data, **{ 'importance': importance }) %} + {% if android_high_priority %}{% set payload.data = dict(payload.data, **{ 'priority': 'high', 'ttl': 0 }) %}{% endif %} + {% if notification_link|length %}{% set payload.data = dict(payload.data, **{ 'clickAction': notification_link }) %}{% endif %} + {% if attachment_type == 'camera_entity' and (media_url|length) %}{% set payload.data = dict(payload.data, **{ 'image': media_url }) %}{% endif %} + {% if notification_icon|length %}{% set payload.data = dict(payload.data, **{ 'notification_icon': notification_icon }) %}{% endif %} + {% if enable_icon_color %}{% set payload.data = dict(payload.data, **{ 'color': icon_color_hex }) %}{% endif %} + {% if enable_timeout and clear_on_timeout %}{% set payload.data = dict(payload.data, **{ 'timeout': timeout_seconds }) %}{% endif %} + {% if channel|length %}{% set payload.data = dict(payload.data, **{ 'channel': channel }) %}{% endif %} + {% if persist %}{% set payload.data = dict(payload.data, **{ 'persistent': persist }) %}{% endif %} + {% if car_ui %}{% set payload.data = dict(payload.data, **{ 'car_ui': car_ui }) %}{% endif %} + {% endif %} + {# Common #} + {% set payload.data = dict(payload.data, **{ 'actions': options }) %} + {% set payload.data = dict(payload.data, **{ 'tag': tag }) %} + {% if group|length %}{% set payload.data = dict(payload.data, **{ 'group': group }) %}{% endif %} + {# Push payload to array #} + {% set memo.data = dict(memo.data, **{ "{}".format(memo_key): payload.data }) %} + {% endif %} + {# Update notification data array with the memoized payload. #} + {% set notifications.data = notifications.data + [memo.data[memo_key]] %} + {% endfor %} + + {{ notifications.data }} + + - alias: Expect response + variables: + expect_response: "{{ enable_timeout or option_one_enabled or option_two_enabled or option_three_enabled }}" # If there's no timeout nor options, then no point waiting. Stop script. ############################## - # Send Notification + # Send Notification to multiple devices ############################## - alias: "Send notification" - service: "{{ notify_service }}" - data: - title: "{{ title }}" - message: "{{ message }}" - data: "{{ notification_data }}" + repeat: + for_each: "{{ notify_service }}" + sequence: + - service: "{{ repeat.item }}" + data: + title: "{{ title }}" + message: "{{ message }}" + data: >- + {{ notification_data[repeat.index - 1] }} ############################## # Evaluate Response @@ -1223,21 +1429,35 @@ sequence: ############################## - alias: "Parse response into variable" variables: - user_response: >- + user_response: >- {% set response = namespace(data={ 'payload': notification_data }) %} {% if not expect_response %} - {% set response.data = dict(response.data, **{ 'result': "no_response" }) %} - {% elif run_timeout_actions and wait.trigger == none %} - {% set response.data = dict(response.data, **{ 'result': "timeout" }) %} - {% elif run_timeout_actions and swipe_away_as_timeout and wait.trigger.event.event_type == 'mobile_app_notification_cleared' %} - {% set response.data = dict(response.data, **{ 'result': "notification_cleared" }) %} - {% elif wait.trigger.event.data.action == option_one['action'] %} - {% set response.data = dict(response.data, **{ 'result': "option_one" }) %} - {% elif wait.trigger.event.data.action == option_two['action'] %} - {% set response.data = dict(response.data, **{ 'result': "option_two" }) %} - {% elif wait.trigger.event.data.action == option_three['action'] %} - {% set response.data = dict(response.data, **{ 'result': "option_three" }) %} - {%- endif %} + {% set response.data = dict(response.data, **{ 'result': 'no_response' }) %} + {% elif wait.trigger == none %} + {% if run_timeout_actions %} + {% set response.data = dict(response.data, **{ 'result': 'timeout' }) %} + {% else %} + {% set response.data = dict(response.data, **{ 'result': 'no_response' }) %} + {% endif %} + {% elif wait.trigger.event is defined %} + {% if run_timeout_actions and swipe_away_as_timeout and wait.trigger.event.event_type == 'mobile_app_notification_cleared' %} + {% set response.data = dict(response.data, **{ 'result': 'notification_cleared' }) %} + {% elif wait.trigger.event.data is defined %} + {% if wait.trigger.event.data.action == option_one['action'] %} + {% set response.data = dict(response.data, **{ 'result': 'option_one' }) %} + {% elif wait.trigger.event.data.action == option_two['action'] %} + {% set response.data = dict(response.data, **{ 'result': 'option_two' }) %} + {% elif wait.trigger.event.data.action == option_three['action'] %} + {% set response.data = dict(response.data, **{ 'result': 'option_three' }) %} + {% else %} + {% set response.data = dict(response.data, **{ 'result': 'unknown_action' }) %} + {% endif %} + {% else %} + {% set response.data = dict(response.data, **{ 'result': 'invalid_event_data' }) %} + {% endif %} + {% else %} + {% set response.data = dict(response.data, **{ 'result': 'invalid_trigger' }) %} + {% endif %} {{ response.data }} ############################## @@ -1263,20 +1483,25 @@ sequence: sequence: !input option_three_action # "{{ option_three_actions }}" ############################## - # Compatibility: iOS Clear Notification + # Clear Notifications ############################## - - alias: "Send clear notification commands" + - alias: "Clear notifications" if: - - alias: "Should send clear notification command? (for iOS/macOS)?" - condition: template - value_template: "{{ expect_response and enable_timeout and clear_on_timeout and notification_data.apple_device }}" + - condition: template + value_template: > + {{ + (clear_on_response and user_response.result not in ['timeout', 'notification_cleared', 'no_response']) or + (expect_response and enable_timeout and clear_on_timeout) + }} then: - - alias: "Send clear notification command to iOS device" - service: "{{ notify_service }}" - data: - message: "clear_notification" - data: - tag: "{{ tag }}" + - repeat: + for_each: "{{ notify_service }}" + sequence: + - service: "{{ repeat.item }}" + data: + message: "clear_notification" + data: + tag: "{{ tag }}" ############################## # Return user response