Correcting the previous commit, which said the :8080 stream could not be
restored without cross-compiling a streamer. Both halves are actually true:
* firmwareExe really did serve the stream itself -- its own accept loop,
`GET /?action=stream`, boundarydonotcross, even announcing
`Server: MJPG-Streamer/0.2` -- so killing it does take the camera down.
* ...but /usr/prog/mjpg-streamer/ ships the genuine article: mjpg_streamer,
input_uvc.so, output_http.so, its own libjpeg.so.9 and www/.
app_startup.sh:159 exports LD_LIBRARY_PATH for it and then never launches
it. Nothing needs building; the binary just needs starting.
S65camera does that, on the S50wifi pattern -- the wait for /dev/video0 and the
respawn loop run in a background subshell, so a printer with no camera plugged
in never holds up Klipper or the UI. stop() kills the supervisor before the
streamer, or it would come back three seconds later.
Two details are load-bearing and easy to lose: libjpeg.so.9 lives in the
mjpg-streamer directory, so without LD_LIBRARY_PATH the binary dies on a
missing shared object (the same trap moonrakerDaemon has in S60web); and the
plugin .so names resolve against the working directory, hence the cd.
nginx proxies it at /webcam/ with buffering off and no read timeout, since
MJPEG is one endless response, and moonraker.conf's [webcam] entry uses
relative URLs through that proxy -- so one forwarded port carries the stream,
tunnels included. MOD_CAM=0 turns it off; MOD_CAM_RES/FPS/PORT tune it.
The earlier claim is corrected in docs/notes/25 and in the README, which no
longer lists the camera as something you give up.
Verified: parses under the printer's own busybox ash, lint-danger clean. The
full suite was not re-run to completion -- the working tree is being edited
concurrently and a build lane raced it (tar: file changed as we read it).
bin/patch.sh's MOD_CAM line is deliberately left out of this commit for the
same reason.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The mod replaces FlashForge's application outright, so the reasoning that
still framed the web stack as coexisting with it was wrong on its own terms.
* nginx and moonraker are documented as the only web stack on the printer.
MOD_WEB=0 is a debugging switch that leaves ssh and the touchscreen, not a
way back to stock -- that is a stock FlashForge package. The own-prefix rule
stays, for the reason that is actually true: /usr/prog is the firmware
partition and every FlashForge package reinstalls it, so a config written
there is undone by the next stock flash.
* Configs the mod ships now update when you have not edited them. A live file
still byte-identical to the one the last package wrote is replaced; one you
changed is kept and the new version lands beside it as .mod-new.
$MODDIR/config-installed holds that last-written copy. Without this a config
we own could only ever be written once: it exists on the second flash, so it
would land as .mod-new forever and updates would never reach the printer.
* Dropped the three dead /server/files/ alias blocks from nginx.conf. The regex
location above them matches /server/ too and nginx gives regex locations
precedence, so they never fired -- and had they fired, serving those paths
from disk would 405 the DELETE and POST that Mainsail sends to the very same
URLs.
* Recorded what dies with firmwareExe, in docs/notes/25 and in the README: the
:8898 REST API (FlashPrint, Orca's FlashForge profile, the mobile app) and
the :8080 camera stream. The camera is the one that looks restorable and is
not -- the MJPEG server is compiled into firmwareExe (its own accept loop,
`GET /?action=stream`, boundarydonotcross) rather than being mjpg-streamer,
so there is no daemon left to point a [webcam] at. assets/moonraker.conf
carries the block, commented, for when a streamer is built for this board.
Also in this change: the MOD_UI switch and the stock-UI path are gone, the
chamber-heater model gate arrives with ff-model.cfg/ff-chamber.cfg, and the
tests follow.
make test: 32 passed, 1 failed. The failure is the probe end-to-end, which
dies at "mount: failed to setup loop device for /stick.img" -- leaked loop
devices on this build host, not the package. Probe installs nothing, and the
default profile's install -> re-install -> boot passes in the same run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The imported README and notes still described a standalone checkout:
relative links to klippy-extras/ and config/ that no longer resolve, an
scp recipe naming the old directories, and a header about the
klipper-vanilla and main branches, neither of which exists here.
Paths now point at payload/klipper/ and assets/orca/, and the header
keeps the not-yet-run-on-hardware warning without the branch
bookkeeping. Every relative link in docs/ resolves.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgNhSa1Qvwvxb2nQXT6b1Y
Pure renames, no content changes, so `git log --follow` walks straight
back into the toolchange history imported by the previous commit.
klippy-extras/ff_*.py -> payload/klipper/extras/
config/ff-*.cfg -> payload/klipper/config/
helixscreen/*.json -> payload/helixscreen/printer_database.d/
orca/ -> assets/orca/
docs/notes/ -> docs/notes/
README.md -> docs/toolchange.md
payload/ is the right home for the first three: they are files that
ship to the printer, which is what everything else under payload/ is.
The Orca snippets go to assets/ instead -- they are pasted into a
slicer on the desktop and never reach the machine.
bin/patch.sh still reads them from $TOOLCHANGE; the next commit points
it here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgNhSa1Qvwvxb2nQXT6b1Y