Batch create multiple template sensors

I have the following as an attribute on a REST sensor:

[
{
"channel":0,
"Vrms":214.4288,
"Hz":50.0122
},
{
"channel":1,
"Watts":" 6",
"Pf":0.554446,
"reversed":true
},
{
"channel":2,
"Watts":" 5",
"Pf":0.352379
},
{
"channel":3,
"Watts":" 8",
"Pf":0.782653
},
{
"channel":4,
"Watts":"219",
"Pf":0.998824
},
{
"channel":7,
"Watts":"1554",
"Pf":0.984729
},
{
"channel":9,
"Watts":" 5",
"Pf":0.847378,
"reversed":true
},
{
"channel":10,
"Watts":" 0",
"Pf":0
},
{
"channel":11,
"Watts":" 0",
"Pf":0
},
{
"channel":12,
"Watts":" 0",
"Pf":0
},
{
"channel":13,
"Watts":"129",
"Pf":0.642825,
"reversed":true
},
{
"channel":14,
"Watts":"10",
"Pf":0.618324
}
]

And would like to create template sensors for each of the elements with something like this:


{% for input in states.sensor.iotawatt.attributes.inputs %}
  {%- if input.Watts %}
    {{ input.channel }}: {{ input.Watts }} W, {{input.Pf}}
  {%- endif %}
{%- endfor %}

Is that possible or do I need to create 14 separate template sensors like this below?

sensor:
  - platform: template
    sensors:
      iotawatt_input_1:
        friendly_name_template: {{ states.sensor.iotawatt.attributes.inputs[1].channel }}
        value_template: {{ states.sensor.iotawatt.attributes.inputs[1].Watts }}

not possible, gotta create each one individually. You can use the template editor to do it for you though so you can just copy and paste. If you know python, you can have that auto generate the yaml too.

1 Like

Thank you for clearing things up. Here are the final jinja template to generate the yaml.

sensor:
  - platform: template
    sensors:
{%- for i in range(states.sensor.iotawatt.attributes.inputs| length) %}
{%- set input = states.sensor.iotawatt.attributes.inputs[i] %}
  {%- if input.Watts %}
      iotawatt_input_{{ input.channel }}:
        value_template: {{"{{states.sensor.iotawatt.attributes.inputs["}}{{i}}{{"].Watts}}"}}
        unit_of_measurement: Watts
  {%- endif %}
{%- endfor %}
{%- for i in range(states.sensor.iotawatt.attributes.outputs| length) %}
{%- set output = states.sensor.iotawatt.attributes.outputs[i] %}
      iotawatt_output_{{ output.name }}:
        value_template: {{"{{states.sensor.iotawatt.attributes.outputs["}}{{i}}{{"].value}}"}}
        unit_of_measurement: {{ output.units }}
{%- endfor %}

Outputs the following:

sensor:
  - platform: template
    sensors:
      iotawatt_input_1:
        value_template: {{states.sensor.iotawatt.attributes.inputs[1].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_2:
        value_template: {{states.sensor.iotawatt.attributes.inputs[2].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_3:
        value_template: {{states.sensor.iotawatt.attributes.inputs[3].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_4:
        value_template: {{states.sensor.iotawatt.attributes.inputs[4].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_7:
        value_template: {{states.sensor.iotawatt.attributes.inputs[5].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_9:
        value_template: {{states.sensor.iotawatt.attributes.inputs[6].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_10:
        value_template: {{states.sensor.iotawatt.attributes.inputs[7].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_11:
        value_template: {{states.sensor.iotawatt.attributes.inputs[8].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_12:
        value_template: {{states.sensor.iotawatt.attributes.inputs[9].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_13:
        value_template: {{states.sensor.iotawatt.attributes.inputs[10].Watts}}
        unit_of_measurement: Watts
      iotawatt_input_14:
        value_template: {{states.sensor.iotawatt.attributes.inputs[11].Watts}}
        unit_of_measurement: Watts
      iotawatt_output_Appliencies:
        value_template: {{states.sensor.iotawatt.attributes.outputs[0].value}}
        unit_of_measurement: Watts
      iotawatt_output_Inverter:
        value_template: {{states.sensor.iotawatt.attributes.outputs[1].value}}
        unit_of_measurement: Watts
      iotawatt_output_Total:
        value_template: {{states.sensor.iotawatt.attributes.outputs[2].value}}
        unit_of_measurement: Watts
      iotawatt_output_VVB:
        value_template: {{states.sensor.iotawatt.attributes.outputs[3].value}}
        unit_of_measurement: Watts
1 Like

Yep, you could have also just used the object instead of using range in conjunction with .format to get away from the crazy {{}} that templating brings.

enumerate iterates over an object and returns the enumeration and object. So you don’t need to use range. Enumeration is returned first, object second. EDIT: enumerate isn’t available in Jinja, only python. Revising post.

.format() will look at a string and replace {} with whatever is provided in format. This is very powerful and theres other functionality to it.

sensor:
  - platform: template
    sensors:
{%- for i in range(states.sensor.iotawatt.attributes.inputs | length) %}
  {%- set input = states.sensor.iotawatt.attributes.inputs[i] %}
  {%- if input.Watts %}
      iotawatt_input_{{ input.channel }}:
        value_template: {{'"{{ states.sensor.iotawatt.attributes.inputs[{}].Watts }}"'.format(i)}}
        unit_of_measurement: Watts
  {%- endif %}
{%- endfor %}
{%- for i in range(states.sensor.iotawatt.attributes.outputs | length) %}
  {%- set input = states.sensor.iotawatt.attributes.outputs[i] %}
      iotawatt_output_{{ output.name }}:
        value_template: {{'"{{ states.sensor.iotawatt.attributes.outputs[{}].value }}"'.format(i)}}
        unit_of_measurement: {{ output.units }}
{%- endfor %}
1 Like

@fredrike I am trying to use the sensor template for my iotawatt however it keeps complaining about the first % symbol when I goto validate the configuration. Is the platform: template block supposed to be run in a script or should I just be able to place that code directly in my configuration.yaml file?

Thanks!
Ty

These are template sensors, they go in the sensor section:

Yes, I know what .format() does (in Python3). Basically are your and mine solutions similar with exception of your use of .format() (which indeed are much nicer than mine }}{{i}}{{.

The idea is to paste the code from @petro in the template editor to generate the right configuration to use in configuration.yaml. Below is the code I’m currently using for iotawatt (generated at the template editor):

sensor:
  - platform: rest
    resource: 'http://iotawatt.local/status?outputs=yes&inputs=yes'
    name: iotawatt
    value_template: '{{ value_json.outputs[2].value | float | round(1) }}'
    unit_of_measurement: "W"
    json_attributes:
      - outputs
      - inputs
  - platform: template
    sensors:
      iotawatt_appliences:
        value_template: '{{ states.sensor.iotawatt.attributes.outputs[0].value }}'
        friendly_name_template: '{{ states.sensor.iotawatt.attributes.outputs[0].name }}'
        unit_of_measurement: "W"
      iotawatt_inverter:
        value_template: '{{ states.sensor.iotawatt.attributes.outputs[1].value | round(1) }}'
        friendly_name_template: '{{ states.sensor.iotawatt.attributes.outputs[1].name }}'
        unit_of_measurement: "W"
      iotawatt_total:
        value_template: '{{ states.sensor.iotawatt.attributes.outputs[2].value | round(1) }}'
        friendly_name_template: '{{ states.sensor.iotawatt.attributes.outputs[2].name }}'
        unit_of_measurement: "W"

Sorry if you got a notification about this. Someone on discord pinged me about the code I posted and that’s when I found out that enumerate wasn’t available in Jinja2. That’s why I edited the post and made changes. I’m guessing you were notified automatically when the edits went through, but the changes were for the other guy asking questions. Didn’t feel like creating a whole new post.

1 Like

Thanks I was able to get it figured out with the help form @petro. It sure would be nice if there was a component that handled all of this for us. Maybe I will take a crack at writing one at some point. Right now I just want to get this data into HA so I can write a couple of automation’s around it. Thanks for replying and all the help.

-Ty

The “right way” would be to get iotawatt to support mqtt and read the data from there. I think we should try to get the developers of iotawatt to do that.

1 Like

Looks like it is back on the table here is a link to a recent thread about adding native MQTT support.IoTaWatt Community

1 Like

I found this thread and used the template proposed by @petro but I had to modify it to make it work

I think it could be useful for others also.
I had to fix some syntax otherwise sensors wouldn’t show, I also added the right device class for power and voltage sensors, as well as some rounding

sensor:
  - platform: template
    sensors:
{%- for i in range(states.sensor.iotawatt.attributes.inputs | length) %}
  {%- set input = states.sensor.iotawatt.attributes.inputs[i] %}
  {%- if input.Watts %}
      iotawatt_input_{{ input.channel }}:
        value_template: {{'\'{{{{ states.sensor.iotawatt.attributes.inputs[{}].Watts }}}}\''.format(i)}}
        unit_of_measurement: Watts

  {%- endif %}
{%- endfor %}
{%- for i in range(states.sensor.iotawatt.attributes.outputs | length) %}
  {%- set output = states.sensor.iotawatt.attributes.outputs[i] %}
      iotawatt_output_{{ output.name }}:
        value_template: {{'\'{{{{ states.sensor.iotawatt.attributes.outputs[{}].value }}}}\''.format(i)}}
        unit_of_measurement: {{ output.units }}
        {%- if output.units == 'Watts' %}
        device_class: power
        {%- elif output.units == 'Volts' %}
        device_class: voltage
        {%- endif %}
        
  {%- set output = states.sensor.iotawatt.attributes.outputs[i] %}
      iotawatt_output_{{ output.name }}_rounded:
        value_template: {{'\'{{{{ states.sensor.iotawatt.attributes.outputs[{}].value | round(0) }}}}\''.format(i)}}
        unit_of_measurement: {{ output.units }}
        {%- if output.units == 'Watts' %}
        device_class: power
        {%- elif output.units == 'Volts' %}
        device_class: voltage
        {%- endif %}        
{%- endfor %}

the template above creates 3 types of sensors:

  • inputs
  • outputs
  • outputs rounded

the rounded ones are useful for immediate data visualization, so that annoying decimals don’t show up in graphs and gauges

Hmmm would this still work?
I’m trying to make something like this as part of “packages”, but getting a bunch of validation errors like “missed comma between flow collection entries”.

Example:

alarm_low_battery_warning:
  sensor:
  - platform: template
    sensors:
{%- set ns = namespace(low_battery_sensors=[]) -%}

I am obviously missing something important in achieving this :slight_smile:

Thanks,
mb

see my post

Thanks for your reply.
I know some Python, so generating the yaml should be fine; the challenge would be to identify a change (add/remove entries in Yaml when adding/removing sensors for various integrations, and restarting/reloading the template entities). Sounds possible but needs some reading / experimenting.

For now I think I’m gonna rely on groups, adding - removing sensors as needed; and deal with the dynamic bits at a later point in time.

My comment about using python was to generate the yaml and paste it into your configuration. Not automatically make template sensors.

In reality, having something automatic is pointless and doesn’t save much time. Just create jinja that makes your template. Paste that as a comment in your file. Then when you need to make adjustments, change the code, run it in the template editor, and copy/paste the results back.

I can count the amount of times I’ve had to change scripts on my hand that generate my template sensor and I’ve been doing this for 6 years. The juice is not worth the squeeze.