mni82
(Mni82)
March 30, 2023, 9:05am
1
Hi there,
Sorry, im new at HA.
i try to create a smart washing machine by How To Monitor Your Washing Machine in Home Assistant - YouTube
But i don’t understand how i can re-use the Set’s (washingStarted, expectedEndTime, expectedTimeLeft in the sensors.yaml.
In my templates.yaml i have the code:
- sensor:
#### Washing machine states ####
- name: "Washing machine states"
state: >
{% set washingStarted = as_timestamp(states('input_datetime.washing_started')) -%}
{% set washingStopped = as_timestamp(states('input_datetime.washing_stopped')) -%}
{% set washingExpectedRunTime = states('input_number.washing_expected_runtime') | float(0) -%}
{% set expectedEndTime = washingStarted + washingExpectedRunTime -%}
{% set expectedTimeLeft = expectedEndTime - now().timestamp() -%}
{{ expectedTimeLeft }}
and the sensors.yaml
- platform: template
sensors:
washingstarted_date:
friendly_name: Washing Started
icon_template: mdi:clock-start
value_template: >-
{% set start = state_attr('sensor.washing_machine_states', 'washingStarted') | as_datetime %}
{{ start | as_timestamp | timestamp_custom("%d.%m.%Y %H:%M") }}
washingstopped_date:
friendly_name: Washing Stopped
icon_template: mdi:clock-end
value_template: >-
{% if is_state("input_boolean.washing_running", "on") -%}
Wasmachine draait nog
{%- else -%}
{% set start = states('input_datetime.washing_stopped') | as_datetime %} {{ start | as_timestamp | timestamp_custom("%d.%m.%Y %H:%M") }}
{%- endif %}
Is there a way to replace:
{% set start = states('input_datetime.washing_stopped') | as_datetime %} {{ start | as_timestamp | timestamp_custom("%d.%m.%Y %H:%M") }}
to something like this:
{{ washingStopped | as_timestamp | timestamp_custom("%d.%m.%Y %H:%M") }}
Is there a reason you are using both legacy and current format template sensors?
As it is currently, your first example will only ever return the expected time left.
Not currently. Variables within a template are not accessible outside of the configuration stanza they are in. To access them as attributes of the sensor, you need to create those attributes and define their values. But you would still need to use state_attr()
to get the data in other configuration entries.
In your second example, the first line of the value_template
will always be “None” if you do not define the attribute in sensor.washing_machine_states
.
mni82
(Mni82)
March 30, 2023, 1:37pm
3
Hi Drew, thank you for your time to answer my question.
Is there a reason you are using both legacy and current format template sensors?
No more than ignorance. Wich is legacy and wich is current format?
Didgeridrew:
Not currently. Variables within a template are not accessible outside of the configuration stanza they are in. To access them as attributes of the sensor, you need to create those attributes and define their values. But you would still need to use state_attr()
to get the data in other configuration entries.
Is there another way to achieve the re-using calculated fields. Or should i simply put it all in one yaml file?
The current format is the one that you are using in your templates.yaml
file.
Currently, there aren’t global template variables in Home Assistant. But you are also doing “calculations” that aren’t necessary. Every date-and-time Input datetime helper already includes a timestamp
attribute, you do not need to use the as_timestamp()
function.
Example: state_attr('input_datetime.washing_started', 'timestamp')
In your previous post you asked about the following template used in the last example sensor:
{% set start = states('input_datetime.washing_stopped') | as_datetime %}
{{ start | as_timestamp | timestamp_custom("%d.%m.%Y %H:%M")
Which can be simplified by removing unecessary conversions:
{{ (states('input_datetime.washing_stopped')
| as_datetime).strftime('%d.%m.%Y %H:%M') }}
It is difficult to give advice on how you might best structure your entities without knowing what the intended use or goal is for those entities.
mni82
(Mni82)
April 4, 2023, 1:35pm
5
Thank you for your assistance.
I updated my sensor in the templates.yml:
- sensor:
#### Washing machine states ####
- name: "Washing machine states"
unique_id: "sensor.washing_machine_states"
icon: mdi:clock-start
state: >-
{{ this.attributes.ExpectedTimeLeft | default('Value when missing') }}
attributes:
WashingStarted: "{{ ((states('input_datetime.washing_started')) | as_datetime)}}"
# WashingStarted: "{{ as_timestamp(states('input_datetime.washing_started')) | timestamp_custom('%d.%m.%Y %H:%M')}}"
WashingStopped: >
{% if is_state("input_boolean.washing_running", "on") %}
Wasmachine draait nog
{% else %}
{{ (states('input_datetime.washing_stopped') | as_datetime).strftime('%d-%m-%Y %H:%M') }}
{% endif %}
ExpectedEndTime: "{{ (this.attributes.WashingStarted | as_datetime) + timedelta(seconds=states('input_number.washing_expected_runtime') | int) }}"
ExpectedTimeLeftSeconds: "{{ (this.attributes.ExpectedEndTime | as_timestamp) - ('2023-04-03 16:07:29' | as_timestamp) }}"
ExpectedTimeLeft: >
{% if is_state("input_boolean.washing_running", "on") %}
"{{ '%02d:%02d' % ((this.attributes.ExpectedTimeLeftSeconds/3600)|int, (this.attributes.ExpectedTimeLeftSeconds%3600)/60) }}"
{% endif %}
I would like the day format to be as “Stopped” in the green square.
If i change the code
WashingStarted: "{{ ((states('input_datetime.washing_started')) | as_datetime)}}"
to this code
WashingStarted: "{{ as_timestamp(states('input_datetime.washing_started')) | timestamp_custom('%d.%m.%Y %H:%M')}}"
The started (red square) is in the expected format.
Howerver then this code will fail:
ExpectedEndTime: "{{ (this.attributes.WashingStarted | as_datetime) ....
Does anybody know how to solve it?
Or is there another way to format the datetime in the attribute/entity card
- type: attribute
entity: sensor.washing_machine_states
attribute: WashingStarted
name: Gestart
icon: mdi:clock-start
format: datetime
@Didgeridrew : Do you have any idea?
Can you clarify what your goal is? I think something is getting lost in translation.
Are you trying to get the value in the red box to be the same format as the value in the green box?
mni82
(Mni82)
April 5, 2023, 6:22pm
7
Yes, but i would like to use this.attributes.WashingStarted
in “ExpectedEndTime”.
ExpectedEndTime doesnt show if i use
WashingStarted: "{{ as_timestamp(states('input_datetime.washing_started')) | timestamp_custom('%d.%m.%Y %H:%M')}}"
Ok. The core Entities cards don’t allow templates. Based on that limitation you will need a seperate attribute that returns the information formatted the way you want it.
- sensor:
- name: "Washing machine states"
unique_id: "sensor.washing_machine_states"
icon: mdi:clock-start
state: >-
{{ this.attributes.ExpectedTimeLeft | default('Value when missing') }}
attributes:
WashingStarted: >
{{ states('input_datetime.washing_started') | as_datetime }}
wash_start_format: >
{{ this.attributes.WashingStarted.strftime('%d-%m-%Y %H:%M') }}
WashingStopped: >
{% if is_state("input_boolean.washing_running", "on") %}
Wasmachine draait nog
{% else %}
{{ (states('input_datetime.washing_stopped') | as_datetime).strftime('%d-%m-%Y %H:%M') }}
{% endif %}
ExpectedEndTime: >
{% set runtime = states('input_number.washing_expected_runtime') | int %}
{{ this.attributes.WashingStarted + timedelta(seconds= runtime) }}
ExpectedTimeLeftSeconds: >
{{ (this.attributes.ExpectedEndTime - now()).total_seconds() }}
ExpectedTimeLeft: >
{% if is_state("input_boolean.washing_running", "on") %}
{% set seconds = this.attributes.ExpectedTimeLeftSeconds %}
{{ '%02d:%02d' % (( seconds // 3600), (seconds % 3600)/60) }}
{% else %}
Wasmachine Gestopt
{% endif %}
Then the card config would be:
type: vertical-stack
title: Wasmachine
cards:
- type: entities
entities:
- type: attribute
entity: sensor.washing_machine_states
attribute: wash_start_format
name: Gestart
icon: mdi:clock-start
- type: attribute
entity: sensor.washing_machine_states
attribute: WashingStopped
name: Gestopt
icon: mdi:clock-end
mni82
(Mni82)
April 5, 2023, 8:58pm
9
That was also my alternative.
I was wondering if there another way to work arround this.
Thank you!
mni82
(Mni82)
April 6, 2023, 4:49pm
10
Hi, it is working. However in the home-assistant.log i see a few warnings:
Is this only at starup of home-assistant?
Template variable warning: ‘homeassistant.util.read_only_dict.ReadOnlyDict object’ has no attribute ‘WashingStarted’ when rendering ‘{{ as_timestamp(this.attributes.WashingStarted, 0) | timestamp_custom(’%d.%m.%Y %H:%M’)}}’
mni82
(Mni82)
April 7, 2023, 6:30pm
11
If someone needs it. There were a few small bugs with quotes.
I ended up with this. It works for me.
- sensor:
#### Washing machine states ####
- name: "Washing machine states"
unique_id: "sensor.washing_machine_states"
state: >-
{{ this.attributes.ExpectedTimeLeft | default('Value when missing') }}
attributes:
WashingStarted: "{{ ((states('input_datetime.washing_started')) | as_datetime)}}"
WashingStarted_format: "{{ as_timestamp(this.attributes.WashingStarted, 0) | timestamp_custom('%d.%m.%Y %H:%M')}}"
WashingStopped: >
{% if is_state("input_boolean.washing_running", "on") %}
Wasmachine draait nog
{% else %}
{{ (states('input_datetime.washing_stopped') | as_datetime).strftime('%d-%m-%Y %H:%M') }}
{% endif %}
ExpectedEndTime: >
{% if is_state("input_boolean.washing_running", "on") %}
{{ (this.attributes.WashingStarted | as_datetime) + timedelta(seconds=states('input_number.washing_expected_runtime') | int) }}
{% endif %}
ExpectedEndTime_format: >
{% set expEndTime = this.attributes.ExpectedEndTime %}
{% if is_state("input_boolean.washing_running", "on") %}
{{ as_timestamp(this.attributes.ExpectedEndTime) | timestamp_custom('%H:%M')}}
{% endif %}
ExpectedTimeLeftSeconds: >
{% if is_state("input_boolean.washing_running", "on") %}
{{ (this.attributes.ExpectedEndTime | as_timestamp) - (now() | as_timestamp) }}
{% endif %}
ExpectedTimeLeft: >
{% if is_state("input_boolean.washing_running", "on") %}
{{ '%02d:%02d' % ((this.attributes.ExpectedTimeLeftSeconds/3600)|int, (this.attributes.ExpectedTimeLeftSeconds%3600)/60) }}
{% endif %}
mni82
(Mni82)
April 7, 2023, 8:37pm
12
Damn… Almost right. Getting another error now.
2023-04-07 21:56:00.406 WARNING (MainThread) [homeassistant.helpers.template_entity] Template loop detected while processing event: <Event state_changed[L]: entity_id=sensor.washing_machine_states, old_state=<state sensor.washing_machine_states=00:46; WashingStarted=2023-04-07 21:02:39, WashingStarted_format=07.04.2023 21:02, WashingStopped=Wasmachine draait nog, ExpectedEndTime=2023-04-07 22:42:24, ExpectedEndTime_format=22:42, ExpectedTimeLeftSeconds=2783.6173210144043, ExpectedTimeLeft=00:46, friendly_name=Washing machine states @ 2023-04-07T21:56:00.328643+02:00>, new_state=<state sensor.washing_machine_states=00:46; WashingStarted=2023-04-07 21:02:39, WashingStarted_format=07.04.2023 21:02, WashingStopped=Wasmachine draait nog, ExpectedEndTime=2023-04-07 22:42:24, ExpectedEndTime_format=22:42, ExpectedTimeLeftSeconds=2783.6068120002747, ExpectedTimeLeft=00:46, friendly_name=Washing machine states @ 2023-04-07T21:56:00.328643+02:00>>, skipping template render for Template[{% if is_state(“input_boolean.washing_running”, “on”) %}
{{ (this.attributes.ExpectedEndTime | as_timestamp) - (now() | as_timestamp) }}
{% endif %}]
mni82
(Mni82)
April 14, 2023, 4:58pm
13
Got rid of the warnings. The log is now calm.
Here is what i ended up with:
- sensor:
#### Washing machine states ####
- name: "Washing machine states"
unique_id: "sensor.washing_machine_states"
state: >-
{{ this.attributes.ExpectedTimeLeft | default('N/A') }}
attributes:
WashingStarted: "{{ ((states('input_datetime.washing_started')) | as_datetime)}}"
WashingStarted_format: "{{ as_timestamp(this.attributes.WashingStarted, 0) | timestamp_custom('%d.%m.%Y %H:%M')}}"
WashingStopped: >
{% if is_state("input_boolean.washing_running", "on") %}
Wasmachine draait nog
{% else %}
{{ (states('input_datetime.washing_stopped') | as_datetime).strftime('%d-%m-%Y %H:%M') }}
{% endif %}
ExpectedEndTime: >
{% if is_state("input_boolean.washing_running", "on") %}
{{ (this.attributes.WashingStarted | as_datetime) + timedelta(seconds=states('input_number.washing_expected_runtime') | int) }}
{% endif %}
ExpectedEndTime_format: >
{% set expEndTime = this.attributes.ExpectedEndTime %}
{% if is_state("input_boolean.washing_running", "on") %}
{{ as_timestamp(this.attributes.ExpectedEndTime) | timestamp_custom('%H:%M')}}
{% endif %}
ExpectedTimeLeft: >
{% if is_state("input_boolean.washing_running", "on") %}
{% set seconds = (this.attributes.ExpectedEndTime | as_timestamp) - (now() | as_timestamp) %}
{% set minutes = ((seconds % 3600) // 60) | int %}
{% set hours = (seconds // 3600) | int %}
{{ '{:02}:{:02}'.format(hours, minutes) }}
{% endif %}