Passing variables with single and double quotes in scripts

Hi!

I’m having a little trouble passing special characters through a script. I’ve simplified the script for the sake of the question:


fields:
  words:
    selector:
      text:
        multiline: true
    description: The text to display on the Vestaboard
    required: true
    name: Message
sequence: 
        - action: vestaboard.message
          metadata: {}
          data:
            device_id: "xxxxxxxx"
            vbml:
              components: |-
                [
                  {               
                    "style": {
                      "justify": "center",
                      "align": "center",
                      "width": 5,
                      "height": 1
                    },
                    "template": "{{ words }}"
                  }                  
                ]

The problem I’m having is that that field “words” can have single and double quotes in the inputted text, and I need those passed into the JSON in the action. This scripts uses the HACS-Vestaboard integration, which if used directly has no issue with single or double quotes, so I’m fairly sure the problem is with my script, not the integration.

The script sends the text to a message board, but when I try to send a double quote the script throws an error because it is breaking the dictionary that vbml: expects.

Any ideas?

Thanks,
Seth

Anyone? I’ve tried different variations of passing the variable but I still can’t get all characters to pass.

Just as an experiment, see what happens if you escape the meaning of the double-quotes.

"template": "{{ \"test\" }}"

Why are you writing the value like that? The safer way to do it is either use as much YAML and little Jinja as possible, or you do it all with Jinja and let the templating engine worry about generating output with correct formatting. Don’t manually write a big string in the hope that HASS will be able to reinterpret it all correctly, that seldom works out well…

Pick one, not both:

components:
- style:
    justify: center
    align: center
    width: 5
    height: 1
  template: "{{ words }}"
components: >-
  {{
    [ {
      'style': {
        'justify': 'center',
        'align': 'center',
        'width': 5,
        'height': 1
      },
      'template': words
    } ]
  }}

I’m adding this pic for simplicity:

The Message box is where I want to be able to use double quotes.

Ok, so if I add the escape in the Message box, it works!

\“test\” → “test” on the board.

Now is there a way to change the script so the escaping is not necessary? Maybe a field setting that will auto escape any doublequotes?

I appreciate your help.

If I try the second format, I get this error:

Failed to perform the action script.vestaboard_message_with_options. expected a dictionary @ data['vbml']['components'][0]. Got None

I’m not able to use the first method due to a bunch of {% if %} script I removed to keep the question simple.

{               
                    "style": {
                      "justify": "center",
                      "align": "center",
                      "width": 5,
                      "height": 1
                    },
                    "template": "{{ words }}"
                  } 

This block gets repeated with different inputs and different conditions. So the full payload might need 3 or 4 of these blocks to build a message. Using yaml did not allow for adding blocks to components conditionally. At least not in a way I could figure out.

Here’s the actual script, with all the conditionals. Everything works except sending double quotes:

action: vestaboard.message
metadata: {}
data:
  device_id: "{{ repeat.item }}"
  vbml:
    props:
      text: "{{ words }}"
      date: "{{ as_timestamp(now())|timestamp_custom('%d') }}"
      month: "{{ as_timestamp(now())|timestamp_custom('%b') }}"
      hours: "{{ as_timestamp(now())|timestamp_custom('%H') }}"
      day: "{{ as_timestamp(now())|timestamp_custom('%A') }}"
      minutes: "{{ as_timestamp(now())|timestamp_custom('%M') }}"
      temp: "{{ states(temp_source) | int }}"
      temp_color: |-
        {% if states(temp_source) | int <= 32 %}
          {69}
        {% elif states(temp_source) | int <= 55 %}
          {67}
        {% elif states(temp_source) | int <= 75 %}
          {66}
        {% elif states(temp_source) | int <= 90 %}
          {65}
        {% else %}
          {63}
        {% endif %}
      alert_color: |-
        {% if alert == 'none' %}
          {0}
        {% elif alert == 'blue' %} 
          {67}
        {% elif alert == 'green' %} 
          {66}
        {% elif alert == 'yellow' %} 
          {65}
        {% elif alert == 'orange' %} 
          {64}
        {% elif alert == 'violet' %} 
          {68}
        {% elif alert == 'white' %} 
          {69}  
        {% else %}
          {63}
        {% endif %}
    components: |-
      [
        {
        {% if alert != 'none' %}
          "style": {
            "justify": "center",
            "align": "center",
            "width": 22,
            "height": 1
          },
          "template": "{{ '{{alert_color}}' * 22 }}"
        },
        {
          "style": {
            "justify": "center",
            "align": "center",
            "width": 1,
            "height": "{{ '3' if status_bar else '4' }}"
          },
          "template": "{{ ('{{alert_color}}' * 3) if status_bar else ('{{alert_color}}' * 4) }}"
        },
        {
        {% endif %}
        
          "style": {
            "justify": "center",
            "align": "center",
            "width": "{{ '20' if alert != 'none' else '22' }}",
            "height": "{% if alert != 'none' and status_bar %}3{% elif status_bar %}5{% elif alert != 'none' %}4{% else %}6{% endif %}"
          },
          "template": "{{ words }}"
        {% if alert != 'none' %}
        },
        {
          "style": {
            "justify": "center",
            "align": "center",
            "width": 1,
            "height": "{{ '3' if status_bar else '4' }}"
          },
          "template": "{{ ('{{alert_color}}' * 3) if status_bar else ('{{alert_color}}' * 4) }}"
        },
        {
          "style": {
            "justify": "center",
            "align": "center",
            "width": 22,
            "height": 1
          },
          "template": "{{ '{{alert_color}}' * 22 }}"
        {% endif %}
        {% if status_bar %}
        },
        {
          "style": {
            "justify": "left",
            "align": "center",
            "width": 5,
            "height": 1
          },
          "template": "{{ '{{date}}{{month}}' }}"
        },
        {
          "style": {
            "justify": "center",
            "align": "center",
            "width": 12,
            "height": 1
          },
          "template": "{{ '{{day}}' }}"
        },
        {
          "style": {
            "justify": "right",
            "align": "center",
            "width": 5,
            "height": 1
          },
          "template": "{{ '{{temp}}{62}{{temp_color}}' }}"
        {% endif %}
        }
        
        ]

Now modify the following line in your script and test it.

"template": "{{ words | replace('"', '\\"') }}"

(The double backslash is intentional.)

That was it. Thank you, Taras, once again.

1 Like

You’re welcome!

Please consider marking my post above with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic has been resolved. This helps users find answers to similar questions.

For more information about the Solution tag, refer to guideline 21 in the FAQ.

I’ve used this in a blueprint as well

1 Like