mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
cooling.gate-off: a gate setting trips in range and is off at its far end
The acceptance catalog gains the test behind forgectrl 9e44fdc: the coolant ceiling set just over its legal minimum must trip OVERTEMP with a hold and fire blocked at the next run start; set to its top the engine must skip the gate (verdict OK), report it in gates_off on /status and /cool/status, and log the run-start line; the original values are restored, on failure too, and proven restored. Five host cases against a scripted engine. The cooling covers map now names the files that carry gate state (gates, settings, status, the panel) and corrects a glob that matched nothing: the GRBL cooling client is src/glowforge_cooling.c, not src/gfcool*. The fake forgectrl serves /logs/tail and keeps blank form values as "clear", which is what the daemon does with them. Docs: COOLING.md section 8 carries each setting's legal range and recommended band and a new 8a on turning a gate off; SAFETY.md names what no setting can reach; ACCEPTANCE.md records that gates are exercised through the settings API, never GFCOOL_* env overrides; BRINGUP item 19 records the pattern as landed and the catalog is 43. forgectrl pin moves to 9e44fdc; fetch-verified.
This commit is contained in:
@@ -102,6 +102,7 @@ class FakeForgectrl:
|
||||
"cam": {"running": False, "clients": 0},
|
||||
"diag": {"running": False},
|
||||
"settings": {"controller_mode": "grbl", "lid_lamp_idle": ""},
|
||||
"logs_tail": {"name": "forgectrl", "text": "", "truncated": False, "exists": True},
|
||||
}
|
||||
self.posts = []
|
||||
self.on_post = None
|
||||
@@ -122,7 +123,8 @@ class FakeForgectrl:
|
||||
def do_GET(self):
|
||||
path = self.path.split("?", 1)[0]
|
||||
key = {"/mode": "mode", "/status": "status", "/cool/status": "cool", "/cam/status": "cam",
|
||||
"/diag/status": "diag", "/settings": "settings"}.get(path)
|
||||
"/diag/status": "diag", "/settings": "settings",
|
||||
"/logs/tail": "logs_tail"}.get(path)
|
||||
if key is None:
|
||||
return self._send(404, {"error": "no " + path})
|
||||
self._send(200, fake.state[key])
|
||||
@@ -131,7 +133,7 @@ class FakeForgectrl:
|
||||
path, _, query = self.path.partition("?")
|
||||
n = int(self.headers.get("Content-Length") or 0)
|
||||
raw = self.rfile.read(n).decode() if n else ""
|
||||
form = dict(_up.parse_qsl(raw)) if raw else dict(_up.parse_qsl(query))
|
||||
form = dict(_up.parse_qsl(raw if raw else query, keep_blank_values=True))
|
||||
fake.posts.append((path, form))
|
||||
if fake.on_post:
|
||||
r = fake.on_post(path, form)
|
||||
@@ -143,6 +145,7 @@ class FakeForgectrl:
|
||||
fake.state["settings"]["controller_mode"] = form["controller"]
|
||||
elif path == "/settings":
|
||||
fake.state["settings"].update(form)
|
||||
return self._send(200, fake.state["settings"])
|
||||
self._send(200, {"ok": True})
|
||||
|
||||
self._srv = http.server.ThreadingHTTPServer(("127.0.0.1", 0), H)
|
||||
|
||||
Reference in New Issue
Block a user