Skip to content

Creality: K1/K2 gcode root, start-print errors, and profile host_type (C1+C2+C5) - #618

Draft
aceRage wants to merge 4 commits into
mainfrom
cursor/creality-k1-k2-root-d523
Draft

aceRage wants to merge 4 commits into
mainfrom
cursor/creality-k1-k2-root-d523

Conversation

@aceRage

@aceRage aceRage commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Description

Phase 1 of the Creality send-gap stack (research C1+C2+C5). Closes the “Upload and print reports success but never starts” class of bugs on K2-platform printers, and surfaces start failures instead of swallowing them.

Does not affect Snapmaker printers. Needs a Creality K1/K2 hardware smoke before merge (not a U1 check).

Review 1/3 (F1, F2)

  • F2: tcp_stream::expires_after does nothing on synchronous Beast. CrealityWsClient now runs every resolve / connect / handshake / write / read as an async op with io_context::run_for, and closes the socket on expiry. Shared by start_print, the Phase 2 CFS probe, and Phase 3 sync.
  • F1: when /info is empty or unknown, resolve_model() falls back to the preset printer_model (Creality K1C → K1C) so a K1 never regresses to /mnt/UDISK.

Re-review 1/3 (B3, F15)

  • B3: ready_to_start() refuses to start an op when budget() <= 0 or the client is cancelled, and run(timeout_ms <= 0) still cancels then ioc.restart(); ioc.run() so every path drains before the locals go out of scope.
  • F15: resolver.cancel() cannot interrupt getaddrinfo; the DNS wait is bounded by the OS. Literal IPv4/IPv6 skip resolve via asio::ip::make_address.

Re-review 2/3 (B5)

  • B5: cancel() is now UI-thread safe. It only stores cancelled and net::post()s cancel_socket() onto this client’s io_context. It does not call ioc.stop() and does not touch open / ws off-thread. open() no longer clears cancelled, so a cancel before open() is not lost. open is std::atomic<bool> (worker-only writes). Every run() path still drains (B3): timeout, already-cancelled, and cancel-during-run_for all on_timeout() then ioc.restart(); ioc.run().
  • Catch2: cancel from another thread before open(), and during a never-accepting connect.

Upstream sources

What was adapted

  • Network-free helpers live in CrealityPrintModel.hpp so Catch2 can pin them without a printer. Not a cherry-pick of upstream CrealityPrint.cpp.
  • Kept this fork’s PrintHost::apply_tls on /info and upload (upstream still uses #ifdef WIN32 ssl_revoke_best_effort only).
  • start_print still sends only opGcodeFile (CFS colorMatch / multiColorPrint is Phase 2). Root is /usr/data for K1-family (including preset names) and /mnt/UDISK for everything else (K2 / K2 Pro / K2 Plus / SPARKX i7).
  • WebSocket connect uses TEXT frames and Http::url_host so a print_host written as http://host:80 resolves.
  • A failed start now calls the job’s error_fn and returns false from upload().
  • Profiles: only host_type / printer_agent added (or octoprint → crealityprint on K1_CFS-C). No other preset fields touched. Cross-checked against Profiles: Creality preset sanity fixes #319 (Creality sanity: default process / max_layer_height) and Profiles: refresh vendors to upstream Orca + preset sanity fixes #320 (Creality was out of scope). Vendor version 02.03.02.05 → 02.03.02.06.

Expected conflicts

Untested

  • No Creality hardware in this environment.
  • slic3rutils_tests was not compiled here. Catch2 cases were added to the existing tests/slic3rutils/printhost_devices_tests.cpp (no CMake test edits).
  • No G-code output changes.

Tests

Catch2 v2 in printhost_devices_tests.cpp:

  • K1-family → /usr/data/..., omit upload path
  • F008/F012/F021/F022 → /mnt/UDISK/...
  • empty / unknown /info falls back to preset printer_model
  • ws_host strips scheme and port
  • parse_model_from_info is hostile-JSON safe
  • expired total budget fails before any I/O (B3)
  • local acceptor that never accepts times out and drains (B3)
  • cancel from another thread before open() and during a never-accepting connect (B5)

Smoke checklist (Creality hardware)

  1. K1C (or K1 / K1 SE): Host Type CrealityPrint, Upload — file lands under /usr/data/printer_data/gcodes.
  2. K1C Upload and print — print starts; a refused start shows an error, not success. An unreachable printer must not hang (F2 deadline).
  3. K2 / K2 Plus / K2 Pro / SPARKX i7: Upload and print — print starts from /mnt/UDISK/printer_data/gcodes (the old /usr/data path is the C1 bug).
  4. print_host as http://<ip> and http://<ip>:80 still connects (scheme/port stripped).
  5. Plain Upload (no print) still succeeds.
  6. A K1 whose /info omits model still uses /usr/data (preset fallback).
  7. Calibration toggle / CFS mapping are not in this PR (Phase 2).
Open in Web Open in Cursor 

cursoragent and others added 3 commits October 19, 2026 01:35
K1-family printers keep /usr/data; K2/K2 Pro/K2 Plus/SPARKX i7 use
/mnt/UDISK. start_print now returns a failure to the job callback, and
print_host URLs are stripped of scheme/port before the WebSocket connect.
K1, K1 SE, K1C, K1_CFS-C and K2 Plus profiles get host_type crealityprint.

Co-authored-by: aceRage <aceRage@users.noreply.github.com>
Synchronous Beast ignores tcp_stream::expires_after, so a silent printer
could hang start_print. Every resolve/connect/handshake/write/read now
runs async with io_context::run_for and closes the socket on expiry.

When /info is empty or unknown, the preset printer_model chooses the
K1 /usr/data root so a K1 never regresses to /mnt/UDISK.

Co-authored-by: aceRage <aceRage@users.noreply.github.com>
A zero remaining budget used to cancel run() without draining, so a
queued handler could write to dead stack locals when close() polled the
ioc. Refuse to start an async step when budget() is 0, and always drain
after cancel. Literal IPs skip resolve because resolver.cancel() cannot
interrupt getaddrinfo.

Co-authored-by: aceRage <aceRage@users.noreply.github.com>
cancel() only sets the atomic flag and net::post()s cancel_socket().
It no longer calls ioc.stop() or touches open/ws off-thread, and open()
does not clear a cancel that already happened. run() still drains on
every timeout and cancel path.

Co-authored-by: aceRage <aceRage@users.noreply.github.com>

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.

2 participants