feat(U1): make the printer panel read the machine — sync, marks, ACE assignment and filament inventory - #40
Open
physicsG wants to merge 18 commits into
Open
feat(U1): make the printer panel read the machine — sync, marks, ACE assignment and filament inventory#40physicsG wants to merge 18 commits into
physicsG wants to merge 18 commits into
Conversation
…d a plate The Printer section is shared by Prepare and Preview, and on a U1 it draws four tabs that each hold the same Diameter combo, says nothing about which toolhead an ACE feeds, and hides its sync behind an unlabelled glyph. Measured by running the app rather than by reading it. Doc 15 takes Bambu Studio's panel apart against the screenshots and applies its shape to four heads. Two things it turned up are defects in existing code, both written down: a unit shared between two heads double-counts capacity in the planner, so the infeasible-plate refusal would pass a plate it exists to catch; and Combined mode emits the wrong ACE= and SLOT= because the emitter has one unit per head while the plan's slot is an index within the head. Doc 16 settles how an ACE is drawn. It was drawn four ways - circles on one page, cards on another, bars on a third - while the filament-mapping popup already used Orca's own AMS widgets, because the ACE is projected onto amsList. So the AMS is the standard, and the geometry is lifted from AMSItem.hpp rather than invented, which is what stops it drifting again. Doc 17 does the same for the build plate. The silhouette is measured, not traced: a first attempt drawn by eye was wrong in every dimension, so the product PNG was decoded to raw pixels and its edges sampled per column. It is drawn deliberately overstated, because at 44 px the true notch is one pixel and a truthful outline says nothing. Snapmaker's own plates are photographed; anything else is drawn generically, so the app never brands a bed type with a vendor it does not mention. The ACE mode switch is the printer's own - SET_ACE_MODE MODE=normal|multi|head, read from the firmware's macro help, not guessed. It also answers whether one unit can feed several heads: in head mode it can, and the popover is where that happens. Design only; no code. NEXT.md carries the decisions, the two things still open, the shipping order and the traps on this branch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mockups embedded Bambu Studio's screenshots and Snapmaker's product photos as base64, which put third-party imagery into an AGPL-3.0 repository to make a design document render. Reference material is worth keeping; redistributing it is not ours to do. The snapshots move to ui-snapshots-inspiration/, which is gitignored and carries a README saying what is in it and where to re-download it. The mockups now reference those files by relative path, so with the folder present they render exactly as before, and without it each frame shows a caption naming the folder rather than a blank. The panel mockup drops from 344 KB to 51 KB and the plate mockup from 631 KB to 26 KB. Nothing about the designs changes. The drawn cool plate was already ours and is untouched, and it is the model for replacing the photographs if permission is not sought - the silhouette, sampling and sizes in 17-plate-template.md hold either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Doc 17's fill table and the mockup's "same value, different names" note both read the BedType identifiers literally, and the identifiers do not mean what they say. s_keys_map_BedType crosses them deliberately: "Textured PEI Plate" is btPTE and "High Temp Plate" is btPEI. So Textured PEI is btPTE and Smooth PEI is btPEI, both the opposite of what the doc and the mockup said. Settled by running the app rather than by reading it again: with curr_bed_type 4 the sidebar names the plate Textured, with 3 it names it Smooth. Worth fixing rather than footnoting, because the doc is what an implementation reads. This one sent the plate card straight into painting every U1 plate as its neighbour, and the error survived a second look precisely because the doc agreed with the guess. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…pology
Three keys the U1 panel needs before it can say anything about ACE units at all:
ace_mode normal|multi|head - the firmware's own three words, so the stored
value is the SET_ACE_MODE argument verbatim and lines up with the
mode the printer reports back
ace_head_unit which ACE feeds each head, stored 0-based because that is the ACE=
argument, -1 for a head on its own stock feeder
ace_head_capacity how many slots that head is offered, 1 meaning a stock feeder
ace_head_unit and ace_head_capacity are taken verbatim from feat/ace-mmu-slicing -
definitions, enum labels and tooltips - so the branch that already reads them merges
onto this rather than colliding with it. ace_mode is new: that branch reads the mode
from the printer over the network and never stores it, and a panel has to draw
something with the printer switched off.
Both vectors join m_extruder_option_keys as well as s_Preset_printer_options, so they
resize with the nozzle count instead of coming up short on a four-headed machine.
Config only. Nothing sends SET_ACE_MODE - that needs the provider, which is not on this
branch - so ace_mode records the wiring and no more.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…head grid
The Printer section is one widget seen in both Prepare and Preview. On a U1 it drew four
tabs named Nozzle 1..4 that each held the same Diameter combo - changing any one writes
all four and switches the whole preset, because the machine refuses a mixed set - and it
hid its sync behind an unlabelled 16px glyph in the title bar. Measured by running the
app, not by reading it.
It now follows docs/ace-mmu/15-printer-panel.md and its mockup:
- three cards at equal height. Printer with its thumbnail over the preset combo, plate,
and Sync info. The plate card absorbs what was a full-width Bed type row, which is
where the height for the head boxes comes from, and the whole card opens the list so
the picture is the target rather than the narrow combo under it
- an ACE mode row, U1 only, mirroring the printer's own three-way switch with the raw
SET_ACE_MODE in its tooltip
- a bordered box per toolhead wrapped 2x2, each with an ACE row and a Diameter row,
named Toolhead N - what the machine's own interface calls them, and the sidebar was
the last place saying Nozzle N. Every other printer keeps the names it had, so an
IDEX machine's Left/Right tabs are untouched
update_nozzle_settings builds those boxes instead of notebook pages, which leaves
CustomNotebook with no callers; it goes, 269 lines and the stray #pragma once that warned
on every build. The 135-line sync handler is lifted verbatim out of the title-bar lambda
into Sidebar::sync_printer_info, so the card and the icon on it reach one place.
Seven plate assets, one per bed type, all carrying the same measured silhouette from
doc 17 in their alpha so photographed and drawn plates sit in one shape. Snapmaker's
three U1 plates are cropped from its product photography; Cool Steel and the
advanced-mode plates are drawn, because Snapmaker does not sell Cool Steel separately
and the nearest real product is a third party's - using it would brand a bed type, an
abstract setting, with a vendor the app never otherwise mentions. PNG rather than SVG:
icon SVGs go through nanosvg, which has no patterns and could not carry a surface.
The photographed three put third-party product imagery in an AGPL-3.0 repository.
That is a deliberate decision taken here, not an oversight, and it still wants
Snapmaker's sign-off before this ships publicly. Replacing them is a swap of the fill:
the silhouette, sizes and drawing code are shared with the four drawn plates already.
Four things the widgets required, each found by running rather than reading:
- the plate is keyed off the BedType value, never the combo's index. A U1 is offered a
different and shorter list than every other printer, so position means nothing
- StaticBox zeroes its border width under wxBORDER_NONE, so the cards are created
bordered rather than styled that way
- the Sync card's LEFT_UP handler calls Skip(), or StaticBox's state handler never
clears the pressed state and the card stays drawn as pressed
- it also hands itself a leave event, because every path out of the sync opens a modal
and the card never sees the pointer cross behind it
Still missing against the mockup, and each needs something this branch does not have:
the green corner ticks (a diff against the connected machine), the assign popover behind
the ACE row and the ACE badge in place of its words (the live provider), and sending
SET_ACE_MODE rather than only recording it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…with it
The Sync info card synced nozzle diameters and nothing else, and the ACE row said what the
preset held with no way to change it. One press now reads the machine twice, writes what it
finds, marks every box that agrees, and ends by offering the filament sync. Verified against
the U1 at 192.168.2.242, not by reading code.
- the ACE read is a second, independent read. Nozzles come over the webview bridge;
ace_mode and the per-head wiring come from the printer's own multiACE service over
plain HTTP. Either half can fail alone and the dialog says which did
- green corner ticks on the printer card and on each head box that matches the machine,
computed from what was actually read. A panel that has never asked shows none - that
absence is the honest answer, not a defect
- the assign popover behind each ACE row: a choice, not a count, because the firmware
offers exactly two macros. Stock feeder, then one row per unit named as the printer
names it, with a tick. It writes ace_head_unit and ace_head_capacity and tells the
machine nothing - Sync info is what reconciles the two
- the ACE badge in place of the words, carrying the unit's own slot colours when the
machine has been read and the disabled greys when it has not
AceMmuState.hpp and AceMmuProvider come over verbatim from feat/ace-mmu-slicing so that
branch merges onto this rather than colliding with it. The snapshot -> preset mapping is new
and lives in libslic3r/AceMmuTopology.hpp rather than in the GUI, because the sync writes it,
the ticks diff against it and TabPrinter's Multimaterial page will read it: one function, so
a tick cannot claim an agreement the next sync would undo. Nine test cases cover it against a
payload captured from the live machine.
Four things the machine taught us, each found by running:
- head_ace is not wiring. The live U1 reports {"0":0,"1":1,"2":2,"3":0} with ONE unit
plugged in; only head 3 is ACE-fed. `feeder` is the flag to trust, and the test case
exists to keep it that way
- the connected-device gate was on the wrong thing. It required the webview bridge before
doing anything, so a printer answering on its own address was refused. The gate now only
guards the half that needs it
- Label applies its font after wxStaticText has cached a best size for the default one, so
a heading measures short and the sizer clips the tail - here, the head number out of
"Which ACE feeds Toolhead 4?"
- a popup whose parent is a head box dies with it, since choosing rebuilds the boxes. It
parents to the sidebar and dismisses before the callback runs
The card's tooltip said "Synchronize nozzle information" in two places; it syncs rather more
than that now.
Not done here, and each needs something this branch does not have: sending SET_ACE_MODE
rather than only recording it, the per-unit capacity pool that stops a shared unit
double-counting, and Combined mode's slot -> (unit, slot) map.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…heir room
Four adjustments from looking at it running, not at the code.
- the corner tick was 17px and its check crossed the hypotenuse, so white landed
outside the triangle. Against a white card that does not read as a check hanging
over an edge - it reads as a notch cut out of the mark, which is what it looked
like. The triangle goes to 22px, the check moves into the corner's thick end, and
the whole glyph is clipped to the polygon so no DPI can put it outside again
- the printer thumbnail goes 48 -> 60 and sits between two stretch spacers rather
than above one, so the leftover height is shared instead of pooling under it. A
card that is a picture of the machine should be mostly machine
- the plate drawing goes 51 -> 58 high inside the same 106px card, taking the slack
the info glyph row was leaving. The card does not grow; the plate does
- the assign popover carries S4, the square front face, where it had the wide filled
badge. Doc 16 gives the 44x26 cabinet to a head box and the 24x24 line form to a
menu, which is what that list is; it carries no slot colours by design, because the
row is choosing a unit and its contents are the detail line's job
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Step two of the press opened a dialog that could only see half the machine. Its machine list
came from build_machine_filament_list, which reads what the webview bridge pushed: one row per
toolhead. A head fed by an ACE carries whatever slot happens to be loaded at that moment, and
the other three spools in the unit are invisible - so the sync mapped against a snapshot of
four heads rather than the inventory.
append_ace_filament_list now relabels the toolhead rows with where each is fed from and appends
every ACE slot:
T1 · PLA loaded at the head
T4 · from A1 fed by a unit; shown for context, greyed, not selectable, because
mapping the head would address whichever slot is loaded right now
A1-S1 · PETG the slot rows, which are the stable thing to map to
A1-S4 · empty empty slots listed too, the way an empty head is
None an explicit way back to unmapped - empty rows are NONE-typed and
unclickable by design, so without this there was no way to say it
Taken from feat/ace-mmu-slicing, where it was written against the same dialog, along with the
three FilamentData fields it needs and the picker's handling of them. Not taken: that branch's
2-row-to-3-row layout rework of FilamentColorMapBoxGroup, which is separate work.
Two things this branch adds on top:
- the picker's popup grew with its list. It was a fixed height sized for a handful of rows
and does not scroll; four toolheads plus four slots plus None is nine, and the tail was
simply not on screen
- the dialog's "No printer is connected" gate now also asks the ACE. That gate tested the
webview bridge, so with the Device page unvisited the sync refused - while the machine was
answering on its own address with four spools it could have listed. Same gate on the same
wrong thing as the one Sync info had
Verified against 192.168.2.242 with the bridge deliberately absent: the dialog listed all four
ACE slots in their real colours, mapped both project filaments, and the plate came back PETG.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…s empty, and size the cards
Three things, from running it.
The filament list did not follow the machine. With nothing on the plate the sync applies
directly, and collectVisibleOverwriteMachineFilaments clamped what it took to the count the
project happened to be carrying:
size_t visibleCount = std::min(designCount, machineDataList.size());
so a four-slot ACE could only ever recolour the two filaments already there. The clamp is right
when objects are on the plate - they reference filaments by index, and renumbering them under an
overwrite would be a quiet corruption - so it stays, and the empty-plate call passes
whole_machine. Then the project takes the machine's inventory: four ACE slots become four
filaments in their own colours. With a model the mapping dialog opens exactly as before.
Two rows are skipped either way, which is what makes the count mean something: NONE-typed rows
(an empty slot, and the explicit "Assign None" action) and disabled ones. A disabled row is a
toolhead fed by an ACE, carrying whatever slot is loaded this second - taking it as well as that
slot lists one spool twice. A head with nothing loaded is now marked disabled too, for the same
reason an empty slot is.
The printer thumbnail goes 60 -> 68 with a 2px top spacer, since it had room above and below.
The plate had more room than it looked, in two places. The info glyph was a sizer row: about a
fifth of a 106px card spent showing a 14px button. It is positioned in the corner now instead,
which costs nothing and keeps its place. And the swatch takes the leftover height rather than a
fixed block - two things had to change together for that to work:
- the drawing is fitted to the panel instead of drawn at the size that was asked for.
DrawBitmap centres, so a drawing taller than its panel loses both ends at once, which is
exactly what happened first at 72px
- the stretch spacers around the swatch went. They carry proportion 1 as well, so "give the
swatch the leftover" split it three ways and the plate came out smaller than before
Result is ~72px of plate in the same 106px card, on any DPI, because nothing about it is now a
fixed number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The account lived only in GUI_App::m_login_userinfo and was never written anywhere, so every launch started logged out and the cloud half of the app - the model library, WAN devices, and anything else behind a token - had to be logged into again each time. SMAccountPersist comes over verbatim from feat/ace-mmu-slicing, wired at the same three points: post_init() restore, once, after app_config has been loaded in the ctor sm_request_user_logout() clear and save, after the revoke has used the token WebSMUserLoginDialog save, right after set_user_login(true) set_user_login() notifies its subscribers, so the webview learns the restored state through the path it already uses; nothing else had to change. Two things it deliberately does not do. It does not re-validate the token against the server at startup - a stale one simply fails on the next call and the user logs in again, which is cheaper than blocking every launch on a round trip. And it stores the bearer token in plaintext in app_config, the way this fork stores everything else; an OS keychain would be better and is noted in the header as future work. Worth knowing before this ships. Verified on a real restore rather than by reading: [info] sm_restore_login: restored account gordian.zomer@gmail.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…not pick The picker greys two kinds of row and refuses clicks on them - NONE-typed ones (an empty slot or head, and the explicit "Assign None" action) and disabled ones, a U1 toolhead fed by an ACE. The auto-matcher only knew about the first kind, so it could hand a project filament a mapping the user was then not allowed to change. Seen on the connected U1: Toolhead 4 is fed by ACE 1 slot 3 and therefore reports that slot's spool, #632c2c. compute_color_match found T4 the perceptually nearest PETG and mapped project filament 5 to it - a greyed row - while A1-S3, the same spool under its own name and fully selectable, sat two rows below. Both matchers now share one is_selectable_source() with the picker's rule, and that filament maps to A1-S3. Verified against 192.168.2.242 with the Device page connected: six project filaments onto T1, T2, A1-S1..S4, one to one, no greyed row used. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…'s stranded labels Two small things, both from looking at the panel with six filaments in it. The filament rows carried no mark. Every other surface that agrees with the machine says so - the printer card, the plate, each toolhead box - and the rows underneath them, which the sync had just written, said nothing. They have one now: a plain check rather than a corner triangle, because a triangle only means anything in a corner, in the same green making the same claim. It is a diff, not a badge. Each filament is matched against the machine list the sync itself builds - toolheads plus ACE slots - on type and colour, which is all the sync writes, as its own dialog says: "Only filament types and colors are synchronized". Rows that are not sources are skipped, so an empty slot or an ACE-fed head cannot be what a filament claims to match. Nothing fetches: a machine nobody has read marks nothing, and the marks are gone again after a restart even though the filaments are unchanged. They are recomputed wherever the filaments can move. The mapping dialog's left label column goes, taken from feat/ace-mmu-slicing along with its reason: "Source Filament" / "Printer Filament" only lined up with the first row of cards and read as broken once they wrapped - which a U1 reaches immediately, since six filaments is what two toolheads and four ACE slots come to. A caption above the grid says the same thing for any number of them, the grid widens to six columns so sixteen spools land in three rows, and the dialog shows three rows before it scrolls. Verified against 192.168.2.242: six filaments, six marks; the caption above one row of six cards. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… cards The filament rows carried a check beside the combo while every other synced surface carried a green corner triangle over its own top-right. Two marks for one claim; they are one now. The drawing comes out of SyncMarkBox into draw_sync_mark(), so a card and a combo are marked by the same code rather than by two that resemble each other, and the mark follows whatever corner radius the thing being marked is drawn with. On a combo it is an overlay window rather than a paint hook. PlaterPresetComboBox is a TextInput and every preset combo in the app is one, so a hook there would mark the print and printer combos too; this mark belongs to six rows in one panel. The overlay forwards its clicks, because a corner that swallowed them would be a dead spot on a dropdown, and it raises itself over the combo's own children. Sized 18, not the card's 22 and not the 14 it started at. Below about 18 the check has no room left inside the triangle once the stroke has its own width, and the mark reads as a plain green corner - which is what 14 did, seen on screen rather than reasoned about. A combo is 30 tall, so 18 is as much as the mark can take without crowding the text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…view is listening
The restore ran in post_init(), and the account was live in C++ from then on - but the home page
still offered Login/Register over it. Two separate reasons, one per end of startup, and fixing
either alone does not work:
- post_init() is too late for anything that asks. The webview queries the login state once,
early, and by then the answer was still "offline". PR Snapmaker#715, an outside contributor's, moved
its restore into init_app_config() for exactly this reason, and that placement is right
- init_app_config() is too early to tell anyone. set_user_login() notifies through
m_user_login_subscribers, and at that point in startup the webview does not exist, so the
notification reaches nobody. Moving the restore there alone made it worse, not better:
measured, the webview went from being told "online" once to never being told at all
So both. The state is restored in init_app_config(), before anything can ask for it, and
sm_announce_login() repeats it in post_init() once there is something subscribed to hear it. The
log now shows the restore, the re-announce, and the webview receiving status: online.
The page still renders Login/Register after all that, which is as far as this can be taken from
here: the saved token is days old, and the header says plainly that nothing re-validates it -
"a stale token simply fails on the next API call and the user re-logs in". Whether a fresh token
lands differently is a question for the next real login, not for this branch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The filament rows drew the mark at 18 while the cards and head boxes drew it at 22, and side by side the difference showed. The size is now a single constant both take, so they cannot drift apart again. Twenty-two is a much larger share of a 30px combo than of a 106px card, which is why it started smaller. But the mark says the same thing in both places, and reading as the same mark is worth more than sitting at the same proportion - and 22 still clears the filament name, which is left-aligned. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The panel was designed against another slicer's, and the docs said so by name throughout - 52 mentions across eight files, plus five embedded screenshots of its UI. A public AGPL-3.0 repository is not the place to carry a competitor's brand or its interface, whatever the screenshots were useful for while the design was being argued. The substance stays. Every measurement, proportion and decision is still there, and so is the record of what was deliberately *not* copied - the four places the panel cannot follow its reference are still four, still explained. What goes is the name: "the reference slicer", "the reference's Left/Right Nozzle panes", "the width the reference uses". A reader who wants to know which slicer can still tell from the description; the repository no longer advertises it. The five screenshot columns in the mockup go with it, along with the CSS that framed them. They pointed into `ui-snapshots-inspiration/`, which commit 3bbb943 already kept out of git, so they had been dead links for as long as they have been public; the prose beside each one carried the argument anyway and is untouched. Two things deliberately left alone: - `ui-snapshots-inspiration/Snapmaker_U1_plates/` in plate-thumbnails-options.html. Those are Snapmaker's own plate photographs, not the competitor's screenshots - the source art for the plate thumbnails, and their own licensing question is already open in doc 17 - `AceMmuProvider.cpp`'s "(Bambu-style path)" comment. It came over verbatim from feat/ace-mmu-slicing rather than being written here, and keeping it verbatim is what lets that branch merge onto this one cleanly All three mockups re-checked in WebKit after the edit: no JS errors, all still render. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…files win
feat/ace-mmu-slicing ships the same vendor bundle at 02.02.55.05, with two placeholders in
machine_start_gcode that only that branch defines:
; multiACE plan: {ace_plan_summary}
{ace_plan_preload}
Its profiles land in ~/.config/Snapmaker_Orca/system/ and stay there. check_installed_vendor_profiles()
only reinstalls from resources when the resource bundle is newer, and 02.02.55.02 is not, so this
branch kept reading the other branch's start gcode and refused to slice:
machine_start_gcode Parsing error at line 105: Not a variable name
02.02.55.06 makes this branch's bundle the newer one. The fourth component is not decoration -
semver.c folds it into the patch as patch*100+value, so 55.02 is 5502 and 55.05 is 5505; 55.06
is 5506 and wins.
Deleting the cached bundle also fixes the parse, and is what I tried first - but removing
Snapmaker.json makes the app read the install as a first run and put the config wizard up, which
resets the selected printer and the filament slots. A version bump takes the same profiles down
the ordinary update path instead. Verified on a copy of a config in exactly that state: the
bundle went to 02.02.55.06, both placeholders gone, and firstguide stayed finished - no wizard.
When feat/ace-mmu-slicing merges, the merged bundle needs a version above both, or whichever
profiles lose the merge will be the ones that stick on every machine that already has the other.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…bundle fail to load
One process profile is on disk as
0.10mm Color Mixing @Snapmaker U1 (0.4 Nozzle).json
while Snapmaker.json lists it, and the preset inside it names itself, with a lowercase "nozzle".
It is the only one of 198 profile filenames spelled that way; every other file, every manifest
entry and every compatible_printers string uses "nozzle".
On Windows and macOS the filesystem hides this. On Linux the file is simply not found,
load_vendor_configs_from_json fails on it, and it takes the entire vendor bundle down with it -
no Snapmaker machine presets load at all, so the printer combo is empty, the sidebar shows NO
IMAGE with a blank nozzle diameter, and any user preset inheriting one of them is orphaned:
load_from_json: parse .../0.10mm Color Mixing @Snapmaker U1 (0.4 nozzle).json got a parse_error
can not find parent for config .../user/default/machine/Snapmaker U1 (0.4 nozzle) - multiACE.json!
This is not new here: origin/main and develop/add-multiace-support both list the entry and both
lack the file. It has been dormant because the profiles were never actually loaded from resources
on a machine that already had a newer bundle in its datadir - which, on a developer machine with
feat/ace-mmu-slicing's 02.02.55.05 sitting there, is every machine. Bumping this branch's version
to .06 in the previous commit made the app read these profiles for the first time, and the bug
came with them. A clean Linux install of main should hit it too.
The fix is the filename, not the manifest: the manifest, the preset's own name field and its
compatible_printers all already agree on lowercase.
The version goes to 02.02.55.07 so the corrected bundle installs over the broken .06 that
commit 37c617e will have left in datadirs.
Verified on a copy of a config in exactly that state: bundle 02.02.55.06 -> 02.02.55.07, zero
parse errors, zero orphaned parents, all 570 manifest entries resolving, and the U1 back in the
printer panel with its thumbnail and plate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds the U1 printer panel out into something that can actually talk to the machine: one press
reads the printer, writes what it finds, marks what agrees, and hands the filament list both of
the machine's sources. Verified throughout against a live U1 at
192.168.2.242— a connectedACE 2 Pro in
headmode feeding Toolhead 4, three stock feeders, four PETG spools — not byreading code. Follows
docs/ace-mmu/15-printer-panel.mdand its mockup.What it does
Sync info now does two independent reads in one press. Nozzle diameters come over the webview
bridge;
ace_modeand the per-head ACE wiring come from the printer's own multiACE service overplain HTTP. Either half can fail on its own and the dialog says which did. It ends by offering the
filament sync rather than stopping at an OK.
Green corner ticks on the printer card and on each toolhead box that matches the machine, and
on each filament combo the machine actually has loaded. They are a diff against what was read, not
a record that a sync once ran — edit a value afterwards and the mark goes; restart and nothing is
marked until something is read again.
The assign popover behind each ACE row: a choice, not a count, because the firmware offers
exactly two macros. It writes
ace_head_unit/ace_head_capacityand tells the machine nothing —Sync info is what reconciles the two. The ACE badge replaces the words, drawn in code per
docs/ace-mmu/16-ace-visuals.md, carrying the unit's own slot colours once the machine has been read.The filament sync sees the whole machine. Its list was one row per toolhead; a head fed by an
ACE carries whatever slot is loaded that second and the other spools were invisible. It now
relabels the heads with where each is fed from and appends every ACE slot. On the live machine that
is 2 toolheads + 4 ACE slots = 6 filaments, with Toolhead 3 (nothing loaded) and Toolhead 4 (it is
slot 3) correctly excluded — no spool listed twice.
Overlaps with Snapmaker#715
The account-persistence commits overlap Snapmaker#715 (@amitamit10), which fixes the same thing in
GUI_App.cppandWebSMUserLoginDialog.cpp. That PR's placement is better than where this onestarted and has been adopted here: restoring in
init_app_config()rather thanpost_init(),because the webview asks for the login state once, early.
Measuring it showed that placement is necessary but not sufficient — at
init_app_config()nothingis subscribed yet, so the notification reaches nobody, and the webview went from being told
"online" once to never being told at all. This branch does both: restore early, then re-announce in
post_init(). The home page still renders Login/Register afterwards, with a token some daysold and nothing re-validating it; whether a fresh token behaves differently is untested. Reviewers
may prefer to take Snapmaker#715 and drop the two commits here.
Not included
Sending
SET_ACE_MODErather than only recording it; the per-unit capacity pool that stops ashared unit double-counting (
AceMmuPlan.hpp); Combined mode's slot → (unit, slot) map inGCode.cpp. Each needs work outside this branch, and the last two are pre-existing defectsdocumented in
docs/ace-mmu/15-printer-panel.md.Known gap: the nozzle half of the press needs Orca's own device flag, which lags the webview's
connect by a few seconds. Pressing Sync info immediately after connecting gets the ACE half only,
and says so; a second press a moment later returns the full result.