Great news!
Thank you for your feedback.
Great news!
Thank you for your feedback.
I had to float(0) in line 66:
{{ as_timestamp(now()) - (state_attr('sensor.stopwatch','initial_time') | float(0) ) + (state_attr('sensor.stopwatch','elapsed_time') | float(0) ) }}
…or it failed to work, giving errors in the log and sensor.stopwatch not available.
sensor.stopwatch shows to milliseconds, which I don’t need for my application - I only need hours/minutes… is there an easy way to tweak to that? EDIT - saw the post above which had the same question, fixed.
Thanks for the stopwatch - I’m using it to track how long my pool pump runs on solar energy
In my case, it works without casting to float(0)
. I don’t know why, really.
The stopwatch shows hundredths of a second if you use my code. If you only need hours:minutes, put this in the state
of the sensor:
state: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{ '00:00' }}
{% elif is_state_attr('sensor.stopwatch','running','on') %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{{ value|float|timestamp_custom("%H:%M", False)|string }}
{% else %}
{{ states('sensor.stopwatch') }}
{% endif %}
If you use the lap feature, and you also want values in hours:minutes, do the same change there.
Thank you mate for sharing. I was looking for this feature to track how long my dish washer, washing machine and so on have been working and display it in dashboard.
Would be cool anyway to have this feature as helper natively integrated.
Thanks for your work! Since history stats aren‘t working properly I used your stopwatch for counting some states. Like Someone mentioned above I had to reset the watches after I added them to Homeassistant to get them to work. But no problem.
Is there an easy way to geht the Sensor in an hour format (1,54 h for example) instead of 00:00:00:00? I am just tracking long term.
You have to change the state
of the sensor with:
state: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{ '0:00 h' }}
{% elif is_state_attr('sensor.stopwatch','running','on') %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{{ value|float|timestamp_custom("%H:%M h", False) |string }}
{% else %}
{{ states('sensor.stopwatch') }}
{% endif %}
and in the button:
name: >-
{% if is_state('input_boolean.start_stopwatch','off') %}
{% if is_state('sensor.stopwatch','0:00 h') %}
Start
{% else %}
Resume
{% endif %}
{% else %}
Stop/Pause
{% endif %}
If you use the laps, and you also want it in the same format:
laps: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{[]}}
{% elif is_state('input_boolean.lap_stopwatch','on') and is_state_attr('sensor.stopwatch','running','on') %}
{% set data = namespace(laps=state_attr('sensor.stopwatch','laps')) %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{% set data.laps = (data.laps + [value|float|timestamp_custom("%H:%M h", False) |string]) %}
{{ data.laps }}
{% else %}
{{ state_attr('sensor.stopwatch','laps')}}
{% endif %}
I’ve changed the code to show only hundreds of second when the stopwatch is stopped.
Thank you for your reply.
For my usecase (doing some graphs with plotly interactive graph card). I need a decimal point. So that instead of 01:54 h sensor should have the value 1.90 h is this possible?
In that case, state should be:
unit_of_measurement: 'h'
state: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{ '0,00' }}
{% elif is_state_attr('sensor.stopwatch','running','on') %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{{(value|float/3600)|round(2)}}
{% else %}
{{ states('sensor.stopwatch') }}
{% endif %}
Thank you sooooo much! This really helps me a lot
Thanks very much for providing this solution, its hopefully just what I’m looking for! Does anyone have any examples of how they have utilised this stopwatch into a front end display of state time?
What I’m hoping to achieve is to start this stopwatch when my clothes dryer enters a state of ‘running’, which will let me display the running duration of the drying cycle on a card. I would like tge stopwatch to stop, probably using the ‘lap’ function, when my dryer changes to the anti-crease cycle. I would need the last cycle run duration to remain visible while the machine is in the anti-crease cycle, kind of like a ‘split’ in a regular stopwatch.
Then when the anti-crease cycle ends, to stop the stopwatch and display that cycles run duration, and possibly a total combined run time. I could probably add a door sensor so that the dryer door is opened, it triggers a reset, ready for the next load of drying.
I’m not sure if I can achieve this but this stopwatch code seems like it should do what I need, along with some automations on top, but if anyone can help I would really appreciate it.
You can create automations with triggers, the sensors in your clothes dryer, and the actions would be setting on and off the input_booleas
: start_stopwatch
, reset_stopwatch
, and lap_stopwatch
.
For instance, to start the stopwatch you can create an automation similar to this one:
description: "..."
mode: single
trigger:
- platform: state
entity_id:
- binary_sensor.clothes_dryer
from: "off"
to: "on"
condition: []
action:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.start_stopwatch
Of course, if you have several automations related to the same application, like in this case, you can use id’s to use a single automation for all the triggers and actions:
description: "Clothes dryer stopwatch automation"
mode: single
trigger:
- platform: state
entity_id:
- binary_sensor.clothes_dryer
from: "off"
to: "on"
id: start
- platform: state
entity_id:
- binary_sensor.anticrease_cycle
from: "off"
to: "on"
id: anti-crease_cycle
condition: []
action:
- choose:
- conditions:
- condition: trigger
id: start
sequence:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.start_stopwatch
- conditions:
- condition: trigger
id: anti-crease_cycle
sequence:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.lap_stopwatch
@miguelpucela Thank you very much - I should be able to put something together with a bit of trial and error and get the state generating the relevant time periods, so that I can display them in my dashboard while the machine is running. Looks like I will need a couple of additional sensors than what I have already set up but it sounds like it’s going to work. Once I’ve put it together and tested, I’ll post back here in case the code is helpful for anyone wanting to use the stopwatch in a similar way
It’ll be great if you come back and share your code/final setup.
Just wanted to share an alternate solution. I wanted a timer for the office showing how stale the current pot of coffee is. I basically just needed a label showing the elapsed time. It would be reset automatically with code when a fresh pot of coffee was ready, but I also wanted to be able to start/stop/reset manually just in case. This is how I ended up doing it, crude but works for me.
3a. If you only want to display the current timer on a dashboard, you can now just create a basic sensor card, add the stopwatch entity and you have a timer on your dashboard. Then just use whatever automation you want to reset the timer by using Call Service: input_number.set_value, and set it to zero.
Done! If you want an interactive control you can tap to start/stop/reset read on.
3b. I personally wanted to format into HH:MM plus give it some interactivity, and already had the HACS button-card frontend integration. So I created a manual card and put in the code below.
type: custom:button-card
entity: input_number.stopwatch
show_icon: false
show_name: false
show_state: false
show_label: true
label: |
[[[
function minutesToTime(mins) {
let hours = Math.floor((mins % (60 * 60)) / 60);
let minutes = Math.floor(mins % 60);
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
}
let minutes = parseInt(entity.state);
return minutesToTime(minutes);
]]]
tap_action:
action: call-service
service: >
[[[ return states['automation.stopwatch_increment'].state === 'on' ?
'automation.turn_off' : 'automation.turn_on'; ]]]
service_data:
entity_id: automation.stopwatch_increment
hold_action:
action: call-service
service: input_number.set_value
service_data:
entity_id: input_number.stopwatch
value: 0
Now I have a timer showing hours and minutes. Clicking/Tapping it will stop/start (enable/disable the automation) and holding down will set the timer number helper to zero.
NOTE: This will puke all over the Home Assistant Logbook so if you need it for troubleshooting anything else in HA you need to filter out these events. I have found no way of changing the logging level for an individual automation, if anyone knows how do let me know.
Is there anyone that have done a very simple version of the stopwatch were you just push a button (ZigBee) to start it and when you push the button again you stop the stopwatch. Minutes and seconds just. I was also planing that it could be read up on a media player with the time.
My daughter is training math and she is clocking here self and always asking me to take the time and I was thinking that HA could do that and I also get a log on it…
You can set precission as you want, as explained here:
You can create automations with the button press as trigger and the stopwatch to start/stop/reset depending on the precious state and the button pressings. Similar to these:
Hi! Thank you for sharing your code. It is great! I am trying to time the ON time for my garden pump. I would create two timers - one would be reset every 24h and the other would never be reset.
Since I will not need the tic tac timer and the lap timer, I was trying to remove that part of the code. I am relatively new to this and I am not sure if I did it correctly. I actually do not even need any buttons since the start, pause and reset of the stopwatch would be handled by simple automations.
Does the below make sense? I am asking because when I start the timer, I do not see the status updating. It only shows me the current stopwatch time when I pause it.
input_boolean:
start_stopwatch:
# It triggers stopwatch to start/stop(pause)
name: Start/Stop Stopwatch
# initial: off
reset_stopwatch:
# It triggers stopwatch to reset
name: Reset
# initial: off
tictac_stopwatch:
template:
- trigger:
# Stopwatch sensor with Start, Stop/Pause, Reset and Lap features. Hundreds of second precission
- platform: state
entity_id: input_boolean.start_stopwatch
from: "off"
to: "on"
- platform: state
entity_id: input_boolean.start_stopwatch
from: "on"
to: "off"
- platform: state
entity_id: input_boolean.reset_stopwatch
from: "off"
to: "on"
sensor:
- name: "Stopwatch"
state: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{ '00:00:00' }}
{% elif is_state('input_boolean.start_stopwatch','off') and is_state('input_boolean.lap_stopwatch','off') %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{{ value|float|timestamp_custom("%H:%M:%S", False) + '.' + ((value|float*100)%100)|round(0)|string }}
{% elif is_state_attr('sensor.stopwatch','running','on') %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{{ value|float|timestamp_custom("%H:%M:%S", False) |string }}
{% else %}
{{ states('sensor.stopwatch') }}
{% endif %}
icon: mdi:timer
attributes:
initial_time: >-
{% if is_state('input_boolean.start_stopwatch', 'on') and is_state_attr('sensor.stopwatch','running','off') %}
{{ as_timestamp(now()) }}
{% else %}
{{ state_attr('sensor.stopwatch','initial_time') }}
{% endif %}
elapsed_time: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{ 0 }}
{% elif is_state('input_boolean.start_stopwatch','off') and is_state('input_boolean.lap_stopwatch','off') %}
{{ as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') }}
{% else %}
{{ state_attr('sensor.stopwatch','elapsed_time') }}
{% endif %}
running: >-
{{ states('input_boolean.start_stopwatch') }}
laps: >-
{% if is_state('input_boolean.reset_stopwatch','on') %}
{{[]}}
{% elif is_state('input_boolean.lap_stopwatch','on') and is_state_attr('sensor.stopwatch','running','on') %}
{% set data = namespace(laps=state_attr('sensor.stopwatch','laps')) %}
{% set value = as_timestamp(now()) - state_attr('sensor.stopwatch','initial_time') + state_attr('sensor.stopwatch','elapsed_time') %}
{% set data.laps = (data.laps + [value|float|timestamp_custom("%H:%M:%S", False) + '.' + ((value|float*100)%100)|round(0)|string]) %}
{{ data.laps }}
{% else %}
{{ state_attr('sensor.stopwatch','laps')}}
{% endif %}
# Start/Stop(Pause) button
- button:
- unique_id: 'start_stop_stopwatch'
name: >-
{% if is_state('input_boolean.start_stopwatch','off') %}
{% if is_state('sensor.stopwatch','00:00:00') %}
Start
{% else %}
Resume
{% endif %}
{% else %}
Stop/Pause
{% endif %}
icon: >-
{% if states('input_boolean.start_stopwatch') == 'off' %}
mdi:play-circle-outline
{% else %}
mdi:stop-circle-outline
{% endif %}
press:
service: input_boolean.toggle
target:
entity_id: input_boolean.start_stopwatch
automation:
- id: reset_stopwatch
alias: "Reset Stopwatch"
description: "It reset input_booleans when input_boolean.reset_stopwatch is set to on"
trigger:
- platform: state
entity_id: input_boolean.reset_stopwatch
from: "off"
to: "on"
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.start_stopwatch
- service: input_boolean.turn_off
target:
entity_id: input_boolean.tictac_stopwatch
- service: input_boolean.turn_off
target:
entity_id: input_boolean.reset_stopwatch
mode: single
You have to include all the tictac stuff, which is in charge of updating the status.
So, you should keep:
input_boolean.tictac_stopwatch
including the name TicTac
.input_boolean.tictac_stopwatch
in sensor.Stopwatch
.sensor.tictac_stopwatch
.automation.tic_tac_stopwatch
.I hope this helps.