mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-19 15:54:27 +02:00
fix(printer): bed-jog "Home Z" could crash bed into toolhead on H2C/H2D/H2S/X1 (#1052)
Critical safety fix. The bed-jog dialog's "Home Z" button sent a bare
`G28 Z` over gcode_line. On Bambu printers where the Z endstop is at
the top (bed moves UP into it — H2C, H2D, H2S, X1 family), `G28 Z`
skips the toolhead-park step that a full `G28` runs first, so the bed
rises at full speed with nothing getting out of the way. The reporter
only escaped damage because the toolhead happened to be parked on the
purge chute.
The /printers/{id}/home-axes endpoint and BambuClient.home_axes() now
always send bare `G28` regardless of the axes argument, triggering the
firmware's safe multi-step routine (park toolhead → home XY → home Z).
The axes argument is kept for API compat but ignored; invalid values
still return 400.
Frontend retitles the button "Auto Home" and updates the dialog copy
in all 7 locales so users aren't surprised when X/Y motion happens
before Z. Parameterized regression test asserts z/xy/all all produce
bare G28.
(cherry picked from commit 7026a6de77)
This commit is contained in:
@@ -2497,19 +2497,30 @@ async def bed_jog(
|
||||
@router.post("/{printer_id}/home-axes")
|
||||
async def home_axes(
|
||||
printer_id: int,
|
||||
axes: str = Query("z", description="Axes to home: 'z', 'xy', or 'all'"),
|
||||
axes: str = Query(
|
||||
"all",
|
||||
description="Legacy; accepted values are 'z' | 'xy' | 'all'. Always runs the printer's full auto-home sequence — see below.",
|
||||
),
|
||||
_=RequirePermissionIfAuthEnabled(Permission.PRINTERS_CONTROL),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Home one or more axes via G28."""
|
||||
"""Run the printer's full auto-home sequence via bare `G28`.
|
||||
|
||||
Bambu printers (H2C / H2D / H2S / X1 family) home the Z axis by moving
|
||||
the BED UP toward an endstop at the top of travel. If the toolhead is
|
||||
not already parked out of the way, a bare `G28 Z` will crash the bed
|
||||
into the toolhead — #1052 reported exactly that on H2C: the bed rose
|
||||
without stopping at a safe height because `G28 Z` skipped the
|
||||
toolhead-park step that a full `G28` runs first.
|
||||
|
||||
The endpoint therefore ignores the `axes` argument and always sends a
|
||||
bare `G28`, which the firmware expands into a safe multi-step sequence
|
||||
(park toolhead → home XY → home Z). The argument is kept only for
|
||||
backward-compat with existing clients; sending an invalid value still
|
||||
returns 400 so typos surface instead of silently proceeding.
|
||||
"""
|
||||
axes = axes.lower()
|
||||
if axes == "z":
|
||||
gcode = "G28 Z"
|
||||
elif axes == "xy":
|
||||
gcode = "G28 X Y"
|
||||
elif axes == "all":
|
||||
gcode = "G28"
|
||||
else:
|
||||
if axes not in ("z", "xy", "all"):
|
||||
raise HTTPException(400, "axes must be 'z', 'xy', or 'all'")
|
||||
|
||||
result = await db.execute(select(Printer).where(Printer.id == printer_id))
|
||||
@@ -2521,10 +2532,10 @@ async def home_axes(
|
||||
if not client:
|
||||
raise HTTPException(400, "Printer not connected")
|
||||
|
||||
if not client.send_gcode(gcode):
|
||||
if not client.send_gcode("G28"):
|
||||
raise HTTPException(500, "Failed to send home command")
|
||||
|
||||
return {"success": True, "message": f"Home {axes} command sent"}
|
||||
return {"success": True, "message": "Full auto-home sequence sent"}
|
||||
|
||||
|
||||
@router.post("/{printer_id}/hms/clear")
|
||||
|
||||
Reference in New Issue
Block a user