I’m trying to get a script built. I want to check if a variable exist and include it if it does. Just really struggling to figure out the formatting. Something like

script:
  sequence:
    target:
      entity_id: "{{ entity }}"
    {% if variable is defined %}
      data: "{{ variable }}"
    {% endif %}
  • Otkaz@lemmy.worldOP
    link
    fedilink
    English
    arrow-up
    2
    ·
    10 months ago

    Is it possible to do this in a way that completely omits data: from the command if the variable isn’t defined?

    • bob_wiley@lemmy.world
      link
      fedilink
      English
      arrow-up
      2
      ·
      edit-2
      10 months ago

      You can see if jinja filters work. Ansible has a bunch, but I’m not sure if it’s an Ansible thing or some of it is native to jinja. I know Ansible defines a lot of custom ones.

      Assuming it works, for what you’re doing it could be simplified to…

      script:
        sequence:
          target:
            entity_id: "{{ entity }}"
            data: "{{ variable | default(omit) }}"
      

      This basically says for data, use {{ variable }}, unless it doesn’t exist, in which case omit data. Omit could also be replaced with some another variable or static string (quoted) to use that as a default if {{ variable }} doesn’t exist.

      I tried quickly looking on the Home Assistant site to see if this would work and didn’t see anything, but if it’s anything like Ansible, the documentation leaves a lot of room for finding stuff through experience and leaning on other resources. I’d say try it and see what happens. That’s probably the fastest way to know if it will work.

      Depending on what data does here, you might be able to just add an else condition to set it to a blank string. That works better in some cases than others. I’m not sure if there is an “official” way to do this, but {{- '' -}} seems to work for me. I usually add those extra minus signs on everything when using jinja to avoid issues with extra spaces (those trim white space). If you don’t want to go the empty string route, or it doesn’t play well, you might be able to try NONE as well, as mentioned here.

      • Otkaz@lemmy.worldOP
        link
        fedilink
        English
        arrow-up
        1
        ·
        10 months ago

        It worked the same as your suggestion above. In cases the variable is used it does works as intended but in the situation the variable is not set it’s still sending data: just with a blank value.

        • bob_wiley@lemmy.world
          link
          fedilink
          English
          arrow-up
          1
          ·
          10 months ago

          hmm… It looks like default is a built-in jinja filter, either omit isn’t a built in option (which would make sense), or Home Assistant doesn’t play nice with it, or doesn’t support it. I’m guessing it’s a special Ansible add-on, as it requires the jinja to impact the yaml outside it (and there is also some artifacts I’ve seen that lend to that happening as well).

          https://jinja.palletsprojects.com/en/latest/templates/#jinja-filters.default

          Maybe you can refactor things a bit to only run this sequence when the variable exists?

          It looks like there are conditionals that can be added. I’m not sure if this will work for your specific use case or not, but it’s worth looking into if you haven’t already.

          https://www.home-assistant.io/docs/scripts/conditions/

          • Otkaz@lemmy.worldOP
            link
            fedilink
            English
            arrow-up
            1
            ·
            10 months ago

            When I tried playing with omit in the template editor I got an error about omit being undefined so probably not built in. Bummer because that would be a very elegant solution to this. I’m going to put this down for the night and try picking it back up tomorrow. I really appreciate all the suggestions. Hopefully it will lead me to a solution.

            • bob_wiley@lemmy.world
              link
              fedilink
              English
              arrow-up
              1
              ·
              10 months ago

              I looked at all the comments after I posted this and saw your full code. The suggestion I put there isn’t as nice as default(omit), but still probably much better than trying to go with this conditional route, which will probably increase code instead of reducing it. I think that should solve your problem. I didn’t really think about building the entire data payload on the fly until seeing your post, but it makes sense as a solution.

    • Otkaz@lemmy.worldOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      edit-2
      10 months ago

      To give more context I’m working on a media control dashboard. The script or rather scripts I have to send commands to kodi is as follows

      kodi_control:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data:
            method: '{{ kodi_method }}'
      
      kodi_control_playback:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data:
            method: '{{ kodi_method }}'
            playerid: '{{ kodi_playerid }}'
      
      kodi_control_subtitles:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data:
            method: '{{ kodi_method }}'
            action: '{{ kodi_action }}'
      
      kodi_control_seek:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data:
            method: '{{ kodi_method }}'
            playerid: '{{ kodi_playerid }}'
            value: '{{ kodi_value }}'
      
      kodi_control_playlist:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data:
            method: '{{ kodi_method }}'
            window: '{{ kodi_window }}'
            parameters: '{{ [ kodi_parameters ] }}'
      

      I would like to condense all of this down to a single script using “is defined” to omit the parts not needed for certain commands so something like

      kodi_control:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data: >-
            method: '{{ kodi_method }}'
            {% if kodi_playerid is defined %}
              playerid: '{{ kodi_playerid }}'
            {% endif %}
            {% if kodi_action is defined %}
              action: '{{ kodi_action }}'
            {% endif %}
            {% if kodi_value is defined %}
              value: '{{ kodi_value }}'
            {% endif %}
            {% if kodi_window is defined %}
              window: '{{ kodi_window }}'
            {% endif %}
            {% if kodi_parameters is defined %}
              parameters: '{{ [ kodi_parameters ] }}'
            {% endif %}
      

      Problem with the above is I get “result is not a dictionary”

      • bob_wiley@lemmy.world
        link
        fedilink
        English
        arrow-up
        3
        ·
        10 months ago

        Ok, I think I got you. With your current setup, you’re not going to get the proper data structure, as it’s going to return all your key/value pairs as one big string. What you need to do here is create your empty dictionary, then add the key/value pairs, based on your logic, then return the resulting dictionary at the end.

        Something like this…

        kodi_control:
        sequence:
        - service: kodi.call_method
          target:
            entity_id: '{{ kodi_entity }}'
          data: >-
            {% set my_dict = {} %}
            {% set x=my_dict.__setitem__("method", {{ kodi_method }}) %}
            {% if kodi_playerid is defined %}
              {% set x=my_dict.__setitem__("playerid", {{ kodi_playerid }}) %}
            {% endif %}
            {% if kodi_action is defined %}
              {% set x=my_dict.__setitem__("action", {{ kodi_action }}) %}
            {% endif %}
            {% if kodi_value is defined %}
              {% set x=my_dict.__setitem__("value", {{ kodi_value }}) %}
            {% endif %}
            {% if kodi_window is defined %}
              {% set x=my_dict.__setitem__("window", {{ kodi_window }}) %}
            {% endif %}
            {% if kodi_parameters is defined %}
              {% set x=my_dict.__setitem__("parameters", {{ [ kodi_parameters ] }}) %}
            {% endif %}
            {{ my_dict }}