@Tommmii I would encourage you to run some tests. uptime in minutes divided by the number of minutes in [hour, day, week] modulo the number of minutes in [hour, day, week] should yield the correct output. If you can demonstrate it does not, I’m happy to change the coding to fix!
from : Technicolor TG-789vac V2 DSL Stats
{%- set TIME_MAP = {
'week': (uptime / 604800) % 10080,
'day': (uptime / 86400) % 7,
'hour': (uptime / 3600) % 24,
'minute': (uptime % 60)
}
-%}
Also, one of the uptimes i’m tracking is at 1064848 seconds right now.
That converts to 1 w, 5 d, 7 h, 47 m, 28 s according to my calculation.
Confirmed by https://www.tools4noobs.com/online_tools/seconds_to_hh_mm_ss/
I’m sorry, I’m confused as to what the problem is. I receive a similar result of “1 week, 5 days, 7 hours, 47 minutes” with the code in my snippet. The smallest denomination in my snippet is minutes, so you would need to first divide 1,064,848 by 60.
This thread being named “Convert seconds to days, hours, minutes”, I hadn’t noticed your template is based on sensor.hass_uptime_minutes
which has minute resolution.
My bad.
He, really great, thanks @SupahNoob!
But where do you get the units from? And are they exchangable to jus ‘d’ instead of days for expample?
I tried googling after time formatting for jinja or pyhton but didn’t find a thing on what methods you are relying here.
I don’t necessarily think this has anything specifically to do what you are asking but here is something I wrote up a while back that has some info on time formatting:
Now there is an understatement.
My apologies, I realized this is a 3-year-old thread. However, it’s still very relevant; and, easily searchable on Google.com.
I just wanted to post ChatGPT’s solution; which I think IMHO is the nicest solution out of all the examples above. The resulting output and the code itself are both easier to read. It also supports years
and months
, and does NOT unnecessarily display 0 years or 0 months or 0 weeks or 0 hours for those cases.
Output Example:
8d 11h 45m
sensor.rt_ac5300_uptime
value is in seconds
template:
- sensor:
- name: "Asus Router Uptime"
state: >
{% set uptime = states.sensor.rt_ac5300_uptime.state | int %}
{% set years = uptime // 31536000 %}
{% set months = (uptime % 31536000) // 2592000 %}
{% set days = (uptime % 2592000) // 86400 %}
{% set hours = (uptime % 86400) // 3600 %}
{% set minutes = (uptime % 3600) // 60 %}
{{ '%dy ' % years if years else '' }}{{ '%dm ' % months if months else '' }}{{ '%dd ' % days if days else '' }}{{ '%dh ' % hours if hours else '' }}{{ '%dm' % minutes if minutes else '' }}
My UPS gives the time in seconds. I have added that to your ChatGPT example and it displays nicely.
- type: custom:mushroom-template-card
entity: sensor.ups_battery_runtime
primary: Runtime
secondary: |
{% set uptime = states.sensor.ups_battery_runtime.state | int %}
{% set years = uptime // 31536000 %}
{% set months = (uptime % 31536000) // 2592000 %}
{% set days = (uptime % 2592000) // 86400 %}
{% set hours = (uptime % 86400) // 3600 %}
{% set minutes = (uptime % 3600) // 60 %}
{% set seconds = (uptime % 60) %}
{{ '%dy ' % years if years else '' }}
{{ '%dm ' % months if months else '' }}
{{ '%dd ' % days if days else '' }}
{{ '%dh ' % hours if hours else '' }}
{{ '%dm ' % minutes if minutes else '' }}
{{ '%ds' % seconds if seconds else '' }}
Is there a way to get the minutes and seconds to always display 2 digits with a leading zero if necessary?
Thank you.
`
Nice! I purposefully didn’t add the seconds for mine since it was completely unnecessary in my case. But, nice that you were able to add seconds too.
Works well! Thank you very much!
So, I am trying the above timeticks conversion and am getting nowhere… I have my sensor configs in a sensors directory with files per device under that. This works and has worked for ages. But, when I put the below code in my mikrotik sensors file and run a configuration check it just sits and spins until I cut the code out and check it again… What have I done wrong? I have included the snmp sensor that sources the data and works fine.
- platform: snmp
name: "MT610 uptime"
unique_id: mt610uptime
host: 192.168.1.9
community: homeread
baseoid: .1.3.6.1.2.1.1.3.0
accept_errors: true
- platform: template
sensors:
mt610_real_uptime:
friendly_name: Mt610 Real Uptime
value_template: >-
{% set time = states.sensor.mt610_uptime.state | int %}
{% set minutes = ((time % 360000) / 6000) | int%}
{% set hours = ((time % 8640000) / 360000) | int %}
{% set days = (time / 8640000) | int %}
{%- if time < 6000 -%}
Less than a minute
{%- else -%}
{%- if days > 0 -%}
{%- if days == 1 -%}
1 day
{%- else -%}
{{ days }} days
{%- endif -%}
{%- endif -%}
{%- if hours > 0 -%}
{%- if days > 0 -%}
{{ ', ' }}
{%- endif -%}
{%- if hours == 1 -%}
1 hour
{%- else -%}
{{ hours }} hours
{%- endif -%}
{%- endif -%}
{%- if minutes > 0 -%}
{%- if days > 0 or hours > 0 -%}
{{ ', ' }}
{%- endif -%}
{%- if minutes == 1 -%}
1 minute
{%- else -%}
{{ minutes }} minutes
{%- endif -%}
{%- endif -%}
{%- endif -%}
So, when I put the above template sensor it the template tool, it works. It is off a couple of minutes, but it works.
When I save it to the yaml file that has the associated snmp sensor, save it and run a configuration check the configuration check just spins and never resolves.
Running the following on an i5 USSF.
Home Assistant 2023.8.4
Supervisor 2023.08.1
Operating System 10.5
Frontend 20230802.1 - latest
Results of the template test:
- platform: template
sensors:
mt610_real_uptime:
friendly_name: Mt610 Real Uptime
value_template: >-
8 days, 17 hours, 30 minutes
I think this is associated from the logs during check…
Logger: aiohttp.server
Source: helpers/config_validation.py:872
First occurred: 12:25:34 PM (3 occurrences)
Last logged: 12:29:04 PM
Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 433, in _handle_request
resp = await request_handler(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 504, in _handle
resp = await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_middlewares.py", line 117, in impl
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 85, in security_filter_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 236, in auth_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 148, in handle
result = await handler(request, **request.match_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/config/core.py", line 33, in post
errors = await async_check_ha_config_file(request.app["hass"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/config.py", line 978, in async_check_ha_config_file
res = await check_config.async_check_ha_config_file(hass)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/check_config.py", line 235, in async_check_ha_config_file
p_validated = platform_schema(p_validated)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 232, in __call__
return self._exec((Schema(val) for val in self.validators), v)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 351, in _exec
v = func(v)
^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
return base_validate(path, iteritems(data), out)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 387, in validate_mapping
cval = cvalue(key_path, value)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/config_validation.py", line 568, in verify
return cast(dict, schema(value))
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
return base_validate(path, iteritems(data), out)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 387, in validate_mapping
cval = cvalue(key_path, value)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 229, in _run
return self._exec(self._compiled, value, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 353, in _exec
v = func(path, v)
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/config_validation.py", line 872, in validator
if key in config:
^^^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable
im using this with a shunt in an off grid battery back up system. I have it working, but one thing id like to do is have it display the words “AC Power” when the unit is being charged. currently this code displays as per the attached photo when AC power is connected. Is there a way to do this.
Were you able to figure out how to resolve your problem?
Nope, would love to though.
I think the issue lies in the fact that states.sensor.mt610_uptime.state
is unknown
at the time of configuration check:
TypeError: argument of type 'NoneType' is not iterable
'| int
’, '| float'
, etc. need default values so try changing:
{% set time = states.sensor.mt610_uptime.state | int %}
{% set minutes = ((time % 360000) / 6000) | int%}
{% set hours = ((time % 8640000) / 360000) | int %}
{% set days = (time / 8640000) | int %}
to:
{% set time = states('sensor.mt610_uptime') | int(0) %}
{% set minutes = ((time % 360000) // 6000) %}
{% set hours = ((time % 8640000) // 360000) %}
{% set days = (time // 8640000) %}
and see if configuration check can complete.
My personal use of the coding in this topic looks like this:
{% set uptime = as_timestamp(now(),0) - as_timestamp(states('sensor.system_started'),0) -%}
{%- set years = uptime // 31536000 -%}
{%- set months = uptime % 31536000 // 2592000 -%}
{%- set days = uptime % 2592000 // 86400 -%}
{%- set hours = uptime % 86400 // 3600 -%}
{%- set minutes = uptime % 3600 // 60 -%}
{{ '%dy ' % years if years else '' }}{{ '%dm ' % months if months else '' }}{{ '%dd ' % days if days else '' }}{{ '%dh ' % hours if hours else '' }}{{ '%dm' % minutes if minutes else '' }}
Note the use of ‘//’.
Floor division is an operation in Python that allows us to divide two numbers and rounds the resultant value down to the nearest integer. The floor division occurs through the double-backslash (//) operator .
So, gave it a shot… still will not verify config.
Also tried it with just the template in yaml file. It is definitely a problem in the main conversion logic.
It still works this way in template test, but still about 9 minutes off.
Same logs… included below and triggered by configuration check.
sensors:
mt610_real_uptime:
friendly_name: Mt610 Real Uptime
value_template: >-
{% set time = states('sensor.mt610_uptime') | int(0) %}
{% set minutes = ((time % 360000) // 6000) %}
{% set hours = ((time % 8640000) // 360000) %}
{% set days = (time // 8640000) %}
{%- if time < 6000 -%}
Less than a minute
{%- else -%}
{%- if days > 0 -%}
{%- if days == 1 -%}
1 day
{%- else -%}
{{ days }} days
{%- endif -%}
{%- endif -%}
{%- if hours > 0 -%}
{%- if days > 0 -%}
{{ ', ' }}
{%- endif -%}
{%- if hours == 1 -%}
1 hour
{%- else -%}
{{ hours }} hours
{%- endif -%}
{%- endif -%}
{%- if minutes > 0 -%}
{%- if days > 0 or hours > 0 -%}
{{ ', ' }}
{%- endif -%}
{%- if minutes == 1 -%}
1 minute
{%- else -%}
{{ minutes }} minutes
{%- endif -%}
{%- endif -%}
{%- endif -%}
2024-01-01 22:43:54.095 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request
resp = await request_handler(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 543, in _handle
resp = await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_middlewares.py", line 114, in impl
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 85, in security_filter_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 233, in auth_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 31, in headers_middleware
response = await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 149, in handle
result = await handler(request, **request.match_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 63, in with_admin
return await func(self, request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/config/core.py", line 34, in post
res = await check_config.async_check_ha_config_file(request.app["hass"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/check_config.py", line 292, in async_check_ha_config_file
p_validated = platform_schema(p_validated)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 232, in __call__
return self._exec((Schema(val) for val in self.validators), v)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 351, in _exec
v = func(v)
^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
return base_validate(path, iteritems(data), out)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 387, in validate_mapping
cval = cvalue(key_path, value)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/config_validation.py", line 563, in verify
return cast(dict, schema(value))
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
return self._compiled([], data)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
return base_validate(path, iteritems(data), out)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 387, in validate_mapping
cval = cvalue(key_path, value)
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 229, in _run
return self._exec(self._compiled, value, path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 353, in _exec
v = func(path, v)
^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
return schema(data)
^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/config_validation.py", line 866, in validator
if key in config:
^^^^^^^^^^^^^
TypeError: argument of type 'NoneType' is not iterable
What does Dev Tools > Template show for {{ states('sensor.mt610_uptime') }}
?
Try adding the sensor via HA Helpers > Template a sensor:
Can you try setting up the sensor using HA modern configuration?
I use modern style and my uptime sensor is this:
configuration.yaml:
template: !include_dir_merge_list templates/
templates/sensor.yaml:
- sensor:
- name: "System Uptime"
unique_id: system_uptime
state: >
{% set uptime = as_timestamp(now(),0) - as_timestamp(states('sensor.system_started'),0) -%}
{%- set years = uptime // 31536000 -%}
{%- set months = uptime % 31536000 // 2592000 -%}
{%- set days = uptime % 2592000 // 86400 -%}
{%- set hours = uptime % 86400 // 3600 -%}
{%- set minutes = uptime % 3600 // 60 -%}
{{ '%dy ' % years if years else '' }}{{ '%dm ' % months if months else '' }}{{ '%dd ' % days if days else '' }}{{ '%dh ' % hours if hours else '' }}{{ '%dm' % minutes if minutes else '' }}
You can use modern format within configuration.yaml without !include_dir_merge_list
in which case your template
would be:
template:
- sensor:
- name: "System Uptime"
unique_id: system_uptime
state: >
{% set uptime = as_timestamp(now(),0) - as_timestamp(states('sensor.system_started'),0) -%}
. . .
It shows 432427643
So I currently have a /sensor/mikrotiksnmp.yaml file that pulls other snmp data and applies templates to all the different data. They are working… I have converted some of the included yaml files to the “modern” style, but I really do not understand the process fully. I can get them to work, but you know…
So, looking at the last block you have included it looks like that would provide the uptime already in proper format? There must be more to it? Can I include a template section in the configuration.yaml if I have !include files that also have templates?