Clear a setting the only way the daemon accepts, everywhere it is cleared

An empty form field never reaches the request, so POST /settings with an
empty value in the body carries no key at all and the daemon answers 400,
"no known setting in request". Only the query-string form gets an empty
value through. Measured on the bench reference:

    POST /settings -d "lid_policy="   -> 400, the value unchanged
    POST /settings?lid_policy=        -> 200, the key cleared

Three places in the suite already knew this and say so in a comment; two
did not.

motion.lid-policy-hold restored with the form body, so on a machine whose
lid_policy has never been set the restore was refused and the test failed
its own check. It now uses the query-string form for the empty value, as
the others do. This is the same test as the commit before: that one
stopped it from writing the word "cancel" where the machine had nothing,
and this one lets it write the nothing.

cloud.mode-switch had the older shape of the same fault: it restored
homing_mode to the literal "none" where the machine had it unset. On the
bench reference the restore branch never ran, because that machine homes
through the cloud, so it has not fired yet; on a machine with homing_mode
unset it would have. It now restores exactly what it found.

The rest of the suite was audited for this and is clean: camera.key-read,
cooling.critical-tier, cooling.tec-drive, cooling.crash-watch-plumbing,
cooling.fire-watch-tiers, cooling.floor-and-warm-up, cloud.verdict-hold,
forgectrl.settings, logs.levels and motion.xy-microsteps all either guard
the empty value or go through the shared Restore helper, which has always
done it correctly. commission.cloud-header-capture uses that helper too.
This commit is contained in:
ScottW514
2026-09-10 10:26:25 -04:00
parent d58ee39086
commit 57ba3454b4
2 changed files with 12 additions and 2 deletions
+7 -1
View File
@@ -372,7 +372,13 @@ def mode_switch(ctx):
gfhome_homing(ctx, ev, g)
finally:
if ev["homing_mode"] != "gfcloud":
st, body = fc.post("/settings", data={"homing_mode": ev["homing_mode"] or "none"})
# Back to exactly what the machine had: unset is the empty
# string, and clearing a key needs the query-string form.
# "none" is a value, and writing it where the machine had
# nothing is a leftover the hand-back reports.
st, body = (fc.post("/settings", params={"homing_mode": ""})
if not ev["homing_mode"]
else fc.post("/settings", data={"homing_mode": ev["homing_mode"]}))
ctx.log("restore homing_mode=%r -> %s", ev["homing_mode"], st)
ctx.log("PASS: grbl -> cloud (session, hunt with the lid open, lens homed, airflow unjudged) -> "
"grbl (port open, %s), then $H homed in %.1f s", ev["grbl_state"], ev["homing_s"])
+5 -1
View File
@@ -1337,7 +1337,11 @@ def lid_policy_hold(ctx):
g.command("G90")
machine_idle(ctx)
finally:
st, _b = fc.post("/settings", data={"lid_policy": was})
# An empty value clears the key, and only the query-string form
# carries one: an empty form field never reaches the request, and
# the write is refused with "no known setting in request".
st, _b = (fc.post("/settings", params={"lid_policy": ""}) if not was
else fc.post("/settings", data={"lid_policy": was}))
ev["lid_policy_restored"] = (fc.settings() or {}).get("lid_policy", "")
ctx.log("lid_policy restored to %s", ev["lid_policy_restored"])
ctx.check(ev["lid_policy_restored"] == was, "lid_policy was not restored to %r", was)