Skip to content

Fix device page and camera streaming over LAN connections - #39

Open
sudharsan-gandhi wants to merge 1 commit into
FlashForge:mainfrom
sudharsan-gandhi:upstream/fix-lan-device-camera
Open

Fix device page and camera streaming over LAN connections#39
sudharsan-gandhi wants to merge 1 commit into
FlashForge:mainfrom
sudharsan-gandhi:upstream/fix-lan-device-camera

Conversation

@sudharsan-gandhi

Copy link
Copy Markdown

Summary

Three related defects leave the device page degraded and the camera dark on any locally connected printer. Present on main, develop, release_0715 and beta_hunse — verified individually on each.

This is not model-specific; it affects every FlashForge printer connected over LAN rather than the cloud. It's most visible on the Creator 5 / 5 Pro, where the device page shows no video at all.

Light control is unaffected, and that turned out to be the clue: ComLightCtrl already has a working LAN branch via fnet_ctrlLanDevLight, which is exactly why lights respond locally while the camera does not.

1. ComGetDevProductDetail gives up on LAN

if (data.connectMode == COM_CONNECT_LAN) {
    return COM_UNSUPPORTED;

The network library does expose LAN equivalents — getLanDevProduct and getLanDevDetail — and they're already used individually by ComGetDevProduct and ComGetDevDetail a few lines above in the same header.

Because this returned COM_UNSUPPORTED, devProduct and devDetail stayed null on every LAN connection, so each capability the device page reads from them was silently absent: camera, lightCtrlState, internalFanCtrlState.

Now fetches both, freeing the product if the detail call fails so a partial success doesn't leak.

2. ComCameraStreamCtrl has no LAN path

Also returned COM_UNSUPPORTED on LAN. Here there genuinely is no ctrlLanDev* counterpart to fnet_camera_stream_ctrl_t in the library.

But SingleDeviceState::fillValue issues the "open" command precisely when connectMode is LAN, and the camera only serves frames once explicitly opened. So the stream could never start — a dead end by construction.

Implemented the LAN path as a POST to the printer's local /control endpoint. This is the same request the library already performs for lightControl_cmd via fnet_ctrlLanDevLight, using the ip, port, serialNumber and checkCode already carried in com_command_exec_data_t:

{ "serialNumber": "...", "checkCode": "...",
  "payload": { "cmd": "streamCtrl_cmd", "args": { "action": "open" } } }

A non-2xx reply, or a JSON body with a non-zero code, is treated as failure. An unparsable body on a 2xx is accepted, since the command was acknowledged.

If you'd prefer this went through the network library instead, that works too — it would need a fnet_ctrlLanDevCameraStream counterpart exposed, and I'd happily rework the patch against it.

3. Null dereference plus a missing stream-URL fallback in fillValue

std::string state = data.devDetail->status;      // unconditional
if (wanDev) { state = data.wanDevInfo.status; }  // ...but WAN reads elsewhere

devDetail is dereferenced unconditionally, including on the WAN path where status comes from wanDevInfo. Since it can legitimately be null when the fetch hasn't run or has failed, this was a live null dereference. Now returns early.

Separately, when the printer reported no stream URL — which happens on LAN — the function did nothing at all. It now falls back to the standard local MJPEG endpoint so the panel has something to load, and assigns the resolved URL rather than re-reading the empty field.

Verification

  • Compiles on macOS arm64 and x86_64 (Build slicer mac green on both). The build I ran was the beta_hunse-based variant of this patch; the main-adapted version differs only in the camera block, which follows main's existing structure since main has no isSupportCamera gate.
  • Not yet validated against hardware. I don't have a printer to test with, so I'd welcome someone confirming the camera comes up on a LAN-connected device. I did not want to sit on the diagnosis while waiting for that.
  • The LAN control protocol was cross-checked against two independent open-source implementations that drive these printers over LAN and stream their cameras successfully: GhostTypes/ff-5mp-api-py and its Home Assistant integration GhostTypes/ff-5mp-hass. Both use the same /control envelope and the same MJPEG endpoint, and their printer-ID table matches FFUtils::printer_preset_map exactly (AD5X 0x26, C5 0x28, C5P 0x29).

Scope

Three files, +119/−4. No behaviour change on WAN connections. No new dependencies — Http and nlohmann/json are both already used in this directory.

Three related defects leave the device page degraded and the camera dark on any
locally connected printer. Present on main, develop, release_0715 and
beta_hunse.

1. ComGetDevProductDetail reported the whole command unsupported on LAN. The
   network library does expose LAN equivalents, already used individually by
   ComGetDevProduct and ComGetDevDetail a few lines above, so devProduct and
   devDetail stayed null on every LAN connection and each capability the device
   page reads from them was silently absent: camera, lightCtrlState,
   internalFanCtrlState. Now fetches both via getLanDevProduct and
   getLanDevDetail, freeing the product if the detail call fails.

2. ComCameraStreamCtrl also returned COM_UNSUPPORTED on LAN, and here there is
   genuinely no ctrlLanDev* counterpart to fnet_camera_stream_ctrl_t. But
   SingleDeviceState issues the "open" command precisely when connectMode is
   LAN, and the camera only serves frames once explicitly opened, so the stream
   could never start. Implemented the LAN path as a POST to the printer's local
   /control endpoint: the same request the library performs for
   lightControl_cmd via fnet_ctrlLanDevLight, using the ip, port, serialNumber
   and checkCode already carried in com_command_exec_data_t.

3. SingleDeviceState::fillValue dereferenced data.devDetail unconditionally,
   including on the WAN path where status is read from wanDevInfo instead.
   devDetail can legitimately be null when the fetch has not run or failed, so
   this was a live null dereference; it now returns early. fillValue also did
   nothing when the printer reported no stream URL, which happens on LAN, and
   now falls back to the local MJPEG endpoint.

Light control is unaffected: ComLightCtrl already had a working LAN branch,
which is why lights respond locally while the camera does not.
@sudharsan-gandhi

Copy link
Copy Markdown
Author

Additional build verification, since I could only cite macOS when opening this:

Platform Compile step Result
macOS arm64 Build slicer mac ✅ success
macOS x86_64 Build slicer mac ✅ success
Windows / MSVC Build slicer Win ✅ success
Windows / MSVC Create installer Win ✅ success

Zero compile errors on any of the three compilers, and none of the three changed files appear in any diagnostic.

Two unrelated failures in those same runs, both pre-existing on a clean checkout and neither touched by this PR — noting them only so they aren't mistaken for fallout:

  • Pack app / Pack macOS app bundle look for build/OrcaSlicer, but build_release_macos.sh emits build/<arch>/Orca-Flashforge/Orca-Flashforge.app (OUT_APP_BUNDLE). The same mismatch makes scripts/flatpak/com.orcaslicer.OrcaSlicer.yml ask make for a target named OrcaSlicer and fail with No rule to make target.
  • build_linux.sh and scripts/run_unit_tests.sh are committed mode 100644 but invoked directly, so CI fails them with exit 126 (Permission denied). This is what blocks the Linux build and, transitively, the Unit Tests job.

Happy to send either as its own small PR if useful — I kept them out of this one to keep the diff focused on the LAN defects.

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