Three things, all downstream of klippy having moved to $MODDIR and our own
CPython 3.13.
SECTIONS 8 AND 9 ARE GONE. Both files install at $MODDIR/prog/ and
anvil-link-prog.sh points the stock paths at them -- from run-append.sh on a
flash and from anvil-core's postinst on `opkg upgrade anvil-core`. Nothing
execs either between run.sh distributing the component and link-prog running,
so the component copy bought no ordering. It cost, though: our firmwareExe
with no payload behind it logs "no anvil-env.sh", finds no s6-svscan and then
`while true; do sleep 3600; done` -- a printer that boots to a blank screen for
ever and never reaches app_startup.sh's own recovery. Absent, that recovery
restores a firmwareExe from a version directory. So patch.sh now REMOVES both
from the component: the stock component carries them, and deleting the two cp
lines alone would have shipped FlashForge's originals.
SECTION 5c IS GONE. It did no work -- two du prints and a comment whose first
line was the falsehood below.
THE FALSEHOOD. "klippy runs on the stock 3.8.2, started by
/usr/prog/klipper/start.sh" had spread well past patch.sh, and it had reached
things people follow:
- docs/toolchange.md told owners to scp the ff_*.py extras to
/usr/prog/klipper/klippy/extras/ -- the wrong partition -- and warned that
an OTA would delete them there. Same wrong path in three ff-*.cfg headers
and in ff_toolchange.py.
- versions.env labelled our CPython 3.13 and its eighteen packages
"SHIPPED BUT NOT USED".
- docs/how-it-works.md said Moonraker runs on python3.8, contradicting line
126 of the same file.
All corrected. Historical notes keep their history and get a [Superseded: ...]
marker instead -- including 80-s6-migration.md's "s6-rc-compile is not
shipped", which pkgs/3rdparty/s6-rc/build.sh contradicts deliberately.
Found while reviewing: every docs/ reference to the ff-*.cfg pointed at
pkgs/anvil-core/payload/config/, which does not exist -- they are
anvil-klipper-config's. 28 references across 9 files, several of them broken
markdown links on the published site. All 24 relative links under docs/ now
resolve.
Gates: verify.sh syntax-checks prog/start.sh and prog/firmwareExe out of the
payload (firmwareExe was never syntax-checked before) and fails if the
component carries either. A new replica test asserts both stock paths are
symlinks into $MODDIR/prog and do not dangle. One existing replica test stubbed
firmwareExe by redirecting into $FE, which now writes THROUGH the symlink into
the packaged wrapper; it moves the link aside instead.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01La5MaDKqTW675k5fsXsP6S
4.5 KiB
Print lifecycle, address-verified
Everything below lives in the APP, not in Klipper: the fork ships only bare
[pause_resume] and [virtual_sdcard]. pkgs/klipper-config/payload/config/ff-print-macros.cfg reproduces the
sequences for Mainsail-started prints.
How they are entered now. START_PRINT is no longer something the slicer has to
call. [ff_print] (pkgs/klipper/payload/klipper/klippy/extras/ff_print.py) wraps SDCARD_PRINT_FILE and
M23, reads the slicer metadata out of the file itself, and calls
FF_BEFORE_PRINT_START (which runs START_PRINT when its prepare variable is 1, the
shipped default) and FF_AFTER_PRINT_END. CANCEL_PRINT is overridden too. So the
Orca profile stays stock and a print started from Mainsail gets the whole sequence
without any per-print arguments — set prepare: 0 only if your own profile already
calls START_PRINT. See ff-print-macros.cfg's tail.
Flow map (touchscreen print)
BuildPage::doPreparetion @0x9f0fbc
-> prepareForEddy @0x9f1068 (this unit: generalFirmware=false)
BuildPage::startPrint @0x9fc148 -> absolute print Z offset (40-offsets.md),
then spawns the print engine thread
CommMgr::serialPrint @0x79c8e0 -> the 37 KB engine thread
Preparation (prepareForEddy) — reproduced by START_PRINT
G90,M82,BED_MESH_CLEAR,M400G28(full home); abort on failureSET_GCODE_OFFSET X=0 Y=0 MOVE=1 MOVE_SPEED=600- two probe touch checks (app-internal
checkProbeZValue) - heat bed + chamber; dock whatever tool is held; presence check of the file's first
tool (E0165) — ported as
_FF_PREFLIGHTfor every tool inTOOLS= SET_IDLE_TIMEOUT TIMEOUT=1800000; eddy probe at (265, 4.8); nozzle clean of every tool the file uses (purge at the chute, wipe at (266.5, 13.8), cool by 100 °C, release) — ported as_FF_NOZZLE_CLEAN, see50a/50b- bed+chamber soak wait (keepBedTempPrint = 5 min), then
G28 Zre-home - per-print leveling toggle: ON →
BED_MESH_CALIBRATEat ACCEL=2000 thenBED_MESH_PROFILE LOAD=default; OFF →BED_MESH_PROFILE LOAD=MESH_DATA(a mesh is ALWAYS active for a print) - heat + grab the first tool;
G1 Z10 F1200clearance
serialPrint preamble (fresh print)
G1 X250 F2400 (clear of docks), SDCARD_SET_CHANNEL CHANNEL=<tool>, then
M21 → M23 /<name> → M26 S0 → M24, SET_IDLE_TIMEOUT TIMEOUT=864000. The app sends
NO heating for a fresh print — temps come from preparation + the sliced file itself.
Pause (inline in serialPrint; UI buttons send no gcode themselves)
SET_IDLE_TIMEOUT TIMEOUT=864000,M400,M25, wait for sd state "paused"- save all tool target temps
SAVE_GCODE_STATE NAME=PAUSE_state- all hotends OFF (bed and chamber stay on)
- park lift
G1 Z<park> F500(thresholds 50/100; exact clamp formula unrecovered) - write power-loss recovery record
Resume
- staged reheat from saved targets: e1+e2 → wait → e3+e4 → wait
- re-grab head if needed
SET_IDLE_TIMEOUT TIMEOUT=600000(sic — the app's odd value)RESTORE_GCODE_STATE NAME=PAUSE_state MOVE=1,CLEAR_PAUSE,M24
Cancel and normal completion share ONE exit block @0x7a25f0
Cancel additionally sends CANCEL_PRINT first; then, in order: heaters off (hotends,
bed, chamber), fans off; ACCEL=5000, G92 E0, G1 E-1 F300, G92 E0, M400;
bed presentation drop G1 Z150/200/256.8 F1800 by current-Z thresholds 100/150;
SET_FAN_M106[P2] reset, SET_PA_ADVANCE .. ENABLE=0, MUTE_MODE_DISABLE,
M220 S100, SET_VELOCITY_LIMIT VELOCITY=500 ACCEL=20000, BED_MESH_CLEAR,
CLEAR_PAUSE; dock the mounted tool; TOOLCHANGE_SET_PRINT_OFFSET CLEAR=1
(the app's SET_GCODE_OFFSET Z=0 MOVE=1, which cleared the babystep too); M18;
SET_IDLE_TIMEOUT TIMEOUT=600.
Divergences in ff-print-macros.cfg (deliberate)
- resume reheats all tools in parallel, not e1+e2-then-e3+e4 staged
- no dmesg/meminfo dumps, no drop_caches shell calls
- idle timeout after resume back to 864000, not 600000
- pause park: +10 mm clamped to 256 (app's exact formula unrecovered)
- tool gate covers all of TOOLS, not just the first tool; nozzle clean uses slicer temperatures (TEMPS=) and the fixed purge_z instead of a fresh eddy probe
- CANCEL_PRINT override runs our cleanup for every cancel. The job-origin flag it used to check existed for the touchscreen's own cancel, which did its own motion cleanup; that UI is not one this mod ships.