Using a button card parameter to select a script entity by id

I am having a hard time understanding how to mix jinja and yaml.
To reduce code duplication, I started what I thought was a simple script that could toggle poe on a number of ports on several network switches. I am using this button

type: button
entity: switch.poeswitch13_p10
name: POE switch 13 port 10
show_state: true
tap_action:
  action: call-service
  perform_action: script.poe_switchport_toggle
  service_data:
    id_switch: 13
    port: 10

with this script

poe_switchport_toggle:
  description: "Turn poe on or off on a specific switch and port"
  fields:
    id_switch:
      description: "poe switch id"
      example: "13"
    port:
      description: "poe switch port"
      example: "10"
  sequence:
    - action: >
        {% if states.switch.poeswitch{{ id_switch }}_p{{ port }}.state == "on" %}
          switch.turn_off
        {% else %}
          switch.turn_on
        {% endif %}
      target:
        entity_id: switch.poeswitch{{ id_switch }}_p{{ port }}

which does not compile due to

{% if states.switch.poeswitch{{ id_switch }}_p{{ port }}.state == "on" %}

which I have to replace with fixed values

{% if states.switch.poeswitch13_p10.state == "on" %}

to make it work for one specific port, which of course defeats the purpose. The final

entity_id: switch.poeswitch{{ id_switch }}_p{{ port }}

works fine, though.

I know I could use

action: switch.toggle

but do not wish to do so as a. I want to understand parameters better and b. I am not sure if it covers an ‘undefined’ entity state.

Anyway - is it possible to construct entity names inside scripts?
Alternatively, could I use an ‘oldstate’ parameter that looks something like

service_data:
  oldstate: {{ this.state }}

in the button card?

Don’t nest template delimiters inside other delimiters, just use the variables inside the statement delimiters {% %}.

Yes. When using the state object method (which is not necessary in this case and is not preferred) you would need to switch to bracket notation to construct the entity ID:

{% if states.switch[ 'poeswitch'~ id_switch ~'_p'~ port ].state == "on" %}

Using the one of the states() functions is preferred.

In this case you need the entity ID in multiple places, so it is best to concatenate the entity ID string into a script variable:

...
  sequence:
    - variables:
        ent: "switch.poeswitch{{ id_switch }}_p{{port}}"
    - action: "switch.turn_{{ 'off' if is_state(ent, 'on') else 'on' }}"
      target:
        entity_id: "{{ ent }}"

Few cards support Jinja templates, and almost none support them in card actions.

1 Like

Thank you for answering all my questions! This is what I consider a high-quality response