Template to add values of all sensors with certain name ending

indeed , and yes those 2 would suffice. Good to understand why there is no updating.

But since we successfully use the endswith filter now, I thought it might be possible to use it in this sensor value_template too somehow. I thought that might be an option since we’re not using a loop here, and, since you’ve successfully created a value_template using the endswith in the automation’s condition:

 value_template: >
      {{ trigger.event.data.entity_id.startswith('sensor.') and
         trigger.event.data.entity_id.endswith('actueel') }}

totaal_actueel_sensors:
  friendly_name: Totaal actueel
  unit_of_measurement: 'Watt'
  value_template: >
    {{ states.sensor|selectattr( 'entity_id','endswith','actueel')
    |map(attribute='state')|map('int')|sum }}

unfortunately this errors out: Error rendering template: TemplateRuntimeError: no test named 'endswith'
would be cool…probably my imagination taking the better of me again…?

or:

{{ states.sensor |map(endswith='actueel')|map(attribute='state')|map('int')|sum }}

error: Error rendering template: FilterArgumentError: map requires a filter argument

or take the endswith out of the filter mappings and try it as a condition:

{% if states.entity_id.endswith('actueel') %}
{{ states.sensor |map(attribute='state')|map('int')|sum }}
{%endif%}

would be nice too… but nothing happens (of course…) anyways, you get my drift…

something else:

this is a very nice template:

map_totaal_actueel_sensors:
  friendly_name: Overzicht sensors actueel
  unit_of_measurement: 'Watt'
  value_template: >
    {%-for state in states.sensor 
      if state.entity_id.endswith('actueel') and state.state >'0' %}
    {{state.name}} : {{state.state}}
    {%-endfor%}
  {{ '-'.ljust(30, '-') }} {{ '-'.ljust(30, '-') }}

based on @skalavala 's nrs 1 and 4 jinja, but there no way I can get it to show in the frontend (max 255 character count), and even with the custom-ui state card value_only, which i use in other places with sensors or log file like this, it doesn’t show up, either giving the Unknown, or stopping the system in a permanent loop it seems.

Could you see why that is?

Would be nice, and I even looked for something like that, but as you can see here there is no such test available.

Yes, state strings are limited to 255 characters. So you’d have to compact it until it was no more than that. Still, I don’t see how this would stop the system.

BTW, state.state >'0' - that is doing a string comparison, not a number comparison. That will not work in many cases. E.g., '0.0' > '0' is True. But '0.0'|float > 0 is False.

ah, thats why my stove reporting 0.0 is still showing…
cool: this does the trick: state.state|float > 0 !

still the 255 limit should be circumvented by the custom card. Somehow it doesn’t work here. Ive set the customization:

sensor.map_totaal_actueel_sensors:
  custom_ui_state_card: state-card-value_only

this will help: {{state.name[:-8]}} : {{state.state}}

well it does…
The system startsup, I can see all my startup notifications but cant reach the frontend in the browser nor app.
I’ve compacted it by adding the {{state.name[:-8]}} : {{state.state}}

this is flooding the log, apparently hogging the system.

2018-08-19 16:47:04 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 282, in async_update_ha_state
    self.entity_id, state, attr, self.force_update, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 851, in async_set
    context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 622, in __init__
    "State max length is 255 characters.").format(entity_id))
homeassistant.exceptions.InvalidStateError: Invalid state encountered for entity id: sensor.map_totaal_actueel_sensors. State max length is 255 characters.
ountered for entity id: sensor.map_totaal_actueel_sensors. State max length is 255 characters.
ttr, self.force_update, context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 851, in async_set
    context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 622, in __init__
    "State max length is 255 characters.").format(entity_id))
homeassistant.exceptions.InvalidStateError: Invalid state encountered for entity id: sensor.map_totaal_actueel_sensors. State max length is 255 characters.
.map_totaal_actueel_sensors. State max length is 255 characters.
t)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 851, in async_set
    context)
  File "/usr/local/lib/python3.6/site-packages/homeassistant/core.py", line 622, in __init__
    "State max length is 255 characters.").format(entity_id))

Well that sounds like a bug to me. Sure, it’s an error for an entity’s state string to be longer than 255 characters, but it shouldn’t have that effect.

I am following this with interest it is a bit of an education :slight_smile:
However is it possible that this…

…is related to my error here?

The sensor in question for me is the custom component Places. I only ask because the error refers to a ‘byte offset 284’.

(I don’t mean to hijack this thread, I will not continue this here but if you think it might be connected perhaps you could respond in my original thread. Thanks).

i fear for you this has nothing to do with each other. My 255 character error is a known issue, where the state of the sensor is 255+ characters, which the system does not allow.

Im trying to overcome that with a dedicated ‘text-only’ custom card, but am lost for the moment how to…

sorry, this doesn’t help you…

1 Like

maybe we can overcome this too using the Python.
I need an attribute ‘text’ with the outcome of the sensor as value. So where the regular jinja template sensor is:

map_totaal_actueel_sensors:
  friendly_name: Overzicht sensors actueel
  unit_of_measurement: 'Watt'
  value_template: >
    {%-for state in states.sensor 
    if state.entity_id.endswith('actueel') and state.state|float > 0 %}
    {{state.name[:-8]}}: {{state.state}}
    {%-endfor%}
    {{ '-'.ljust(30, '-') }} {{ '-'.ljust(30, '-') }}
   'Count sensors :' {{ state_attr('sensor.total_sensors', 'count') }} 'totaal: ' {{ states.sensor|selectattr( 'entity_id','in',state_attr('group.iungo_actueel_verbruik','entity_id'))
    |map(attribute='state')|map('int')|sum }} 

id need that to be calculated in Python, and be the value for text.

I can then create the sensor in Python as follows:

hass.states.set(
‘sensor.map_totaal_actueel_sensors’, ‘’, {
‘custom_ui_state_card’: ‘state-card-value_only’,
‘text’: outcome-of-template-here
})

I think an attribute ‘text’ cant be set in a regular sensor? If so that would be even easier to try.

Would you please have another go for me? Seems we have almost all already, the count, the total power usage, and the states.

Only thing left in this nicely printed overview is the formatting.

 ##########################################################################################
# map_total_sensors.py
# reading all sensors.*_actueel using power (>0), listing and counting them, and
# calculate summed power consumption
# by @Mariusthvdb  and big hand Phil, @pnbruckner
##########################################################################################
sensor_list = []
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))
        sensor = '{} : {}'.format(entity_id, state.state)
        try:
            power = float(state.state)
        except:
            continue
        if power > 0:
            total_power = round((total_power + power),2)
            count = count + 1

            sensor_list.append(sensor)

summary = '*============== Sensors ==============\n' \
          '----- Sensor ------------ Power -----\n' \
          '${}\n' \
          '*=============== Sumary ==============\n' \
          '$  Sensors    {}  :  Total Power  {}\n' \
          '*=====================================\n' \
          .format(sensor_list,
                  count,
                  total_power)

hass.states.set('sensor.map_total_sensors', '', {
        'custom_ui_state_card': 'state-card-value_only',
        'text': summary
        })
##########################################################################################
# map_total_sensors.py
##########################################################################################

showing as:

57

quite the result already, and updating immediately, both per sensor, as the total.

changed is somewhat to do away with the opening and closing list brackets, and the apostrophes around each sensor. As often the case, one needs intermediate variables, and a bit of playing with join, append and format…

This way each sensor gets and stays on its own line too, which is very nice when changing the browser window. (before it filled out, since the sensor section was seen as 1 entity.)

22

changed code:

sensor_list = []
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))
        #sensor_id = '{}'.format(entity_id)
        #sensor_power = '{}'.format(state.state)
        #sensor = '{}   -   {}\n'.format(sensor, senor_power)
        sensor = '{}   -   {}\n'.format(entity_id[7:-8], state.state)
        try:
            power = float(state.state)
        except:
            continue
        if power > 0:
            total_power = round((total_power + power),2)
            count = count + 1

            sensor_list.append(sensor)

sensor_map = '\n'.join(sensor_list)

summary = '*============== Sensors ==============\n' \
          '$----- Sensor ------------ Power -----\n' \
          '{}\n' \
          '*=============== Sumary ==============\n' \
          '$  Sensors    {}  :  Total Power  {}\n' \
          '*=====================================\n' \
          .format(sensor_map,
                  count,
                  total_power)

Of course ill need to reformat the rest of the map too, using some of the color options in the custom card, and better justification, as in the original jinja template.

1 Like

Looking good. Do you still need any help, with formatting, or whatever, or are you good now?

almost good…

trying to get the tabs or justification in there. No such luck. Somehow these option in the {} seem not to have the desired effect:

https://pyformat.info

and the ljust() and rjust() in @skalavala’s templates dont work being jinja…

so yes, im still in need of some cosmetical help :wink:

als tried to separate the entity_id from the state.state to play with colorizations, but that doesnt work. I can only get 1 color setting per line, which is of no big consequence. the tabbing would be really cool though.

got this working fine:

sensor_list = []
total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('actueel') and not 'sensors' in entity_id:
        state = hass.states.get(entity_id)
#        logger.debug('entity_id = {}, state = {}'.format(entity_id, state.state))
        sensor_id = '{}'.format(entity_id[7:-8].replace('_',' ').title())
        sensor_power = '\t{}'.format(state.state)
        sensor = '#{} :'.format(sensor_id) + ' {}\n'.format(sensor_power)
        try:
            power = float(state.state)
        except:
            continue
        if power > 0:
            total_power = round((total_power + power),2)
            count = count + 1

            sensor_list.append(sensor)

sensor_map = '\n'.join(sensor_list)

summary = '*============== Sensors ==============\n' \
          '$----------  Sensor    :     Power  ----------\n' \
          '{}\n' \
          '*=============== Sumary ==============\n' \
          '$  Total: Sensors    {}  :  Power  {}\n' \
          '*====================================\n' \
          .format(sensor_map,
                  count,
                  total_power)

and looking for a way to have it show as:

map_totaal_actueel_sensors:
  friendly_name: Overzicht sensors actueel
  unit_of_measurement: 'Watt'
  value_template: >
   {{ '-'.ljust(30, '-') }} {{ '-'.ljust(30, '-') }}
   {{ 'Entity ID'.ljust(30, ' ') }} {{ 'Actueel verbruik'.ljust(30, ' ') }}
   {{ '-'.ljust(30, '-') }} {{ '-'.ljust(30, '-') }}
   {%-for state in states.sensor 
     if  state.entity_id.endswith('actueel') and state.state >'0' %}
   {{state.name[:-8]}}: {{state.state.ljust(30, ' ')}}
   {%-endfor%}
   {{ '-'.ljust(30, '-') }} {{ '-'.ljust(30, '-') }}
   'Count sensors :' {{ state_attr('sensor.total_sensors', 'count') }} 'totaal: ' {{ states.sensor|selectattr( 'entity_id','in',state_attr('group.iungo_actueel_verbruik','entity_id'))
    |map(attribute='state')|map('int')|sum }} 

btw, there’s no way one can directly import/convert a yaml/jinja template like this in python is there? would be a great tool…
example:

i have a sensor.log_tail:

  - platform: file
    file_path: /config/home-assistant.log
    name: Log tail

which shows the last line in the log in the frontend. Every now and then this is more than 255 characters, so it errors out.
If i could make a pythons script like above, with the same value in ‘attribute’ : text that would be so nice.

hass.states.set('sensor.log_tail', '', {
        'custom_ui_state_card': 'state-card-value_only',
        'text': log-tail
        }) 

now how to get the log tail in a file through a python script…ill take it to a new thread, since it is a new subject, sort of. :wink:

That’s actually Python. Jinja let’s you use a lot of Python “stuff”. So '-'.ljust(30, '-') is Python. state.name[:-8] is Python. state.state.ljust(30, ' ') is Python.

right. sorry. should have phrased that differently.

what I meant was that i cant get these '-'.ljust(30, '-') and state.state.ljust(30, ' ') to behave as expected in the script…

[:-8] was my own doing, and reworked that to format(entity_id[7:-8].replace('_',' ').title()) in the python. showing nicely!

01
now the tabbing/justification … thats a whole challenge in itself

Why? Are you getting errors, and if so, what errors? Or does it just not do what you expect, and if so, what is it doing?

Those are valid Python statements, so I’m not sure why they wouldn’t work for you, even in the limited sandbox environment of python_scripts.

most of the time it just doesn’t do anything.

Try this:

sensor_list = []
total_power = 0
count = 0
for entity_id in hass.states.entity_ids('sensor'):
    if entity_id.endswith('_actueel') and 'sensors' not in entity_id:
        state = hass.states.get(entity_id)
        try:
            power = round(float(state.state), 2)
        except:
            continue
        if power > 0:
            total_power = total_power + power
            count = count + 1
            sensor_list.append('#{:21}: {:>7.2f}'.format(
                state.object_id.replace('_actueel','').replace('_',' ').title(),
                power))

summary = '\n'.join([
    '*{:=^30}'.format(' Sensors '),
    '${:-^20} : {:-^7}'.format(' Sensor ', 'Power '),
    *sensor_list,
    '*{:=^30}'.format(' Summary '),
    '$ Total: # {:<4} Power : {:>7.2f}'.format(count, total_power),
    '*' + '='*30])
    
hass.states.set('sensor.map_total_sensors', '', {
    'custom_ui_state_card': 'state-card-value_only',
    'text': summary})

o wow, thats a big change!

effect is rather small… sorry to say:

43

seems the Summary and sensor {:=^30}'.format works, their nicely centered. The order has changed, no clue yet which it is, not alphabetically, nor on value. But thats no big deal (would be nice though)

the other justifications seem not to stick yet.

Can’t explain why the spaces from the actual list of sensors seem to have disappeared. Could be something the custom UI formatting is doing. I tried this code in a Python shell and it worked fine. Here’s my example output:

>>> summary = '\n'.join([
...     '*{:=^30}'.format(' Sensors '),
...     '${:-^20} : {:-^7}'.format(' Sensor ', 'Power '),
...     *sensor_list,
...     '*{:=^30}'.format(' Summary '),
...     '$ Total: # {:<4} Power : {:>7.2f}'.format(count, total_power),
...     '*' + '='*30])
>>> print(summary)
*========== Sensors ===========
$------ Sensor ------ : Power -
#Abc 123              :    1.20
#Hey There            :  123.45
*========== Summary ===========
$ Total: # 2    Power : 1234.56
*==============================

Maybe check your HA log to see the actual state change to sensor.map_total_sensors to see if the spaces are there or not.

Not sure if the python_scripts environment includes the sorted function, but if it does you can change:

    *sensor_list,

to:

    *sorted(sensor_list),

yes, thats exactly what i am looking for!

how do you do that? try it in a Python shell?

it does!

Are you able to get to a shell (aka command line) on your HA system? If so, just execute the command python3. If not, then use any computer that has python installed, or install it. If you need help with the details I’d suggest Googling. That’s a bit beyond the scope of this forum. :wink: