Concatenate variable 1 with variable 2 (extracted from array)

I have the following variables.

variables:
  voice_assistant: " {{ trigger.device_id }} "
  media_player: " {{ device_entities(voice_assistant) }} "
  voice_assistant_device: " {{ (media_player) | regex_findall('media_player.*player') }} "
  test: " {{ expand(voice_assistant_device) | regex_findall('Small.*Player') | regex_replace(find='\\s', replace='_', ignorecase=True) | lower }} "
  test2: media_player.
  test3: " {{ (test2) ~ (test) }} "

Using this data in a trigger from device_id

test1: >-
  [<template TemplateState(<state
  media_player.home_assistant_voice_xxxxx_media_player=idle;
  volume_level=0.09999996, is_volume_muted=False, device_class=speaker,
  friendly_name=Small Bedroom assistant Media Player, supported_features=1200653
  @ 2025-01-07T13:43:16.295124+00:00>)>]

In particular I want to get the ‘test3’ variable to output to string value of ‘media_player.small_bedroom_assistant_media_player’

However I get the following:

test:
  - small_bedroom_assistant_media_player
test2: media_player.
test3: media_player.['small_bedroom_assistant_media_player']

Your input is very much appreciated.

test is a list out of the regex operation, hence the [...]. Try:

test3: "{{ test2 ~ test[0] }}"

Even better, use Jinja filters to extract the list item(s) you want from the expand operation rather than regex.

1 Like

@Troon thank you for providing a solution to my problem. I have now reported a bug as the above regex is a work around for the following problem I am experiencing (not sure if I should post it here):

FYI, all of this:

regex_replace(find='\\s', replace='_', ignorecase=True) | lower

Is performed by slugify.

I agree with Troon that your goal can be achieved, far more concisely, by using appropriate Jinja filters.

1 Like

@Troon thank you for pointing me back to Jinja filters. I did try to use this initially however I can never get a value returned using this method on the below output:

test1: >-
  [<template TemplateState(<state
  media_player.home_assistant_voice_xxxxx_media_player=idle;
  volume_level=0.09999996, is_volume_muted=False, device_class=speaker,
  friendly_name=Small Bedroom assistant Media Player, supported_features=1200653
  @ 2025-01-07T13:43:16.295124+00:00>)>]

I keep getting “undefined”,
<generator object do_map at …> or similar with select/ selectattr when trying to return the value in the “friendly_name” attribute which is why I turned to using regex. I presume it is possible with Jinja filters?

Again thank you for your help and input.

{{ test1[0]['attributes']['friendly_name'] }}

Your test1 variable is a one-item list containing a State object. As you can see here, friendly_name is an element of the attributes dictionary of a State object.

The result of your Jinja template is a list containing an entity object, but while these are possible to store in a Jinja variable, you cannot store them in a HASS variable. At the end of your Jinja template the final output must be a basic data type (dict, list, string, number, boolean, etc.).

If you try to return an entity object what you will actually end up with is a string. In fact all output from Jinja is only ever a string, but depending on what this string contains it may then be reinterpreted by HASS as other basic data types.

1 Like

When I try:

voice_assistant: " {{ trigger.device_id }} "
media_player: " {{ device_entities(voice_assistant) }} "
voice_assistant_device: " {{ (media_player) | regex_findall('media_player.*player') }} "
test1: " {{ expand(voice_assistant_device) }} "
testx: " {{ test1[0]['attributes']['friendly_name'] }} "

It fails to run the automation, no steps run and I get the following in the logs:

Error rendering variables: UndefinedError: 'str object' has no attribute 'attributes'

Going round in circles here, as you are generating strings not real objects. Explain what you’re trying to achieve.

You should be able to test this in Developer Tools / Template by substituting in the device ID of one of your media players rather than blindly running automations.

I already explained exactly what your problem is. You cannot store an entity object, as in the direct result of an expand() as you attempt to do for test1, in a HASS variable.

I have managed to achieve what I want . To have music assistant to play radio/ music from the device I request it from. The requesting device is the entity_id that Music Assistant derived it’s MediaPlayer entity from and is now using friendly name instead of entity_id with _2 appended. I have voice PE devices (media players).

Here’s a snippet of what is working:

variables:
  media_player_id: " {{ trigger.device_id }} "
  media_players: " {{ device_entities(media_player_id) | regex_findall('media_player.*player') }} "
  friendly_name: " {{ expand(media_players) | regex_findall('friendly_name=.+,') | regex_replace(find='friendly_name=', replace='')  }} "
  prepend: media_player.
  voice_assistant_device: " {{ prepend ~ (friendly_name[0]) | slugify}} "

An example of an action using the above:

- conditions:
          - condition: trigger
            id:
              - Magic FM
        sequence:
          - action: media_player.play_media
            target:
              entity_id: " {{ (voice_assistant_device) }} "
            data:
              media_content_id: library://radio/10
              media_content_type: music
            metadata:
              title: Magic FM London
              thumbnail: >-
                https://planetradio.co.uk/tesla/static/favicons/magic/apple-touch-icon.png
              media_class: music
              children_media_class: null
              navigateIds:
                - {}
                - media_content_type: music_assistant
                  media_content_id: radio

It was working before as music assistant used to appended _2 to the media player entity_id for it’s own use.

So I did this before “friendly name” was used:

trigger: conversation
command:
  - "[Clay] [Play] [Plays] Classic [FM]"
id: Play Classic F-M
variables:
  voice_assistant: " {{ trigger.device_id }} "
  voice_assistant_mediaplayer2: " {{ device_entities(voice_assistant) | regex_replace(find='_media_player', replace='_media_player_2', ignorecase=False) }} "
  voice_assistant_device: " {{ (voice_assistant_mediaplayer2) | regex_findall('media_player.h.*_2') }} "

but it seems it has now changed to friendly name instead.

As always thank you all for your input.

Glad you’ve fixed it, but it still seems wrong to be using regex operations that turn a data structure into a string, then trying to force it back again. If you’re up for experimentation, try this in the Template Editor with your own device ID and requirements for the entity ID pattern:

Hard-coding a device ID: get this from the URL of the device page:
{% set media_player_id = "ea986a7eb43bd2317ea442b202ce63a1" %}
{{ media_player_id }}

Get a list of all entity IDs associated with that device that start with
"media player" and end with "room"; get the first such entry:
{% set media_player = device_entities(media_player_id)
                      |select('search','^media_player\..*room$')|first %}
{{ media_player }}

That is the entity ID done, now pull the friendly name
assuming that is still required:
{% set friendly_name = states[media_player]['attributes']['friendly_name'] %}
{{ friendly_name }}

1 Like

I have now changed my variables to the following:

variables:
  media_player_id: " {{ trigger.device_id }} "
  media_player: " {{ device_entities(media_player_id) |select('search','^media_player.*player')|first }} "
  friendly_name: " {{ states[media_player]['attributes']['friendly_name'] }} "
  prepend: media_player.
  voice_assistant_device: " {{ prepend ~ (friendly_name) | slugify}} "

This what I was trying to do at first but was unsure of syntax. But good for comparison to put both methods in this topic. Thank you.

1 Like