Rows are rendered as the BFF returns them. The screen does not synthesise
robots, and it does not hide a robot that has stopped reporting telemetry —
a registered robot with no live session still occupies a row.
The status model: ok, warn, bad, offline
Every row carries astatus of ok, warn, bad, or offline. The
status is computed by the BFF and delivered on the row; the console only
renders it (as the status dot, as the map pin colour, and as a filter
value).
Two consequences of that table are worth internalising:
badis still online. A robot in error is connected and talking, which is why the “Robots online” tile can read12 / 12while the hint underneath says3 errored.offlineis the only status excluded from the online count. The console’s fallback online count isok + warn + bad, and its fallback errored count is the number ofbadrows. These fallbacks are used only whenkpiStripdoes not returnonline_robots/errored_robots.
Any → ok → warn → bad → offline.
It is an exact match on the row’s status, not a severity threshold, so
filtering to warn does not include bad.
Where each row field comes from
pose.x / pose.y are not shown in the list. They are used only by the
map view, which drops a pin per robot with the row’s status as the pin
colour and the robot id as the label.
Clicking a row navigates to that robot’s detail screen at /robot/<id>.
Missing values and the degraded-telemetry flag
Telemetry fields can be absent while the robot record still exists. The screen distinguishes “unknown” from a real zero rather than collapsing both to0.
Per row:
fpsandrttrender as an em dash (—) when the field isnullor absent. A reported0fps renders as0.0in grey — that is a robot publishing nothing on its video track, which is a different condition from no telemetry at all.- A row with no
pose.x/pose.yis filtered out of the map view. It still appears in the list. The map’s “N robots” hint counts the rows passing your filters, not the number of pins drawn, so a fleet with partial pose data shows fewer pins than that number. - The Battery filter reads a missing
batteryas0. A robot with no battery reading therefore survives the< 20%filter and is excluded by≥ 20%and≥ 50%.
kpiStrip returns source: "degraded", there is no
live session to aggregate. The console then blanks the three
session-derived tiles rather than showing zeros:
Total robots and active alerts are not session-derived, so they keep
their values under the degraded flag. If every tile but “Robots” is
dashed out, the fleet is registered but nothing is streaming; that is not
an error in the console.
Filters, search, and pagination
robotsList is paginated server-side at 50 rows per page. Search and the
filter chips are then applied in the browser, to the rows of the current
page. The counter in the filter bar reads X of Y, where Y is the row
count delivered for that page.
- Search matches a case-insensitive substring against
id,name,model,task, andsitejoined together. - Site and Model chips are built from the distinct non-empty values present in the loaded rows, so their option lists reflect the current page.
- Status cycles the four statuses. Battery cycles
Any → ≥ 20% → ≥ 50% → < 20%. - Tag filter narrows further, and reports how many rows matched out of the rows that survived the other filters.
fleet-robots.csv with
the columns id, name, model, site, status, battery, task,
fps, rtt, alerts, last_seen. It exports what you can see — the
filtered current page — not the whole fleet. The button is disabled when
no rows match.
Bulk actions and their current status
Select rows with the checkboxes to raise the bulk bar. Only one action is wired up in the current build:
Emergency stop asks for confirmation first, naming the number of robots
and the topic it will publish to. It then attempts each robot
independently and reports the ones it could not reach in an alert listing
their ids. A failure for one robot does not abort the others, and the
list is not rolled back — treat the reported ids as robots that are still
moving and re-issue the stop for them.
How a registered robot becomes live
A row exists because the robot is registered, not because it is connected. The lifecycle you see in this screen is:- Registered. Add the robot with Add robot, or let it register
with the relay. Until
robotsListreturns any rows, the table showsRobots appear here once they register with the relay — add one to begin.(If rows exist but your filters exclude all of them, you get the different messageNo robots match the current filters — clear them to see the whole fleet.) - Registered, not reporting. The row shows identity fields —
name,id,model,site, tags — withstatus: offline, a non-livelastSeen, and dashes forfpsandrtt. With no session anywhere in the fleet,kpiStripreportssource: "degraded"and the online, fps, and RTT tiles dash out. - Live. Once the robot publishes telemetry,
lastSeenbecomes the literalliveand renders as the blinking indicator,statusmoves took,warn, orbad, andbattery,task,fps,rtt,alerts, andposepopulate. The robot now counts toward the online tile and, with a pose, appears as a pin on the map.
offline to live. Use the
refresh button in the filter bar to refetch both the rows and the KPI
strip immediately; the timestamp beside it shows when the row data last
arrived.
Related
- Telemetry — the metric, trace, and CDR streams behind these numbers
- Authentication — API keys and relay tokens used by control-plane calls

