Public: anyone can read this; the crew can change it.
Migrated from github.com/Trevato/SO-ARM100
workbenchthis machine
uhubctl try-out outlasts the relay's 2.5 s light write timeout: the card shows "the arm server did not answer" while the try-out succeeds #638
Check · Review · Land done · Live — Landed; nothing deploys from this branch, so this is the end of its path.
smith/arm:smith/637-uhubctl-try-out-outlasts-the-relay-s-2-5 → main 1 commit fork
2 files
changed +17
−1
Software/so101/src/admin-relay.test.ts +16
| @@ -233,3 +233,19 @@ test("/admin: a uhubctl light-switch flashes lightTried, a light-confirm posts { | ||
| 233 | 233 | arm.stop(true); |
| 234 | 234 | } |
| 235 | 235 | }); |
| 236 | ||
| 237 | test("/admin: a uhubctl try-out that outlasts the read timeout still flashes lightTried", async () => { | |
| 238 | const arm = Bun.serve({ port: 0, fetch: async (req) => { if (req.method === "POST") await Bun.sleep(400); return Response.json({}); } }); | |
| 239 | try { | |
| 240 | dir = mkdtempSync(join(tmpdir(), "so101-admin-relay-")); | |
| 241 | lobby = new Lobby({ identityKey: KEY, adminFile: join(dir, "admin.json") }); | |
| 242 | relay = await startRelay({ port: 0, simulation: `http://127.0.0.1:${arm.port}`, lobby, growKey: "grow-key", readTimeoutMs: 100 }); | |
| 243 | const base = `http://127.0.0.1:${relay.port}`; | |
| 244 | const owner = as("trevato", "admin"); | |
| 245 | const tried = await fetch(`${base}/admin`, form(owner, { action: "light-switch", device: "light", driver: "uhubctl", hub: "1-1", port: "2" })); | |
| 246 | expect(tried.status).toBe(303); | |
| 247 | expect(await (await fetch(new URL(tried.headers.get("location")!, base), { headers: owner })).text()).toContain("switched off for 2 s and back on"); | |
| 248 | } finally { | |
| 249 | arm.stop(true); | |
| 250 | } | |
| 251 | }); |
Software/so101/src/relay.ts +1 −1
| @@ -681,7 +681,7 @@ export async function startRelay(options: RelayOptions): Promise<RunningRelay> { | ||
| 681 | 681 | }, |
| 682 | 682 | write: async (device, body) => { |
| 683 | 683 | try { |
| 684 | const answer = await fetch(armGrow(`/${device}`), { method: "POST", headers: growAuth(), body: JSON.stringify(body), signal: AbortSignal.timeout(Math.min(readTimeoutMs, 8000)) }); | |
| 684 | const answer = await fetch(armGrow(`/${device}`), { method: "POST", headers: growAuth(), body: JSON.stringify(body), signal: AbortSignal.timeout(Math.max(readTimeoutMs, 10_000)) }); | |
| 685 | 685 | if (answer.ok) return null; |
| 686 | 686 | const err = (await answer.json().catch(() => null)) as { error?: unknown } | null; |
| 687 | 687 | return typeof err?.error === "string" ? err.error.replace(/[\p{Cc}\p{Cf}]/gu, "").slice(0, 300) : `the arm server answered ${answer.status}`; |