Skip to content

dotbot/site: add objects such as chargers to a site pack - #329

Open
geonnave wants to merge 71 commits into
DotBots:mainfrom
geonnave:site-editor-p4
Open

geonnave wants to merge 71 commits into
DotBots:mainfrom
geonnave:site-editor-p4

Conversation

@geonnave

@geonnave geonnave commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #328 (walls and obstacles), on #327, #326, #315 and the LH2 stack to #343. Merges after them; until then the diff also carries their commits.

Things on the floor become part of a site pack, read by every surface in this PR:

[objects.pad-a]    # a named table per object, like areas
kind = "charger"   # charger, dock, landmark or camera
x = 3200
y = 3900
heading_deg = 180.0   # optional, the robots' convention (0 faces +y)
  • Schema: SiteSection.objects, a kind from the four above (anything else is refused), Site.objects and Site.objects_of(kind).
  • Controller: GET /controller/site carries objects.
  • Console: the map draws each object as a rounded square in its kind's colour with a tick for its heading.
  • Simulator: a robot whose axle midpoint is within 100 mm of a charger charges, empty to full in 120 s, and drains as before elsewhere. Without a charger the battery follows the same linear discharge as today.
  • Charging-station example: the charger is the site's first charger object, and the queue lines up with it. A site without one keeps today's derived point on staging's far edge. Its README says how to add one.
  • Editor: an Object tool (B) places a charger on a click, and the inspector sets its name, kind, position, heading and comment. Objects move by drag or arrows, with Undo, and are checked for unique names and for lying inside the extent. The patcher now writes [areas.*] and [objects.*] through one function, so objects get the areas' guarantees: an untouched object is left byte for byte, a rename keeps its place and comment, a zero heading is not written.

Plan: rendered copy https://claude.ai/artifact/LHUXjhx1nMWifC2oGRBayt, source https://github.com/DotBots/dotbot-workspace/blob/main/plans/site-editor/plan.html (both internal).

A robot with a learned battery model charges on a charger too. Object names may hold a comma (only an area name is read as an x,y,w,h literal), inline objects are refused like inline areas, and a body that leaves out objects leaves the file's objects alone.

Validation. pytest: objects read, refused for an unknown kind, served and round-tripped through the REST model; the patcher's byte-identical round trip, a move and rename keeping the comment and heading, an add without a zero heading; the charging-station layout taking its charger from the site; in the simulator, a robot on a charger gains a twelfth of a full charge in ten seconds while one off it drains. vitest: the map draws an object; the editor places a charger, turns it into a dock, renames it and saves it on the grid; name and extent checks. npm run lint, typecheck and build; pre-commit run --all-files; full pytest 1841 passed, vitest 871 passed.

By hand, headless: a charger added to a new pack through the editor's REST save; dotbot run simulator --site charged --robots 4; python -m dotbot.examples.charging_station.charging_station against it queues the robots at x = 3200 and charges each at (3200, ~3820), the charger's place from the pack rather than the derived (2000, 4000), then parks them.

+ - Files
#315, the LH2 stack to #343, #326, #327 and #328, carried underneath (merge separately) +11237 -395 93
This PR, tests +223 -3 7
This PR, source +575 -60 18
This PR's files + -
dotbot/tests/test_site_objects.py +165 -0
dotbot/site_toml.py +86 -32
dotbot/console-web/src/siteEditor/Inspector.tsx +110 -2
dotbot/console-web/src/siteEditor/Canvas.tsx +69 -3
dotbot/console-web/src/siteEditor/SiteEditor.tsx +58 -6
dotbot/dotbot_simulator.py +38 -4
dotbot/console-web/src/MapView.tsx +33 -0
18 small files: dotbot/models.py, edit.ts, charging_station.py, siteObjects.ts, dotbot/site.py, edit.test.ts, dotbot/config.py, siteEditor.test.tsx, types.ts, README.md, test_site_editor.py, types.ts, dotbot/site_editor.py, barrierLayer.test.tsx, plant.py, api.ts, test_server.py, test_qrkey_app.py +239 -16
Total, 25 files +798 -63

Docs (the site pack format page) follow after review.

@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.71750% with 258 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.43%. Comparing base (ddc43f7) to head (96f4a05).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
dotbot/console-web/src/siteEditor/Canvas.tsx 81.71% 117 Missing ⚠️
dotbot/console-web/src/siteEditor/SiteEditor.tsx 87.30% 80 Missing ⚠️
dotbot/console-web/src/siteEditor/api.ts 83.33% 15 Missing ⚠️
dotbot/console-web/src/siteEditor/Inspector.tsx 97.79% 10 Missing ⚠️
dotbot/console-web/src/siteEditor/main.tsx 0.00% 8 Missing and 1 partial ⚠️
dotbot/console-web/src/siteEditor/edit.ts 96.58% 7 Missing ⚠️
dotbot/cli/swarm_lh2.py 91.80% 5 Missing ⚠️
dotbot/tests/lh2_multi_fixture.py 94.80% 4 Missing ⚠️
dotbot/console-web/dev/fake_swarmit_server.py 0.00% 3 Missing ⚠️
...ot/console-web/src/siteEditor/CalibrationPanel.tsx 97.76% 3 Missing ⚠️
... and 4 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #329      +/-   ##
==========================================
+ Coverage   88.21%   88.43%   +0.22%     
==========================================
  Files         227      240      +13     
  Lines       36147    39142    +2995     
  Branches     2324     2872     +548     
==========================================
+ Hits        31886    34616    +2730     
- Misses       4257     4521     +264     
- Partials        4        5       +1     
Flag Coverage Δ
console 83.37% <89.93%> (+1.38%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
dotbot/cli/main.py 95.83% <ø> (ø)
dotbot/cli/site_cmd.py 91.54% <ø> (-0.04%) ⬇️
dotbot/config.py 98.59% <ø> (-0.29%) ⬇️
dotbot/console-web/src/BotMarker.tsx 100.00% <100.00%> (ø)
dotbot/console-web/src/GridView.tsx 88.20% <100.00%> (-0.22%) ⬇️
dotbot/console-web/src/ListView.tsx 88.78% <100.00%> (+0.64%) ⬆️
dotbot/console-web/src/LocalizationPanel.tsx 86.09% <100.00%> (ø)
dotbot/console-web/src/MapView.tsx 97.63% <100.00%> (+0.09%) ⬆️
dotbot/console-web/src/botFacts.ts 98.10% <100.00%> (+0.66%) ⬆️
dotbot/console-web/src/heldWaypoints.ts 100.00% <100.00%> (ø)
... and 46 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

AI-assisted: Claude Opus 5.5
AI-assisted: Claude Opus 5.5
… page

Any web page in the browser can send requests to 127.0.0.1 with a valid
Host header, and behind a permissive CORS policy read the replies, so the
Host check alone let it save site.toml; a server bound beyond loopback
took any Host. The peer address, Origin and Sec-Fetch-Site are checked.

AI-assisted: Claude Opus 5.5
…ng tables

A patched file is read back and must give the model that was sent, so a
layout the patcher does not follow is refused rather than written.

AI-assisted: Claude Opus 5.5
Breaking: schema 3 calibration files are refused, so a calibration is
collected again. swarmit's own calibration reader still expects schema 3
and needs its matching change before the dashboard reads these files.

AI-assisted: Claude Opus 5.5
…tangle

Breaking, cross-repo: the messages and the config page (magic SWRP, 872
bytes) only match a swarmit bootloader and net core that store stations
by mask, and swarmit's Python must accept mask messages before it relays
them. Robots below device info 4 are refused with a reflash.

AI-assisted: Claude Opus 5.5
Breaking wire change, landing with DotBot-libs' 16-bit calibrated field:
every advertisement field after the mask moves by one byte and the
vendored dotbot_control.wasm is rebuilt at ABI 3 from that change. With
the one-byte mask, a calibration naming station 8 or above read every
sandbox robot as missing it and resent homographies on each advert.

AI-assisted: Claude Opus 5.5
AI-assisted: Claude Opus 5.5
… a file

A placement's id comes from its stations, not its tag or anchor, so the
same move saved twice, or a move into the source's own site, landed on an
existing path; save_placed keeps that file and refuses the source's id.

AI-assisted: Claude Opus 5.5
…leave omitted tables

AI-assisted: Claude Opus 5.5

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant