Compatibility issues with Klipper Mobile Apps / Clients (Obico, OctoApp, Mobileraker) #48
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hi,
First of all, thank you for this amazing project! It’s a game-changer for bringing the Anycubic Kobra X into a modern slicing and monitoring ecosystem.
I am running kx-bridge inside a Docker container on a Ubuntu server. It works well for printing directly from OrcaSlicer KX (apart from the generic materials issue I already reported in issue #38) but I am encountering several compatibility issues when trying to connect external Moonraker/OctoPrint clients and mobile apps.
Here is a detailed breakdown of the behavior with different applications:
Webcam: The printer's native camera stream (http://:7125/api/camera/stream) cannot be pulled by the moonraker-obico plugin. However, if I map a secondary standard USB webcam running on port 8080, Obico can capture the stream and Janus WebRTC works perfectly.
Controls: From the Obico web dashboard, toolhead/movement controls do not work (commands seem to be ignored or not properly translated).
Android App: While the printer is discovered and shows up in the general list, clicking on the printer details page results in a permanent blank/white screen. This is likely due to a silent JSON parsing crash when the app requests printer object states that the bridge doesn't currently expose.
The app successfully connects and correctly receives temperature data, but it cannot interact with anything else (no movement controls, no status updates).
The video stream from the printer's native camera is missing/not detected.
When trying to connect, the app crashes immediately and outputs the following explicit stack trace:
Technical Insight: It seems that mobile apps strictly require Moonraker to return full printer object states (such as configfile, toolhead, virtual_sdcard, etc.). Since kx-bridge translates Moonraker API calls on the fly into Anycubic's native MQTT protocol, the absence of these standard Klipper endpoints/fields causes mobile clients to crash or freeze.
A quick question for the maintainer: Would you prefer me to close this issue and open three separate, dedicated tickets for each application (Obico, OctoApp, and Mobileraker) to better track the development/fixes?
Thank you for your time and support!
Thank you for this detailed and well-structured report!
Here is the current status for each app:
Obico
Obico support is actively being worked on. Stop and Pause commands already work. Webcam stream and full printer controls are in progress. For now, the USB webcam workaround on port 8080 + Janus WebRTC (as you described) is the recommended approach. No separate ticket needed — this issue covers it.
OctoApp / Mobileraker
These apps require a fully implemented Moonraker/Klipper object model (
configfile,toolhead,virtual_sdcard, etc.). KX-Bridge is not a full Moonraker replacement — it translates a subset of the Moonraker API into the Anycubic MQTT protocol. Full compatibility with OctoApp and Mobileraker is currently out of scope.No need to open separate tickets — one issue per app is fine if you want to track them individually, but this issue already captures the full picture.
Thanks again for the detailed breakdown — it is very helpful!
I haven't yet tried to setup Obico, but are you already using the moonraker-obico plug-in?
Update (2026-06-06): After further investigation, I have good news on two fronts:
Mobileraker crash (
Missing field: configFile)Root cause confirmed:
configfilewas missing from the printer objects the bridge exposes. A fix is in progress — the bridge will return a minimalconfigfilestub with the settings structure that Mobileraker expects. This should resolve the immediate crash.Webcam stream URL for Obico / OctoApp
The bridge already serves its own MJPEG proxy at
/api/camera/streamand H.264 at/api/camera/h264, and/server/webcams/listis implemented. The issue is thatstream_urlis returned as a relative path (/api/camera/stream). If moonraker-obico or the app runs on a different host than the bridge, it cannot resolve the stream. The fix is to return an absolute URL — this requires knowing the bridge host/IP at runtime, which we can derive from the incoming request.Movement controls (Obico / OctoApp)
Not yet investigated in depth — will follow up once the above two are addressed.
I will update this issue once the fixes are released. No need to open separate tickets.
Hi viewit and gangoke,
Thank you both for the quick and incredibly positive feedback! It's amazing to see that you've already identified the root causes for the Mobileraker crash and the webcam URL resolution.
@gangoke: Yes, I am using the official moonraker-obico plugin running directly on my Ubuntu host, pointing via network to the kx-bridge Docker container. To make the installation pass the Moonraker configuration checks, I had to create a dummy "obico_moonraker.conf" and a blank "printer.cfg" locally on the host, otherwise the installer script would fail. It works surprisingly well for telemetry and notifications!
@viewit: These updates are fantastic news. I will gladly wait for the next release to test the configfile stub with Mobileraker and check if the absolute webcam URL fixes the native stream on Obico/OctoApp.
Keep up the amazing work, I'm ready to test the fixes as soon as they are deployed!
Hi viewit,
Please hold on! I just checked the logs again after updating to v0.9.20 and realized that your configfile stub for Mobileraker IS actually there and working, but the app is now throwing a different crash because the stub is a bit too minimal for its JSON parser.
The initial "Missing field: configFile" error is gone, but Mobileraker now crashes with a type cast error, expecting some mandatory fields inside the extruder settings that are currently returning Null.
Here is the new stack trace and the exact raw JSON response captured during the crash:
Exception:
type 'Null' is not a subtype of type 'Object' in type cast
Stack Trace:
#0 _$ConfigExtruderFromJson (package:common/data/dto/config/config_extruder.g.dart:17)
#1 new ConfigExtruder.fromJson (package:common/data/dto/config/config_extruder.dart:30)
#2 new ConfigFile.parse (package:common/data/dto/config/config_file.dart:75)
#3 PrinterBuilder._updateConfigFile (package:common/data/dto/machine/printer_builder.dart:246)
#4 PrinterBuilder.partialUpdateField (package:common/data/dto/machine/printer_builder.dart:216)
Failed-Key: configfile
Raw Json returned by the bridge:
{"extruder":{"temperature":32.0,"target":0.0,"power":0.0},"heater_bed":{"temperature":29.0,"target":0.0,"power":0.0},"print_stats":{"state":"standby","filename":"","print_duration":0,"total_duration":0,"remain_time":0,"info":{"current_layer":0,"total_layer":0}},"display_status":{"progress":0.0,"message":""},"virtual_sdcard":{"progress":0.0,"is_active":false,"file_path":"","file_position":0},"toolhead":{"position":[0,0,0,0],"homed_axes":"xyz","print_time":0,"estimated_print_time":0},"gcode_move":{"speed_factor":1.0,"extrude_factor":1.0,"speed":0,"gcode_position":[0,0,0.0,0],"absolute_coordinates":true,"absolute_extrude":true,"homing_origin":[0,0,0,0],"position":[0,0,0.0,0]},"fan":{"speed":0.0,"rpm":null},"gcode_macro _OBICO_LAYER_CHANGE":{"current_layer":0,"first_layer_scanning":false,"first_layer_scan_enabled":false},"gcode_macro TIMELAPSE_TAKE_FRAME":{"is_paused":false},"configfile":{"config":{},"settings":{"printer":{"kinematics":"cartesian","max_velocity":450,"max_accel":10000,"max_z_velocity":12,"max_z_accel":100,"square_corner_velocity":20.0},"extruder":{"nozzle_diameter":0.4,"min_temp":0,"max_temp":320,"min_extrude_temp":10},"heater_bed":{"min_temp":0,"max_temp":120},"stepper_x":{"position_min":-18.5,"position_max":280},"stepper_y":{"position_min":-6.5,"position_max":272.5},"stepper_z":{"position_min":-4,"position_max":262},"virtual_sdcard":{"path":"/data/gcodes"},"pause_resume":{},"display_status":{}},"warnings":[],"save_config_pending":false,"save_config_pending_items":{}}}
As you can see, Mobileraker's ConfigExtruder.fromJson parser is strictly looking for some extra standard fields inside configfile.settings.extruder (like sensor_type, filament_diameter, etc.) and panics when they aren't provided.
Regarding Obico, the native video stream on port 7125 still fails to load, and the app continues to show a blank screen (probably for a similar JSON parsing reason as Mobileraker). For now, I've reverted back to the external USB webcam on port 8080 to keep it running.