#Getting entities from a script field

1 messages · Page 1 of 1 (latest)

shy violet
#

Hey folks!

I have a script that has a field like this:

  target:
    name: Target
    required: true
    selector:
      target:
        entity:
          domain: media_player

The UI allows people to select zero or more media player entities, devices, areas and labels, and as a result the target dictionary will contain keys like device_id, area_id, label_id and entity_id, each of which will have either a string value (if only one of those items was selected) or a list value (if multiple of those items was selected).

So this already presents the interesting challenge of having to detect if the values are strings or lists, but on top of that, since what I ultimately need is a list of the appropriate entity IDs, I have to process the devices/areas/labels to turn them into entity IDs.

I have some code which does this all, but when I look at it, I can't help but suspect I have missed some magic helper that could do all of this for me:

  - variables:
      expanded_targets: >
        {# Create the namespace object we'll use to store all our working data #}
        {% set data = namespace(expanded_targets=[]) %}
        
        {# Declare two helper macros #}
        {% macro m_listifyIfNot(someValue, returns) %}
        {%   if someValue is list %}
        {%     do returns(someValue) %}
        {%   else %}
        {%     do returns([someValue]) %}
        {%   endif %}
        {% endmacro %}
        {% macro m_noop(someValue, returns) %}
        {%   do returns(someValue) %}
        {% endmacro %}
        
        {# Declare our helper macros as functions, so they can return values #}
        {% set f_listifyIfNot = m_listifyIfNot | as_function %}
        {% set f_noop         = m_noop | as_function %}
        
        {# Iterate our input dictionary #}
        {% for value in target %}
        
        {#   Store a function pointer we'll use to turn the input value into a list of entities #}
        {%   if value == "device_id" %}
        {%     set f_getEntities = device_entities %}
        {%   elif value == "area_id" %}
        {%     set f_getEntities = area_entities %}
        {%   elif value == "label_id" %}
        {%     set f_getEntities = label_entities %}
        {%   elif value == "entity_id" %}
        {%     set f_getEntities = f_noop %}
        {%   else %}
        {#     This should never be hit #}
        {%     set f_getEntities = none %}
        {%   endif %}
        
        {#   Ensure the input value is a list. It will be a string if only one value is supplied #}
        {%   set listifiedValues = f_listifyIfNot(target[value]) %}
        
        {#   Iterate the input list and use our function pointer to expand it to a list of entities, and filter out anything that isn't a media_player #}
        {%   for entry in listifiedValues %}
        {%     set data.expanded_targets = data.expanded_targets + expand(f_getEntities(entry)) | map(attribute="entity_id") | select("match", "media_player") | list %}
        {%   endfor %}
        
        {% endfor %}

        {# Output our working data, limited to unique entities, into the script variable #}
        {{ data.expanded_targets | unique | list }}

Is there such a thing?

spiral fiber
#

I don't think there is such a thing, you need to do it like you're doing above

#

The only thing you are missing (which is an edge case, and will only happen in case the GUI is not used) is that targets are allowed to be provided as a comma separated string

target: 
  entity_id: media_player.player1, media_player.player2
shy violet
#

interesting, thanks! I plan on only using the UI, but at this point I may as well add support for that too 😄

#

I suppose my next question would be whether I can externalise all of that into its own file so I can include it in other scripts?

spiral fiber
#

Yes, 2 ways.
Either use a script which supplies it as an action response (using the stop action)
Or as a macro using custom_templates