Repository navigation
Releases: bjan/pycentauri
Releases · bjan/pycentauri
Release list
v0.9.0 — opt-in dashboard update check
Adds an optional "update available" indicator to the web dashboard.
Added
centauri server --check-updates(off by default). When enabled, the server does one cached PyPI lookup every 12 h and the dashboard shows a subtle ↑ vX.Y.Z badge next to the version when a newer release exists, linking to its notes.- Fail-silent, and the only outbound (non-printer) call in the whole tool — so the default still "talks only to your printer."
/api/infogainslatest_version+update_available(inert unless opted in). PEP 440 comparison, so a local dev build ahead of PyPI never false-nags.
No new dependencies.
v0.8.0 — CC1 file management (list/delete/history) + safety guards
CC1 file browsing is local SDCP, not cloud — this release overturns the prior belief. The SDK's commented-out Cmds work with the right payload (258 list, 259 delete, 320+321 history), confirmed live on V0.3.0-o.
Added
- CC1 file management —
list_files,delete_files,print_historynow work on the original Centauri Carbon, matching the CC2. History status normalised across both printers. - Web dashboard Files + Print-history panels (both models); light toggle + delete wired through with
--enable-control.
Safety & robustness
- Delete refuses the currently-printing file (both models) — verified live against a running print; reads confirmed safe mid-print.
- Transient timeouts on
/history·/disk·/files/deletemap to 504 (not 501/502) so a blip doesn't permanently hide a panel. /files/deletevalidatesfilenamesis a list; uploads hash/read off the event loop so a large gcode can't stall the status stream.
Stock CC1 firmware (V1.1.46) was not re-tested for these Cmds; behaviour there is inferred from the shared app binary.
Full notes: see CHANGELOG.md.
v0.7.0 — file management, upload, light control, camera + speed-mode fixes
Fixed
- CC2 speed mode no longer flips, and the pin no longer misfires on
firmware 02.01.00.00. The newer firmware streams
gcode_move.speed_modein its real-time (method 6000) pushes as the
current gcode move's speed factor, which oscillates 1↔2 as the head
runs different features — it is no longer the stable "set" mode the
older firmware exposed. This caused two problems: the UI flipped
~1×/sec, and the old wire-observation pin logic mistook a long
balanced-speed feature stretch for a human choosing balanced and
spuriously released the pin (and could re-learn/re-apply the wrong
mode). The speed pin is now explicit only: set via
set_print_speed, re-applied once when a Canvas filament switch
completes (the point the firmware historically reset it — harmless if
already correct), and cleared when the print ends. pycentauri never
infers or sends a speed command from wire observation. The displayed
mode reflects the pin (or a debounced wire value when unpinned), so it
stays stable. Backward compatible: the switch-completion re-apply
covers the older firmware's post-switch reset without depending on the
wire value. - CC2 web UI now shows the current layer. The CC2's status payload
has no total-layer field (onlycurrent_layer), so the UI — which
required both — showed nothing.CC2Printernow looks up the printing
file's layer count from its metadata (method 1044) once per file and
caches it, so the UI shows "layer N / total". The layer also renders
with just the current number when the total isn't yet known. - Webcam no longer stalls after a second / on refresh. The printer's
MJPEG camera server has very few connection slots and releases them
badly (closed connections linger inFIN-WAIT-2, still holding a
slot). The old/streamopened a fresh upstream connection per request
— every tab, and every client-side reload — which exhausted the slots
and starved the stream (observed live 2026-07-08 on CC1: a sole fresh
client got zero frames)./streamnow shares a single upstream
connection across all browsers via aCameraBroadcaster, so the
printer only ever sees one camera connection regardless of tabs,
refreshes, or reloads. Verified live: 4 concurrent clients → 1 printer
connection, ~10 fps sustained, no connection pileup. - The camera broadcaster detects a stale upstream (TCP alive but no
frames for 15 s) and reconnects automatically, instead of silently
hanging forever (observed 2026-07-09 on CC1).
Added
- File management (CC2, firmware 02.01.00.00+). Four new MQTT methods
reverse-engineered from Orca's live wire traffic (2026-07-10):list_files(storage, offset=, limit=)— method 1044, params
{"storage_media": "local"|"u-disk", "offset", "limit"}. Returns
file_listwith filename, size, create_time, layers, print_time,
color_map, total_filament_used. Surfaced ascentauri files,
GET /files, and MCPlist_files.delete_files(filenames, storage=)— method 1047, params
{"storage_media", "file_path": [...]}(batch delete, array of
names). Surfaced ascentauri delete,POST /files/delete, and
MCPdelete_files. Requiresenable_control.disk_info()— method 1048. Returnstotal_bytes,used_bytes.
Surfaced ascentauri disk,GET /disk, and MCPdisk_info.print_history()— method 1036. Returnshistory_task_list.
Surfaced ascentauri history,GET /history, and MCP
print_history.
All four are CC2-only; CC1 raisesPrinterError(SDCP Cmd 258 for
file listing is disabled in the firmware). Full upload-list-delete
cycle verified live on CC2.
- Chamber light on/off (both models).
set_light(on)— surfaced as
centauri light on|off,POST /light, MCPset_light, and a Light
toggle in the web UI. Requiresenable_control. CC2 uses MQTT method
1029{"power": 0|1}(captured from Orca's wire traffic); CC1 uses
SDCPCmd 403{"LightStatus": {"SecondLight": 0|1}}(verified live
on V0.3.0-o). Both field names were commented out in Elegoo's SDK. - File upload across every surface.
upload_file()pushes a local
file to the printer's internal storage over chunked HTTP (port 80),
independent of the control channel. CC1 uses multipart
POST /uploadFile/upload; CC2 usesPUT /uploadwith Content-RangeX-Token. Surfaced ascentauri upload(with--start),
POST /files/upload(multipart), MCPupload_file, and a web UI
upload control. Requiresenable_control. Verified live on CC2.
v0.6.5 — surface CC2 'LAN Only' requirement
Fixed
- CC2 connect now surfaces a clear error when the printer's HTTP API is
unreachable instead of leaking a rawhttpx.ConnectError. The CC2
gates its local API behind "LAN Only" mode — with it off, the
printer works through Elegoo's cloud and leaves port 80 closed, so the
serial-number bootstrap fails even though MQTT :1883 answers. The
error now says exactly that and names the setting to change. (Reported
by a user on firmware 02.00.02.00 whose connection worked the moment
they enabled LAN Only.)
Documentation
- README and
docs/PROTOCOL.mdnow document that "LAN Only" mode must
be enabled on the CC2 for local control, and note that firmware
02.00.02.00 is a lockdown release (removes SSH, blocks downgrades)
with a community repacked v01.03.02.51 available if needed.
v0.6.4 — fix /openapi.json 500
Fixed
GET /openapi.json(and therefore the/docsSwagger UI) returned a
500 instead of the API schema. The CanvasRefillBodyrequest model
was defined insidecreate_app(), so under
from __future__ import annotationsits forward references couldn't be
resolved at schema-generation time (request validation still worked,
which is why nothing else surfaced it). Moved it to module scope with
the other request-body models; added a test that renders the schema.
v0.6.3 — auto-detect human balanced vs firmware reset
Changed
- CC2 speed pinning now tells a human's balanced apart from a firmware
reset — no more Auto escape hatch. The firmware resets speed_mode to
balanced as the leading edge of every Canvas filament switch, a few
seconds before the head parks; measured reset→park lead times are
tight (6–8 s, never above ~9 s). pycentauri uses that: a drop to
balanced followed by a park within ~12 s is the firmware and the
pinned mode is re-applied when the switch completes; a drop that sits
at balanced for ~12 s with no park is a human tapping balanced on the
touchscreen, so the pin is released and balanced is honored. A
sustained non-balanced touchscreen mode is still adopted as the pin
outright. Both paths live-verified 2026-07-05 (firmware re-apply and
human release, each with journal-logged decisions). - Removed the
autospeed mode / Auto button. It existed only to
release the pin for the touchscreen-balanced case, which is now
detected automatically.speed auto,{"mode": "auto"}, and the web
UI Auto button are gone.
v0.6.2 — pin-and-enforce speed mode, with Auto release
Changed
- CC2 speed-mode persistence redesigned as pin-and-enforce. The
0.6.1 snapshot-per-switch restore lost an arms race with the
firmware: after eight consecutive successful restores, a reset
arriving outside the covered window (late after a restore, or
mid-print with no switch at all — observed 2026-07-05 ~15:00)
poisoned the baseline and silently disabled every restore after it.
The firmware only ever resets TO balanced, so the model is now: the
mode you set is pinned (immediately via pycentauri; after holding
15 s when set from the touchscreen, since a non-balanced mode can
only come from a human), and any disagreement lasting 12 s while
printing is re-applied, at most every 30 s. One consequence,
deliberate: while a mode is pinned, selecting balanced from the
touchscreen is indistinguishable from a firmware reset and will be
reverted — switch to balanced through pycentauri instead, which
re-pins. Pins clear when the print ends, andspeed auto(CLI),
{"mode": "auto"}(HTTP), or the web UI's Auto button release the
pin explicitly, returning speed control to the printer. - Root cause fully mapped (wire captures, 2026-07-05): every reset is
a service operation — full filament switches, plus brief nozzle
wipe / purge operations at the chute that are too short to register
as "switching" — and a human's touchscreen tap is byte-identical to
a firmware reset on the wire, so balanced-from-touchscreen cannot be
auto-detected while a pin is active. Use Auto or set balanced via
pycentauri instead.
v0.6.1 — speed mode survives Canvas filament switches
Fixed
- CC2: the user's speed mode now survives Canvas filament switches.
The firmware resetsspeed_modeto balanced on every mid-print
switch and leaves it there (verified 2026-07-05: mode stayed reset
after the switch completed).CC2Printernow snapshots the mode in
effect when a switch begins and re-applies it once printing resumes —
regardless of whether the mode was set via pycentauri or the
touchscreen. Requiresenable_control; read-only sessions log the
reset instead. The restore baseline is debounced (a mode must hold
15 s to count) because the firmware fires its reset several seconds
before the head parks — without the debounce, that transient
poisoned the snapshot. Verified across two hands-free switch cycles
with journal-logged restores ~3 s after each resume. centauri servernow surfaces pycentauri's own log lines (speed-mode
restores, reconnects) in its output — previously only uvicorn's
loggers were configured and library INFO logs were invisible.
v0.6.0 — Centauri Carbon 2 + Canvas multi-filament
Added
- Centauri Carbon 2 support. The CC2 uses MQTT on port 1883
(instead of the CC1's WebSocket SDCP on 3030) with a JSON-RPC
envelope, X-Token auth, and a completely different command set
(1001/1002/1020–1031 vs 0/1/128–512). This release adds:CC2Printer— async MQTT client that subclassesPrinter,
translating CC2 payloads into the sameStatus/Attributes
models so every surface (CLI, HTTP, MCP, web UI) works unchanged.connect_auto(host, access_code=...)— factory that detects the
model (probes:1883only — a CC1 answers with a harmless kernel
RST, and the CC1's real WebSocket connect doubles as its own probe)
and returns the rightPrintersubclass. Callers never need to
know which model they're talking to.--access-code/PYCENTAURI_ACCESS_CODEon every CLI command
and MCP launch (required for CC2, ignored for CC1).paho-mqtt>=2.0added to core dependencies.
- CC2 status exposes
gcode_move.speed— live head speed as the
commanded speed of the current move, in mm/min (÷60 matches the
printer screen's mm/s readout)
andspeed_mode(integer 0–3) — fields the CC1 lacks entirely. Both
are preserved inStatus.raw["_cc2"]alongsideremaining_time_sec,
filament_detected,external_device, andexception_status. - CC2 methods 1028 (SET_TEMPERATURE), 1029 (SET_LIGHT), 1030
(SET_FAN_SPEED), 1031 (SET_PRINT_SPEED), 1023 (RESUME), and 1036
(PRINT_TASK_LIST) all confirmed working. 1042 (VIDEO_STREAM) and
1044 (GET_FILE_LIST) are non-responsive on firmware 01.03.02.51. - Canvas multi-filament system integration (CC2 only):
Printer.canvas_status()— returnsCanvasStatuswith connected
units, tray list (filament name/type/color/brand/temp range/loaded
status), active tray, and auto-refill state. Method 2005.Printer.set_auto_refill(enabled)— toggles auto-refill. Method
2004. Gated byenable_control.- CLI:
centauri canvas(read) +centauri refill --on/--off
(write, requires--enable-control). - HTTP:
GET /canvas(always) +POST /canvas/refill(control-gated). - MCP:
get_canvas_status(always) +set_auto_refill(control-gated). CanvasStatus,CanvasUnit,CanvasTraymodel classes exported
from the package for typed access.
Fixed (pre-release hardening — none of these shipped in an earlier release)
- CC1
status()/watch()self-heal through a wedged push
scheduler. Discovered live 2026-07-04 on V0.3.0-o: the firmware can
enter a state whereCmd 512subscribes are accepted but no status
frames are ever pushed, while the request path stays healthy — and a
reboot does not clear it (verified 2026-07-05). Both methods now fall
back to explicitCmd 0status requests (documented to emit a
one-shot status frame) whenever a subscribe produces no push within
one period, instead of hanging forever. Seedocs/PROTOCOL.md
"Operational quirks". CC2Printer.watch()now polls method 1002 inline whenever pushes go
quiet instead of silently terminating after one push period — CC2
centauri watchand the SSE stream no longer die on an idle printer.- MQTT responses are correlated by the client's exact
api_response
topic and non-push method. Previously any client's response — or the
printer's own 6000/6008 broadcasts, which reuse small auto-increment
ids — could resolve a pending request future with the wrong payload
(including reporting success for a control command). - Registration is re-published from
_on_connect, so paho's automatic
MQTT reconnect re-registers with the printer and pushes survive a
printer reboot without restartingcentauri server. - All MQTT-callback work that touches futures, events, queues, or the
merged status dict is marshalled onto the asyncio loop (fixes the
cross-thread delta merge and lateset_resultraces). GET /streamuses a bounded connect timeout (read stays unbounded
for MJPEG) instead of hanging forever against a wedged camera port.GET /canvasreturns 504 for printer timeouts, reserving 501 for
"no Canvas on this printer"; the web UI now retries transient Canvas
failures instead of hiding the panel until a page reload.- A wrong CC2 access code now raises a clear auth error (MQTT reason
code / HTTP 401 hint) instead of a generic timeout or raw traceback. connect_auto()andcentauri rtspno longer probe :3030 — the CC1
WebSocket connect doubles as the probe, avoiding the connect/close
churn that port is sensitive to.centauri rtspand the HTTP server
both pick the right MJPEG port (CC1 :3031 / CC2 :8080) automatically,
including reconnects after starting with the printer offline.- Unknown CC2
machine_statusvalues map to sentinel code 99 instead
of leaking raw values into the CC1 status-code space;PrintStatus
gains constants for the CC2 codes 27/28/29. CanvasStatus.from_payloadsurvives malformed/absentcanvas_info
payloads;CanvasUnit/CanvasTrayare exported from the package
root;typing_extensionsdeclared as a direct dependency.- CC2 sessions send the app-level
{"type": "PING"}keepalive every
30 s. The firmware expires a client's registration after several
quiet minutes and then silently stops answering that session's
requests — the MQTT connection stays up, responses just never come
(verified 2026-07-05: a dashboard went request-deaf after ~6 minutes
while a fresh session answered instantly). MQTT-level keepalive does
not prevent this; only the app-level PING does. centauri serverbounds uvicorn's graceful shutdown at 5 s. Open
SSE/MJPEG streams never close on their own, and without the bound a
stopped server lingered forever as a zombie still holding a printer
connection (observed 2026-06-23 and 2026-07-05).- CC2 lifecycle commands (start/pause/stop/resume) use a 90 s timeout —
the firmware answers only after the mechanical sequence completes
(observed 2026-07-05: a resume succeeded but its confirmation
arrived after the old 15 s window, surfacing a false error). When a
confirmation still doesn't arrive,POST /print/*returns 504
("sent, unconfirmed — check printer status") instead of 502, and the
web UI shows it as a warning rather than a failure.
Tests
- New
tests/test_cc2_mapping.py: pure dict-in/dict-out coverage of
the CC2→CC1 translation layer — machine_status/sub_status mapping
(including purge-zone filament-switch detection and its progress
guard), partial-delta deep merge, full 1002 payload round-trip, and
Canvas parsing. Plus a server test pinningGET /canvas→ 501 on
CC1.
Documentation
docs/PROTOCOL.mdgains a full CC2 section: MQTT transport, topic
structure, connection/registration dance, the confirmed method table
(12 probed, 10 working), error codes, the complete status payload,
and a CC1-vs-CC2 comparison table. Probed on 2026-06-30 through
2026-07-04 against firmware 01.03.02.51 (Canvas methods 2004/2005
verified live with a 4-slot Canvas attached; CC2 webcam confirmed
unauthenticated MJPEG on :8080).docs/ARCHITECTURE.mdrewritten for the two-transport reality:
module map withcc2/connect, per-model ports, CC1-vs-CC2
/statusand SSE flow differences, and an honest test-architecture
section (no automated live suite exists; live verification is manual
CLI runs).
v0.5.1 — CLI + MCP parity for live print-parameter adjust
Added
- CLI parity with the new live-adjust API. Three new top-level
commands matching the library and HTTP surfaces shipped in 0.5.0:centauri speed <silent|balanced|sport|ludicrous|50|100|130|160>centauri fan [--model N] [--aux N] [--chamber N]centauri temp [--nozzle N] [--bed N] [--chamber N]
All require--enable-controland accept any subset of fan/heater
flags (omitted axes are left untouched).
- MCP tool parity: three new tools (only registered with
--enable-control) —set_print_speed,set_fan_speed,
set_temperatures. Same shapes as the HTTP endpoints; not marked
"DESTRUCTIVE" because live runtime adjustment is their entire
purpose.
Fixed
- 0.5.0 shipped the live-adjust API to the library, HTTP server, and
web UI but missed the CLI and MCP server. This release closes that
parity gap — every surface now exposes the same control set.