my gift for all those who in this sad period, to keep a little fit, are forced to run around their garden. The system will allow you to listen to information from your phone on the number of laps completed, the time taken, and also some extra comments on your performance ; -) …
Required … for the software part: Home Assistant and the Lannouncer application. For hardware, a smartphone and a Pir sensor, preferably mobile ones that work with Sonoff rf bridge.
Here are the codes …
configuration.yaml:
timer:
stopwatch:
name: ''
duration:
seconds: 540
input_number:
averageminutes:
name: minutes
initial: 0
max: 9
min: 0
step: 1
averageseconds:
name: seconds
initial: 0
max: 59
min: 0
step: 1
delay:
name: delay
initial: 5
max: 59
min: 5
step: 1
input_text:
averagelap:
name: averagelap
initial: '0'
timelap:
name: timelap
initial: '00:00'
counter:
revcounter:
name: ''
initial: 0
step: 1
maximum: 500
restore: true
icon: mdi:walk
input_boolean:
revcounter:
name: revcounter
initial: off
motivator:
name: motivator
initial: off
averagelap:
name: averagelap
initial: off
notify:
- platform: lannouncer #(you need to download the app to your smartphone)
name: lannouncertts
host: 192.168.0.xxx #(you have to set the static ip for your smartphone)
port: 1035
# This works with a Sonoff Pir sensor and a SONOFF 433 RF Bridge)
binary_sensor:
- platform: mqtt
state_topic: "tele/sonoff-bridge/RESULT"
name: 'sensor pir'
value_template: '{{value_json.RfReceived.Data}}'
payload_on: 'xxxxxx' # (SONOFF RF BRIDGE codes)
payload_off: 'xxxxxx'
off_delay: 10
device_class: motion
qos: 0
AUTOMATION
- id: 'revcounteron'
alias: revcounteron
trigger:
- entity_id: input_boolean.revcounter
platform: state
from: 'off'
to: 'on'
action:
- data:
entity_id: timer.stopwatch
service: timer.cancel
- service: counter.reset
entity_id: counter.revcounter
- data:
entity_id: timer.stopwatch
service: timer.start
- data:
entity_id:
- automation.stopwatch
service: automation.turn_on
initial_state: 'on'
- id: 'revcounteroff'
alias: revcounteroff
trigger:
- entity_id: input_boolean.revcounter
platform: state
from: 'on'
to: 'off'
action:
- data:
entity_id:
- automation.stopwatch
service: automation.turn_off
- data:
entity_id: timer.stopwatch
service: timer.cancel
- service: counter.reset
entity_id: counter.revcounter
- service: input_text.set_value
data:
entity_id: input_text.averagelap
value: '0'
- service: input_text.set_value
data:
entity_id: input_text.timelap
value: '00:00'
initial_state: 'on'
- id: 'stopwatch'
alias: stopwatch
trigger:
- entity_id: binary_sensor.sensor_pir
from: 'off'
platform: state
to: 'on'
action:
- data:
entity_id: timer.stopwatch
service: timer.pause
- service: counter.increment
entity_id: counter.revcounter
- service: input_text.set_value
data_template:
entity_id: input_text.averagelap
value: >
{% if is_state('counter.revcounter', '2') and is_state('input_boolean.averagelap', 'on') %}
{% set min = state_attr('timer.stopwatch', 'remaining')|replace('0:0', '') %}
{% set sec = 59 - min[2:]|int %}
{% set min2 = min|truncate(1,false,'',0) %}
{% set min3 = 8 |float - min2| round(0) %}
{% set min4 = min3| round(0) %}
{% set minsec = min4 * 60 %}
{% set sectot = minsec + sec %}
{{ sectot }}
{% else %}
{{ states(input.text.averagelap) }}
{% endif %}
- service: input_text.set_value
data_template:
entity_id: input_text.timelap
value: >
{% set min = state_attr('timer.stopwatch', 'remaining')|replace('0:0', '') %}
{% set sec = 59 - min[2:]|int %}
{% if sec < 10 %}
{% set sec ="0" + sec|string %}
{% endif %}
{% set min2 = min|truncate(1,false,'',0) %}
{% set min3 = 8 |float - min2| round(0) %}
{% set min4 = min3| round(0) %}
{% set min5 ="0" + min4|string + ":" + sec|string %}
{{min5}}
- service: notify.lannouncertts
data_template:
message: >
{% set media = states('input_number.averageminutes') | float * 60 | float + states('input_number.averageseconds') | int %}
{% set marg = states('input_number.delay')| int %}
{% set min = state_attr('timer.stopwatch', 'remaining')|replace('0:0', '') %}
{% set sec = 59 - min[2:]|int %}
{% set min2 = min|truncate(1,false,'',0) %}
{% set min3 = 8 |float - min2| round(0) %}
{% set min4 = min3| round(0) %}
{% set minsec = min4 * 60 %}
{% set sectot = minsec + sec %}
{% if min4 == 0 %}
{% set min4 = '' + sec|string + " seconds"%}
{% elif min4 == 1 %}
{% set min4 = min4|string + ' minute and ' + sec|string + " seconds" %}
{% else %}
{% set min4 = min4|string + ' minutes and ' + sec|string + " seconds" %}
{% endif %}
{% if states('counter.revcounter') | float > 2 %}
lap {{ states('counter.revcounter') }}... Time {{min4}} .
{% endif %}
{% if is_state('input_boolean.motivator', 'on') %}
{% if is_state('counter.revcounter', '1') and is_state('input_boolean.averagelap', 'on') %}
now go at a regular pace that I take your time
{% endif %}
{% if is_state('counter.revcounter', '2') and is_state('input_boolean.averagelap', 'on') %}
your reference time {{min4}}
{% endif %}
{% if states('counter.revcounter') | float > 2 %}
{% if is_state('input_text.averagelap', '0') %}
{% else %}
{% set media = states('input_text.averagelap')| int %}
{% endif %}
{% if sectot < media| float -marg %}
{{["great, you are doing well", "today nobody beats you", "great time" ] | random}}
{% elif sectot > media| float +marg %}
{{["Can you do any better", "you look like a snail", "you are slowing down a bit" ] | random}}
{% else %}
{{["regular pace", "you are average" ] | random}}
{% endif %}
{% endif %}
{% endif %}
- data:
entity_id: timer.stopwatch
service: timer.cancel
- data:
entity_id: timer.stopwatch
service: timer.start
initial_state: 'off'
LOVELACE CARDs
PICTURE ELEMENTS:
elements:
- entity: input_boolean.revcounter
image: /local/images/runner.gif
state_image:
'off': /local/images/revcounteroff.png
style:
left: 50%
top: 40%
width: 30%
tap_action:
action: toggle
type: image
- entity: input_boolean.revcounter
image: /local/images/null.png
state_image:
'on': /local/images/stopwatch.gif
style:
left: 15%
top: 25%
width: 15%
tap_action:
action: none
type: image
- entity: counter.revcounter
style:
font-size: 22px
left: 80%
top: 25%
tap_action:
action: null
type: state-badge
- entity: input_text.timelap
style:
font-size: 16px
left: 80%
top: 35%
type: state-label
- entity: input_boolean.averagelap
image: /local/images/averagelapon.png
state_image:
'off': /local/images/averagelapoff.png
style:
left: 16%
top: 70%
width: 20%
tap_action:
action: toggle
type: image
- entity: input_boolean.motivator
image: /local/images/ttson.png
state_image:
'off': /local/images/ttsoff.png
style:
left: 80%
top: 70%
width: 20%
tap_action:
action: toggle
type: image
image: /local/images/race.jpg
type: picture-elements
CONDITIONAL CARD
card:
entities:
- entity: input_number.delay
type: entities
conditions:
- entity: input_boolean.motivator
state: 'on'
type: conditional
card:
entities:
- entity: input_number.averageminutes
- entity: input_number.averageseconds
type: entities
conditions:
- entity: input_boolean.averagelap
state: 'off'
- entity: input_boolean.motivator
state: 'on'
type: conditional