How to make Sensor show minutes or hours instead of 0.52 hours = 30 minutes

Hello,

Have a sensor that takes attribute of my thermostat to tell me if its on or off, then have a sensor created to tell me it in time being on state.

it currently shows 0.5 hours which is 30 minutes, bit confusing to me to quickly gather, i’d prefer either minutes or hours and minute.

how would I do this, preferable both options as might depend, ie 120 minutes or 1 Hour 20 minutes
either help with code or guidance to which HA docs this would be, i’m virgin to templating so not great as grasping yet.

# Hvac Activiy - picks up when its on
  - platform: template
    sensors:
      hvac_activity:
        friendly_name: 'HVAC Activity'
        value_template: '{{ state_attr("climate.wiser_thermostat", "hvac_action") }}'


# Thermostat Day - Records it in days
  - platform: history_stats
    name: Thermostat Heating Today
    entity_id: sensor.hvac_activity
    state: 'heating'
    type: time
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"

Make a template sensor and multiply by 60.

where in the code do I put x60?

Just updating as petro pointing me in the right direction, got it working had to make another sensor using my other number sensor to x60 with below code

# Hvac Activiy
  - platform: template
    sensors:
      hvac_activity:
        friendly_name: 'HVAC Activity'
        value_template: '{{ state_attr("climate.wiser_thermostat", "hvac_action") }}'
# Hvac Activiy x 60
  - platform: template
    sensors:
      hvac_test:
        friendly_name: 'HVAC test'
        value_template: "{{ states('sensor.thermostat_heating_today') | float(default=0.0) | multiply(60) | round(1) }}"

He mentioned this should be easier with the next wednesday release as something is coming with it

At the moment, the history_stats senor has an attribute value that shows days, hours, minutes.


This ‘value’ will be removed in the upcoming 2022.5 release to avoid to many attribute records in the database.

The device_class ‘duration’ shows the state in a human readable format in the frontend.
20220502_224811

1 Like

Thanks, Entities now show in a Human readable number now in the new Release,

however they are still showing incorrect in bar charts, not sure if its a bug or not

Created a test “duration” sensor:

sensor:
  - platform: template
    sensors:

      test_device_class_duration:
        device_class: duration
        value_template: >-
          {% set INPUT_NAME = "input_number.test_device_class_duration" -%}
          {{ states(INPUT_NAME) }}

But this sensor does not show a time:
изображение

Also, I expected a special icon automatically assigned for this sensor.

Tried the same, it shows a time if you add unit_of_measurement: h to the template sensor.
20220512_120803

No clue about the icon.

1 Like

I managed to get a proper presentation by adding UoM!

I wonder which device_classes also need adding UoM to be presented properly…

All of them for sensors.

I mean:

  1. To make the value to be displayed with UoM - surely we must specify UoM.
  2. But at least the duration sensor is displayed in hh:mm:ss format only if UoM is specified.

i.e. the displayed VALUE is different for the “duration”.
That is why I am asking (sorry for off-topic) about different device_classes whose presentation depends on presence of UoM.

All device classes for sensor need UoM so that it can be used properly in home assistant. This is the bases for converting values from one unit to another (I.e. energy panel, converting c to f, etc). This is no different for duration. You need to let the system know what the duration units are in so that it can properly change the display for you.

EDIT: I think the only exception is timestamps, which are unitless

Probably I need to create test sensors for all device_classes and see what changes if UoM is specified.
Thanks a lot for clarifications!

It’s in the early stages, so I wouldn’t expect sweeping changes to your UI. C to F has been there from the beginning of time. So that one is unique. All the rest are within the last year.

I created test sensors for different dev_classes - here is a code-generator below.
Probably my test is wrong since I am using input_number values which do not have device_class specified, but they have UoMs specified.

{% set CLASSES_SENSOR = [
  ("aqi","AQI"),
  ("apparent_power","VA"),
  ("battery","%"),
  ("carbon_dioxide","CO2"),
  ("carbon_monoxide","CO"),
  ("current","A"),
  ("duration","h"),
  ("energy","kWh"),
  ("frequency","MHz"),
  ("gas","\u006d\u00b3"),
  ("humidity","%"),
  ("illuminance","lx"),
  ("monetary","€"),
  ("nitrogen_dioxide","µg/m³"),
  ("nitrogen_monoxide","µg/m³"),
  ("nitrous_oxide","µg/m³"),
  ("ozone","µg/m³"),
  ("pm1","µg/m³"),
  ("pm10","µg/m³"),
  ("pm25","µg/m³"),
  ("power_factor","%"),
  ("power","W"),
  ("pressure","hPa"),
  ("reactive_power","var"),
  ("signal_strength","dB"),
  ("sulphur_dioxide","µg/m³"),
  ("temperature","°C"),
  ("volatile_organic_compounds","µg/m³"),
  ("voltage","V")
] %}

{% set CLASSES_BINARY_SENSOR = [
  "battery",
  "battery_charging",
  "cold",
  "connectivity",
  "door",
  "garage_door",
  "gas",
  "heat",
  "light",
  "lock",
  "moisture",
  "motion",
  "moving",
  "occupancy",
  "opening",
  "plug",
  "power",
  "presence",
  "problem",
  "running",
  "safety",
  "smoke",
  "sound",
  "tamper",
  "update",
  "vibration",
  "window"
] %}

{% set code_input_boolean = '
  test_device_class_{0}:' %}

{% set code_input_number = '
  test_device_class_{0}:
    min: -1000000
    max: 1000000
    step: 0.01
    mode: box
    initial: 0
    unit_of_measurement: "{1}"
' %}

{% set code_binary_sensor = '
      test_device_class_{0}:
        device_class: {0}
        value_template: >-
          {{% set INPUT_NAME = "input_boolean.test_device_class_{0}" -%}}
          {{{{ states(INPUT_NAME) }}}}
' %}

{% set code_sensor = '
      test_device_class_{0}:
        device_class: {0}
        unit_of_measurement: "{1}"
        value_template: >-
          {{% set INPUT_NAME = "input_number.test_device_class_{0}" -%}}
          {{{{ states(INPUT_NAME) }}}}
' %}

input_boolean:
{% for class in CLASSES_BINARY_SENSOR -%}
  {{ code_input_boolean.format(class) }}
{%- endfor %}

############################################################################

input_number:
{% for class,uom in CLASSES_SENSOR -%}
  {{ code_input_number.format(class,
                              uom) }}
{%- endfor %}
############################################################################

binary_sensor:
  - platform: template
    sensors:
{% for class in CLASSES_BINARY_SENSOR -%}
  {{ code_binary_sensor.format(class) }}
{%- endfor %}
############################################################################

sensor:
  - platform: template
    sensors:
{% for class,uom in CLASSES_SENSOR -%}
  {{ code_sensor.format(class,
                        uom) }}
{%- endfor %}

Here is a card - use it in Panel mode:

type: horizontal-stack
cards:
  - type: custom:auto-entities
    card:
      type: entities
      title: input_boolean
    unique: entity
    show_empty: true
    filter:
      template: |-
        {% for state in states.input_boolean -%}
          {%- if state.entity_id | regex_match("input_boolean.test_device_class_", ignorecase=False) -%}
            {{
              {
                'entity': state.entity_id,
                'name': state.entity_id.split('test_device_class_')[1]
              }
            }},
          {%- endif -%}
        {%- endfor %}
    sort:
      method: name
  - type: custom:auto-entities
    card:
      type: entities
      title: binary_sensor
    unique: entity
    show_empty: true
    filter:
      template: |-
        {% for state in states.binary_sensor -%}
          {%- if state.entity_id | regex_match("binary_sensor.test_device_class_", ignorecase=False) -%}
            {{
              {
                'entity': state.entity_id,
                'name': state.entity_id.split('test_device_class_')[1]
              }
            }},
          {%- endif -%}
        {%- endfor %}
    sort:
      method: name
  - type: custom:auto-entities
    card:
      type: entities
      title: input_number
    unique: entity
    show_empty: true
    filter:
      template: |-
        {% for state in states.input_number -%}
          {%- if state.entity_id | regex_match("input_number.test_device_class_", ignorecase=False) -%}
            {{
              {
                'entity': state.entity_id,
                'name': state.entity_id.split('test_device_class_')[1]
              }
            }},
          {%- endif -%}
        {%- endfor %}
    sort:
      method: name
  - type: custom:auto-entities
    card:
      type: entities
      title: sensor
    unique: entity
    show_empty: true
    filter:
      template: |-
        {% for state in states.sensor -%}
          {%- if state.entity_id | regex_match("sensor.test_device_class_", ignorecase=False) -%}
            {{
              {
                'entity': state.entity_id,
                'name': state.entity_id.split('test_device_class_')[1]
              }
            }},
          {%- endif -%}
        {%- endfor %}
    sort:
      method: name

So, I do not see any changes in presentation if UoM is specified - only difference is that UoM is displayed after the value.
Exceptions:

  1. “duration” is displayed w/o UoM in “hh:mm:ss” format (which does not occur if UoM is not specified);
  2. “monetary” - no UoM is displayed for sensor:

Also, I changed UoM for some values to see what could happen.
For example, for “frequency” - the value was “xxx MHz”, I changed UoM to “Hz” and reloaded templates - the displayed value is “xxx Hz”:

As for temperature: initially the sensor has UoM =C, then I changed to F - and the value is changed (not correct), UoM not changed:

Is there any template function to show the duration value in a human readable format?

{{ states.sensor.history_stats_sensor.state }} shows a decimal number of hours

timedelta I think.

I would like to know this as well. Here’s what I worked out, but I’m not sure if it’s the right/best way to do it.

{{ timedelta(float(states.sensor.duration.state) / 24) }}

This converts a value like 4.64 to 4:38:24.
It works, but is there a better way?

{{ timedelta(states('sensor.duration') | float(0) / 24) }}

Rather use the states function and provide a default. It’s more robust.

Thanks! It seems like extra ‘work’ to do actual maths when the sensor already ‘knows’ what the time is. If I just show the value without a template, it shows as time nicely already, but I want to use the template-entity-row entity, which doesn’t automatically convert.
Is there a simpler way that doesn’t involve this manual work?