1fd6529376c677c9480665d1a89f09e9704489db
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1fd6529376
|
Add get_calibration; fix a real 10KB packet-size ceiling; revert bad correlation-field experiment
Real bug found and fixed live: both rumqttc clients default to a 10KB max packet size in both directions. A real H2C's get_version reply (25625 bytes - it reports a lot of modules: dual AMS, AMS HT, six WTM units, ...) blew straight through that on the v5 client and killed the whole connection outright (a real MQTT protocol error, not a timeout). Raised to 1MB on both clients - print.push_status reports can get large too. Also tried, and reverted after live-testing disproved it: replacing request()'s sequence_id correlation with a homemade continuum_correlation_id field, on the understanding that most replies echo back arbitrary extra request fields. True in general, false for get_version specifically - a real H2C's reply had exactly ["command", "module", "sequence_id"], nothing extra survived, so every get_version call started timing out. Reverted to sequence_id, which is what's actually proven (twice now, on both protocol versions) to round-trip for this command. Added BambuPrinter::get_calibration(option) - print.calibration gets a real, correlated reply (confirmed live: it does echo sequence_id) on both protocol versions, per the schema fixes in continuum-schemas. `option` is the request's own bitmask, left to the caller rather than defaulled to "run everything" - this triggers a real physical calibration sequence on the printer, not a read-only query like get_version, so it hasn't been live-tested here without explicit confirmation first. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g |
||
|
|
133db9e4aa
|
Add pushall + print_status cache; fix envelope, race, and matching bugs
PrintReport now flattens CommandEnvelope (sequence_id/command) - push_status.schema.json composes the shared envelope like every other Bambu message; the struct's old doc comment concluded otherwise from a capture that turned out to be an incomplete example (also missing dozens of other real fields), not proof the message lacks them. Added BambuMqttSession's PrintStatusCache: the in-memory print.push_status object, replaced wholesale on v2 (always full) or on a v1 message with msg != 1 (forced/full), merged field-by-field otherwise (v1's organic partial updates) via PrintReport::merge_from. Tracks last_sequence_id to warn on a gap in the organic stream. BambuPrinter gets pushall() (v1-only; pushing.pushall doesn't exist in v2's schema at all) and print_status(). Three real bugs found and fixed via live testing against an actual P1P, none of them guessable from the schema alone: - pushall's reply doesn't echo the sequence_id we send - the printer stamps its own free-running counter regardless of what triggered it. request()'s ID correlation silently can't work here; first fix attempt added request_next_of_category (wait for the next message under a category, no ID needed). - That undershot too: matching by category alone let an unrelated "print" message (that category carries many commands - gcode_line, pause, push_status, ...) satisfy the wait before the real push_status reply arrived, so pushall() returned Ok having consumed the wrong message - now keyed by (category, command). - A real ordering race: handle_incoming_report woke a waiting oneshot before updating the print_status cache, so a caller could resume and check print_status() before the write landed - pushall() returned Ok immediately followed by print_status() still showing None. Fixed by applying the cache update before sending on any matched oneshot. Superseded by real protocol knowledge before any of the above needed to ship, though: push_status carries its own msg field (1 = automatic/ partial, 0 = forced/full) - the actual, reliable, self-describing signal for which kind a message is, regardless of timing or which client (if any) triggered it. PrintStatusCache now reads that directly instead of inferring it from request correlation, and pushall() is plain fire-and- forget (publish, no wait) since there's nothing left to correlate for - confirmed live: msg reads correctly off a real P1P, and the cache populates/updates correctly with no gap warnings across several organic pushes. request_next_of_category is kept (a future case may still need "no correlation ID at all" for real), just no longer used here. Also: the poll loop now logs when it exits instead of returning silently - that silence is exactly what made a real dropped MQTT connection to a live H2C indistinguishable from "nothing happening" during testing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g |
||
|
|
db9b575b55
|
Wire fleet::load into main.rs; fix request() reply unwrapping
main.rs never actually loaded printers.toml or connected anything -
fleet/printer were only ever exercised by standalone examples. Now
main() loads the fleet (path configurable via CONTINUUM_PRINTERS_PATH,
default "printers.toml") and connects every printer concurrently at
startup, logging success/failure per printer rather than failing
startup over one bad printer.
That surfaced a real bug the instant it ran against a live printer:
complete_pending() was sending the whole {"info": {...}} wrapper through
the pending oneshot, not the unwrapped body - BambuPrinter::get_version
deserializing that into GetVersionResponse failed with "missing field
module" even though module was right there, just one level deeper than
expected. Fixed by unwrapping the single category key before completing
the pending request, symmetric with how a request gets wrapped on the
way out.
Verified live against a real H2C (MQTT v5/BambuMQTT v2): connect,
get_version, and the full pending-request correlation all worked
end-to-end, returning real firmware versions for every module (main
board 01.01.05.00, both AMS units, AMS HT, etc). The other configured
printer (P1P, forced v1) failed with a real, expected TLS error - it
doesn't chain to the bundled CA, matching the already-documented P1P
quirk; needs the ca_cert_path/fetch_bambu_cert workflow, not a code fix.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g
|
||
|
|
5d6e2e9e03
|
Add BambuPrinter::get_version, the first real request/response round trip
Documents request()'s real constraint on BambuMqttSession directly (not all Bambu commands map 1:1 to a reply, and even where one exists its shape can differ by protocol version - e.g. pushing.pushall triggers an ongoing print.push_status stream rather than a direct reply, and print.calibration data lives inside push_status on BambuMQTT v1 but gets its own report on v2 - so request() is only correct for genuinely one-shot, sequence_id-correlated commands like info.get_version). get_version itself is Bambu-only (no GenericPrinter equivalent, matching test_tls_handshake/fetch_certificate/ensure_trusted's existing pattern): builds the request via continuum-schema-instance, sends it through BambuMqttSession::request, and parses the reply into the existing hand-written GetVersionResponse - reusing the struct already validated against real captured Bambu JSON in bambu_commands_demo.rs, rather than introducing a second response representation. Verified structurally (no real broker reachable from here - confirmed this sandbox has no route into the printer's LAN at all, not just a blocked port): connect fails gracefully against an unreachable host, and get_version correctly reports "not connected" rather than panicking when called without a live session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g |
||
|
|
773898b682
|
Real MQTT wiring for Bambu: connect, auto-detect v5/v3.1.1, request/reply
Removes GenericPrinter::receive (two disconnected fire-and-forget stubs that didn't actually give request/response) in favor of a real mechanism in the new src/printer/bambu_mqtt.rs: - BambuMqttSession wraps whichever rumqttc client a connection ended up using (v3.1.1's AsyncClient/EventLoop for BambuMQTT v1, v5's for BambuMQTT v2 - different types, different event/error shapes) behind one interface. `open()` respects ForceV1/ForceV2, and for Auto tries v5 first, falling back to v3.1.1 on any failure (see the module doc comment for why "any failure", not a precisely-matched version- rejection code - unverified against a live printer, no broker here to test against). - Reuses BambuTls::build_connector (now pub(crate)) for rumqttc's TLS transport via TlsConfiguration::NativeConnector, instead of a second, separate TLS trust story - hence rumqttc now pulls in use-native-tls instead of its default rustls stack, so there's one TLS implementation in the binary, not two. - request() publishes and waits (with a timeout) for a report whose sequence_id matches, correlated via a shared pending-request table that a spawned background task completes as reports arrive - the first real tokio::spawn in this crate, flagged as deferred since printer/mod.rs's very first doc comment; this is why it was deferred until now, and why it's needed now (polling the eventloop has to run continuously, independent of whatever call site is waiting). - publish()/publish_raw() are the fire-and-forget half, for commands like gcode_line that only get acknowledged implicitly. BambuPrinter::connect/send_gcode_line/publish now call the real session instead of printing what they would do. Verified against 192.0.2.1 (a reserved, never-routable test address): both AsyncClient/EventLoop pairs actually attempt a real TCP connection and fail gracefully (network timeout, not a panic) when nothing answers, and Auto genuinely attempts both while ForceV1 skips straight to v3.1.1. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g |