Skip to content

Instantly share code, notes, and snippets.

@mikey0000
Last active December 1, 2025 23:26
Show Gist options
  • Select an option

  • Save mikey0000/4a576511db3173780727b09f1d2943b5 to your computer and use it in GitHub Desktop.

Select an option

Save mikey0000/4a576511db3173780727b09f1d2943b5 to your computer and use it in GitHub Desktop.
blueprint:
name: Smart Multi-Zone Mammotion Mowing with Height Descent
description: >
Automatically mow zones using Mammotion mowers (Luba + Yuka).
Supports:
• Custom starting height and target height per zone
• Controlled descent: current_height = max(target, current - 5)
• Stores current height in an input_number
• Weather checks
• Tomorrow-rain override
• Per-zone frequencies
• Multi-switch zones (multiple areas per zone)
• Wait until mower is docked + no active task
• Uses areas[] with switch entities as required
domain: automation
input:
weather_entity:
name: Weather Entity (OpenWeatherMap)
selector:
entity:
domain: weather
mow_time:
name: Start Time
default: "11:00:00"
selector:
time: {}
zones:
name: Zones
description: >
Define zones. Each must include:
• switches: list of zone switch entities
• mower: lawn_mower.* entity
• last_mow: input_datetime for storing last mow timestamp
• frequency: days between mows
Optional (Luba):
• height_store: input_number for storing current height
• starting_height
• target_height
selector:
object: {}
trigger:
- platform: time
at: !input mow_time
variables:
weather: !input weather_entity
zones: !input zones
now_dt: "{{ now() }}"
forecast: "{{ state_attr(weather, 'forecast') }}"
weather_ok: >
{% if forecast and forecast[0] %}
{% set cond = forecast[0].condition | lower %}
{{ 'rain' not in cond }}
{% else %}
true
{% endif %}
rain_tomorrow: >
{% if forecast and forecast[1] %}
{% set cond = forecast[1].condition | lower %}
{{ 'rain' in cond }}
{% else %}
false
{% endif %}
condition:
- condition: template
value_template: "{{ weather_ok }}"
action:
- repeat:
for_each: "{{ zones }}"
sequence:
- variables:
zone: "{{ repeat.item }}"
switches: "{{ zone.switches }}"
mower_entity: "{{ zone.mower }}"
last_mow_entity: "{{ zone.last_mow }}"
frequency: "{{ zone.frequency | int }}"
height_store: "{{ zone.height_store | default('') }}"
starting_height: "{{ zone.starting_height | default(0) | int }}"
target_height: "{{ zone.target_height | default(0) | int }}"
last_mow: "{{ as_datetime(states(last_mow_entity)) }}"
days_since: >
{% if last_mow %}
{{ (now_dt - last_mow).days }}
{% else %}
999
{% endif %}
progress_sensor: >
sensor.{{ mower_entity.split('.')[1] }}_start_progress
stored_height: >
{% if height_store != '' %}
{{ states(height_store) | float(0) }}
{% else %}
none
{% endif %}
# Determine mow eligibility
- variables:
mow_today: >
{{ days_since >= frequency
or (days_since == frequency - 1 and rain_tomorrow) }}
- choose:
- conditions:
- condition: template
value_template: "{{ mow_today }}"
sequence:
# Wait until mower is ready
- wait_until:
- condition: state
entity_id: "{{ mower_entity }}"
state: "docked"
- condition: template
value_template: >
{{ states(progress_sensor) | int == 0 }}
# Compute blade height if applicable
- variables:
next_height: >
{% if height_store == '' %}
none
{% else %}
{% if stored_height == none or stored_height == 0 %}
{{ starting_height }}
{% else %}
{{ [target_height, stored_height - 5] | max }}
{% endif %}
{% endif %}
# Start mow
- service: mammotion.start_mow
data:
entity_id: "{{ mower_entity }}"
blade_height: "{{ next_height }}"
areas: "{{ switches }}"
# Update last mow timestamp
- service: input_datetime.set_datetime
target:
entity_id: "{{ last_mow_entity }}"
data:
datetime: "{{ now_dt }}"
# Update stored height
- choose:
- conditions: "{{ height_store != '' }}"
sequence:
- service: input_number.set_value
target:
entity_id: "{{ height_store }}"
data:
value: "{{ next_height }}"
mode: parallel
max: 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment