Template to add values of all sensors with certain name ending

Hi,

Remember seeing it on the forum before, but just cant find it… sorry, so please let me ask:

what is the correct value_template for adding the value of all sensors ending with _actueel…

I now have a value_template that lists all of these templates individually, but that makes it rather a long and error_prone template.

sensor.living_actueel, sensor.kitchen_actueel, etc etc.

Ive tried the endswith filter but cant get it right, nor use the _actueel in sensor.name -construction.

value needs |int to add them all and use in automations.
thx for having a look.
MArius

Does this hep? Help with value template

Not sure how to select sensors whose entity_id ends with a particular string. But if you created a group of these (say, group.actueel_sensors), then you could to it something like this:

{{ states.sensor|selectattr(
     'entity_id','in',state_attr('group.actueel_sensors','entity_id'))
   |map(attribute='state')|map('int')|sum }}
1 Like

Yes thank you.
I use that in other places. The sum filter was unknown to me yet, this will help for sure !

Thought to be able to use this

{% if state.name.endswith('actueel ')%}

and not be forced to use the group technique.

Not sure how to fit that in the sensor though… will experiment some more with you’re template and see what gives.
Thx

The problem is you can’t do that, as far as I know, with selectattr because there is not test for endswith. And you can’t do it in a for loop, because for loops in jinja, again, as far as I know, won’t remember values of variables from iteration to iteration, or outside of the for loop. Which is why I said the only way I could think of doing it is by creating a group of the entities of interest. There might be a way, but I haven’t found it. :slight_smile:

cool, this works alright:

{{ states.sensor|selectattr( 'entity_id','in',state_attr('group.iungo_verbruik_actueel','entity_id'))
   |map(attribute='state')|map('int')|sum }}

nice!

tried {{ states.sensor|selectattr( ‘entity_id’,‘in’, 'state_attr('state.name.endswith('actueel ‘)’,‘entity_id’))
|map(attribute=‘state’)|map(‘int’)|sum }}

which fails as you explained…

this (thanks @tom_l) :

{%-for state in states 
    if (
          (state.entity_id.endswith("actueel"))
        )  -%}        
        {%- if loop.first -%}The {% elif loop.last -%} and the {% else -%} the {% endif -%} 
           {{state.name}} {% if state.name.endswith('actueel')%} are {%else%} is {%endif%} {{state.state}},
       {%- if loop.last %}
         {%- if loop.index >0 %}
           Everything else is off. .
         {%- endif%} 
        {%- endif%} 
    {%- else%}
       Everything is off.
{% endfor%}

works almost, and at least shows the endswith test works.

{%-for state in states.sensor
    if  state.entity_id.endswith("actueel")%}
  {{ state.name}}

{%-endfor%}

give me all the right sensors…
{{ state.state}} their values…

both even {{state.name}} : {{state.state}} which is also quite nice.

or this, only the active ones:

{%-for state in states.sensor 
   if  state.entity_id.endswith('actueel') and state.state>'0' %}
{{state.name}} : {{state.state}}
{%-endfor%}

Now how to get this in the other template…

Got to give you points for imagination! Problem with software, though, is you have to use things that exist, and in the ways they actually work, not things you imagine might exist or in ways you imagine they might work. Computers aren’t very forgiving that way. :wink:

Lol. oth, computers are programmed by people , so thats where the lack lies… dont blame the messenger.

Still think it is not to daring a question to want to

find all sensors with name _actueel, and add their values.
Somehow this must be doable, maybe Python could come to the rescue. seems so very simple.

hass.states.set('sensor.total_actual_power_sensors', sum(sensors_on), {
    'unit_of_measurement': Watt,
    'friendly_name': 'Sensors total actual'
     })

now build sensors_on…please help me with this:

##########################################################################################
# total_power.py
##########################################################################################
total_power = '0'
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    state = hass.states.get(entity_id)
    if state.state > '0' and state.endswith('actueel'):
            total_power = total_power + state.state
            count = count + 1

hass.states.set('sensor.total_sensors', total_power, {'unit_of_measurement': 'Watt'})

conflict of string and integer ( the comparison >) , and Nonetype (the endswith) but the structure should be something like this?

Yep, that is definitely doable as a python_script.

total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel'):
        state = hass.states.get(entity_id)
        try:
            total_power += int(state.state)
        except:
            pass
        else:
            count += 1
hass.states.set(
    'sensor.total_sensors', total_power, {'unit_of_measurement': 'Watt'})

Haven’t tested it but it should work, although the environment python_scripts are run in is a bit limited so sometimes normal Pyhon stuff doesn’t work.

Also, in the except clause you could log a warning or error if you like.

Lastly, you had a count in your code, but then didn’t use the result. If you don’t need it, then you can just remove the corresponding statements.

thx!
it runs! unfortunately is doesnt add the values, and the result is 0…

ive tried the int(state.state) in my first attempt,

total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    state = hass.states.get(entity_id)
    if state.state > '0': #and state.endswith('actueel'):
       total_power = total_power + int(state.state)
       count = count + 1

hass.states.set('sensor.total_sensors', total_power, {'unit_of_measurement': 'Watt'})

but the interpreter errors out with:
Error executing script: invalid literal for int() with base 10: '10:00'

it is the same as you use so im puzzled.
when is the value an integer, and when is it a string? state.state should be an integer. I need that because the >0 test (no use adding 0 for all off sensors)

ive also seen the sum() function be used, can I use the in my setting too, after having selected all values to sum? Don’t know how to do that yet, but it might be another way to reach the same goal?

anyways, Ive adapted it a bit to use the count, which makes clear why the sensor has value 0: no sensors are counted…

59

total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel'):
        state = hass.states.get(entity_id)
        try:
            total_power += int(state.state)
            count += 1
        except:
            pass
        else:
            count += 1
hass.states.set(
    'sensor.total_sensors', total_power, {
    'unit_of_measurement': 'Watt',
    'friendly_name': '{} sensors'.format(count)
     })

All state object’s states are strings, even if they look like a number. So they have to be converted to an int (or float) if you want to add them.

But, ‘00:00’ is not a valid int. Why would your sensor that is supposed to be reporting power usage in Watts have a state of ‘00:00’?

You can use sum with a list, but it would be a little more work to add the converted numbers to a list and then sum them later. Might as well just keep a running sum as you go.

BTW, you shouldn’t add the increment of count to the try clause if it’s already in the else clause. If the conversion to int worked it would have incremented count twice.

What does the state of one of these sensors look like? I.e., what is its state and its attributes? Is it maybe an attribute that should be summed?

they all are mqtt sensors:

  • platform: mqtt
    state_topic: ‘mac_address/powerswitch-zwave/id/usage’
    name: “Kantoor actueel”
    unit_of_measurement: “Watt”

with this state:

indeed that’s what i do in the original template sensor:

calculated_actual_usage_switches:
  friendly_name: 'Actueel gebruik switches'
  unit_of_measurement: 'Watt'
  value_template: >
    {{ (states('sensor.1_actueel')|int)
     + (states('sensor.2_actueel')|int)
     + (states('sensor.3_actueel')|int)
     + (states('sensor.4_actueel')|int)
     + (states('sensor.5_keuken_actueel')|int)
     + (states('sensor.6_actueel')|int)
     + (states('sensor.kantoor_actueel')|int)
     + (states('sensor.master_bedroom_actueel')|int)
     + (states('sensor.multi_purpose_actueel')|int)
     + (states('sensor.7_actueel')|int)
     + (states('sensor.tester_actueel')|int)
     + (states('sensor.8_actueel')|int)
     + (states('sensor.9_actueel')|int)
     + (states('sensor.10_actueel')|int)
     + (states('sensor.11_actueel')|int)
     + (states('sensor.12_actueel')|int)
     + (states('sensor.freezer_actueel')|int)
     + (states('sensor.13_actueel')|int)
     + (states('sensor.14_actueel')|int)
     + (states('sensor.15_actueel')|int)
     + (states('sensor.16_actueel')|int)
     + (states('sensor.17_actueel')|int) }}

I dont understand this either, hope you can se where it comes from now ive included the original sensors?

cool, KISS as a principle.
maybe later you could unveil how to use the list-sum construction. Always keen to learn here.

alright, my thought was to have the sensor show the added value for the sensors, and the count of these sensors. So the incremented count would need to be under Try? Since I couldn’t find a valid else I thought if the If condition wouldn’t be true, it would only increment count under Else, and not increment value… Hope this makes sense.
Should i do something else under the Else section then?

The else doesn’t go with the if, it goes with the try. Notice that it is at the same indentation level as try and except. In a try statement, if an exception occurs the except clause is executed. But if no exception occurs, then the else clause is executed (if there is one.) So, in this case, if the conversion to int works, then the else clause it executed, which increments the count.

I don’t see any reason why you got the exception when it tried to convert ‘00:00’ to int, because in theory the states should be numbers, not times. One thing you can try is to add logging to output what entity_id’s are being used and their states. See below.

BTW, looks like the numbers are floating point, not integers. So you should probably convert them to floats, not ints.

So, try this:

total_power = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel'):
        state = hass.states.get(entity_id)
        logger.debug('entity_id = {}, state = {}'.format(entity_id, state.state))
        try:
            total_power += float(state.state)
        except:
            pass
hass.states.set(
    'sensor.total_sensors', total_power, {'unit_of_measurement': 'Watt'})

Or, if you want the count of “valid” sensors, then this:

total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel'):
        state = hass.states.get(entity_id)
        logger.debug('entity_id = {}, state = {}'.format(entity_id, state.state))
        try:
            total_power += float(state.state)
        except:
            pass
        else:
            count += 1
hass.states.set(
    'sensor.total_sensors', total_power, {
        'unit_of_measurement': 'Watt',
        'count': count})

thank you very much for your efforts, unfortunately still only 0 …
seems no matter what i try , even tested hass.states.entity_ids('stupid'), the output stays the same… what on earth could be going wrong here, my other python scripts work all fine…

Ok, I figured it out. I tried a similar script on my system and added more logging. Turns out += doesn’t work in the sandboxed environment python_script’s run in. Argh! So, this should work:

total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel'):
        state = hass.states.get(entity_id)
        logger.debug('entity_id = {}, state = {}'.format(entity_id, state.state))
        try:
            total_power = total_power + float(state.state)
        except:
            pass
        else:
            count = count + 1
hass.states.set(
    'sensor.total_sensors', total_power, {
        'unit_of_measurement': 'Watt',
        'count': count})

bingo!


now add the count to the jinja…and we’re off! so cool this is,
a huge thx!