Can I use if/else with webhooks in automations?

I have created a setup for my daugther where she can play songs on a Sonos speaker with NFC-cards. The cards has a NFC-chip which contains an URL (An example is 192.168.1.30:8123/api/webhook/BeastieBoysSabotage) which is fired when she scans the card on a NFC-terminal (a Raspberry Pi with a PN532 hat) in her room.

This is my current Automation in Home Assistant / Automations (which works)

alias: Webhook, Beastie Boys - Sabotage
description: ''
trigger:
  - platform: webhook
    webhook_id: BeastieBoysSabotage
condition: []
action:
  - service: media_player.play_media
    target:
      device_id: f1c8ea9e94a80657684c473370632d59
    data:
      media_content_type: music
      media_content_id: spotify:track:0Puj4YlTm6xNzDDADXHMI9
mode: restart

Now I want to add another NFC-terminal next to another speaker in my sons room. And since I have more than 150 cards with different songs I want them to be able to use the same cards (but when my daugther use the card on her terminal it is played in her room and when my son use it on his it is played on his speaker)

I have made a small chance in the new NFC-terminal, so that it always adds a small suffix, Peter, to all webhooks, so that the same card fires either BeastieBoysSabotage or BeastieBoysSabotagePeter depending on which terminal I use.

That way I can just create two automations for all my music cards… But I would really prefer if it was possible to just create one automation for each card that activates one speaker if the first webhook is triggered and another if the second is fired. And it leaves me with the question:

Can I use if/else with webhooks in automations?

As far as I can see in this page Script Syntax - Home Assistant it is possible to use some kind of if/else logic. But when I try to change the example from that page it leaves me with the error: “Message malformed: expected dictionary”

This is what I tried to do:

# Example with "if" and "else"
- trigger:
    - platform: webhook
      id: BeastieBoysSabotage
    - platform: webhook
      id: BeastieBoysSabotagePeter
  mode: queued
  action:
    - alias: "Play on Speaker 1"
      choose:
        # IF motion detected
        - alias: "trigger 1"
          condition: trigger
          id: BeastieBoysSabotage
          sequence:
            - service: media_player.play_media
              target:
                    device_id: f1c8ea9e94a80657684c473370632d59
              data:
                media_content_type: music
                media_content_id: spotify:track:3lGSvaRpO8Y7B8hwQYWRbH
      # ELSE (i.e., motion stopped)
      default:
        - service: media_player.play_media
          target:
            device_id: cac231c4a669630fc2f521484e87e4f3
          data:
            media_content_type: music
            media_content_id: spotify:track:3lGSvaRpO8Y7B8hwQYWRbH

Is there any possibility of re-engineering the system to work with the Tag Trigger? It’s a bit more flexible, and informative, than a Webhook Trigger.

If that’s too much work then perhaps this will do what you want with a Webhook Trigger.

alias: Webhook, Beastie Boys - Sabotage
description: ''
trigger:
  - platform: webhook
    webhook_id: BeastieBoysSabotage
  - platform: webhook
    webhook_id: BeastieBoysSabotagePeter
condition: []
action:
  - service: media_player.play_media
    target:
      device_id: "{{ 'cac231c4a669630fc2f521484e87e4f3' if trigger.webhook_id[-5:] == 'Peter' else 'f1c8ea9e94a80657684c473370632d59' }}"
    data:
      media_content_type: music
      media_content_id: spotify:track:0Puj4YlTm6xNzDDADXHMI9
mode: restart
1 Like

A version capable of handling multiple songs:

alias: Example
description: ''
trigger:
  - platform: webhook
    webhook_id: BeastieBoysSabotage
  - platform: webhook
    webhook_id: BeastieBoysSabotagePeter
  - platform: webhook
    webhook_id: SomebodySomething
  - platform: webhook
    webhook_id: SomebodySomethingPeter
  - platform: webhook
    webhook_id: WhateverAnotherSong
  - platform: webhook
    webhook_id: WhateverAnotherSongPeter
condition: []
action:
  - variables:
      songs: {'BeastieBoysSabotage': '0Puj4YlTm6xNzDDADXHMI9', 'SomebodySomething': '9YhjDol8m6x5zZzAoXHpkgIi', 'WhateverAnotherSong': 'kF5j7Gtsm6xsg2BAoXHpkuFe' }
  - service: media_player.play_media
    target:
      device_id: "{{ 'cac231c4a669630fc2f521484e87e4f3' if trigger.webhook_id[-5:] == 'Peter' else 'f1c8ea9e94a80657684c473370632d59' }}"
    data:
      media_content_type: music
      media_content_id: "spotify:track:{{ songs.get(trigger.webhook_id.replace('Peter', ''), '0Puj4YlTm6xNzDDADXHMI9') }}"
mode: restart

Its as simple as that - it works! Thanks alot.

I am trying to learn as I go along and when I see what you have done, it all makes sense. But I cant figure out why the id is -5? in this line:

device_id: “{{ ‘cac231c4a669630fc2f521484e87e4f3’ if trigger.webhook_id[-5:] == ‘Peter’ else ‘f1c8ea9e94a80657684c473370632d59’ }}”

trigger.webhook_id is a string. When you use List/Array looking syntax on a string, it gives a substring. So the [-5:] actually gets the substring starting 5 characters from the end (the -5) all the way to the end of the string ( the : with nothing after it).

This also means if you have a tag called “ASongForPeter” then this won’t work as expected for the person that isn’t peter. Instead it’ll try to play the tag “ASongFor” for the Peter device. But, without making bigger changes to your tag reading code (as @123 suggested) then this is the best solution.

1 Like

@123 Taras

I was reading into using tags instead of webhooks and decided to order a adonno tagreader to replace my own raspberry pi/nfcpy setup.

So now I am just a bit curious what your idea of a good setup was, when you suggested that I re-engineered the system to work with tags?

It is definitly easier to create the tags from the phone app than using NFC Tools to create webhooks. But my poor imagination has left me with an automation that looks a lot like the one you helped me create for webhooks.

What I did was just altering the code you provided me with a few weeks ago. Its working, but since I am about to change +150 automations with webhooks, I want the new automations to be as smart as possible now instead of changing them again later :slight_smile:

alias: Tag, Beastie Boys - Sabotage
description: ''
trigger:
  - platform: tag
    tag_id: beastieboyssabotage
    device_id: b02dd2642e1e9964e28ecb180c1a0ed6
  - platform: tag
    tag_id: beastieboyssabotage
    device_id: d50e848dfc8d5380ca41ca2b61a22013
condition: []
action:
  - service: media_player.play_media
    target:
      device_id: >-
        {{ 'cac231c4a669630fc2f521484e87e4f3' if trigger.event.data.device_id ==
        'b02dd2642e1e9964e28ecb180c1a0ed6' else 'f1c8ea9e94a80657684c473370632d59' }}
    data:
      media_content_type: music
      media_content_id: spotify:track:0Puj4YlTm6xNzDDADXHMI9
mode: restart

… I guess what you meant was something like the jukebox suggested in this thread - Home Assistant Tags

A hell of a lot easier to have all songs in one automation compared to my setup with +150 individual automations :slight_smile:

This simple setup works for me!

alias: Den kæmpestore sangbog
description: ''
variables:
  media_players:
    d50e848dfc8d5380ca41ca2b61a22013: media_player.nanna
    b02dd2642e1e9964e288cb180c1a0ed6: media_player.peter
  tags:
    beastieboyssabotage:
      media_content_id: spotify:track:0Puj4YlTm6xNzDDADXHMI9
      media_content_type: music
    adelehello:
      media_content_id: spotify:track:1Yk0cQdMLx5RzzFTYwmuld
      media_content_type: music
trigger:
  - platform: event
    event_type: tag_scanned
condition:
  - condition: template
    value_template: '{{ trigger.event.data.tag_id in tags }}'
  - condition: template
    value_template: '{{ trigger.event.data.device_id in media_players }}'
action:
  - variables:
      media_player_entity_id: '{{ media_players[trigger.event.data.device_id] }}'
      media_content_id: '{{ tags[trigger.event.data.tag_id].media_content_id }}'
      media_content_type: '{{ tags[trigger.event.data.tag_id].media_content_type }}'
  - service: media_player.play_media
    data:
      entity_id: '{{ media_player_entity_id }}'
      media_content_id: '{{ media_content_id }}'
      media_content_type: '{{ media_content_type }}'
mode: single

Yes, that’s why I had inquired if it was possible for you to re-engineer your system to use tags. Glad to hear you did and can now take advantage of its simplicity.

1 Like