[Solved] Template sensor to read dynamically nested attribute information

Cool, whenever I see your solutions, I say to myself “maybe you should start doing more things with HA than AppDaemon”.

I’ve been thinking about moving back but I’d need to make some new integrations. Appdaemon is great but I don’t know if it’s needed anymore. It really depends on the automation I guess.

What do you mean with this? Sorry, I don’t understand.

Currently I’m still doing all automations in AppDaemon, however with all the new features (like global variables) that will get introduced in 0.115, I need to rethink this as some of these currently missing features were the reason to use AppDaemon in the first place. However, one of the main uses for AppDaemon for me is to learn Python, in the hope to contribute some code to HA one day.

I have a few appdeamon apps that could be replaced with a built in integration. I’ve just been too lazy to make them. I’ve got one on my list that’s a pretty high up WTH, so I might be doing this pretty soon.

You could probably add stuff now. It’s not that hard and you don’t need to know the core that well. The hardest part is knowing how to use the API. If you can learn appdeamon, you can build an integration.

Thanks for the feedback - as it is always the first item on the list this seems easier to me.

Now I have a formatting problem. This code shows the correct value in the Template Editor in Dev Tools:

{{ state_attr('weather.xyz, 'forecast')[0]['temperature'] }}

If I try to use it as a template sensor it does not:

- platform: template
  sensors: 
    DWD_today_max_temp:
      friendly_name: 'DWD Today Max Temp'
      device_class: temperature
      unit_of_measurement: '°C'
      icon_template: 'mdi:thermometer-high'
      value_template: '{{ state_attr('weather.xyz', 'forecast')[0]['temperature'] }}'

Error Message of HAss File Editor:

can not read an implicit mapping pair; a colon is missed at line 115, column 99:
… forecast’)[0][‘temperature’] }}’
^

Any ideas why the value_template needs different code than the template editor?

You need double quotes outside the curly brackets, like this:

"{{ state_attr('weather.xyz', 'forecast')[0]['temperature'] }}"
1 Like

Otherwise this happens:

Ahh, thanks to both of you for explaining, works!

I am trying to do something similar but seem to be missing something with the last part. I am trying to make a template sensor with just the “score” of my image_processing, and numbers only even when no value/attribute is defined so it is a chartable value… I cannot figure out how to get just the numeric value.
This is the raw attribute:

{
  "matches": {
    "person": [
      {
        "score": 95.44724,
        "box": [
          0.19603582,
          0.408492,
          0.4463838,
          0.46571591
        ]
      }
    ]
  },
  "summary": {
    "person": 1
  },
  "total_matches": 1,
  "process_time": 0.42949440190568566,
  "friendly_name": "Doods side_yard"
}

I have tried a few variations of this which gets me close but I cannot get it to pull the numeric value for score. I tried [0], [‘score’] and a few others I found in some similar posts. I am not sure why it doesn’t like it, the extra curly braces? :

{{ state_attr('image_processing.doods_side_yard', 'score') }}

which gets me to this:

[{'score': 95.44724, 'box': [0.19603582, 0.408492, 0.4463838, 0.46571591]}]

If anyone has any suggestions it would be appreciated…

To pull the 95.4 value out of that structure, you’d need:

{{ WHATEVER_THAT_JSON_IS_FROM['matches']['person'][0]['score'] }}

You say “this is the raw attribute”, but if that is {{ state_attr('image_processing.doods_side_yard', 'score') }} I don’t see how you’d get the result you pasted.

Sorry That is the result of getting just the attribute with no .matches or .person


{{ states('image_processing.doods_side_yard.attributes ')}}

I see now I left that out as that was one of the multiple variations I tried… :sweat_smile: it was way past my bedtime

Right. In that case, try:

{{ state_attr('image_processing.doods_side_yard', 'matches')['person'][0]['score'] }}

Note the warning box in this section — always safer to follow its advice…

I’m also not clear on what you mean by:

Are you saying that the match might be for something other than a person? It’s still solvable if that is the case, but will be a bit more involved. Try this in the template editor, and you can change person for anything else:

{% set j = { "matches": {"person": [
      {
        "score": 95.44724,
        "box": [0.19603582, 0.408492, 0.4463838, 0.46571591]
      }
    ]
  },
  "summary": {
    "person": 1
  },
  "total_matches": 1,
  "process_time": 0.42949440190568566,
  "friendly_name": "Doods side_yard"
}
%}

{% for thing in j['matches'] %}
  {% if 'score' in j['matches'][thing][0] %}
    {{ thing }}: {{ j['matches'][thing][0]['score'] }}
  {% else %}
    0
  {% endif %}
{% endfor %}

If no person is detected the count goes back to zero and this is what I get for that same

{{  states(' image_processing.doods_side_yard.attributes ')}}
unknown

That template won’t ever work. What does this show in the template editor when there is no detection?

{{ state_attr('image_processing.doods_side_yard', 'matches') }}

my apologies i am mixing these up because i was trying to post while getting ready for work and was on mobile…
the result of:

{{ state_attr('image_processing.doods_side_yard', 'matches') }}

with no current person detected is:

{}

Excellent. So this template sensor should give 0 if there’s no detection, or the first non-zero score of however many scores exist:

template:
  - sensor:
      - name: Detection score
        state: >-
          {% set x = state_attr('image_processing.doods_side_yard', 'matches') %}
          {% if not x %}
            0
          {% else %}
            {% set ns = namespace(s=0) %}
            {% for thing in x %}
              {% if 'score' in x[thing][0] and ns.s == 0 %}
                {% set ns.s = x[thing][0]['score'] %}
              {% endif %}
            {% endfor %}
            {{ ns.s }}
          {% endif %}

EDIT: updated in line with @petro’s suggestion, which will also then give zero if the sensor doesn’t even have a matches attribute.

1 Like

You can just use if x and it’ll resolve false if the dictionary is empty, none, zero, etc.

1 Like

Alternatively, if you’re looking for the best score only if it’s a person… This should always work. This data looks like tensorflow, so it should always have summary.

{% set matches = state_attr('image_processing.doods_side_yard', 'matches') %}
{% if matches and matches.summary.person | default(0) > 0 %}
  {{ matches.matches.person | map(attribute='score') | list | max }}
{% else %}
  No People
{% endif %}

However, be forewarned… Tensorflow is being deprecated and removed. I’ve personally removed it. I suggest moving to the custom addon frigate. Much better solution too.

Thank you both so much, this is actually for the DOODS Add-on, but yea operatively pretty much just like Tensorflow… it should work perfectly and I only detect people so I think I’ll be ok with the first example.
I’ve just been trying to fine tune my confidence level to get rid of false positives but it is a pain to have to go to each Image and zoom in on the box to determine the percentage… I’m hoping with a charted value I can better adjust my cameras to catch the most people without the false positives (at night mostly). (I also apparently missed a person on two cameras yesterday because I recently set my confidence too high)
Thank you both again and I will give this a shot when I get home tonight.

Just made the first sensor and seems to be working perfectly thank you.

Quick question about this, if I remember correctly you used to use TensorFlow, how do you feel Frigate accuracy is compared to Tensorflow? (And also processor usage) I simply picked the Doods Add-On because I had used that temporarily the last time Tensorflow was broken… so I still had the settings commented out in my YAML… do you think it is worth the effort of switching over?