Construction of JSON payload in automation action

I want to pass some info out on MQTT to a Tasmotised ESP32 so it can display it.
I’ve sorted the ESP to do the decoding and displaying using the payload below just typed in to the automation action.

{"Hours":2.5,"Oil":20.1,"KWh":17.3,"Cost":6.75}

Now I’m trying to construct a Template to get the 4 values from 4 numeric state entities and I’m struggling.
Is it possible and can someone give me an example template for me to crib from?

Cracked it. Needed to use a |tojson filter on the things needing double quotes.
This went into the Payload template box in the Action/Call Service/MQTT:Publish

{{"{"+"Hours"|tojson +":"+ states("sensor.burn_time_by_day")+","+ 
"Oil"|tojson +":"+ states("sensor.oil_litres_today")+","+
"KWh"|tojson +":"+ states("sensor.oil_energy")+","+
"Cost"|tojson +":"+ states("sensor.oil_cost_today")+"}"}}

Produced this result

{"Hours":3.3,"Oil":7.3644,"KWh":69.531,"Cost":5.41946196}

Left here for anyone else searching for this.

You can reduce the template to this:

{{ {"Hours": states('sensor.burn_time_by_day'),
    "Oil": states('sensor.oil_litres_today'),
    "KWh": states('sensor.oil_energy'),
    "Cost": states('sensor.oil_cost_today')} }}
1 Like

Oh yeah. I’m sure I started out with something like that in the Developer Tools section but just kept getting TemplateSyntaxError. I guess I just didn’t hit it perfectly.
Thanks.
Edit - Actually whilst it looks like works, it put quotes around the numeric values for some reason and that doesn’t get interpreted correctly at the other end. Maybe there’s a simple hybrid solution but for now i’ll stick with my complicated one.
Edit Edit - The quotes go if you stick a |float after each value.

{{ {"Hours": states('sensor.burn_time_by_day')|float,
    "Oil": states('sensor.oil_litres_today')|float,
    "KWh": states('sensor.oil_energy')|float,
    "Cost": states('sensor.oil_cost_today')|float} }}
  1. Your template doesn’t need to concatenate everything with so many + operators.
  2. I don’t see the need for using tojson anywhere in your template. It’s for converting an object to JSON. A string like Hours isn’t an object.

In fact my hybrid with the '|float’s doesn’t cut it. It seems to work in the Developer Tools/Template section where the output looks fine, But when I use it in my Automation with the Service: MQTT_Publish, MQTT Explorer doesn’t recognise it as a JSON object and neither does my ESP32 Tasmota device.
This is copied and pasted from MQTT Explorer using my original Template

{"Hours":0.0,"Oil":0.0,"KWh":0.0,"Cost":0.0}

and this using the one with floats that it doesn’t recognise as JSON

{'Hours': 0.0, 'Oil': 0.0, 'KWh': 0.0, 'Cost': 0.0}

One difference is double vs single quotes. Interesting that they are different colours so there must be some significance in it.
Another are the spaces in the hybrid which if I take them out of the Template get put back in again in the output!
I’m definitely sticking with my original.
PS. I had to use the |tojson to get the double quotes around the keys.

Tack on a tojson at the end and it will ensure it uses double-quotes.

{{ {"Hours": states('sensor.burn_time_by_day') | float(0),
    "Oil": states('sensor.oil_litres_today') | float(0),
    "KWh": states('sensor.oil_energy') | float(0),
    "Cost": states('sensor.oil_cost_today') | float(0)} | tojson }}

The float(0) is needed if you want the key’s value to be reported as a number. Without it, it will be reported as a string value. You should specify a default value. Otherwise, if the sensor’s value is non-numeric, float will fail whereas float(0) will report 0.

If you have a moment, try this version. It separates data from formatting, for improved legibility, and avoids duplicating the float filter, for neatness.

The result looks correct in the Template Editor (double-quotes are preserved) but the real test is how it will be interpreted as an MQTT payload.

{% set x =
   ['sensor.burn_time_by_day',
    'sensor.oil_litres_today',
    'sensor.oil_energy',
    'sensor.oil_cost_today']
  | map('states') | map('float', 0) | list %}
{{ '{"Hours": %d, "Oil": %d, "KWh": %d, "Cost": %d}' | format(*x)  }}
1 Like

Both of those work OK at the far end and in MQTT Explorer.
In the last you had the formatting to d so the values came through as integers; I changed them to 5.2f. And, interestingly, the former one, with tojson at the end, changed the list into alphabetical order which confused me for a few seconds. I keep coming across ‘map’ but have no idea what it is; must look into it.
Good learning.

You can use Home Assistant’s to_json filter and specify if you want sorting or not.

I used %d for illustration purposes only. To display floating point numbers you can simply use %f or what you did which constrains the quantity of significant digits.

Glad to hear it was useful.

May I suggest that you mark one of these templates as the Solution to avoid directing other users to the initial example. It may work but it goes about it in a roundabout way (like adding two numbers this way {{ ['1'|int, '1'|int]|sum }}).

1 Like