Here comes another question or maybe even a challenge.
I have a motion sensor that I want to show the “last motion detected” date/time. One of the attributes of the sensor has “last motion updated” However, the timezone is incorrect and once I pull the information to the front, the formatting is less then attractive: [‘2019-01-27’, ‘23:57:03’]
How would I go about formatting a template with the following:
Dream setup:
Correct time zone.
Day/Month and 24h time formatting.
If motion was detected less then an 1 min ago just show > Less then a min. ago
If motion was detected less then an hour ago just show the minutes. X min. ago
If motion was detected today. I would like it to show > Today at 23:57
If yesterday > Yesterday at 23:57
If later then two days ago, show the day name and time > Monday at 23:57
If later then 7 days ago, the day/month and time > 28/01 at 23:57
Acceptable setup:
Also, alternatively. Just showing the correct date and time for each last movement sensed. 28/01 at 23:57
One of them is a Hue Motion sensor and thats the only one showing an attribute with motion last_updated date/time as shown above. The other three do not have an attribute for time, but the logs register it obviously. I have no idea why the time zone is off by three hours on the Hue. The hue bridge is set to the correct time zone… Instead of using the sensors own time, maybe using the logs time-stamp would be more “practical” for all 4 of them?
All 4 sensors are binary, on the states only show > On or Off
Correct. It is off by three hours, so +3 on whatever the time is saying on the sensor.
What about the idea of pulling the “latest” information/time stamp from the logs, is that even possible?
The Hue sensor has the entity_id > binary_sensor.kitchen_motion_motion_sensor
And since it’s showing UTC time, adding +3 should be correct.
Sine the update to lovelace I have been having problems with the underscores. See, the Hue Motion Sensor is a custom component that I recently installed. But thats another problem for later. If you are planning to create a sample, use that e-id, I will have to change it later if need be. Thanks a million!
I’m having @Ice’s identical issue really, apart from underscores seem to be working. Looking for a way to format the timestamp of the Hue sensor YYYY-MM-DD,HH:MM:SS into something palatable to use in a relative_time template for ‘X minutes ago’
We get the state of your last_updated attribute and set it equal to t. Do not confuse this last_updated attribute with last_updated datetime object. The last_updated datetime object is a homeassistant object that is OUTSIDE the attributes. The last_updated attribute is only supplied by your sensor. All home assistant state objects contain the last_updated datetime object. So why am i saying this? This method will only work on your binary sensor it will not work on any other home assistant object you have. Unless that have the last_updated attribute.
The next thing we do is convert your last_updated into a datetime object in UTC. So we add +0000 to your state which indicates UTC. Then strptime converts it to a datetime object with the correct format. The format is all those funky characters in the strptime function. They basically say “this is the format of the date that we will always get from your sensor”.
Once we have the datetime object, we convert it to a timestamp and then output the correct format we want. This uses the same funky characters in step 2.
sensor:
- platform: template
sensors:
kitchen_motion_last_updated:
friendly_name: Last Kitchen Motion
value_template: >
{% set t = state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated') %}
{% set t = strptime(t+"-+0000", "%Y-%m-%d,%H:%M:%S-%z") %}
{{ as_timestamp(t) | timestamp_custom('%m/%d at %H:%M') }}
I don’t think you should implement this part of your statement, it will complicate your template and it won’t really give you what you want as it will only update once a minute.
I guess I’ll just post the solutions for future people who stumble on this post. These templates will output in the following cases:
If motion was detected less then an 1 min ago just show > Less then a min. ago
If motion was detected less then an hour ago just show the minutes. X min. ago
If motion was detected today. I would like it to show > Today at 23:57
If yesterday > Yesterday at 23:57
If later then two days ago, show the day name and time > Monday at 23:57
If later then 7 days ago, the day/month and time > 28/01 at 23:57
last_updated as an attribute
sensor:
- platform: template
sensors:
kitchen_motion_last_updated:
friendly_name: Last Kitchen Motion
entity_id: sun.sun
value_template: >
{%- set t_string = state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated') %}
{%- if t_string != None %}
{%- set t = strptime(t_string+"-+0000", "%Y-%m-%d,%H:%M:%S-%z") %}
{%- set t = as_timestamp(t) %}
{%- set n = now().timestamp() %}
{%- set d = n-t %}
{%- set midnight_today = as_timestamp(strptime(now().date() | string, "%Y-%m-%d")) %}
{%- set midnight_yesterday = midnight_today - 86400 %}
{%- set midnight_week_ago = midnight_today - 604800 %}
{%- if d < 60 %}
Less then a min. ago
{%- elif d < 3600 %}
{{ (d // 60) | int }} min. ago
{%- elif d < n-midnight_today %}
Today at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_yesterday %}
Yesterday at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_week_ago %}
{{ t | timestamp_custom('%A at %H:%M') }}
{%- else %}
{{ t | timestamp_custom('%m/%d at %H:%M') }}
{%- endif %}
{% else %}
unknown
{% endif %}
Anyone using this template may need to edit the format in this line to have it work with there last_updated attribute: {%- set t = strptime(t+"-+0000", "%Y-%m-%d,%H:%M:%S-%z") %}.
last_updated datetime on state_objects
(99% users should use this template). Just remember to replace binary_sensor.kitchen_motion_motion_sensor with your entity_id inside the first line of the template.
sensor:
- platform: template
sensors:
kitchen_motion_last_updated:
friendly_name: Last Kitchen Motion
entity_id: sun.sun
value_template: >
{%- set entity_id = 'binary_sensor.kitchen_motion_motion_sensor' %}
{%- set domain, object_id = entity_id.split('.') %}
{%- set state_object = states[domain][object_id] %}
{%- if state_object is defined and state_object.last_updated is defined %}
{%- set t = as_timestamp(state_object.last_updated) %}
{%- set n = now().timestamp() %}
{%- set d = n-t %}
{%- set midnight_today = as_timestamp(strptime(now().date() | string, "%Y-%m-%d")) %}
{%- set midnight_yesterday = midnight_today - 86400 %}
{%- set midnight_week_ago = midnight_today - 604800 %}
{%- if d < 60 %}
Less then a min. ago
{%- elif d < 3600 %}
{{ (d // 60) | int }} min. ago
{%- elif d < n-midnight_today %}
Today at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_yesterday %}
Yesterday at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_week_ago %}
{{ t | timestamp_custom('%A at %H:%M') }}
{%- else %}
{{ t | timestamp_custom('%m/%d at %H:%M') }}
{%- endif %}
{% else %}
unknown
{% endif %}
If you are getting unknown in either situation, check your entity_id and verify that it contains last_updated as an attribute. Unknown can also occur during startup but it should rectify when last_updated changed or a minute has passed.
ERROR (MainThread) [homeassistant.helpers.entity] Update for sensor.kitchen_motion_last_updated fails
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 221, in async_update_ha_state
await self.async_device_update()
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 347, in async_device_update
await self.async_update()
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/sensor/template.py", line 196, in async_update
self._state = self._template.async_render()
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/template.py", line 138, in async_render
return self._compiled.render(kwargs).strip()
File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "
TypeError: can only concatenate list (not "str") to list
{%- set t_string = state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated') %}
to
{%- set t_string = ''.join(state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated')) %}
so…
sensor:
- platform: template
sensors:
kitchen_motion_last_updated:
friendly_name: Last Kitchen Motion
entity_id: sun.sun
value_template: >
{%- set t_string = ''.join(state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated')) %}
{% if t_string != None %}
{%- set t = strptime(t_string+"-+0000", "%Y-%m-%d,%H:%M:%S-%z") %}
{%- set t = as_timestamp(t) %}
{%- set n = now().timestamp() %}
{%- set d = n-t %}
{%- set midnight_today = as_timestamp(strptime(now().date() | string, "%Y-%m-%d")) %}
{%- set midnight_yesterday = midnight_today - 86400 %}
{%- if d < 60 %}
Less then a min. ago
{%- elif d < 3600 %}
{{ (d // 60) | int }} min. ago
{%- elif d < n-midnight_today %}
Today at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_yesterday %}
Yesterday at {{ t | timestamp_custom('%H:%M') }}
{%- else %}
{{ t | timestamp_custom('%m/%d at %H:%M') }}
{%- endif %}
{% else %}
unknown
{% endif %}
Update for sensor.kitchen_motion_last_updated fails
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 221, in async_update_ha_state
await self.async_device_update()
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 347, in async_device_update
await self.async_update()
File "/usr/local/lib/python3.6/site-packages/homeassistant/components/sensor/template.py", line 196, in async_update
self._state = self._template.async_render()
File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/template.py", line 138, in async_render
return self._compiled.render(kwargs).strip()
File "/usr/local/lib/python3.6/site-packages/jinja2/asyncsupport.py", line 76, in render
return original_render(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 1008, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/local/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
raise value.with_traceback(tb)
File "
TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'
sensor:
- platform: template
sensors:
kitchen_motion_last_updated:
friendly_name: Last Kitchen Motion
entity_id: sun.sun
value_template: >
{%- set t_string = ','.join(state_attr('binary_sensor.kitchen_motion_motion_sensor','last_updated')) %}
{%- if t_string != None %}
{%- set t = strptime(t_string+"-+0000", "%Y-%m-%d,%H:%M:%S-%z") %}
{%- set t = as_timestamp(t) %}
{%- set n = now().timestamp() %}
{%- set d = n-t %}
{%- set midnight_today = as_timestamp(strptime(now().date() | string, "%Y-%m-%d")) %}
{%- set midnight_yesterday = midnight_today - 86400 %}
{%- set midnight_week_ago = midnight_today - 604800 %}
{%- if d < 60 %}
Less then a min. ago
{%- elif d < 3600 %}
{{ (d // 60) | int }} min. ago
{%- elif d < n-midnight_today %}
Today at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_yesterday %}
Yesterday at {{ t | timestamp_custom('%H:%M') }}
{%- elif d < n-midnight_week_ago %}
{{ t | timestamp_custom('%A at %H:%M') }}
{%- else %}
{{ t | timestamp_custom('%m/%d at %H:%M') }}
{%- endif %}
{% else %}
unknown
{% endif %}