Last active
December 1, 2025 23:26
-
-
Save mikey0000/4a576511db3173780727b09f1d2943b5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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