Jinja2 works in template editor, not in script

This works in template editor :

{% set ENERGY = "{{value_json['ENERGY'].Total}}" %}
{{ ENERGY }}
{"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{ENERGY}}"}

So I try this script :

  scripttasmotapow2:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/sensor/193EF5_ENERGY_Total/config
          payload_template: >
             {% set ENERGY = "{{value_json['ENERGY'].Total}}" %}
             '{"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{ENERGY}}"}'


and I get this error :

Logger: homeassistant.components.websocket_api.http.connection
Source: helpers/template.py:395
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 09:43:43 (2 occurrences)
Last logged: 09:56:43

[1665545936] UndefinedError: 'value_json' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 393, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1398, in _render_with_context
    return template.render(**kwargs)
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
  File "/usr/local/lib/python3.9/site-packages/jinja2/sandbox.py", line 303, in getitem
    return obj[argument]
jinja2.exceptions.UndefinedError: 'value_json' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1491, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1526, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 278, in service_handler
    await script_entity.async_turn_on(
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 382, in async_turn_on
    await coro
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 409, in _async_run
    return await self.script.async_run(script_vars, context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1219, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 353, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 371, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 571, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1491, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1526, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/components/mqtt/__init__.py", line 495, in async_publish_service
    payload = template.Template(payload_template, hass).async_render(
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 395, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'value_json' is undefined

value_json is local to an integration consuming data (like an mqtt sensor, restful sensor, etc…). You can’t use its state outside that configuration.

I don’t want to use its state, I want to publish a message which containts parts quoted with " and inside there quoted with ’

This is what I want to publish :

{"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{value_json['ENERGY'].Total}}"}

Just replacing the variabel {{ ENERGY }} with the literal string “{{value_json[‘ENERGY’].Total}}”

Is this a sample?
If you don’t actually want to template anything, you can just use “payload:”

You could also try:

{% set ENERGY = "{{ ''{{value_json['ENERGY'].Total}}'' }}" %}

I think I did not make my question clear enough.

This script works :

  samplescript1:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/switch/193EF5_RL_1/config
          payload: '{"name":"powr2","cmd_t":"~cmnd/POWER","stat_t":"~tele/STATE","val_tpl":"{{value_json.POWER}}","pl_off":"OFF","pl_on":"ON","avty_t":"~tele/LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_RL_1","device":{"identifiers":["193EF5"]},"~":"powr2/"}'

Why ? Because the payload only contains strings quoted with ", and the entire string is surrounded with ’

This script does not work :

  samplescript2:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/sensor/193EF5_ENERGY_Total/config
          payload: '{"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{value_json['ENERGY'].Total}}"}'

Why ? Because the payload contains both string quoted with " and ’ , and surrounding with ’ throws an error.
Thats why I try to template it.

This :

  scripttasmotapow2:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/sensor/193EF5_ENERGY_Total/config
          payload_template: >
             {% set ENERGY = "{{''value_json['ENERGY'].Total'' }}" %}
             {"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{ENERGY}}"}

and this :

  scripttasmotapow2:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/sensor/193EF5_ENERGY_Total/config
          payload_template: >
             {% set ENERGY = "{{''value_json['ENERGY'].Total'' }}" %}
            ' {"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{ENERGY}}"}'

still throws errors : TemplateSyntaxError: expected token ‘end of print statement’, got ‘value_json’

Use the to_json filter to encode your string.

Won’t that work?

          payload: > 
              {"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{value_json['ENERGY'].Total}}"}

Sometimes a solution can be so simple.

1 Like

In fact, still did not work. This is the finally working script :

  scripttasmotapow2:
    sequence:     
      - service: mqtt.publish
        data:
          retain: true
          topic: homeassistant/sensor/193EF5_ENERGY_Total/config
          payload: >
            {"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":"{{ '{{' }}value_json.ENERGY.Total}}"}

use what @tom_l said instead of your odd work around…

payload: >
  {{ {"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":value_json['ENERGY'].Total} | to_json }}

I tried. The script still tries to evaluate value_json. Even when using payload: instead of payload_template: you still get an error about evaluating value_json. I don’t know if it is a bug in the script handling or the mqtt publishing, but it is very odd.

You’re to just pass the string “{{ value_json[‘ENERGY’].Total }}”?

If that’s the case, use raw.

payload: '{"name":"powr2 ENERGY Total","stat_t":"~SENSOR","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"193EF5_ENERGY_Total","device":{"identifiers":["193EF5"]},"~":"powr2/tele/","unit_of_meas":"kWh","last_reset_topic":"powr2/tele/","last_reset_value_template":"1970-01-01T00:00:00+00:00","device_class":"energy","state_class":"measurement","val_tpl":{% raw %}"{{ value_json['ENERGY'].Total }}"{% endraw %} }'
1 Like

And that is the correct solution.

Yes, whenever you want to transmit jinja without resolving it, wrap it in {% raw %}{% endraw %} which will treat everything between those identifiers as a string regardless of punctuation.

1 Like