Issue when templating sensor in configuration.yaml character '%' that cannot start any token

What I was looking for isn’t possible see responses

Hi

I’ve followed some examples to create sensors using a template to loop an array.
It works when I test my template in Developer Tools

But when I drop the template in configuration.yaml I got an error

Error loading /config/configuration.yaml: while scanning for the next token
found character '%' that cannot start any token

pointing the first % in {%- for allergen

I understand it’s a conflit between yaml and templating syntax but I cannot find how to correct that.
Previous questions on the forum where more on using value_template: > but in my case sensors: >
isn’t the answer.

Any clue or working example ?

sensor:
  - platform: rest
    name: Pollens
    resource: https://www.pollens.fr/risks/thea/counties/11    
    json_attributes:  ['risks', 'riskLevel', 'countyName']
    value_template: '{{ value_json.riskLevel }}'
    # Request every 6 hours
    scan_interval: 21600
  - platform: template
    sensors:
{%- for allergen in state_attr('sensor.pollens', 'risks') %}
      {{ state_attr('sensor.pollens', 'countyName') | lower }}_allergen_{{ loop.index }}:
        friendly_name: {{ state_attr('sensor.pollens', 'countyName') }} {{ allergen.pollenName }}
        value_template: {{ allergen.level }}
{%- endfor %}

This is the value returned from the rest call :

{"countyName":"Jura","countyNumber":"39","risks":[{"pollenName":"Tilleul","level":0},{"pollenName":"Ambroisies","level":0},{"pollenName":"Olivier","level":0},{"pollenName":"Plantain","level":2},{"pollenName":"Noisetier","level":0},{"pollenName":"Aulne","level":0},{"pollenName":"Saule","level":0},{"pollenName":"Cypr\u00e8s","level":0}],"riskLevel":4}

This is incorrect:

  - platform: template
    sensors:
{%- for allergen in state_attr('sensor.pollens', 'risks') %}
      {{ state_attr('sensor.pollens', 'countyName') | lower }}_allergen_{{ loop.index }}:
        friendly_name: {{ state_attr('sensor.pollens', 'countyName') }} {{ allergen.pollenName }}
        value_template: {{ allergen.level }}
{%- endfor %}

Aside from the template’s incorrect indenting, two of the Template Sensor’s options are located within the for-loop and that’s not a supported operation.

Given this payload:

{
	"countyName": "Jura",
	"countyNumber": "39",
	"risks": [{
		"pollenName": "Tilleul",
		"level": 0
	}, {
		"pollenName": "Ambroisies",
		"level": 0
	}, {
		"pollenName": "Olivier",
		"level": 0
	}, {
		"pollenName": "Plantain",
		"level": 2
	}, {
		"pollenName": "Noisetier",
		"level": 0
	}, {
		"pollenName": "Aulne",
		"level": 0
	}, {
		"pollenName": "Saule",
		"level": 0
	}, {
		"pollenName": "Cypr\u00e8s",
		"level": 0
	}],
	"riskLevel": 4
}

What do you want the Template Sensor to extract and use as its state value?

I’m looking to create one sensor per allergen

Then you must define each sensor. You cannot use a Jinja2 template to generate YAML for each sensor (which is what your for-loop is trying to do).

  - platform: template
    sensors:
      jura_allergen_0:
        friendly_name: Jura_Tilleul
        value_template: "{{ state_attr('sensor.pollens', 'risks')[0].level }}"
      jura_allergen_1:
        friendly_name: Jura_Ambroisies
        value_template: "{{ state_attr('sensor.pollens', 'risks')[1].level }}"	
      jura_allergen_2:
        friendly_name: Jura_Olivier
        value_template: "{{ state_attr('sensor.pollens', 'risks')[2].level }}"	
      jura_allergen_3:
        friendly_name: Jura_Plantain
        value_template: "{{ state_attr('sensor.pollens', 'risks')[3].level }}"
#etc etc

Meaning we know exactly which Allergen is given back by the API :frowning:

I suppose that the best was to do is to create an Integration or an HACS plugin ?

Yes, that’s a limitation due to the structure of the received risks data. It’s a list so there’s no guarantee it always contains all the pollen names and in the same order. If it were available as a dictionary then we would have more flexibility.

Another option is to create an external script (using shell-script or python) to receive the data, transform it into a more suitable format, perhaps using jq (JSON processor), then publish it to one or more MQTT topics. You can then define MQTT sensors to subscribe to the topics.

If that sounds like a lot of work, it’s still less than developing a custom integration.

1 Like

If you want only need to display the results (and not track history, use for automations etc.) then you can read it all into one sensor and parse it for display with a for loop in the markdown card.

1 Like