Repository navigation
Reference Planner
Mowing patterns, spot paths and plans.
Base path /api/v1/planner behind the gateway. Authentication, rate limits and the error format are the same for every service: see Scripting MowDeck. Rendered from apps/web/openapi/planner.json (OpenAPI 3.1), which you can also load into any OpenAPI tool.
Coverage Gaps
Covered ground and the gaps of an area from the mower's position track (Telemetry) between start and end, with a remow step for them.
Request body (required): application/json GapsRequestIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json GapsOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Patterns
Every registered pattern with its settings schema (plug-ins included).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PatternList
|
Create Plan
The plan ready to start: the SpotMowPlan with its hash and the start_mow command for Fleet. Nothing is stored; the same request gives the same hash. Needs can_control on the mower (Fleet checks it again when the command arrives).
Request body (required): application/json PlanRequestIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PlanOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Preview Plan
Compute and validate a plan and show it: segments, duration, area, warnings, and how the mower can run it. Needs can_view on the mower (404 when invisible).
Request body (required): application/json PlanRequestIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PreviewOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Templates
Saved chains of the caller's account.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TemplateList
|
Get Template
One saved chain.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
name |
path | string | yes | min length 1; max length 100 |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TemplateOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Put Template
Create (201) or replace (200) a saved chain; needs can_control on the account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
name |
path | string | yes | min length 1; max length 100 |
Request body (required): application/json TemplateIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TemplateOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Template
Delete a saved chain; needs can_control on the account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
name |
path | string | yes | min length 1; max length 100 |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Where to mow. area_id alone is a whole map area; a polygon (local metres or WGS84 [lat, lon]) is a spot, inside area_id when given, else inside the mapped areas.
| Field | Type | Required | Notes |
|---|---|---|---|
area_id |
string or null | no | |
holes |
array of array of array of any | no | max items 50 |
polygon |
array of array of any or null | no | |
polygon_wgs84 |
array of array of any or null | no |
[lat, lon] pairs. |
One pattern of a chain with its settings (validated by the pattern's schema).
| Field | Type | Required | Notes |
|---|---|---|---|
pattern |
string | yes | max length 64; pattern ^[a-z][a-z0-9_]*$
|
settings |
object | no |
Position and orientation of the charging station in the local frame.
| Field | Type | Required | Notes |
|---|---|---|---|
heading_deg |
number | no | Local frame, counter-clockwise from +x.; min 0.0; less than 360.0; default 0.0
|
x |
number | yes | |
y |
number | yes |
How the mower can run the plan.
| Field | Type | Required | Notes |
|---|---|---|---|
mode |
"custom_paths" | "native" | "unsupported" | "unknown"
|
yes |
custom_paths: the mower follows the route; native: it runs native_job on the map area; unsupported: it cannot run this plan; unknown: no capabilities (a raw map). |
native_job |
object or null | no |
StartMow.pattern settings of the native form, if any. |
reason |
string | yes |
Covered ground and gaps; remow is a ready chain step for the gaps.
| Field | Type | Required | Notes |
|---|---|---|---|
area_id |
string or null | yes | |
area_m2 |
number | yes | |
coverage_ratio |
number | yes | |
covered_area_m2 |
number | yes | |
gap_area_m2 |
number | yes | |
gaps |
array of array of array of any | yes | Gap polygons in local metres. |
gaps_wgs84 |
array of array of array of any | yes | The same as [lat, lon]. |
remow |
ChainStepIn or null | no | A remow step over the gaps (None without gaps). |
track_points |
integer | yes | |
truncated |
boolean | yes |
Which parts of an area did the mower miss between start and end?
| Field | Type | Required | Notes |
|---|---|---|---|
area |
AreaIn or null | no | Default: the map area with the most track points. |
cutting_width_m |
number or null | no | |
end |
string (date-time) | yes | |
min_gap_m2 |
number | no | min 0.0; max 100.0; default 0.05
|
mower_id |
string (uuid) | yes | |
start |
string (date-time) | yes |
Anchors the local frame on the earth.
The local point (0, 0) is at (origin_lat, origin_lon). The local axes are the east and north axes rotated counter-clockwise by rotation_deg: a local point (x, y) lies east = x cos(r) - y sin(r) and north = x sin(r) + y cos(r) metres from the origin.
| Field | Type | Required | Notes |
|---|---|---|---|
origin_lat |
number | yes | min -90.0; max 90.0 |
origin_lon |
number | yes | min -180.0; max 180.0 |
rotation_deg |
number | no | min -360.0; max 360.0; default 0.0
|
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
array of ValidationError | no |
A mowable area (a "zone" in the Mammotion app).
| Field | Type | Required | Notes |
|---|---|---|---|
boundary |
array of array of any | yes | min items 3 |
id |
string | yes | Stable id, e.g. the vendor's zone hash.; min length 1; max length 128 |
name |
string or null | no |
A transfer path between areas (driven with blades off).
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string | yes | min length 1; max length 128 |
name |
string or null | no | |
points |
array of array of any | yes | min items 2 |
A polygon the mower must stay out of: a no-go zone or an obstacle.
| Field | Type | Required | Notes |
|---|---|---|---|
boundary |
array of array of any | yes | min items 3 |
id |
string | yes | min length 1; max length 128 |
name |
string or null | no |
The map of one mower: areas, no-go zones, obstacles, paths and the dock.
| Field | Type | Required | Notes |
|---|---|---|---|
areas |
array of MapArea | no | |
dock |
DockPose or null | no | |
no_go_zones |
array of MapZone | no | |
obstacles |
array of MapZone | no | |
paths |
array of MapPath | no | |
reference |
GeoReference | yes | |
revision |
string or null | no | Map version, e.g. the vendor's map hash. |
Overrides of the mower data (defaults: the Planner's settings and the mower's speed).
| Field | Type | Required | Notes |
|---|---|---|---|
cutting_width_m |
number or null | no | |
max_speed_mps |
number or null | no | |
overlap_m |
number or null | no | |
safety_margin_m |
number or null | no | |
transfer_speed_mps |
number or null | no | |
turning_radius_m |
number or null | no |
The mower data a plan was computed with.
| Field | Type | Required | Notes |
|---|---|---|---|
cutting_width_m |
number | yes | |
max_speed_mps |
number | yes | |
overlap_m |
number | yes | |
safety_margin_m |
number | yes | |
spacing_m |
number | yes | |
transfer_speed_mps |
number | yes | |
turning_radius_m |
number | yes |
Every registered pattern, by key.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of PatternOut | yes |
A registered pattern: the app builds the settings form from settings_schema.
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string or null | no | |
key |
string | yes | |
name |
string | yes | |
native |
string or null | no | Name of the native pattern a mower may run instead (on a whole map area); whether a mower supports it is in its capabilities (native_patterns). |
settings_schema |
object | yes | JSON Schema (draft 2020-12). |
A plan ready to start: send command to Fleet (POST /api/v1/fleet/mowers/{mower_id}/commands with {"command": ...}).
| Field | Type | Required | Notes |
|---|---|---|---|
area_m2 |
number | yes | |
command |
StartMow | yes | |
coverage_ratio |
number | yes | |
covered_area_m2 |
number | yes | |
estimated_duration_s |
number | yes | |
execution |
ExecutionOut | yes | |
mow_length_m |
number | yes | |
mower |
MowerSpecOut | yes | |
pattern_chain |
array of string | yes | |
plan_bytes |
integer | yes | |
plan_hash |
string | yes | |
preview |
object | yes | FeatureCollection: one LineString per segment with kind, blades_on, reverse, speed_mps; coordinates local metres, or [lon, lat] with wgs84. |
segment_count |
integer | yes | |
spot_plan |
SpotMowPlan | yes | |
transfer_length_m |
number | yes | |
transit |
TransitOut or null | no | The transit of a spot run, when the request asked for it. |
turn_style |
TurnStyle or null | no | The turn style the lane ends were shaped with (after the multi_point fallback); null without a requested style. |
warnings |
array of string | yes |
A plan for a mower (mower_id: its map and capabilities) or for a raw map.
| Field | Type | Required | Notes |
|---|---|---|---|
area |
AreaIn | yes | |
chain |
array of ChainStepIn | no | max items 8 |
map |
MowerMap or null | no | A map instead of a mower's. |
mower |
MowerSpecIn or null | no | |
mower_id |
string (uuid) or null | no | |
template |
string or null | no | Use the chain of a saved template instead of chain. |
transit |
TransitIn or null | no | Also plan the transit of a spot run from the dock or a position to the plan's first point (ADR 0041). |
turn_style |
TurnStyle or null | no | Shape the lane ends for a spot run that turns this way (ADR 0043): arc (U-turn or bulb turn), multi_point (three-point turn; arc when the mower's drive link cannot reverse) or in_place; null keeps the straight connections. |
wgs84 |
boolean | no | Preview coordinates as [lon, lat].; default false
|
A validated plan: totals, how it runs, and the segments as a GeoJSON-like collection.
| Field | Type | Required | Notes |
|---|---|---|---|
area_m2 |
number | yes | |
coverage_ratio |
number | yes | |
covered_area_m2 |
number | yes | |
estimated_duration_s |
number | yes | |
execution |
ExecutionOut | yes | |
mow_length_m |
number | yes | |
mower |
MowerSpecOut | yes | |
pattern_chain |
array of string | yes | |
plan_bytes |
integer | yes | |
plan_hash |
string | yes | |
preview |
object | yes | FeatureCollection: one LineString per segment with kind, blades_on, reverse, speed_mps; coordinates local metres, or [lon, lat] with wgs84. |
segment_count |
integer | yes | |
transfer_length_m |
number | yes | |
transit |
TransitOut or null | no | The transit of a spot run, when the request asked for it. |
turn_style |
TurnStyle or null | no | The turn style the lane ends were shaped with (after the multi_point fallback); null without a requested style. |
warnings |
array of string | yes |
A computed mowing route for StartMow.spot_plan.
| Field | Type | Required | Notes |
|---|---|---|---|
covered_area_m2 |
number | no | min 0.0; default 0.0
|
estimated_duration_s |
number | no | min 0.0; default 0.0
|
native |
SpotNativeJob or null | no | |
pattern_chain |
array of string | yes | min items 1; max items 16 |
plan_hash |
string | yes | SHA-256 of the chain and the segments (spot_plan_hash); must match.; pattern ^[0-9a-f]{64}$
|
segments |
array of SpotSegment | yes | min items 1; max items 10000 |
The plan expressed as a native job of the mower: whole map areas and one pattern.
Present only when the chain is exactly one pattern the mower may run by itself (stripes, diagonal, checkerboard, edge_only, or border_fill with one of them) on map areas, so a mower without custom_paths can still execute it as an ordinary StartMow(area_ids, pattern).
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | yes | min items 1 |
pattern |
object | yes | Settings in the form of StartMow.pattern (name, angle_deg, spacing_m, border_laps, order). |
One part of a spot plan: drive along path with the blades on or off (backwards with reverse: the mower faces against the direction of travel, part of a three-point turn).
| Field | Type | Required | Notes |
|---|---|---|---|
blades_on |
boolean | yes | |
kind |
"mow" | "turn" | "transfer"
|
no | default "mow"
|
path |
string | yes | Encoded polyline of local metres (x, y), centimetre precision (encode_polyline), at least two points.; min length 4; max length 200000 |
reverse |
boolean | no | Drive the polyline backwards (negative linear speed, the mower faces against the direction of travel); always with the blades off (ADR 0043).; default false
|
speed_mps |
number | yes | max 2.0; greater than 0.0 |
Start mowing the given areas, a stored plan or an inline spot plan (exactly one).
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | no | Map area ids to mow, in order. |
kind |
"start_mow" |
no | default "start_mow"
|
pattern |
object or null | no | Pattern settings (validated by the pattern's own JSON Schema). |
plan_ref |
string or null | no | Reference to a stored mowing plan. |
spot_plan |
SpotMowPlan or null | no | A route computed by the Planner (spot mowing). Runs only on mowers with custom_paths, or natively when the plan carries a native job. |
A saved chain.
| Field | Type | Required | Notes |
|---|---|---|---|
chain |
array of ChainStepIn | yes | min items 1; max items 8 |
description |
string or null | no |
Templates of the account, by name.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of TemplateOut | yes |
A saved chain of the account.
| Field | Type | Required | Notes |
|---|---|---|---|
chain |
array of ChainStepIn | yes | |
created_at |
string (date-time) | yes | |
description |
string or null | yes | |
name |
string | yes | |
updated_at |
string (date-time) | yes |
Where a spot run's transit would start (ADR 0041): from_dock for a docked mower (the map's dock, as the Device-Gateway plans it), else the mower's position in local metres.
| Field | Type | Required | Notes |
|---|---|---|---|
from_dock |
boolean | no | default false
|
position |
array of any or null | no |
The transit a spot run would drive from the start to the plan's first point (blades off), planned by the same algorithm as the Device-Gateway's run.
| Field | Type | Required | Notes |
|---|---|---|---|
found |
boolean | yes | A route exists (the web app's route condition). |
from_dock |
boolean | yes | |
length_m |
number | yes | |
reason |
string or null | no |
no_route: ... without a route. |
route |
array of array of number | yes | The route, local metres or [lon, lat] with wgs84; empty without one. |
How a spot run turns at the end of a lane (ADR 0043).
in_place: the mower rotates on the spot (fast, but an all-wheel-drive mower scuffs the turf). arc: a forward U-turn with a radius of at least half the lane spacing, or a bulb turn over the neighbouring lane when the spacing is narrower than the turning radius. multi_point: a three-point turn (forward arc, reverse arc with the blades off, forward arc); needs a drive link that can reverse (MowerCapabilities.drive_reverse).
Type: "in_place" | "arc" | "multi_point"
| Field | Type | Required | Notes |
|---|---|---|---|
ctx |
object | no | |
input |
any | no | |
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes |
Mirrored from docs/reference/api/planner.md at commit 92e148f2170c557620edba69704ad69dc99a9cba. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 92e148f2170c557620edba69704ad69dc99a9cba. Edit the files in the repository, not this wiki.
MowDeck documentation
- Home
- Phases
- Architecture
-
Decisions (ADR)
- Architecture decisions
- ADR 0001: OpenFGA instead of self-built authorization
- ADR 0002: Self-built Identity service in FastAPI instead of Keycloak or Zitadel
- ADR 0003: SvelteKit for the web app
- ADR 0004: Monorepo with a uv workspace
- ADR 0005: AGPL-3.0 for services and apps, Apache-2.0 for libraries
- ADR 0006: PostgreSQL for all persistence, no SQLite
- ADR 0007: NATS JetStream as event bus
- ADR 0008: Traefik as gateway
- ADR 0009: Command and event envelopes, subject naming and de-duplication
- ADR 0010: Python 3.13 for all services and libraries
- ADR 0011: Separate GPL-3.0 package for the PyMammotion adapter
- ADR 0012: Mower control interface and safety rules
- ADR 0013: Device-Gateway registry, sharding and per-mower concurrency
- ADR 0014: Authorization model, tuple ownership and the mowdeck-authz client
- ADR 0015: Tokens, sessions and key rotation
- ADR 0016: Fleet commands and authorization per command kind
- ADR 0017: Telemetry storage and retention
- ADR 0018: Realtime WebSocket protocol
- ADR 0019: Mammotion adapter transports, manual drive and secrets
- ADR 0020: Web app architecture
- ADR 0021: Browser authentication flow
- ADR 0022: Notifications: rules, recipients and delivery
- ADR 0023: Map rendering and projection
- ADR 0024: Scheduler: recurrence, rain pause and command issuing
- ADR 0025: Home Assistant integration as a pure API client
- ADR 0026: Manual drive channel over the Realtime WebSocket
- ADR 0027: Health history and theft alarm
- ADR 0028: Entitlements: plans as data and enforcement
- ADR 0029: Helm chart and release pipeline
- ADR 0030: Mowing patterns as plug-ins and the Planner
- ADR 0031: Billing with a Stripe adapter
- ADR 0032: Live camera over Agora, joined directly by the browser
- ADR 0033: Vision-assisted recovery with human approval
- ADR 0034: Linked cloud accounts and device discovery
- ADR 0035: Server-side camera frames and automatic AI analysis on errors
- ADR 0036: Native app shells with Capacitor, loading the web app from the server
- ADR 0037: Camera panorama calibration in the browser, with the AI supplying points only
- ADR 0038: Dual link per mower and firmware updates
- ADR 0039: Spot mowing by MowDeck-driven paths
- ADR 0040: Link heartbeat for online status
- ADR 0041: Spot runs from the dock: undock, transit and return
- ADR 0042: Drive calibration
- ADR 0043: Turn styles
- ADR 0044: Drive view with camera
- ADR 0045: Camera relay
- ADR 0046: Device settings as capabilities
- ADR 0047: The RTK base station as a Fleet device
- ADR 0048: Maintenance commands
- ADR 0049: Manual driving over the Mammotion cloud
- ADR 0050: Passkeys and the app login hand-off
- ADR 0051: Sign in with GitHub
- ADR 0052: Sign in with Apple
- ADR 0053: Retention and downsampling of the position track
- ADR 0054: Aerial photo under the mower map
- ADR 0055: Deploy maintenance window
- ADR 0056: Camera photo in push notifications for errors and theft alarms
- ADR 0057: Step-up re-authentication for critical actions
- ADR 0058: Theft tracking mode
- ADR 0059: iOS widgets and the mowing Live Activity
- ADR 0060: Apple Watch app
- ADR 0061: Mowing angle rotation
- ADR 0062: Setup tour for new users
- ADR 0063: Matter server (mowers in Apple Home and Google Home)
- ADR 0064: Personal access tokens and the public API documentation
- ADR 0065: Security center and new-login alerts
- ADR 0066: Cloud provider plugins and adapters for more vendors
- ADR 0067: Error code lexicon, provider independent
- ADR 0068: Public demo mode
-
Development
- Getting started
- Service template
- Shared libraries
- Cloud providers: adding a vendor
- Adding an error lexicon for a vendor
- Design: identity and authorization
- Design: fleet, telemetry, realtime
- Design: web app
- Web app
- Home Assistant integration
- Camera source bridge protocol
- Fuzzing and property-based tests
- GitHub wiki mirror
-
Operations
- Operating the Compose stack
- Operating MowDeck on Kubernetes (Helm)
- Building the Bluetooth bridge (ESPHome on a XIAO ESP32-S3)
- Releases
- Vendor library updates
- Billing operations
- Telemetry: retention and position downsampling
- iPhone and Android apps
- Passkeys
- Sign in with GitHub
- Aerial photo under the map
- Sign in with Apple
- Theft tracking mode
- Matter server
- Source code offer (AGPL-3.0 section 13)
- Public demo
- Spikes
-
Guides
- Guides
- ESP32 bridge: purchase and setup
- Signing in with a passkey
- Signing in with GitHub
- Error codes in plain words
- Aerial photo under the map
- Signing in with Apple
- Confirming critical actions
- Your security page
- iPhone widgets and the mowing Live Activity
- Apple Watch
- The setup tour
- Apple Home and Google Home (Matter)
- Worx Landroid, Kress and LandXcape mowers
- Scripting MowDeck
- API reference
- Original plan (German)