My wife is working from home and I use device_tracker to monitor her laptop on our wifi-network. I can disable certain automations based on the condition she’s at home and also use it to track her working hours. Her laptop is not 100% time online, so there might be caps in device_tracker status here and there. Caps are usually less than 15mins (except lunch break), so I had to filter small “breaks” out.
First I did a history stats for the time laptop is offline:
It’s working fine, but because of the 15min delay I have to wait before I can tell she really has finished working, there’s always 15min extra time in the “working hours” -counter.
How can I subtract this 15mins (or actually 30mins, because lunch break creates another 15mins)?
EDIT: Added the “working hours counter” -sensor as requested.
For future improvements: It would be nice to have some weekly stats about the working hours, like:
Mon: 7.5h
Tue: 8.3h
…
Week 40 total: 40h
It was missing, but I edited the original post to include it.
I came up with one possible solution: Creating another sensor that will subtract 30min from the “working hours sensor”. Not ideal though…
I did the same based on location and tracking when im at work. This also filters out my lunch break as ill be outside the zone specified.
In order to get the statistics about the weekdays i added 5 sensors (one for each day) and an extra one for the whole week with the following config:
- platform: history_stats
name: work monday
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) - now().weekday() * 86400 }}'
duration: '24:00'
- platform: history_stats
name: work tuesday
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) + (1 - now().weekday()) * 86400 }}'
duration: '24:00'
- platform: history_stats
name: work wednesday
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) + (2 - now().weekday()) * 86400 }}'
duration: '24:00'
- platform: history_stats
name: work thursday
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) + (3 - now().weekday()) * 86400 }}'
duration: '24:00'
- platform: history_stats
name: work friday
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) + (4 - now().weekday()) * 86400 }}'
duration: '24:00'
- platform: history_stats
name: work week test
entity_id: person.marcus
state: 'Work'
type: time
start: '{{ as_timestamp( now().replace(hour=0).replace(minute=0).replace(second=0) ) - now().weekday() * 86400 }}'
end: '{{ now() }}'
I also summarize them all in NodeRed and output the values (including overtime calculation etc) into a custom sensor (created via the HTTP API).
One Problem i found with the History Stats Sensor:
Everything works great for the first week. But on week 2 on Monday the Tue - Fri Sensors do not update to the correct (UNKNOWN) value, but keep the value of last week due to the date being in the future. A Restart helps in clearing them and getting to the correct values. I already opened an issue on Github for that component.
Thanks for the daily working hour counter, sounds like just what I’m looking for.
My first problem still remains unsolved.
Let me take a step back from my initial approach. I’ll try to express what I really want to do…
I would like to have a sensor reading the first change of the day from ‘Away’ to ‘Home’, and the last change from ‘Home’ to ‘Away’ and count the hours/minutes in between. It’s never one continuing state of device being ‘Home’, but something like in the picture below:
First you will need to decide what constitutes the “first change of the day”.
The first one after midnight? or the first one around a specific time of day?
Either way once you decide on that you’ll have to have an automation to set the value of an input_datetime.
assuming its the first time after midnight then try:
input_datetime:
first_away_time:
name: First Away Time
has_date: true
has_time: true
input_boolean:
first_time_set:
name: First Time Has Been Set
automation:
- alias: set first away time
trigger:
- platform: state
entity_id: device_tracker.x5cg63723rr00e3
to: 'not_home'
condition:
- condition: state
entity_id: input_boolean.first_time_set
state: 'off'
action:
- delay: '00:00:10'
- service: input_datetime.set_datetime
entity_id: input_datetime.first_away_time
data_template:
time: "{{ states.device_tracker.x5cg63723rr00e3.last_changed }}"
- service: input_boolean.turn_on
entity_id: input_boolean.first_time_set
- alias: reset first time set boolean at midnight
trigger:
- platform: time
at: '00:00:00'
action:
- service: input_boolean.turn_off
entity_id: input_boolean.first_time_set
Thanks a lot for your help!
For the past couple of days I’ve been busy trying to make this all work. Finally I have some results to share.
I’m catching the monitored device changing state from “not_home” to “home” and marking that time as a work starting time. Every time the device changes to “not_home”, input_datetime for that specific day is updated (time elapsed between last ‘not_home’ time and ‘working_start_time’). I’m planning to limit the “last not_home” somehow to prevent false triggers, e.g. if laptop is used in the evening for non-work related things.
This could be achieved by history_stats sensor by checking how long the laptop has been continuously in “not_home” state. If this state exceeds, let’s say 60mins, we can turn off “input_boolean.set_working_started” and call it a day.
input_boolean:
set_working_started:
name: Working has started
input_datetime:
working_start_time:
name: Working start time
has_date: true
has_time: true
working_time_0_monday:
name: Working time Monday
has_date: false
has_time: true
working_time_1_tuesday:
name: Working time Tuesday
has_date: false
has_time: true
working_time_2_wednesday:
name: Working time Wednesday
has_date: false
has_time: true
working_time_3_thursday:
name: Working time Thursday
has_date: false
has_time: true
working_time_4_friday:
name: Working time Friday
has_date: false
has_time: true
automation:
- alias: Set working start time
trigger:
- platform: state
entity_id: device_tracker.x5cg63723rr00e3
to: 'home'
condition:
- condition: state
entity_id: input_boolean.set_working_started
state: 'off'
action:
- service: input_boolean.turn_on
entity_id: input_boolean.set_working_started
- service: input_datetime.set_datetime
data_template:
entity_id: input_datetime.working_start_time
date: '{{ (as_timestamp(states.device_tracker.x5cg63723rr00e3.last_changed) | timestamp_custom("%Y-%m-%d", true)) }}'
time: '{{ (as_timestamp(states.device_tracker.x5cg63723rr00e3.last_changed) | timestamp_custom("%H:%M:%S", true)) }}'
- alias: Reset working start time boolean at midnight
trigger:
- platform: time
at: '00:00:00'
action:
- service: input_boolean.turn_off
entity_id: input_boolean.set_working_started
- alias: Update working time on weekdays
trigger:
- platform: state
entity_id: device_tracker.x5cg63723rr00e3
to: 'not_home'
condition:
- condition: state
entity_id: input_boolean.set_working_started
state: 'on'
action:
- service: input_datetime.set_datetime
data_template:
entity_id: >
{% if (now().weekday()) == 0 %}
input_datetime.working_time_0_monday
{% elif (now().weekday()) == 1 %}
input_datetime.working_time_1_tuesday
{% elif (now().weekday()) == 2 %}
input_datetime.working_time_2_wednesday
{% elif (now().weekday()) == 3 %}
input_datetime.working_time_3_thursday
{% elif (now().weekday()) == 4 %}
input_datetime.working_time_4_friday
{% endif %}
time: >
{{ (as_timestamp(states.device_tracker.x5cg63723rr00e3.last_changed) - as_timestamp(states('input_datetime.working_start_time'))) | timestamp_custom("%H:%M:%S", false) }}
Hi,
Great work.
For some reason i get The value zero on every day.
My history stat sensor without The specificera days work though. Any thoughts on why its not working for me?