Help With value_template

Hi.

I have 6 temperature sensors on a 1-wire bus hanging from a Sonoff TH10. TASMOTA reports them as follows:

22:37:55 MQT: th10_02/tele/SENSOR = {"Time":"2019-03-15T22:37:55", "DS18B20-1":{"Id":"01159038DEFF","Temperature":53.6}, "DS18B20-2":{"Id":"011590B1DEFF","Temperature":53.6}, "DS18B20-3":{"Id":"011590B342FF","Temperature":46.4}, "DS18B20-4":{"Id":"011590E289FF","Temperature":39.9}, "DS18B20-5":{"Id":"0415A231A5FF","Temperature":49.8}," DS18B20-6":{"Id":"0415A28B86FF","Temperature":51.5},"TempUnit":"C"}

All good, except that 1,2,3,4,5,6 is not the order they’re in on the chain. I suspected this might happen, so I took a note of the serial number on each one before I installed them.

At the moment, each sensor is declared simlar to:

- platform: mqtt
  name: **"TankTemp1"**
  state_topic: "th10_02/tele/SENSOR"
  unit_of_measurement: "°C"
  value_template: "{{ value_json[**'DS18B20-6'**].Temperature }}"
  payload_available: "Online"
  payload_not_available: "Offline"

It can be seen that TASMOTA has declared them in numerical order by serial number, so what I wish to call TankTemp1, TASMOTA calls DS18B20-6.

Can anyone please help me formulate a value_template which will allow me, rather than looking up the temperature of “DS18B20-6” to instead lookup the temperature associated with the transducer whose “Id” is “01159038DEFF”?

I’m sure once I see an example, I’ll get the idea pretty quickly. Many thanks.

I don’t know how to do what you requested nor if it’s possible.

I offer you another way to re-map the sensors.

Create an automation that subscribes to th10_02/tele/SENSOR and re-publishes the received payload as six separate topics. Each topic contains one of the six temperature values.

- alias: 'payload demultiplexer'
  hide_entity: true
  trigger:
    - platform: mqtt
      topic: th10_02/tele/SENSOR
  action:
    - service: mqtt.publish
      data_template:
        topic: home/sensor1
        payload: "{{ trigger.payload_json['DS18B20-1'].Temperature }}"
    - service: mqtt.publish
      data_template:
        topic: home/sensor2
        payload: "{{ trigger.payload_json['DS18B20-2'].Temperature }}"
    - service: mqtt.publish
      data_template:
        topic: home/sensor3
        payload: "{{ trigger.payload_json['DS18B20-3'].Temperature }}"
    - service: mqtt.publish
      data_template:
        topic: home/sensor4
        payload: "{{ trigger.payload_json['DS18B20-4'].Temperature }}"
    - service: mqtt.publish
      data_template:
        topic: home/sensor5
        payload: "{{ trigger.payload_json['DS18B20-5'].Temperature }}"
    - service: mqtt.publish
      data_template:
        topic: home/sensor6
        payload: "{{ trigger.payload_json['DS18B20-6'].Temperature }}"

Create six sensors and subscribe each one to a desired temperature topic. The sensor’s name can now be whatever you want it to be and it can be mapped to whichever temperature topic you wish.

In this example, the sensors are in reverse-order, namely TankTemp1 is mapped to home/sensor6, TankTemp2 is mapped to home/sensor5, etc.

- platform: mqtt
  name: "TankTemp1"
  state_topic: home/sensor6
  unit_of_measurement: "°C"

- platform: mqtt
  name: "TankTemp2"
  state_topic: home/sensor5
  unit_of_measurement: "°C"

- platform: mqtt
  name: "TankTemp3"
  state_topic: home/sensor4
  unit_of_measurement: "°C"

- platform: mqtt
  name: "TankTemp4"
  state_topic: home/sensor3
  unit_of_measurement: "°C"

- platform: mqtt
  name: "TankTemp5"
  state_topic: home/sensor2
  unit_of_measurement: "°C"

- platform: mqtt
  name: "TankTemp6"
  state_topic: home/sensor1
  unit_of_measurement: "°C"

I think I see what you’ve done. It’s a good tip: it never occurred to me that an action could be to publish.

Even your solution, though, I’m sure can be done in a FOR loop. I may be mistaken. I’m gonna keep stabbing at it and will let you know if I unearth anything.

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… you have a pain in the ass template here. This should work every time though:

- platform: mqtt
  name: "01159038DEFF Temperature"
  state_topic: "th10_02/tele/SENSOR"
  unit_of_measurement: "°C"
  value_template: >
    {% set serial_number = '01159038DEFF' %}
    {{ ((d.values() | list)[1:-1] | selectattr('Id', 'eq', serial_number) | list)[0].Temperature }}
  payload_available: "Online"
  payload_not_available: "Offline"

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.

Super pain in the ass, but it should work.

1 Like

Always something to learn from your examples!

I’m stumped by the d in d.values, where’s that defined?

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.

That is exactly what I wanted to hear!

No, it’s … almost elegant. I can work with this. It’s a bit like Python except for the one unfamiliar jinja function call.

Thank you! A whole new world literally just opened up.

I don’t suppose the config supports a “global” variable type? Somewhere I could store

{ "01159038DEFF":"TankSensor1", "0115903BCEFF":"TankSensor2",
"011377AADEFF":"TankSensor3", "0113772384AA":"TankSensor4", ...  }

I could then traverse and nest your functionality within?

@KDM @123

That’s a typo on my part. I forgot to replace d w/ the trigger.payload_json

- platform: mqtt
  name: "01159038DEFF Temperature"
  state_topic: "th10_02/tele/SENSOR"
  unit_of_measurement: "°C"
  value_template: >
    {% set serial_number = '01159038DEFF' %}
    {{ ((trigger.payload_json.values() | list)[1:-1] | selectattr('Id', 'eq', serial_number) | list)[0].Temperature }}
  payload_available: "Online"
  payload_not_available: "Offline"

So anyways, you shouldn’t need to map anything with this. Just change the serial number and you’ll get the serial numbers temperature.

1 Like

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).

1 Like

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.

Bother. I get state: Unknown in the HA states screen for each of the sensors.
Do you suppose that’s because they’re not monotonic?

Actually, that’ll be irrelevant. They’re monotonic in TASMOTA as it finds them.

So the template is failing somehow. Errors could be in the log.

Do you have resolve your case? I have a similar problem, I need identify the temperature with serial number. Thanks

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"
2 Likes

I believe there’s a typo in the template’s last line. The test should check selection[0]

    {{ selection[0] if selection[0] > 0 else 0.0 }}

(The template generates an error without the addition of the [0])

Or is this the intended logic?

    {{ selection[0] if selection | count > 0 else 0.0 }}

Yah total typo. Brain fart.

EDIT: Made edit, intention was | count

1 Like

Thanks for this @petro, I don’t fully understand how it works, but it does :slight_smile:
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?