First, a huge thank you to Michael Arthur for the excellent Mammotion Home Assistant Integration! Without it, this whole project wouldn’t be possible.
I wanted a smart, weather-aware mower scheduler using Home Assistant, that:
- Lets me choose when to do the first mow of the week
- Lets me set how many times per week I want the lawn mowed
- Automatically delays mowing if rain is forecast or if it has rained recently
- Keeps checking and reschedules mowing automatically when conditions are right
- Handles everything in the background without me needing to think about it
Why Build a Smarter Scheduler?
The Luba’s built-in schedule is fine — but it doesn’t check your local weather properly. If rain is expected (or if it rained heavily overnight), it will try to mow anyway. I wanted a smarter system, just like how you’d automate lights or heating, but for mowing.
Specifically, I wanted:
- Flexible start time
- Control how many times a week it mows
- Automatic delay and retry if rain is expected or detected
- Self-healing behavior: keep trying until mowing succeeds
Tools and Integrations I Used
- Mammotion-HA Integration (for controlling the Luba)
- Mushroom Cards (for the UI controls)
- Browser Mod (for pop-ups and UI dialogs)
- Map Card (for the mower’s path map)
- Lawn Mower Card (to show mower status visually)
- Met Office Integration (for probability of precipitation forecasts)
- Open Weather History (for actual rain history)
How It Works
The scheduler is built around:
- A few simple input helpers (input_number, input_boolean, input_datetime)
- Automations to start the mow at the right time, based on conditions
- Scripts to send start and stop commands to the Luba
- Automations to delay if rain is likely or has occurred

If you click on a lawn control, you get a pop up like this where you can select the next mow time and how often to mow
Final Thoughts
This setup has worked well for me. The Luba just quietly gets on with mowing when the conditions are right, and skips if it rains. It feels much smarter and way more autonomous — and it’s all 100% controlled inside Home Assistant!
If you have any questions or want help setting up your own Luba scheduler, feel free to leave a comment below.
Key Pieces of YAML Code
Updates will be on Github
Original code below
Input Helpers
Input selects for each lawn
back_lawn_schedule:
name: Back Lawn Schedule
options:
- never
- once per week
- twice per week
bottom_grass_schedule:
name: Bottom Grass Schedule
options:
- never
- once per week
- twice per week
golf_lawn_schedule:
name: Golf Lawn Schedule
options:
- never
- once per week
- twice per week
path_to_top_schedule:
name: Path to Top Schedule
options:
- never
- once per week
- twice per week
top_lawn_schedule:
name: Top Lawn Schedule
options:
- never
- once per week
- twice per week
Input Booleans
do_not_mow:
name: do not mow
block_night_mowing:
name: Block Night Mowing
icon: mdi:weather-night
input_datetime
# Bottom Grass
bottom_grass_last_mow_1:
name: "Bottom Grass Last Mow 1"
has_date: true
has_time: true
icon: mdi:grass
bottom_grass_last_mow_2:
name: "Bottom Grass Last Mow 2"
has_date: true
has_time: true
icon: mdi:grass
bottom_grass_last_mow_3:
name: "Bottom Grass Last Mow 3"
has_date: true
has_time: true
icon: mdi:grass
# Golf Lawn
golf_lawn_last_mow_1:
name: "Golf Lawn Last Mow 1"
has_date: true
has_time: true
icon: mdi:golf
golf_lawn_last_mow_2:
name: "Golf Lawn Last Mow 2"
has_date: true
has_time: true
icon: mdi:golf
golf_lawn_last_mow_3:
name: "Golf Lawn Last Mow 3"
has_date: true
has_time: true
icon: mdi:golf
# Path to Top
path_to_top_last_mow_1:
name: "Path to Top Last Mow 1"
has_date: true
has_time: true
icon: mdi:road-variant
path_to_top_last_mow_2:
name: "Path to Top Last Mow 2"
has_date: true
has_time: true
icon: mdi:road-variant
path_to_top_last_mow_3:
name: "Path to Top Last Mow 3"
has_date: true
has_time: true
icon: mdi:road-variant
# Top Lawn
top_lawn_last_mow_1:
name: "Top Lawn Last Mow 1"
has_date: true
has_time: true
icon: mdi:nature-people
top_lawn_last_mow_2:
name: "Top Lawn Last Mow 2"
has_date: true
has_time: true
icon: mdi:nature-people
top_lawn_last_mow_3:
name: "Top Lawn Last Mow 3"
has_date: true
has_time: true
icon: mdi:nature-people
# Times for mowing
back_lawn_next_time:
name: Back Lawn Mow Time
has_date: true
has_time: true
bottom_grass_next_time:
name: Bottom Grass Mow Time
has_date: true
has_time: true
golf_lawn_next_time:
name: Golf Lawn Mow Time
has_date: true
has_time: true
path_to_top_next_time:
name: Path to Top Mow Time
has_date: true
has_time: true
top_lawn_next_time:
name: Top Lawn Mow Time
has_date: true
has_time: true
Input texts
input_text:
reason_no_mow:
name: Reason No Mow
initial: ""
max: 100
last_selected_scene:
name: Last Selected Scene
initial: ""
max: 100
last_lawn_mowed:
name: Last Lawn Mowed
initial: ""
max: 100
Scheduler Automations
- id: '1727781470109'
alias: Mower Locked Alert
description: ''
trigger:
- platform: state
entity_id:
- sensor.labby_activity_mode
to: MODE_LOCK
action:
- action: notify.mobile_app_petes_14
data:
title: WARNING Mower Locked!
message: Lift sensor triggered
data:
channel: alarm_stream
tag: mower_alert
importance: max
visibility: public
notification_icon: mdi:robot-mower
clickAction: /home/mower
ttl: 0
priority: high
color: red
- alias: Update Back Lawn Mow History
trigger:
- platform: state
entity_id: script.mow_back_lawn
to: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.back_lawn_last_mow_3
data:
datetime: '{{ states(''input_datetime.back_lawn_last_mow_2'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.back_lawn_last_mow_2
data:
datetime: '{{ states(''input_datetime.back_lawn_last_mow_1'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.back_lawn_last_mow_1
data:
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
id: 4f73d82d75134a1b8a1b6e78f783c89f
- alias: Update Bottom Grass Mow History
trigger:
- platform: state
entity_id: script.mow_bottom_grass
to: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.bottom_grass_last_mow_3
data:
datetime: '{{ states(''input_datetime.bottom_grass_last_mow_2'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.bottom_grass_last_mow_2
data:
datetime: '{{ states(''input_datetime.bottom_grass_last_mow_1'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.bottom_grass_last_mow_1
data:
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
id: c08711b82a6343659ec0881f1fbbb5b7
- alias: Update Golf Lawn Mow History
trigger:
- platform: state
entity_id: script.mow_golf_lawn
to: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.golf_lawn_last_mow_3
data:
datetime: '{{ states(''input_datetime.golf_lawn_last_mow_2'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.golf_lawn_last_mow_2
data:
datetime: '{{ states(''input_datetime.golf_lawn_last_mow_1'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.golf_lawn_last_mow_1
data:
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
id: de5793758a814ad8a50f61eeccbaf6ce
- alias: Update Path to Top Mow History
trigger:
- platform: state
entity_id: script.mow_path_to_top
to: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.path_to_top_last_mow_3
data:
datetime: '{{ states(''input_datetime.path_to_top_last_mow_2'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.path_to_top_last_mow_2
data:
datetime: '{{ states(''input_datetime.path_to_top_last_mow_1'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.path_to_top_last_mow_1
data:
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
id: 937936620c504b54845244b16d2a96a1
- alias: Update Top Lawn Mow History
trigger:
- platform: state
entity_id: script.mow_top_lawn
to: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.top_lawn_last_mow_3
data:
datetime: '{{ states(''input_datetime.top_lawn_last_mow_2'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.top_lawn_last_mow_2
data:
datetime: '{{ states(''input_datetime.top_lawn_last_mow_1'') }}'
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.top_lawn_last_mow_1
data:
datetime: '{{ now().strftime(''%Y-%m-%d %H:%M:%S'') }}'
id: 83f60b746ed04ec69ff8e8cd7c9dfc3c
- alias: Update Last Lawn Mowed Name
mode: single
trigger:
- platform: state
entity_id:
- input_datetime.back_lawn_last_mow_1
- input_datetime.bottom_grass_last_mow_1
- input_datetime.golf_lawn_last_mow_1
- input_datetime.path_to_top_last_mow_1
- input_datetime.top_lawn_last_mow_1
action:
- variables:
lawns:
input_datetime.back_lawn_last_mow_1: Back Lawn
input_datetime.bottom_grass_last_mow_1: Bottom Grass
input_datetime.golf_lawn_last_mow_1: Golf Lawn
input_datetime.path_to_top_last_mow_1: Path to Top
input_datetime.top_lawn_last_mow_1: Top Lawn
- choose:
- conditions: []
sequence:
- variables:
last_mow: "{% set last = namespace(entity='', timestamp=0) %} {% for entity_id,
name in lawns.items() %}\n {% set ts = state_attr(entity_id, 'timestamp')
%}\n {% if ts is number and ts > last.timestamp %}\n {% set last.entity
= name %}\n {% set last.timestamp = ts %}\n {% endif %}\n{% endfor
%} {{ last.entity }}\n"
- service: input_text.set_value
target:
entity_id: input_text.last_lawn_mowed
data:
value: '{{ last_mow }}'
id: eaa091c6eed04846ba3f9c7952370ac5
- id: 77af5be6b7ed48db9c40f182667ef3ca
alias: Mow Back Lawn
triggers:
- at: input_datetime.back_lawn_next_time
trigger: time
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.back_lawn_schedule
state: never
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
actions:
- action: script.mow_back_lawn
data: {}
- id: 47a1be93a68941acaa047fb6c8cca9d4
alias: Mow Bottom Grass
triggers:
- at: input_datetime.bottom_grass_next_time
trigger: time
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.bottom_grass_schedule
state: never
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
actions:
- action: script.mow_bottom_grass
data: {}
- id: 6a69af3b1e4944eb84b012051335b91f
alias: Mow Golf Lawn
triggers:
- at: input_datetime.golf_lawn_next_time
trigger: time
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.golf_lawn_schedule
state: never
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
actions:
- action: script.mow_golf_lawn
data: {}
- id: 06aa6489d21648b6a3a7ce39c21008a5
alias: Mow Path to Top
triggers:
- at: input_datetime.path_to_top_next_time
trigger: time
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.path_to_top_schedule
state: never
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
actions:
- action: script.mow_path_to_top
data: {}
- id: b094ad1fa3dc42e3916ece4e0dd8cd76
alias: Mow Top Lawn
triggers:
- at: input_datetime.top_lawn_next_time
trigger: time
conditions:
- condition: not
conditions:
- condition: state
entity_id: input_select.top_lawn_schedule
state: never
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
actions:
- action: script.mow_top_lawn
data: {}
- id: do_not_mow_if_heavy_rain
alias: Do Not Mow if Heavy Rain
triggers:
- entity_id: sensor.owmh_home_day0rain
trigger: state
- minutes: /30
trigger: time_pattern
conditions:
- or:
- condition: template
value_template: '{{ states(''sensor.owmh_home_day0rain'') | float > 3 }}'
- condition: template
value_template: '{{ states(''sensor.sevenoaks_probability_of_precipitation'')
| float > 50 }}'
actions:
- entity_id: input_boolean.do_not_mow
action: input_boolean.turn_on
- if:
- condition: template
value_template: '{{ states(''sensor.owmh_home_day0rain'') | float > 3 }}'
then:
- action: input_text.set_value
metadata: {}
data:
value: wet ground
target:
entity_id: input_text.reason_no_mow
else:
- action: input_text.set_value
metadata: {}
data:
value: rain soon
target:
entity_id: input_text.reason_no_mow
- id: reset_do_not_mow_if_no_heavy_rain
alias: Reset Do Not Mow if No Heavy Rain
triggers:
- entity_id: sensor.owmh_home_day0rain
trigger: state
- minutes: /30
trigger: time_pattern
conditions:
- condition: and
conditions:
- condition: template
value_template: '{{ states(''sensor.owmh_home_day0rain'') | float <= 3 }}'
- condition: template
value_template: '{{ states(''sensor.sevenoaks_probability_of_precipitation'')
| float <= 50 }}'
- condition: state
entity_id: sensor.labby_activity_mode
state: MODE_READY
- condition: numeric_state
entity_id: sensor.labby_battery
above: 95
- condition: sun
before: sunset
before_offset: '1'
actions:
- entity_id: input_boolean.do_not_mow
action: input_boolean.turn_off
- id: do_not_mow_before_sunset
alias: Do Not Mow Before Sunset
triggers:
- event: sunset
offset: -01:00
trigger: sun
conditions:
- condition: state
entity_id: input_boolean.block_night_mowing
state: 'on'
actions:
- target:
entity_id: input_boolean.do_not_mow
action: input_boolean.turn_on
data: {}
- action: input_text.set_value
metadata: {}
data:
value: night time
target:
entity_id: input_text.reason_no_mow
- id: allow_mowing_at_sunrise
alias: Allow Mowing at Sunrise
triggers:
- event: sunrise
trigger: sun
conditions:
- condition: state
entity_id: input_boolean.block_night_mowing
state: 'on'
- condition: template
value_template: '{{ states(''sensor.owmh_home_day0rain'') | float < 3 }}'
- condition: template
value_template: '{{ states(''sensor.sevenoaks_probability_of_precipitation'')
| float < 50 }}' actions: - target: entity_id: input_boolean.do_not_mow action: input_boolean.turn_off data: {} - id: '1729256256360' alias: Update Back Lawn Next Time description: '' triggers: - at: input_datetime.back_lawn_next_time trigger: time conditions: - condition: state entity_id: input_boolean.do_not_mow state: 'on' action: - service: input_datetime.set_datetime target: entity_id: input_datetime.back_lawn_next_time data: datetime: '{% set now = now() %} {# Get the current time #} {% set new_time = now + timedelta(hours=1) %} {# 1 hour from now #} {% set sunset = as_timestamp(state_attr(''sun.sun'', ''next_setting'')) %} {# Sunset today #} {% set sunrise_tomorrow = as_timestamp(state_attr(''sun.sun'', ''next_rising'')) %} {# Sunrise tomorrow #} {% if new_time.timestamp() >=
(sunset - 7200) %} {# If new_time is after 2 hours before sunset #} {% set
final_time = sunrise_tomorrow + 7200 %} {# Set final time to 2 hours after
sunrise tomorrow #} {% else %} {% set final_time = new_time.timestamp() %} {#
Keep new_time if it''s valid; ensure it''s a timestamp #} {% endif %} {{ final_time
| timestamp_custom(''%Y-%m-%d %H:%M:%S'', true) }}'
mode: single
- id: '1729256256361'
alias: Update Bottom Grass Next Time
description: ''
triggers:
- at: input_datetime.bottom_grass_next_time
trigger: time
conditions:
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.bottom_grass_next_time
data:
datetime: '{% set now = now() %} {# Get the current time #} {% set new_time
= now + timedelta(hours=1) %} {# 1 hour from now #} {% set sunset = as_timestamp(state_attr(''sun.sun'',
''next_setting'')) %} {# Sunset today #} {% set sunrise_tomorrow = as_timestamp(state_attr(''sun.sun'',
''next_rising'')) %} {# Sunrise tomorrow #} {% if new_time.timestamp() >=
(sunset - 7200) %} {# If new_time is after 2 hours before sunset #} {% set
final_time = sunrise_tomorrow + 7200 %} {# Set final time to 2 hours after
sunrise tomorrow #} {% else %} {% set final_time = new_time.timestamp() %} {#
Keep new_time if it''s valid; ensure it''s a timestamp #} {% endif %} {{ final_time
| timestamp_custom(''%Y-%m-%d %H:%M:%S'', true) }}'
mode: single
- id: '1729256256362'
alias: Update Golf Lawn Next Time
description: ''
triggers:
- at: input_datetime.golf_lawn_next_time
trigger: time
conditions:
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.golf_lawn_next_time
data:
datetime: '{% set now = now() %} {# Get the current time #} {% set new_time
= now + timedelta(hours=1) %} {# 1 hour from now #} {% set sunset = as_timestamp(state_attr(''sun.sun'',
''next_setting'')) %} {# Sunset today #} {% set sunrise_tomorrow = as_timestamp(state_attr(''sun.sun'',
''next_rising'')) %} {# Sunrise tomorrow #} {% if new_time.timestamp() >=
(sunset - 7200) %} {# If new_time is after 2 hours before sunset #} {% set
final_time = sunrise_tomorrow + 7200 %} {# Set final time to 2 hours after
sunrise tomorrow #} {% else %} {% set final_time = new_time.timestamp() %} {#
Keep new_time if it''s valid; ensure it''s a timestamp #} {% endif %} {{ final_time
| timestamp_custom(''%Y-%m-%d %H:%M:%S'', true) }}'
mode: single
- id: '1729256256363'
alias: Update Path to Top Next Time
description: ''
triggers:
- at: input_datetime.path_to_top_next_time
trigger: time
conditions:
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.path_to_top_next_time
data:
datetime: '{% set now = now() %} {# Get the current time #} {% set new_time
= now + timedelta(hours=1) %} {# 1 hour from now #} {% set sunset = as_timestamp(state_attr(''sun.sun'',
''next_setting'')) %} {# Sunset today #} {% set sunrise_tomorrow = as_timestamp(state_attr(''sun.sun'',
''next_rising'')) %} {# Sunrise tomorrow #} {% if new_time.timestamp() >=
(sunset - 7200) %} {# If new_time is after 2 hours before sunset #} {% set
final_time = sunrise_tomorrow + 7200 %} {# Set final time to 2 hours after
sunrise tomorrow #} {% else %} {% set final_time = new_time.timestamp() %} {#
Keep new_time if it''s valid; ensure it''s a timestamp #} {% endif %} {{ final_time
| timestamp_custom(''%Y-%m-%d %H:%M:%S'', true) }}'
mode: single
- id: '1729256256364'
alias: Update Top Lawn Next Time
description: ''
triggers:
- at: input_datetime.top_lawn_next_time
trigger: time
conditions:
- condition: state
entity_id: input_boolean.do_not_mow
state: 'on'
action:
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.top_lawn_next_time
data:
datetime: '{% set now = now() %} {# Get the current time #} {% set new_time
= now + timedelta(hours=1) %} {# 1 hour from now #} {% set sunset = as_timestamp(state_attr(''sun.sun'',
''next_setting'')) %} {# Sunset today #} {% set sunrise_tomorrow = as_timestamp(state_attr(''sun.sun'',
''next_rising'')) %} {# Sunrise tomorrow #} {% if new_time.timestamp() >=
(sunset - 7200) %} {# If new_time is after 2 hours before sunset #} {% set
final_time = sunrise_tomorrow + 7200 %} {# Set final time to 2 hours after
sunrise tomorrow #} {% else %} {% set final_time = new_time.timestamp() %} {#
Keep new_time if it''s valid; ensure it''s a timestamp #} {% endif %} {{ final_time
| timestamp_custom(''%Y-%m-%d %H:%M:%S'', true) }}'
mode: single
- id: '1729260472686'
alias: Do not mow when working
description: ''
triggers:
- trigger: state
entity_id:
- sensor.labby_activity_mode
to: MODE_WORKING
- trigger: state
entity_id:
- lawn_mower.labby
to: mowing
for:
hours: 0
minutes: 2
seconds: 0
conditions: []
actions:
- action: input_boolean.turn_on
metadata: {}
data: {}
target:
entity_id: input_boolean.do_not_mow
- action: input_text.set_value
metadata: {}
data:
value: mowing or charging
target:
entity_id: input_text.reason_no_mow
mode: single
- id: '1729260621710'
alias: Do not mow reset when charged
description: ''
triggers:
- trigger: numeric_state
entity_id:
- sensor.labby_battery
above: 97
conditions:
- and:
- condition: template
value_template: '{{ states(''sensor.owmh_home_day0rain'') | float <= 3 }}'
- condition: template
value_template: '{{ states(''sensor.sevenoaks_probability_of_precipitation'')
| float <= 50 }}'
actions:
- action: input_boolean.turn_off
metadata: {}
data: {}
target:
entity_id: input_boolean.do_not_mow
mode: single
Mower Control Scripts
mow_bottom_grass:
alias: Mow Bottom Grass
sequence:
- action: mammotion.start_mow
target:
entity_id: lawn_mower.labby
data:
speed: 0.3
ultra_wave: 2
channel_mode: 2
channel_width: 20
rain_tactics: 1
blade_height: 40
toward: 0
toward_included_angle: 0
toward_mode: 0
border_mode: 1
obstacle_laps: 0
start_progress: 0
areas:
- switch.labby_area_bottom_grass
mowing_laps: 0
- target:
entity_id: input_datetime.bottom_grass_next_time
data:
datetime: "{% if is_state('input_select.bottom_grass_schedule', 'once per week')
%}\n {{ (now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S') }}\n{%
elif is_state('input_select.bottom_grass_schedule', 'twice per week') %}\n
\ {{ (now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}\n{% else
%}\n {{ now().strftime('%Y-%m-%d %H:%M:%S') }}\n{% endif %}"
action: input_datetime.set_datetime
description: ''
icon: mdi:robot-mower
mow_golf_lawn:
alias: Mow Golf Lawn
sequence:
- action: mammotion.start_mow
target:
entity_id: lawn_mower.labby
data:
speed: 0.3
ultra_wave: 2
channel_mode: 2
channel_width: 20
rain_tactics: 1
blade_height: 40
toward: -90
toward_included_angle: 0
toward_mode: 0
border_mode: 0
obstacle_laps: 0
start_progress: 0
areas:
- switch.labby_area_golf_lawn
- target:
entity_id: input_datetime.golf_lawn_next_time
data:
datetime: "{% if is_state('input_select.golf_lawn_schedule', 'once per week')
%}\n {{ (now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S') }}\n{%
elif is_state('input_select.golf_lawn_schedule', 'twice per week') %}\n {{
(now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}\n{% else %}\n
\ {{ now().strftime('%Y-%m-%d %H:%M:%S') }}\n{% endif %}"
action: input_datetime.set_datetime
description: ''
icon: mdi:robot-mower
mow_path_to_top:
alias: Mow path to top
sequence:
- action: mammotion.start_mow
target:
entity_id: lawn_mower.labby
data:
speed: 0.3
ultra_wave: 2
channel_mode: 2
channel_width: 20
rain_tactics: 1
blade_height: 40
toward: 0
toward_included_angle: 0
toward_mode: 0
border_mode: 0
obstacle_laps: 0
start_progress: 0
areas:
- switch.labby_3
- target:
entity_id: input_datetime.path_to_top_next_time
data:
datetime: "{% if is_state('input_select.path_to_top_schedule', 'once per week')
%}\n {{ (now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S') }}\n{%
elif is_state('input_select.path_to_top_schedule', 'twice per week') %}\n
\ {{ (now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}\n{% else
%}\n {{ now().strftime('%Y-%m-%d %H:%M:%S') }}\n{% endif %}"
action: input_datetime.set_datetime
description: ''
icon: mdi:robot-mower
mow_top_lawn:
alias: Mow top lawn
sequence:
- action: mammotion.start_mow
target:
entity_id: lawn_mower.labby
data:
speed: 0.3
ultra_wave: 0
channel_mode: 2
channel_width: 20
rain_tactics: 0
blade_height: 30
toward: 0
toward_included_angle: 0
toward_mode: 0
border_mode: 0
obstacle_laps: 0
start_progress: 0
areas:
- switch.labby_area_top_lawn
is_dump: false
is_mow: false
mowing_laps: 0
- target:
entity_id: input_datetime.top_lawn_next_time
data:
datetime: "{% if is_state('input_select.top_lawn_schedule', 'once per week')
%}\n {{ (now() + timedelta(days=7)).strftime('%Y-%m-%d %H:%M:%S') }}\n{%
elif is_state('input_select.top_lawn_schedule', 'twice per week') %}\n {{
(now() + timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S') }}\n{% else %}\n
\ {{ now().strftime('%Y-%m-%d %H:%M:%S') }}\n{% endif %}"
action: input_datetime.set_datetime
description: ''
icon: mdi:robot-mower
mow_back_lawn:
alias: Mow back lawn
sequence:
- action: mammotion.start_mow
target:
entity_id: lawn_mower.labby
data:
speed: 0.2
ultra_wave: 0
channel_mode: 0
channel_width: 20
rain_tactics: 1
blade_height: 30
toward_mode: 0
border_mode: 0
obstacle_laps: 0
areas:
- switch.labby_area_back_lawn
start_progress: 0
toward: -90
is_mow: false
is_dump: false
mowing_laps: 1
Dashboard UI
cards:
- type: horizontal-stack
cards:
- type: custom:mushroom-template-card
primary: |-
{% if is_state('input_boolean.do_not_mow', 'on') %}
Do not mow ON
{% else %}
Ready to mow
{% endif %}
secondary: |-
{% if is_state('input_boolean.do_not_mow', 'on') %}
{{ states('input_text.reason_no_mow') }}
{% else %}
auto or clickable
{% endif %}
icon: |-
{% if is_state('input_boolean.do_not_mow', 'on') %}
mdi:close
{% else %}
mdi:robot-mower
{% endif %}
entity: input_boolean.do_not_mow
icon_color: |-
{% if is_state('input_boolean.do_not_mow', 'on') %}
red
{% else %}
green
{% endif %}
layout: vertical
fill_container: false
- type: custom:mushroom-template-card
primary: |-
{% if is_state('input_boolean.block_night_mowing', 'on') %}
Night mowing blocked
{% else %}
Night mowing allowed
{% endif %}
icon: |-
{% if is_state('input_boolean.block_night_mowing', 'on') %}
mdi:weather-night
{% else %}
mdi:weather-sunset
{% endif %}
entity: input_boolean.block_night_mowing
icon_color: |-
{% if is_state('input_boolean.block_night_mowing', 'on') %}
orange
{% else %}
grey
{% endif %}
tap_action:
action: toggle
layout: vertical
fill_container: false
- type: custom:lawn-mower-card #mower card - the buttons at the bottom all have the same icons
entity: lawn_mower.labby
battery: sensor.labby_battery
show_toolbar: true
show_shortcuts: true
show_status: true
# map: device_tracker.labby_luba_vfblns5n
actions:
start:
service: lawn_mower.start_mowing
service_data:
entity_id: lawn_mower.labby
stop:
service: button.press
service_data:
entity_id: button.labby_cancel_current_task
image: /local/pictures/luba.png
# service: lawn_mower.pause
# service_data:
# entity_id: lawn_mower.labby
pause:
service: lawn_mower.pause
service_data:
entity_id: lawn_mower.labby
resume:
service: lawn_mower.start_mowing
service_data:
entity_id: lawn_mower.labby
return_to_base:
service: lawn_mower.dock
service_data:
entity_id: lawn_mower.labby
stats:
default:
- entity_id: sensor.labby_l1_satellites_co_viewing
subtitle: L1 co viewing
- entity_id: sensor.labby_l2_satellites_co_viewing
subtitle: L2 co viewing
mowing:
- entity_id: sensor.labby_l1_satellites_co_viewing
subtitle: L1 co viewing
- entity_id: sensor.labby_l2_satellites_co_viewing
subtitle: L2 co viewing
- entity_id: sensor.labby_progress
subtitle: progress
unit: '%'
- entity_id: sensor.labby_elapsed_time
unit: minutes
subtitle: Mowing time
- entity_id: sensor.labby_blade_height
unit: 'mm'
subtitle: blade height
shortcuts:
- name: Mow back lawn
service: script.mow_back_lawn
icon: mdi:texture-box
- name: Mow bottom grass
service: script.mow_bottom_grass
icon: mdi:grass
- name: Mow golf lawn
service: script.mow_golf_lawn
icon: mdi:golf
- name: Mow path to top
service: script.mow_path_to_top
icon: mdi:road-variant
- name: Mow top lawn
service: script.mow_top_lawn
icon: mdi:weather-sunny
- type: custom:mushroom-template-card
primary: >
{% if states('lawn_mower.labby') == 'mowing' %}
Mowing {{ states('input_text.last_lawn_mowed') }}
{% else %}
{{ states('lawn_mower.labby') | title }} - last lawn {{ states('input_text.last_lawn_mowed') }}
{% endif %}
secondary: >
{% if states('lawn_mower.labby') == 'mowing' %}
{{ states('sensor.labby_elapsed_time') }} mins done {{ states('sensor.labby_time_left') }} mins left
{% else %}
Status updated: {{ states['lawn_mower.labby'].last_changed | relative_time }} ago
{% endif %}
icon: mdi:robot-mower
icon_color: >
{% set state = states('lawn_mower.labby') %}
{% if state in ['mowing', 'moving'] %}
green
{% elif state == 'returning to dock' %}
red
{% else %}
blue
{% endif %}
entity: lawn_mower.labby
- type: custom:mushroom-chips-card
chips:
- type: entity
entity: switch.labby_blades_on_off
name: Blades
- type: action
icon: mdi:cancel
name: Cancel Task
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_cancel_current_task
- type: action
icon: mdi:logout
name: Undock
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_undock
- type: grid #nudges
columns: 2
square: false
cards:
- type: custom:mushroom-template-card
primary: Nudge Left
icon: mdi:arrow-left-bold
icon_color: blue
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_emergency_nudge_left
- type: custom:mushroom-template-card
primary: Nudge Right
icon: mdi:arrow-right-bold
icon_color: blue
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_emergency_nudge_right
- type: custom:mushroom-template-card
primary: Nudge Forward
icon: mdi:arrow-up-bold
icon_color: blue
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_emergency_nudge_forward
- type: custom:mushroom-template-card
primary: Nudge Back
icon: mdi:arrow-down-bold
icon_color: blue
tap_action:
action: call-service
service: button.press
data:
entity_id: button.labby_emergency_nudge_back
- type: custom:map-card
focus_entity: device_tracker.labby_luba_vp8gt5gp
tile_layer_url: /local/map/{z}/{x}/{y}.png
zoom: 20
entities:
- entity: device_tracker.labby_luba_vp8gt5gp
picture: /local/pictures/luba2.png
size: 20
display: marker
history_start: 96 hours ago
history_line_color: blue
history_show_dots: false
card_size: 5
tile_layers:
- url: https://mt0.google.com/vt/lyrs=s&x={x}&y={y}&z={z}
default_zoom: 18
tile_layer_options:
maxZoom: 18
maxNativeZoom: 20
minZoom: 14
theme_mode: light 5
- type: grid
columns: 2
square: false
cards:
- type: custom:mushroom-template-card
primary: |-
{% set rain = states('sensor.owmh_home_day0rain') | float %}
{% if rain == 0 %}
No rain in last 24h
{% else %}
{{ rain }} mm rain in last 24h
{% endif %}
secondary: |-
{% set rain = states('sensor.owmh_home_day0rain') | float %}
{% if rain < 3 %}
dry
{% else %}
wet
{% endif %}
icon: |-
{% if states('sensor.owmh_home_day0rain') | float < 3 %}
mdi:weather-sunny
{% else %}
mdi:weather-rainy
{% endif %}
entity: sensor.owmh_home_day0rain
icon_color: |-
{% if states('sensor.owmh_home_day0rain') | float < 3 %}
yellow
{% else %}
blue
{% endif %}
tap_action:
action: more-info
- type: custom:mushroom-template-card
primary: |-
{% if states('sensor.sevenoaks_probability_of_precipitation') | float < 50 %} Prob of rain low {% else %} Prob of rain high {% endif %} secondary: >-
{% set prob = states('sensor.sevenoaks_probability_of_precipitation') | float %}
Current prob: {{ prob }}%
icon: |-
{% if states('sensor.sevenoaks_probability_of_precipitation') | float < 50 %}
mdi:weather-sunny
{% else %}
mdi:weather-pouring
{% endif %}
entity: sensor.sevenoaks_probability_of_precipitation
icon_color: |-
{% if states('sensor.sevenoaks_probability_of_precipitation') | float < 50 %} yellow {% else %} blue {% endif %} tap_action: action: more-info - type: custom:mushroom-entity-card entity: sensor.labby_l1_satellites_co_viewing name: L1 Co-Viewing - type: custom:mushroom-entity-card entity: sensor.labby_l2_satellites_co_viewing name: L2 Co-Viewing - type: custom:mushroom-entity-card entity: sensor.labby_progress name: Mowing Progress unit: '%' - type: custom:mushroom-entity-card entity: sensor.labby_elapsed_time name: Mowing Time unit: minutes - type: custom:mushroom-entity-card entity: sensor.labby_blade_height name: Blade Height unit: 'mm' # General Control - type: custom:mushroom-template-card # Back Lawn primary: Back Lawn secondary: "{{ states('sensor.time_since_last_mow_back_lawn_1') }} since last" icon: mdi:texture-box icon_color: |- {% if is_state('input_select.back_lawn_schedule', 'never') %} red {% else %} green {% endif %} tap_action: action: fire-dom-event browser_mod: service: browser_mod.popup data: title: Back Lawn Control content: type: grid columns: 1 square: false cards: - type: custom:mushroom-template-card entity: script.mow_back_lawn primary: Mow back lawn Now icon: mdi:texture-box icon_color: green tap_action: action: call-service service: script.mow_back_lawn hold_action: action: more-info - type: custom:mushroom-select-card entity: input_select.back_lawn_schedule name: Back Lawn Schedule icon_color: green - type: custom:mushroom-entity-card entity: input_datetime.back_lawn_next_time icon_color: green name: Back Lawn Schedule Time - click to change - type: custom:mushroom-template-card entity: input_datetime.back_lawn_last_mow_1 icon: mdi:mower primary: "{{ states('sensor.time_since_last_mow_back_lawn_1') }} last mow" secondary: "{{ states('input_datetime.back_lawn_last_mow_1') }}" icon_color: |- {% set days = states('sensor.time_since_last_mow_back_lawn_1').split()[0] | float(0) %} {% if days > 7 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card
entity: input_datetime.back_lawn_last_mow_2
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_back_lawn_2') }} prev mow"
secondary: "{{ states('input_datetime.back_lawn_last_mow_2') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_back_lawn_2').split()[0] | float(0) %}
{% if days > 14 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card #bottom grass
primary: Bottom Grass Control
secondary: "{{ states('sensor.time_since_last_mow_bottom_grass_1') }} since last"
icon: mdi:grass
icon_color: |-
{% if is_state('input_select.bottom_grass_schedule', 'never') %}
red
{% else %}
green
{% endif %}
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Bottom Grass Control
content:
type: grid
columns: 1
square: false
cards:
- type: custom:mushroom-template-card
entity: script.mow_bottom_grass
primary: Mow bottom grass Now
icon: mdi:grass
icon_color: green
tap_action:
action: call-service
service: script.mow_bottom_grass
hold_action:
action: more-info
- type: custom:mushroom-select-card
entity: input_select.bottom_grass_schedule
name: Bottom Grass Schedule
icon_color: |-
{% if is_state('input_select.bottom_grass_schedule', 'never') %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-entity-card
entity: input_datetime.bottom_grass_next_time
name: Bottom Grass Schedule Time
icon_color: green
- type: custom:mushroom-template-card
entity: input_datetime.bottom_grass_last_mow_1
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_bottom_grass_1') }} since last"
secondary: "{{ states('input_datetime.bottom_grass_last_mow_1') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_bottom_grass_1').split()[0] | float(0) %}
{% if days > 7 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card
entity: input_datetime.bottom_grass_last_mow_2
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_bottom_grass_2') }} since previous "
secondary: "{{ states('input_datetime.bottom_grass_last_mow_2') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_bottom_grass_2').split()[0] | float(0) %}
{% if days > 14 %}
red
{% else %}
green
{% endif %}
dismissable: true
right_button: Close
right_button_action:
service: browser_mod.close_popup
- type: custom:mushroom-template-card #golf lawn
primary: Golf Lawn Control
secondary: "{{ states('sensor.time_since_last_mow_golf_lawn_1') }} since last"
icon: mdi:golf
icon_color: |-
{% if is_state('input_select.golf_lawn_schedule', 'never') %}
red
{% else %}
green
{% endif %}
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Golf Lawn Control
content:
type: grid
columns: 1
square: false
cards:
- type: custom:mushroom-template-card
entity: script.mow_golf_lawn
primary: Mow golf lawn Now
icon: mdi:golf
icon_color: green
tap_action:
action: call-service
service: script.mow_golf_lawn
hold_action:
action: more-info
- type: custom:mushroom-select-card
entity: input_select.golf_lawn_schedule
name: Golf Lawn Schedule
icon_color: |-
{% if is_state('input_select.golf_lawn_schedule', 'never') %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-entity-card
entity: input_datetime.golf_lawn_next_time
name: Golf Lawn Schedule Time
icon_color: green
- type: custom:mushroom-template-card
entity: input_datetime.golf_lawn_last_mow_1
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_golf_lawn_1') }} since last"
secondary: "{{ states('input_datetime.golf_lawn_last_mow_1') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_golf_lawn_1').split()[0] | float(0) %}
{% if days > 7 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card
entity: input_datetime.golf_lawn_last_mow_2
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_golf_lawn_2') }} since last"
secondary: "{{ states('input_datetime.golf_lawn_last_mow_2') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_golf_lawn_2').split()[0] | float(0) %}
{% if days > 14 %}
red
{% else %}
green
{% endif %}
dismissable: true
right_button: Close
right_button_action:
service: browser_mod.close_popup
- type: custom:mushroom-template-card #top lawn
primary: Top Lawn Control
secondary: "{{ states('sensor.time_since_last_mow_top_lawn_1') }} since last"
icon: mdi:weather-sunny
icon_color: |-
{% if is_state('input_select.top_lawn_schedule', 'never') %}
red
{% else %}
green
{% endif %}
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Top Lawn Control
content:
type: grid
columns: 1
square: false
cards:
- type: custom:mushroom-template-card
entity: script.mow_top_lawn
primary: Mow top lawn Now
icon: mdi:weather-sunny
icon_color: green
tap_action:
action: call-service
service: script.mow_top_lawn
hold_action:
action: more-info
- type: custom:mushroom-select-card
entity: input_select.top_lawn_schedule
name: Top Lawn Schedule
icon_color: |-
{% if is_state('input_select.top_lawn_schedule', 'never') %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-entity-card
entity: input_datetime.top_lawn_next_time
name: Top Lawn Schedule Time
icon_color: green
- type: custom:mushroom-template-card
entity: input_datetime.top_lawn_last_mow_1
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_top_lawn_1') }} days since last mow"
secondary: "{{ states('input_datetime.top_lawn_last_mow_1') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_top_lawn_1').split()[0] | float(0) %}
{% if days > 7 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card
entity: input_datetime.top_lawn_last_mow_2
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_top_lawn_2') }} days since previous mow"
secondary: "{{ states('input_datetime.top_lawn_last_mow_2') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_top_lawn_2').split()[0] | float(0) %}
{% if days > 14 %}
red
{% else %}
green
{% endif %}
dismissable: true
right_button: Close
right_button_action:
service: browser_mod.close_popup
- type: custom:mushroom-template-card
primary: Path to Top Control
icon: mdi:road
icon_color: |-
{% if is_state('input_select.path_to_top_schedule', 'never') %}
red
{% else %}
green
{% endif %}
tap_action:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: Path to Top Control
content:
type: grid
columns: 1
square: false
cards:
- type: custom:mushroom-template-card
entity: script.mow_path_to_top
primary: Mow path to top Now
icon: mdi:road
icon_color: green
tap_action:
action: call-service
service: script.mow_path_to_top
hold_action:
action: more-info
- type: custom:mushroom-select-card
entity: input_select.path_to_top_schedule
name: Path to Top Schedule
icon_color: |-
{% if is_state('input_select.path_to_top_schedule', 'never') %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-entity-card
entity: input_datetime.path_to_top_next_time
name: Path to Top Schedule Time
icon_color: green
- type: custom:mushroom-template-card
entity: input_datetime.path_to_top_last_mow_1
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_path_to_top_1') }} days since last mow"
secondary: "{{ states('input_datetime.path_to_top_last_mow_1') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_path_to_top_1').split()[0] | float(0) %}
{% if days > 7 %}
red
{% else %}
green
{% endif %}
- type: custom:mushroom-template-card
entity: input_datetime.path_to_top_last_mow_2
icon: mdi:mower
primary: "{{ states('sensor.time_since_last_mow_path_to_top_2') }} days since previous mow"
secondary: "{{ states('input_datetime.path_to_top_last_mow_2') }}"
icon_color: |-
{% set days = states('sensor.time_since_last_mow_path_to_top_2').split()[0] | float(0) %}
{% if days > 14 %}
red
{% else %}
green
{% endif %}
dismissable: true
right_button: Close
right_button_action:
service: browser_mod.close_popup
This is AMAZING! But I don’t know a lot about computers. How do I get from all this code, to it being functional on my Mac?
Hi – this looks great, and exactly what I need.
My knowledge of HomeAssistant is improving, but I’m not completely there – I’ve got the scripts running, and the dashboard/cards are all in place, so basic functionality is fine. However, when it comes to the lawn controls for example, I get “entity not found” when the card is looking for input_select.bottom_lawn_schedule.
I’ve got the relevant section in input_select.yaml, but I’m probably missing something obvious! Any thoughts? Once I crack this all the other bits will fall into place.
Thanks for the great work and inspiration,
Ian
Hello, Can you show a complete beginner how to transfer your function to HA? I’ve already integrated HACS into HA
Thanks for the guide. I’ve worked my way through it (new to Home Assistant so it’s taken a while!). All appears to be working, except for historic weather says it’s been dry and it’s been raining for 2 days straight here! I think it’s the models/data points they use. Setting up my own weather station soon so hopefully that can be intergrated.
Is there an easy way of adjusting the mow settings from the dashboard somehow? Can prob figure it out but def think that would help in my use case.
Why is there no input_datetime for Back Lawn or is the Back Lawn the default?
Good question and I’m not sure, the version on GitHub is an old version and has been through a few iterations. Will check and update