Please help with template for last motion

Yes, I understand how the code works. My point was: If the code is getting re-rendered because it’s updating every 30 seconds, the code will never give you anything other than less than a minute.

Thanks for all your help so far! Now I understand your point using automations as trigger, that really works brilliantly and together with Petro`s pice of code it delivers exactly what I was looking for. I only removed the seconds to limit the display to minutes.

Bildschirmfoto 2021-01-07 um 16.46.33

One final question if you don’t mind. Occasionally it throws back the following error message, even though all is working. I understand that the root cause is the code I added to sensor.yaml and the system seems to be irritated by the attribute ‘None’. Any idea why?

Logger: homeassistant.components.template.template_entity
Source: components/template/template_entity.py:71
Integration: template (documentation, issues)
First occurred: 16:41:50 (5 occurrences)
Last logged: 16:41:50

  • TemplateError(‘UndefinedError: ‘None’ has no attribute ‘attributes’’) while processing template ‘Template("{%- set up = as_timestamp(now())-as_timestamp(states.automation.letzte_bewegung_im_aussenbereich.attributes.last_triggered) %} {%- macro phrase(name,divisor,mod=None) %} {%- set value = ((up//divisor) % (mod if mod else divisor))|int %} {%- set end = ‘’ if value > 1 else ‘’ %} {{- ‘{} {}{}’.format(value,name,end) if value|int > 0 else ‘’}} {%- endmacro %} {%- set values = [phrase(‘w’,6060247), phrase(‘d’,606024,7), phrase(‘h’,6060,24), phrase(‘m’,60)] |select(’!=’,’’)|list %} {{values[:-1]|join(’, ‘) ~ ’ ’ ~ values[-1] if values|length > 1 else values|first}}")’ for attribute ‘_state’ in entity ‘sensor.since_last_motion_outdoor’

it’s because you’re using states.automation.letzte_bewegung_im_aussenbereich.attributes.last_triggered. Change the syntax to

state_attr('automation.letzte_bewegung_im_aussenbereich', 'last_triggered')

That will not work for last_changed or last_updated.

yes, as I posted/edited above already.
fyi, it has to do with the way templates are dealt with when an entity isnt ‘ready yet’ see the warning at https://www.home-assistant.io/docs/configuration/templating/#states

It’s not looking for an attribute ‘None’, it’s in fact saying there is no attribute (because somehow the state isn’t available in HA’s state machine)

haha, like your ‘irritated’. that’s what we all can relate to in these circumstances… :wink:

Thanks guys…seems to work like a charm now - and so far without errors :slight_smile:

Also thanks for the explanation. I guess I still need some time until I figure those things out in detail!

So following along I got all this working after much headaches with dictionary syntax (this post being very useful https://github.com/rogro82/hass-variables/issues/47#issuecomment-717864105) and variables… the indenting is such a nightmare as well… I guess you get used to it.

I have a History Graph working nicely for variable.last_motion (as per https://diyfuturism.com/index.php/2017/12/15/useful-sensor-motion-last-seen-________/) but now I’d like to add a card as per Alex’s above, i.e, sensor name on the left, last motion on the right and I’m just not sure how to do it.

I have since_last_motion_mhd added as a binary_sensor as per @Mariusthvdb post above but it doesn’t seem to be updating as it shows the time since last boot. I changed the automation name in the template as for some reason in all my fiddling it got renamed to automation.update_last_motion_2 (side note: can I fix this?). It was throwing TypeError: unsupported operand type(s) for -: ‘float’ and ‘NoneType’, I imagine due to automation.update_last_motion having a Null value for last_triggered?

Looking now I see it has thrown it once since the last reboot as well but it’s reporting it a little differently:
File “<template>”, line 7, in top-level template code
TypeError: unsupported operand type(s) for -: ‘float’ and ‘NoneType’

Here is how I have the template set up:

binary_sensor:
  - platform: template
    sensors:
      since_last_motion_mhd:
        friendly_name: 'Since Last Motion'
        value_template: >-
          {%- set up = as_timestamp(now())-as_timestamp(state_attr('automation.update_last_motion_2','last_triggered')) %}
          {%- macro phrase(name,divisor,mod=None) %}
            {%- set value = ((up//divisor) % (mod if mod else divisor))|int %}
            {%- set end = 's' if value > 1 else '' %}
            {{- '{} {}{}'.format(value,name,end) if value|int > 0 else ''}}
          {%- endmacro %}
          {%- set values = [phrase('week',60*60*24*7),
                            phrase('day',60*60*24,7),
                            phrase('hour',60*60,24),
                            phrase('min',60),
                            phrase('sec',1,60)]
                            |select('!=','')|list %}
          {{values[:-1]|join(', ') ~ ' and ' ~ values[-1] if values|length > 1 else
            values|first}}

Also, it does seem to update if I throw it into the Template editor:

binary_sensor:
  - platform: template
    sensors:
      since_last_motion_mhd:
        friendly_name: 'Since Last Motion'
        value_template: >-
          58 secs

Ah, changed from binary_sensor to sensor and I get a value now in lovelace. Also wrapped the template code in an if block to prevent the error… seems effective if maybe not the best way?
{% if state_attr(‘automation.update_last_motion_2’,‘last_triggered’) != None %}

Still not sure how to config the lovelace card for each sensor to show last_triggered.

you mean like this?:

Wow that is pretty cool! I actually meant as per Alex’s screenshot with the name on the left and the data from the template on the right (just to understand how it works), but I do like what you are doing there.

yeah, but tbh, that screenshot is pre-Lovelace I fear :wink:

my screen dump is a section of all my motion sensors, and I can click those to toggle the sensor (green is on/ grey is off) Note these are Philips Hue sensors, so require some serious back end config for the switches.
to get you started, here’s a single button:

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: button_motion
        name: Laundry
        entity: binary_sensor.laundry_sensor_motion
        triggers_update: switch.laundry_sensor_motion
        variables:
          clear_icon: mdi:washing-machine

etcetc

with the button_motion template:

button_motion:
  template: button_body
  variables:
    motion_icon: motion_icon
    clear_icon: clear_icon
  show_last_changed: true
  tap_action:
    action: call-service
    service: switch.toggle
    service_data:
      entity_id: >
        [[[return 'switch.' + entity.entity_id.split('.')[1] ]]]
#        switch.laundry_sensor_motion
#        binary_sensor.laundry_sensor_motion
  state:
    - value: 'on'
      styles:
        card:
          - color: red
        name:
          - color: black
        icon:
          - color: red
    - operator: template
      value: >
        [[[ var id = 'switch.' + entity.entity_id.split('.')[1];
        return states[id].state == 'on';
        ]]]
      icon: >
        [[[ return variables.clear_icon ]]]
      styles:
        card:
          - color: grey
        icon:
          - color: green
        state:
          - color: green
    - operator: default
      icon: >
        [[[ return variables.clear_icon ]]]
      styles:
        card:
          - color: grey
#          - opacity: 0.8
        icon:
          - color: grey

and the used button_body:

button_body:
  color: auto
  size: 30%
  aspect_ratio: 1/1
  show_state: true
  show_label: true
  tap_action:
    action: more-info
    haptic: light
  hold_action:
    action: more-info
    haptic: success
  styles:
    icon:
      - color: grey
    lock:
      - color: red
    card:
      - background-color: var(--card-background-color)
      - color: var(--primary-color)
      - padding-left: 5px
    name:
      - font-family: Helvetica
      - font-size: 13px
      - font-weight: bold
      - justify-self: start
      - text-align: start
      - text-overflow: unset
      - white-space: unset
      - word-break: break-word
    label:
      - font-family: Helvetica
      - font-size: 11px
      - justify-self: start
      - text-align: start
    state:
      - font-family: Helvetica
      - font-size: 11px
      - font-weight: bold
      - justify-self: start
      - text-align: start
      - text-transform: capitalize
    grid:
      - grid-template-areas: '"i" "n" "s" "l"'
      - grid-template-columns: 1fr
      - grid-template-rows: 1fr min-content min-content
    img_cell:
      - align-items: start
      - justify-content: start

So I have it working pretty much as per your screenshot. Since I’m new to this, some discoveries (maybe for my future self when I forget what I did).

  • installed HACS - manually step by step as the install script failed due to permissions even though I was running sudo. Quite a good video here- https://www.youtube.com/watch?v=OcJd3MzCD9A&feature=emb_logo

  • installed button-card custom card via HACS. Since I’m new it wasn’t obvious that this wasn’t core HA.

  • added your button_motion and button_body templates to my Dashboard via the top right “Raw Configuration Editor” when in edit mode. Put them above “title:” and under “button_card_templates:” (create this). If you’re running in YAML mode this needs to go in ui-lovelace.yaml instead.

  • after that make the new card with a combination of vertical and horizontal-stacks with cards like this:

        - type: horizontal-stack
          cards:
            - type: 'custom:button-card'
              template: button_motion
              entity: alarm_control_panel.home
              variables:
                clear_icon: 'mdi:shield-home-outline'
            - type: 'custom:button-card'
              template: button_motion
              name: Front Door
              entity: binary_sensor.front_door
              variables:
                clear_icon: 'mdi:door'
    

So the part I don’t have working is how to use the since_last_motion_mhd to add a custom label. It looks like just a sensor to me that shows the time since any of my sensors (tied to the automation) last saw motion. How would I use that generically for each sensor?

From my reading it seems like I’d need to re-write it as [[[ some javscript equivalent ]]] and add it to a template under button_card_templates: or add to each button individually if I needed one off formatting? Any way to re-use the Jinja2 code that I already have?

unless I misunderstand you, but you don’t have to don’t you? each sensor has got its last motion in the last_changed field, as you already experienced.

your last paragraph is not very clear to me. Please tell us what you want to accomplish (what data do you want to see where)

fwiw, here’s my last_motion button:

      - type: custom:button-card
        template: button_body
        entity: variable.last_motion
        tap_action:
          action: more-info
        name: >
          [[[
          var fakestate = `<span style="color: red;font-size: 11px;word-wrap:break-word;"> ${entity.state.substr(0, entity.state.length-10)} </span>`;
          return 'Last motion' + "<br>" + fakestate
          ]]]
        show_label: false
        show_state: false
        show_last_changed: true
        show_name: true
#        label_template: >
#          return entity.state.substr(0, entity.state.length-11) +
#          "<br>" + entity.last_changed
        state:
          - operator: default
            styles:
              card:
                - color: grey
#                - opacity: 0.8
              icon:
                - color: red

it’s still using a variable fakestate in the name field, because at that time my FR for the now available state_display wasn’t written yet :slight_smile:

Schermafbeelding 2021-01-13 om 09.12.22

That works for me too. Funky. But you’re using your fakestate [[[ JavaScript ]]] to format the data.

I’ll rephrase. This thread started off talking about making a card that showed the last time any sensor was triggered, though formatted in a particular way, then you proposed a YAML template to format week, day, hour, min, sec right? That’s all pretty clear.

Then Alex posts that he got this working and shows an example like this, i.e. two different sensors each displaying their own formatted last_triggered, presumably via the YAML template.
image

The implication, as I read it, was that he used that generic template to somehow pass in a sensor name and output the fomatted last_triggered time for each sensor individually, not just one card with the name and last_triggered of the last sensor that called the automation, but multiple sensors on individual rows.

That’s the bit that stumps me… I feel like I’ve got that completely wrong and he just used JavaScript (much like your fakestate example) on a custom card like button-card (though not sure how he laid it out horizontally like that) and didn’t use the YAML template at all?

Maybe the question is, can you use a YAML template to format the label on custom cards or do you need to use JavaScript? If not, what was the point of writing the template? Was it only for that initial use case of showing the last sensor that triggered?

There’s simply not just 1 answer to this. You’ve got to remember the last_motion (using custom integration Variable) automation and template sensors were written some time ago (before Lovelace came along). Also, this is all done in the backend.

With core Lovelace, (strictly Frontend), you needed backend templates to reveal those last_changed data fields. Until a secondary_info line was introduced, which now can make that happen without any template at all.

Of course, there are other options, to minimize Lovelace card configs even further. Most notable would be to have a look at custom card auto-entities, and throw that at multiple or _globbed entities (seems to be what you ask?)

  - type: custom:auto-entities
    card:
      type: entities
      title: Motion sensors
    filter:
      include:
        - entity_id: binary_sensor.*_sensor_motion
          options:
            secondary_info: last-changed

showing like:


no template used at all.

You can even combine that card with template-entity-row, to have each line configured exactly as you like (using Jinja templates in a Lovelace card config) …

Note though, that doing so doesn’t create any backend state sensor. If you need any data derived from those motion sensors, you’d still have to create template sensors for that (or use templates in an automation/script)
So again, its all up to you, and depending on your needs.

The options are endless.

(must confess the colors and icons are customized, and not in the Lovelace configs). The card will work without that too obviously, albeit not as nicely looking :wink:

OK, so I guess the answer is, it depends then, but if I were to pureful use button-config I’d need some JS, whereas template-entity-row accepts Jinja2… maybe that’s what Alex did in some fashion. I didn’t really need to to do it per se, I just wanted to understand. :slight_smile:

Anyway, thanks for the explanations, it’s been very helpful and I have it working mostly how I want it now. There’s a lot of complexity here and standards vary a lot across customisations. The help could be expanded a lot. Seems there is a lot of local/assumed knowledge going and and you have to trawl through forums to work it out.

Now I just need to work out how to install Add-ons (like Samba) without Supervisor. The help says:
“Add-ons are only available if you’ve used the Home Assistant installer. If you installed Home Assistant using any other method then you cannot use add-ons (but you can achieve the same result manually).”

… which if I’m honest, isn’t very helpful :wink: I suppose I could just install it straight onto the pi.

Thanks again!

I basically used the template and applied it to all sensors and/or groups that I needed. Might not be the most efficient way, but it does the trick. For example:


since_last_motion_outdoor:
friendly_name: ‘Letzte Bewegung im Außenbereich’
value_template: >
{%- set up = as_timestamp(now())-as_timestamp(state_attr(‘automation.letzte_bewegung_im_aussenbereich’,‘last_triggered’)) %}

      {%- macro phrase(name,divisor,mod=None) %}
        {%- set value = ((up//divisor) % (mod if mod else divisor))|int %}
        {%- set end = '' if value > 1 else '' %}
        {{- '{} {}{}'.format(value,name,end) if value|int > 0 else ''}}
      {%- endmacro %}

      {%- set values = [phrase('w',60*60*24*7),
                        phrase('d',60*60*24,7),
                        phrase('h',60*60,24),
                        phrase('m',60)]
                        |select('!=','')|list %}
      {{values[:-1]|join(', ') ~ ' ' ~ values[-1] if values|length > 1 else values|first}}

since_last_motion_storage:
  friendly_name: 'Letzte Bewegung im Abstellraum'
  value_template: >
    {%- set up = as_timestamp(now())-as_timestamp(state_attr('automation.bewegung_im_abstellraum','last_triggered')) %}

      {%- macro phrase(name,divisor,mod=None) %}
        {%- set value = ((up//divisor) % (mod if mod else divisor))|int %}
        {%- set end = '' if value > 1 else '' %}
        {{- '{} {}{}'.format(value,name,end) if value|int > 0 else ''}}
      {%- endmacro %}

      {%- set values = [phrase('w',60*60*24*7),
                        phrase('d',60*60*24,7),
                        phrase('h',60*60,24),
                        phrase('m',60)]
                        |select('!=','')|list %}
      {{values[:-1]|join(', ') ~ ' ' ~ values[-1] if values|length > 1 else values|first}}

After a while running the code, I also got the failure that you mentioned {% if state_attr(‘automation.update_last_motion_2’,‘last_triggered’) != None %}, but I neglected it, as it really appears very infrequent (once every week or so). It also does not seem to impact standard operation.

Ah thanks for that. So basically you made multiple copies of the template.

Which card did you use in that example? It looks like button-card but I couldn’t make it lay out like that.

I used an “entities” card and after Marius’ last input, I added the secondary_info to it, which made the look even smoother and produced the same result.

Bildschirmfoto 2021-01-20 um 08.21.43

Only for “general movement within the house” I am still using sensors.yaml as I am checking if any of the motion sensors is triggered (as per Reolof’s example). I am using this for the movement status in my entities card, but also as trigger for the alarm system. To me this one pice of code was simpler than adding each motion sensor separately as trigger.