Repository navigation
Reference Scheduler
Schedules, their runs, rain pause and the weather.
Base path /api/v1/scheduler behind the gateway. Authentication, rate limits and the error format are the same for every service: see Scripting MowDeck. Rendered from apps/web/openapi/scheduler.json (OpenAPI 3.1), which you can also load into any OpenAPI tool.
Mower Angles
Where the mowing angle rotation of a mower stands (ADR 0061): the last angle per area (from scheduled runs and manual starts with rotation chosen) and the step the start sheet offers for manual starts. can_view on the mower.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerAnglesOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Record Manual Angle
A manual start with rotation chosen sent angle_deg for area_ids: the next run of these areas continues from it. A start with an explicit angle is not reported. can_control on the mower.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json ManualAngleIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerAnglesOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Rotation Settings
Set the rotation step of manual starts (null: off). can_control on the mower.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json RotationSettingsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerAnglesOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Widget
What the iOS schedule and weather widgets show for one mower (ADR 0059): the next runs (at most 3), the verdict of the rain pause for now (runs, rain_pause, unsure) and a few rain facts. can_view on the mower; schedules the caller may not see are left out.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json WidgetScheduleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Schedules
Schedules of the caller's account whose target (mower or group) the caller may view.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ScheduleList
|
Create Schedule
A new schedule: can_edit_schedule and can_control on the target (403 when the target is visible, 404 otherwise, also for a target of another account). The caller becomes the owner; every firing re-checks the owner's can_control.
Request body (required): application/json ScheduleIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json ScheduleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Schedule
One schedule (can_view on its target, 404 otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ScheduleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Schedule
Change a schedule (can_edit_schedule and can_control on the old and a new target); the caller becomes the owner and the next run is recomputed.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes |
Request body (required): application/json SchedulePatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ScheduleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Schedule
Delete a schedule and its runs (can_edit_schedule on the target).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Preview
The next firings and the rain decision for the first one (can_view).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes | |
count |
query | integer | no | min 1; max 20; default 5
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PreviewOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Run Now
Start the schedule now on behalf of the caller (can_control on the target, checked again per mower by Fleet). respect_rain=true applies the rain pause. The next firing stays as it is.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes | |
respect_rain |
query | boolean | no | default false
|
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json RunList
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Runs
Run records of the schedule, newest first (can_view on the target); pass next_before as before for the next page.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes | |
before |
query | string (date-time) or null | no | |
limit |
query | integer | no | min 1; max 200; default 50
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json RunList
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Skip Next
Skip the next firing (recorded as skipped_manual); 409 without a next run.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
schedule_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ScheduleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Weather
The rain decision for the mower now and the forecast hours it used (can_view).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
probability_threshold |
query | integer | no | min 0; max 100; default 60
|
precipitation_mm_threshold |
query | number | no | min 0; max 100; default 0.5
|
lookahead_hours |
query | integer | no | min 0; max 24; default 3
|
cooldown_hours |
query | integer | no | min 0; max 24; default 2
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json WeatherOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
The last angle a job mowed one area with.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number | yes | 0 up to below 180 degrees. |
area_id |
string | yes | |
schedule_id |
string (uuid) or null | yes | |
source |
"schedule" | "manual"
|
yes |
schedule: a schedule's run; manual: a start from the start sheet with rotation chosen. |
used_at |
string (date-time) | yes |
One forecast hour (values cover the hour ending at end).
| Field | Type | Required | Notes |
|---|---|---|---|
end |
string (date-time) | yes | |
past |
boolean | no | The hour ended before the decision time.; default false
|
precipitation_mm |
number or null | yes | |
probability_percent |
number or null | yes | |
rain_mm |
number or null | yes | |
start |
string (date-time) | yes |
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
array of ValidationError | no |
POST /mowers/{mower_id}/angles: a manual start chose rotation and sent this angle.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number | yes | Stored modulo 180.; min 0.0; max 180.0 |
area_ids |
array of string | yes | min items 1; max items 50 |
GET /mowers/{mower_id}/angles: where the angle rotation of a mower stands (ADR 0061).
| Field | Type | Required | Notes |
|---|---|---|---|
areas |
array of AreaAngleOut | yes | The last angle per area, by area id. |
manual_step_deg |
number or null | yes | The rotation step the start sheet offers for manual starts; null: off. |
mower_id |
string (uuid) | yes |
How eagerly the mower avoids obstacles during a native job (MowPattern).
Which modes a mower offers depends on its model and firmware (MowerCapabilities.start_options.obstacle_detection). The names follow the vendor apps: off is the plain bump-and-turn behaviour, standard avoids obstacles it sees ahead, sensitive additionally avoids areas that are not lawn; slow_touch and less_touch exist only on older firmware.
Type: "off" | "slow_touch" | "less_touch" | "standard" | "sensitive"
Whether the border laps run before or after the fill of a native job.
Type: "border_first" | "grid_first"
One upcoming firing.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number or null | no | The mowing angle this firing will use on angle_mower_id (rotation applied, assuming every earlier firing starts); null when skipped, for a pattern without direction or without a target mower. |
at |
string (date-time) | yes | |
skipped |
boolean | yes | Skipped by skip-next. |
window_end |
string (date-time) | yes |
GET /schedules/{id}/preview.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_mower_id |
string (uuid) or null | no | The mower the angles are worked out for (a group: its first mower; each mower continues from its own last angle). |
items |
array of PreviewItemOut | yes | |
weather |
RainDecisionOut or null | yes | The rain decision for the first firing that is not skipped, with today's forecast (null without a target mower). |
weather_mower_id |
string (uuid) or null | yes |
What kind of subject a principal is.
Type: "user" | "subuser" | "api_token" | "service"
A compact reference to a principal, embedded in commands and audit records.
| Field | Type | Required | Notes |
|---|---|---|---|
display_name |
string or null | no | |
kind |
PrincipalKind | yes | Kind of subject. |
subject |
string (uuid) | yes | Stable subject id (JWT sub). |
token_id |
string (uuid) or null | no | Token id (JWT jti), if known. |
A rain decision with what it was based on.
| Field | Type | Required | Notes |
|---|---|---|---|
attribution |
string or null | no | |
holds |
boolean | yes | |
hours |
array of HourOut | yes | The forecast hours the decision looked at. |
latitude |
number or null | yes | |
location_source |
"site" | "map" | "position" or null |
yes | |
longitude |
number or null | yes | |
pause_until |
string (date-time) or null | no | When a hold ends, by the Scheduler's rule; null when not holding or when the forecast does not reach that time. |
provider |
string | yes | |
reason |
string | yes | |
recent_mm_24h |
number or null | no | |
recent_mm_6h |
number or null | no | |
settings |
RainPause | yes | The rain pause settings the decision applied (the schedule's, or the query parameters and defaults). |
verdict |
"run" | "hold" | "unknown_run" | "unknown_hold" | "no_location" | "disabled"
|
yes | |
wet |
boolean | no | The lawn is still wet from earlier rain.; default false
|
wet_until |
string (date-time) or null | no | Estimated dry time. |
Rain pause settings of a schedule.
| Field | Type | Required | Notes |
|---|---|---|---|
cooldown_hours |
integer | no | Hold while rain fell within this many hours.; min 0.0; max 24.0; default 2
|
enabled |
boolean | no | default true
|
lookahead_hours |
integer | no | min 0.0; max 24.0; default 3
|
precipitation_mm_threshold |
number | no | Millimetres per hour; at or above holds the run.; min 0.0; max 100.0; default 0.5
|
probability_threshold |
integer | no | Percent; a forecast hour at or above holds the run.; min 0.0; max 100.0; default 60
|
run_when_unknown |
boolean | no | Without a forecast (provider down): run (true) or hold.; default true
|
PUT /mowers/{mower_id}/angles/settings: the step of manual starts.
| Field | Type | Required | Notes |
|---|---|---|---|
manual_step_deg |
number or null | yes | Degrees the start sheet turns the last angle by; null: no rotation. |
GET /schedules/{id}/runs (newest first) and POST .../run-now.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of RunOut | yes | |
next_before |
string (date-time) or null | no |
One run of a schedule for one mower.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number or null | no | For a started run: the mowing angle the start sent (0 up to below 180 degrees); null for a pattern without direction and for runs that did not start. |
command_id |
string (uuid) or null | yes | |
details |
string or null | yes | |
followup |
string or null | yes | After a start: rain_dock, window_dock, finished, closed or null while the job is followed. |
followup_at |
string (date-time) or null | yes | |
id |
string (uuid) | yes | |
mower_id |
string (uuid) or null | yes | |
outcome |
ScheduleRunOutcome | yes | |
schedule_id |
string (uuid) | yes | |
scheduled_for |
string (date-time) | yes | |
started_at |
string (date-time) | yes | |
trigger |
"schedule" | "manual"
|
yes | |
window_end_at |
string (date-time) or null | yes |
POST /schedules.
kind=weekly needs days_of_week; kind=every_n_days needs anchor_date (the first day it fires) and interval_days. start_time is wall-clock time in the schedule's time zone (the target's site, or timezone). area_ids empty means every area of the mower's map; a group target always mows every area of each mower.
| Field | Type | Required | Notes |
|---|---|---|---|
anchor_date |
string (date) or null | no | |
area_ids |
array of string | no | max items 50 |
blade_height_mm |
integer or null | no | Blade height in millimetres sent before each start (set_blade_height); null keeps the mower's own. Must lie within every target mower's blade_height_range_mm. |
days_of_week |
array of "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun"
|
no | max items 7 |
duration_minutes |
integer | no | The window: no start after it closed.; min 1.0; max 1440.0; default 120
|
enabled |
boolean | no | default true
|
interval_days |
integer or null | no | |
kind |
"weekly" | "every_n_days"
|
yes | |
name |
string | yes | min length 1; max length 100 |
pattern |
SchedulePatternIn or null | no | Start settings of every run (SchedulePattern), laid over the mower's mow defaults. Settings beyond the angle and the border laps must be offered by every mower of the target (422 otherwise). |
pause_running_jobs_on_rain |
boolean | no | Send a running scheduled job back to the dock when it rains.; default true
|
rain_pause |
RainPause | no | |
return_to_dock_at_window_end |
boolean | no | default false
|
rotation_angles |
array of number | no | Angles used round robin, one per run (replace pattern.angle_deg).; max items 24 |
rotation_step_deg |
number or null | no | Step rotation (ADR 0061): each run turns the last angle the mower mowed its areas with by this many degrees (modulo 180); null: off. Excludes rotation_angles. |
speed_mps |
number or null | no | Mowing speed in m/s sent before each start (set_speed); null keeps the mower's own. Must lie within every target mower's speed range. |
start_time |
string (time) | yes | |
target_id |
string (uuid) | yes | |
target_type |
"mower" | "group"
|
yes | |
timezone |
string or null | no | IANA name overriding the site's time zone. |
GET /schedules.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of ScheduleOut | yes |
A schedule.
| Field | Type | Required | Notes |
|---|---|---|---|
anchor_date |
string (date) or null | yes | |
area_ids |
array of string | yes | |
blade_height_mm |
integer or null | yes | |
created_at |
string (date-time) | yes | |
days_of_week |
array of string | yes | |
disabled_reason |
string or null | yes | |
duration_minutes |
integer | yes | |
enabled |
boolean | yes | |
id |
string (uuid) | yes | |
interval_days |
integer or null | yes | |
kind |
string | yes | |
last_run_at |
string (date-time) or null | yes | |
name |
string | yes | |
next_run_at |
string (date-time) or null | yes | |
owner |
PrincipalRef | yes | The subject the schedule runs on behalf of. |
pattern |
SchedulePattern or null | yes | The start settings the schedule sets; keys left out come from the mower's mow defaults, then the mower's own setting. |
pause_running_jobs_on_rain |
boolean | yes | |
permission_skips |
integer | yes | |
rain_pause |
RainPause | yes | |
return_to_dock_at_window_end |
boolean | yes | |
rotation_angles |
array of number | yes | |
rotation_index |
integer | yes | |
rotation_step_deg |
number or null | yes | Step rotation (ADR 0061): degrees each run turns the mower's last angle on its areas by; null: off. |
skip_until |
string (date-time) or null | yes | |
speed_mps |
number or null | yes | |
start_time |
string (time) | yes | |
target_id |
string (uuid) | yes | |
target_type |
string | yes | |
timezone |
string | yes | The effective time zone (override or the site's). |
timezone_override |
string or null | yes | |
updated_at |
string (date-time) | yes |
PATCH /schedules/{id}: only the given fields change; the caller becomes the owner.
| Field | Type | Required | Notes |
|---|---|---|---|
anchor_date |
string (date) or null | no | |
area_ids |
array of string or null | no | |
blade_height_mm |
integer or null | no | Blade height in millimetres sent before each start (set_blade_height); null keeps the mower's own. Must lie within every target mower's blade_height_range_mm. |
days_of_week |
array of "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun" or null |
no | |
duration_minutes |
integer or null | no | |
enabled |
boolean or null | no | |
interval_days |
integer or null | no | |
kind |
"weekly" | "every_n_days" or null |
no | |
name |
string or null | no | |
pattern |
SchedulePatternIn or null | no | null: none |
pause_running_jobs_on_rain |
boolean or null | no | |
rain_pause |
RainPause or null | no | |
return_to_dock_at_window_end |
boolean or null | no | |
rotation_angles |
array of number or null | no | |
rotation_step_deg |
number or null | no | Step rotation (ADR 0061): each run turns the last angle the mower mowed its areas with by this many degrees (modulo 180); null: off. Excludes rotation_angles. |
speed_mps |
number or null | no | Mowing speed in m/s sent before each start (set_speed); null keeps the mower's own. Must lie within every target mower's speed range. |
start_time |
string (time) or null | no | |
target_id |
string (uuid) or null | no | |
target_type |
"mower" | "group" or null |
no | |
timezone |
string or null | no | null: the site's |
The start settings one schedule sets for each of its runs (ADR 0024 amendment of 2026-10-24): the keys of :class:MowPattern that make sense for a recurring job, each optional. A key left out (None) is not part of the schedule: the run takes it from the mower's mow defaults in Fleet, and without those the mower keeps its own setting (for the pattern, angle and border laps the clients' fallback, stripes at 0 degrees with one lap).
start_progress_pct is not offered: it skips the first part of one job's route, which only makes sense to resume an interrupted job, never for every run of a schedule.
Which values fit one mower is decided with its :class:MowerCapabilities (:meth:problem); a group schedule must fit every mower of the group.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number or null | no | Base angle in degrees; null: the mow defaults'. A schedule's rotation_angles replace it run by run; with rotation_step_deg it is the angle of the first run, later runs turn the last angle by the step (ADR 0061). |
border_laps |
integer or null | no | |
name |
"stripes" | "diagonal" | "checkerboard" | "edge_only" | "random_angle" or null |
no | The native pattern; null: the mow defaults'. |
obstacle_detection |
ObstacleDetection or null | no | Needs the mode in start_options.obstacle_detection. |
obstacle_laps |
integer or null | no | Needs start_options.obstacle_laps_range. |
order |
PathOrder or null | no | Needs the order in orders. |
spacing_m |
number or null | no | Path spacing in metres; needs MowerCapabilities.path_spacing_range_mm. |
The start settings of a schedule (SchedulePattern): every key optional, null or left out falls back to the mower's mow defaults, then to the mower's own setting. Unknown keys, including start_progress_pct, are refused.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number or null | no | Base angle in degrees; null: the mow defaults'. A schedule's rotation_angles replace it run by run; with rotation_step_deg it is the angle of the first run, later runs turn the last angle by the step (ADR 0061). |
border_laps |
integer or null | no | |
name |
"stripes" | "diagonal" | "checkerboard" | "edge_only" | "random_angle" or null |
no | The native pattern; null: the mow defaults'. |
obstacle_detection |
ObstacleDetection or null | no | Needs the mode in start_options.obstacle_detection. |
obstacle_laps |
integer or null | no | Needs start_options.obstacle_laps_range. |
order |
PathOrder or null | no | Needs the order in orders. |
spacing_m |
number or null | no | Path spacing in metres; needs MowerCapabilities.path_spacing_range_mm. |
What one run of a schedule did for one mower.
Type: "started" | "skipped_rain" | "skipped_permission" | "skipped_window" | "skipped_mower_busy" | "skipped_manual" | "failed"
| Field | Type | Required | Notes |
|---|---|---|---|
ctx |
object | no | |
input |
any | no | |
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes |
GET /weather/{mower_id}: the rain decision now, with the default settings unless query parameters change them.
| Field | Type | Required | Notes |
|---|---|---|---|
at |
string (date-time) | yes | |
decision |
RainDecisionOut | yes | |
mower_id |
string (uuid) | yes |
Rain facts for the widgets (everything null when no forecast is available).
| Field | Type | Required | Notes |
|---|---|---|---|
expected_mm_next_hours |
number or null | yes | Precipitation of the coming hours the rain pause looks at (its look-ahead). |
pause_until |
string (date-time) or null | yes | When a rain pause ends, if one holds. |
raining_now |
boolean or null | yes | The forecast hour that contains at has measurable precipitation. |
recent_mm_6h |
number or null | yes | |
wet |
boolean | yes | The lawn is still wet from earlier rain. |
wet_until |
string (date-time) or null | yes |
One upcoming run in the widget overview.
| Field | Type | Required | Notes |
|---|---|---|---|
duration_minutes |
integer | yes | |
name |
string | yes | |
schedule_id |
string (uuid) | yes | |
starts_at |
string (date-time) | yes |
GET /mowers/{mower_id}/widget: what the schedule and weather widgets of the iOS app show for one mower (ADR 0059).
| Field | Type | Required | Notes |
|---|---|---|---|
at |
string (date-time) | yes | |
mower_id |
string (uuid) | yes | |
rain |
WidgetRain | yes | |
runs |
array of WidgetRunOut | yes | The next runs, soonest first (at most 3). |
verdict |
"runs" | "rain_pause" | "unsure"
|
yes |
runs: the next run would start; rain_pause: the rain pause holds it; unsure: no forecast or no location, or the forecast is unknown. |
Mirrored from docs/reference/api/scheduler.md at commit 0b51164ccae892daef8e7473da86ee072409d2f4. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 0b51164ccae892daef8e7473da86ee072409d2f4. 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
- ADR 0069: Provider conformance kit and provider package template
- ADR 0070: Virtual zones for mowers without a vendor map
- ADR 0071: Capability matrix generated from the adapters
- ADR 0072: API explorer in the web app, for the public demo
-
Development
- Getting started
- Service template
- Shared libraries
- Cloud providers: adding a vendor
- Adding a provider: template and conformance kit
- 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
- Capability matrix
- API reference
- Original plan (German)