Tell me how you wish to re-map the sensors. Is it simply putting them in reverse-order (like I’ve done in the example above) or is there no pattern to it?
If it’s reverse-order then there may be a way to do it elegantly with a for-loop (and I may be able to help you). If there’s no pattern, then the for-loop will have a long chain of if-else tests to perform the re-mapping. The end-result will be no more elegant than the simplistic approach used in my example.
However, if you wish to pursue the for-loop approach as an exercise in improving your Jinja2 skills, I encourage you to continue! There are several community members who are very skilled with Jinja2 (I exclude myself from that short-list) and they may stop by to help you.
so what it does is it turns the output into a list of dictionaries that only contain your id’s and temperatures. Next it selects the correct item that contains the serial number you are looking for (That returns a list). So then, the list should only be 1 item, so we take the first item, then return the temperature.
No pattern, I’m afraid. These represent sensor in a chain up the side of a hot water tank. I didn’t know what order TASMOTA was going to put them in, since I knew it was going to have to “find” them. I have remapped them manually using the config: I’m happy with sensor 6 being called TankTemp1, etc. The problem arose last night when I added a sensor to the bottom of the chain and it appeared in the middle of TASMOTA’s list. I figured since I know the order of the sensors by Id, I may as well use that information.
I’d hope there would only be 6 if-else statements in a for loop. Since I’ve already manually mapped them and I don’t plan on adding any more sensors, it’s as much a programming exercise for me as anything else. I am a software engineer, as it happens; I’ve just never done anything with this type of architecture before.
Thank! I guessed that might be the case … but wasn’t 100% that you weren’t doing something extra tricky!
I put the relevant bits into the Template Editor to poke at it and learn how it works. I have to hand it to you, that first part that converts the data into a list, then lops off the leading and trailing elements, is pretty slick. I bookmarked your post for future reference (one of many of your Jinja2 posts).
I couldn’t think of any way to do it so that I could use selectattr! I’m just hoping that his dictionary is somewhat ordered. Otherwise, some other finagling would need to happen.
With apologies for taking so long to reply. Particular apologies to petro, because despite his best efforts, I didn’t try any further with this.
I still find the YAML and JSON (or whatever this mixture is) syntax utterly stupefying. I found my solution by writing post processor scripts in Python and publishing the results in a format which was more useful. In this case, I don’t actually WANT to display the sensors data, I just want to know what order they’re in and which of them is above a certain setpoint, so I can calculate my hot water tank level.
Now, I use my Python postprocessor to handle all my 433MHz traffic and have coded up quite a functional zoned burglar alarm.
I really wish I could grasp the YAML thing. I’m a software engineer, believe it or not, but I just have some kind of block its paradigms. It’s irritating, because I feel I’m close: the brackety dictionaries and things look exactly like Python, but just with none of the flexability.
Well, the issue was the fact we were using trigger.payoad_json. It should be replaced with value_json.
Part of the issue was that I had never used MQTT at the time and I wasn’t aware of the available variables. And the resulting template would be:
- platform: mqtt
name: "01159038DEFF Temperature"
state_topic: "th10_02/tele/SENSOR"
unit_of_measurement: "°C"
value_template: >
{% set serial_number = '01159038DEFF' %}
{% set selection = value_json.values() | list | selectattr('Id', 'eq', serial_number) | map(attribute='Temperature') | list %}
{{ selection[0] if selection | count > 0 else 0.0 }}
payload_available: "Online"
payload_not_available: "Offline"
Thanks for this @petro, I don’t fully understand how it works, but it does
I’m trying to expand on this and also add the id as an attribute. I’ve tried to use the same style template for the json_attributes_template as for the value_template, but no success.
So how do I tweek this to add the id number, and maybe also the sensor name as given by tasmoto (DS18B20-x), as attributes?
Hm, this doesn’t work…
Had to add a colon after json_attributes_template, after that I get this error when checking the config.
Invalid config for [sensor.mqtt]: extra keys not allowed @ data[‘id’]. Got “{% set serial_number = ‘01159038DEFF’ %} {% set selection = value_json.values() | list | selectattr(‘Id’, ‘eq’, serial_number) | map(attribute=‘Id’) | list %} {{ selection[0] if selection | count > 0 else 0.0 }}\n”
template value is None for dictionary value @ data[‘json_attributes_template’]. Got None. (See ?, line ?).
Edit: I played around with it some more to see if I could extract the name and the ID separately. The below snippet successfully puts the Id as an attribute:
json_attributes_template: >
{% set serial_number = '0114580048AA' %}
{% set selection = value_json.values() | list | selectattr('Id', 'eq', serial_number) | map(attribute='Id') | list %}
{% set serial = selection[0] if selection | count > 0 else 0.0 %}
{{ {'Id' : serial} | tojson}}
But the below version does not work for the name, it seems to return the whole json structure from the sensor:
json_attributes_template: >
{% set serial_number = '0114580048AA' %}
{% set selection = value_json.items() | list | selectattr('[-1].Id', 'eq', serial_number) | map(attribute='[0]') | list %}
{% set name = selection[0] if selection | count > 0 else 0.0 %}
{{ {'Name' : name} | tojson}}