How do I do more than one regex_replace on the trigger payload in a define variable

I have 13 possible, different triggers, that will turn on and off integrations through Spook. And I’d like to use only one automation instead of 26 for that. I’m using a persistent notification to see if I get it right. So I need to define a variable based on the trigger payload. For one of them it’s easy:

  - variables:
      integration: >-
        {{ trigger.payload | regex_replace(find='7',
        replace='01JNRRGVEJH5Z5MD54YVTW2XV7') }
  - action: notify.persistent_notification
    data:
      title: "{{ now() | as_local }}"
      message: |-
        Integration: {{ integration }} 
        Zone: {{ trigger.payload }}

Then I get the integration ID in the persistent notification. The problem comes when I want to expand that to two, and I’m sure it’s just that I don’t know the correct syntax to it:

  - variables:
      integration: >-
        {{ trigger.payload | regex_replace(find='7',
        replace='01JNRRGVEJH5Z5MD54YVTW2XV7') }} {{ trigger.payload |
        regex_replace(find='8', replace='01JNRRJX6QAZWM1A1RXAAR8EXQ') }}
  - action: notify.persistent_notification
    data:
      title: "{{ now() | as_local }}"
      message: |-
        Integrasjon: {{ integration }} 
        Zone: {{ trigger.payload }}

What I want is for the variable integration to be 01JNRRGVEJH5Z5MD54YVTW2XV7 if the trigger payload is 7 and the same varible to be 01JNRRJX6QAZWM1A1RXAAR8EXQ if the trigger payload is 8. Then I’ll expand that to all the available integration ID’s for all the 13 zones. Can somebody please help me with that?

Maybe I’m missing something here but why does it need to be regex?
If the input is just numbers as 7 or 8 then a simpler method is probably to create a lookup table.

{% set t = {7:'01JNRRGVEJH5Z5MD54YVTW2XV7',
            8:'01JNRRJX6QAZWM1A1RXAAR8EXQ' } %}

{{ t[trigger.payload] }}

Thank you for answering! You’re not missing anything, I would think. I’m the one missing something, a grasp on what I’m doing… So how do I implement that one? I have found a post you made about the ability to use tables in macros, but I doubt that’s the correct answer. I tried to shoehorn it into a set variable action, but failed misreably. Maybe because my indentation was wrong, maybe because that’s not how it is to be used?

Using your example this should work…

- variables:
      integration: >-
        {% set t = {7:'01JNRRGVEJH5Z5MD54YVTW2XV7',
                    8:'01JNRRJX6QAZWM1A1RXAAR8EXQ' } %}

        {{ t[trigger.payload] }}
  - action: notify.persistent_notification
    data:
      title: "{{ now() | as_local }}"
      message: |-
        Integrasjon: {{ integration }} 
        Zone: {{ trigger.payload }}

You could use a macro but I doubt that will help in this case.
As I understand it, you are just using the code here. Macro is for when you use the same code at several places.

Thank you again! The code was not working, but I actually understood why: The digits 1-13 from the payload were strings, not integers, which means that a table lookup won’t work. So I added another variable, sonenummer (zone number) like this:

sonenummer: "{{ trigger.payload | int(0) }}"

And then changed the last line to:

{{ t[sonenummer] }}

And now it works! Thanks again! Now I only have to modify it to do all the 13 zones, but that’s just labour without thinking. :grin:

Great!

You could have done this also:

- variables:
      integration: >-
        {% set t = {7:'01JNRRGVEJH5Z5MD54YVTW2XV7',
                    8:'01JNRRJX6QAZWM1A1RXAAR8EXQ' } %}

        {{ t[trigger.payload | int ] }}
  - action: notify.persistent_notification
    data:
      title: "{{ now() | as_local }}"
      message: |-
        Integrasjon: {{ integration }} 
        Zone: {{ trigger.payload }}

I should have known it was a string…

1 Like

That works too, thanks! And how could you know it was a string? I didn’t, until I saw that the table didn’t work. I could probably set it to be an integer in the sending end, but that code is old and 100 % stable, so I don’t mess with it if I don’t really, really have to.

States are strings in HA.
Trigger variables are probably based on the state, that’s my reasoning.

Two minor comments.

I suspect you know that you don’t have to use templates there:

  - variables:
      payload: "{{ trigger.payload }}"
      integration_map:
        "7": 01JNRRGVEJH5Z5MD54YVTW2XV7
        "8": 01JNRRJX6QAZWM1A1RXAAR8EXQ
      integration_id: "{{ integration_map[payload] }}"

And second, have you considered using config_entry_id('media_player.foo') instead of hard-coding config entry IDs? I also use Spook to disable/enable an integration and it’s nice to have a more human-readable name in the automation.

Actually I didn’t know that. But it does work. :slight_smile: As for the readable name, I didn’t think that was possible. I just went from choosing the integration for each zone and going from UI to YAML edit to get the entry ID. I did not know how to get the integration name for this integration. Do you maybe know? Then I don’t need the table or anything, I can just template the name of the integration being activated and deactivated.

It’s not the media_player.foo, btw. I stopped useing that because it was not possible to deactivate. It does not have a unique ID, and the integration doesn’t support adding one either. So with that I would have 13 zones of foo trying to contact Foobar instances that weren’t running. With Scrape I can activate just the zone that’s running at any given time, if any.

I’m not quite sure what “each zone” is there. An integration doesn’t really have an ID, an integration is one or more config entries (e.g. some integration can have more than one “hub”). I assume those hex values you have are from a URL that might look like this:

http://homeassistant.local:8123/config/zwave_js/dashboard?config_entry=01JGZBEPYVGAQKW6FFYBG0WX9M

I have a door deadbolt/lock entity on that hub and I can get its config entry ID by using the entity name:

{{ config_entry_id('lock.front_door_deadbolt') }} 

Returns: 01JGZBEPYVGAQKW6FFYBG0WX9M

I have other zwave devices on another hub:

{{ config_entry_id('switch.coffee_maker') }}

Returns: f890ca897acc7ae3dcf39ceca9103a35

Differnt config entry IDs, but same z-wave integration.

If you want to get the hub’s name you can do this (for my example above):

{{ config_entry_attr(config_entry_id('switch.coffee_maker'),'title') }} = Z-Wave JS Main

I’m not sure what you are trying to do, but this is just showing how to get those IDs from more human-friendly entity names (entity_ids).

In my case I have an integration that fills my logs with messages, and I only rarely use it, so I use Spook to disable that config entry when not in use, and I use config_entry_id() to look it up.

Link to config_entry_id() docs:

I guess I need to explain a bit better, yeah.

A zone is one instance of Foobar, with it’s own designated number from 1-13 for calling them from different sources, like IR remotes, webpage and automations. They are playing to their own sound card on the server, that goes to it’s own amplifier. I have room for all those sound cards in my server because I use the Sound Blaster Audigy cards with the kX drivers that make every card three addressable cards through three mini jacks. So five physical cards gives me 15 zones.

You mentioned media_player.foo, which I understood as the integration for Foobar. That integration is quite old and doesn’t support being turned off from the UI or Spook, when you try it says it can’t be done because it doesn’t have it’s own ID.

Now SCRAPE, which I am using to get info from the Foobar instances works like this:

  1. You set up a ressource, in my case 13 instances with the URL’s from (http://192.168.1.4:8881/default) and up to http://192.168.1.4:8893/default for zone 1-13.
  2. You create sensors on those ressources. In my case Title and Artist for each of them. So all in all 26 sensors for zone 1-13.

The problem is that even if I disable the sensors, which are entities, the ressource will still be constantly trying to contact Foobar (which is not running when the zone is not playing), filling the log with errors.

Disabling the sensors/entities does not stop these constant attempts of polling. The parent integration/ressource must be disabled to avoid that. They are not really integrations in the correct usage of that word within Hass. The integration is still SCRAPE, but Spook sees the ressources as separate integrations, and disabling those is what I use to stop the polling.

Again, if it was possible to find the human readable form of the name and use that, it would be great. But since the ressources are not accessible through entities or anywhere else I can find them, I’m stuck with the hardcoded ID’s. If it is possible to go from ID to name, I haven’t found out how.

Haha. When I wrote media_player.foo I was just making up a name – didn’t realized the actual integration was named “foobar”. :wink:

And what is SCRAPE? Something for scraping web pages?

I don’t see how you can have an integration configured in HA and not have a config entry. But maybe that’s some old legacy stuff I’m not familar with.

Exactly. That was my issue.

Seems like that integration should have just connect to one port and support multiple (the 13) devices? I think that’s a more common way to go. Then you just have one config entry to disable. But, I digress.

What does the integration page look like?

I’m sorry, I don’t really follow that. My original post was you can use entity_ids to look up the config entry that entty belongs to and then send that to Spook to enable/disable it. Just to make it more human friendly (and if the config entry ID ever changes if you remove and re-add it).

If the entity ids had a similar naming convention you could also find those by looking at all sensors and then mappying those to the config entry and then passing that to Spook. Right?

The Scrape is a service to scrape info from a web page, yeah. And Foobar (which has been around for ages, I’m 60, and I remember it back to the early 2000’s) is the Foobar2000 media player. :slight_smile: As for the integration for it, yeah, it’s old.

No, the integration needs to connect to 13 different ports, one for each instance of Foobar2000. It is not a multi-zone media player, it’s a portble install media player that can be installed (or copied, rather) several times to the same computer, and the scrape works as long as each has it’s own port, hence ports from 8881 to 8893.

Here’s the integration, I have on purpose enabled one of the instances when Foobar isn’t running:

The problem with the naming is that I can’t find the naming convention for it. I have no idea what the ressources are named, which could for instance be scrape.foobar_sone_8 but isn’t, I only know what the ID for each of them is.

Ok. I’m UTC-8 so a bit slow first thing… But, I’m curious.

Foobar isn’t a typical integration where it has a page like the one you showed for Scrape. It’s just creating media entities. And it’s Scrape you want to disable, right, not Foobar? Scrap is the integration that is generating errors when one or more of your Foobar2000 instances are not running.

And what exactly is triggering the automation?

Right, you have to disable the Scrape config entry, not the associated entities.

In your image for Scrape it has multiple config entries, “Foobar some 7”, “Foobar some 1”, etc. correct? And when you click on the cog you can see each related config_entry id.

And each config_entry has two sensors that you are scraping. And the idea is when something happens to one of those you disable the associated Scrape entry?

When Scrape can’t, eh, scrape a web page does its entities change to “unavailable” or “unknown”?

Actually Foobar isn’t creating anything at all in Home Assistant. Foobar is running on a separate computer (with IP 192.168.1.4), creating the webpages with the playback info that Scrape reads. I can’t disable scrape itself, I have to disable all the ressources independantly, so when one zone starts playing that scrape ressource is activated, not all of them. The activation/deactication is triggered by an MQTT message that is sent by the Windows program on the server that starts and stops the Foobar instances.

When Scrape can’t scrape, the entities change to unavailable, but the ressource still keeps polling and polling and polling. So the way I’m doing it is the only possible way, as far as I can see.

In general, I’d trigger on the entity_id becoming unavailable and then look up the config_entry for that entity.

No time to test. I set Scrape up via configuration.yaml but then this returns null:

{{ config_entry_id('sensor.my_foo') }}

Later I’ll set it up via the UI and play a bit.

Thanks a lot, but you are overthinking this. :slight_smile: I have it the way I want it, and I need to use the MQTT to start it up. Then I have template timer that polls for changes every ten seconds. So no need to spend any time on that.

Edit: The Scrape sensor keeps polling even if you don’t set it to poll every ten seconds like my template timer does. So the only way to actually stop it is to deactivate the ressource. And with the ressource deactivated it of course can’t see if the sensor becomes available again. So the way I’m doing it now with the table is more than good enough for me. :slight_smile:

That’s self-inflicted, and on purpose. At somewhat your expense… Sorry about that. :wink:

Not sure if you mentioned which logs, but Scrape does spit out a bit in the HA logs if the resource isn’t available. Maybe Scrape is the real problem?

I have a few scripts that I run from automations that do stuff (like grep something) and then update sensors. One of many ways…

curl -s \
  -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"state": "unavailable", "attributes": {"some_attribute": "Something here", "friendly_name": "This Shell Sensor"}}' \
  http://localhost:8123/api/states/sensor.my_shell_sensor

Well, I think I will stick with what I have now, thanks! It just works. Without those nasty entries in the main log. :+1: