Skip to content

Commit 87e0052

Browse files
Staacksclaude
andcommitted
Decide that cmd=start must report a refused start; record it and wait on the API for baselines
The maintainer's call (2026-08-28): /control?cmd=start answering {"result": true} for a start the app refused is wrong, however the current wording reads. openapi.yaml now says the result reflects whether the measurement actually began, both control operations reference the new `control-start-refused` entry, and that entry is `decided` with the canonical behaviour and what each platform does today. Both app TODO files carry the item; the entry goes when both agree. Separately, --record-ble-baseline no longer reads stdin. Switching remote access on is the operator's last step and is exactly what makes the phone answer, so the tool waits for the API instead of for a keypress (--record-wait, default 240 s). It runs the same whether or not anyone is at the terminal it started from, which is what this session needs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 8a32112 commit 87e0052

4 files changed

Lines changed: 68 additions & 14 deletions

File tree

docs/remote-interface/openapi.yaml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,12 +260,19 @@ paths:
260260
tags: [control]
261261
summary: Start, stop, clear, or write a value
262262
operationId: control
263+
x-phyphox-inconsistency: [control-start-refused]
263264
description: |
264265
Sends a command to the running experiment. Always answers with
265266
`{"result": true}` or `{"result": false}`; the response says whether the
266-
command was accepted, not whether it has finished taking effect.
267+
command was accepted, not whether it has finished taking effect — except
268+
for `start`, where the result must reflect whether the measurement
269+
actually began (see `cmd=start` below).
267270
268271
- `start` — begin measuring, or begin the countdown if timed run is on.
272+
An experiment can refuse to start — most commonly because a Bluetooth
273+
device it needs is not connected yet — and the result is then `false`.
274+
A client that must be certain can also read `status.measuring` from a
275+
subsequent `/get`.
269276
- `stop` — stop measuring.
270277
- `clear` — discard buffered data, stopping the measurement if it is running.
271278
- `set` — write a single value into a buffer. This is how the remote
@@ -326,6 +333,7 @@ paths:
326333
tags: [control]
327334
summary: Start, stop, clear, or write a value (POST)
328335
operationId: controlPost
336+
x-phyphox-inconsistency: [control-start-refused]
329337
description: |
330338
Identical to `GET /control`, with the command and its parameters in the
331339
request body, e.g. `{"cmd": "set", "buffer": "height", "value": 1.87}`.
@@ -737,7 +745,10 @@ components:
737745
properties:
738746
result:
739747
type: boolean
740-
description: Whether the command was accepted.
748+
description: |
749+
Whether the command was accepted. For `cmd=start` this means the
750+
measurement actually began: a start the experiment refuses answers
751+
`false`.
741752
742753
SetResult:
743754
type: object

inconsistencies.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,37 @@
8989
A non-power-of-two number of input samples yields a different output
9090
length and different values on the two platforms; a power-of-two input
9191
gives identical results on both.
92+
93+
- id: control-start-refused
94+
title: 'A refused start still answers {"result": true}'
95+
area: remote-interface
96+
status: decided
97+
canonical: >-
98+
`/control?cmd=start` must answer `{"result": false}` when the experiment
99+
was not started. Whether a start succeeds is not something a remote client
100+
can otherwise determine: the only other signal is `status.measuring` in a
101+
subsequent `/get`, which requires a second request and a race-free moment
102+
to make it in.
103+
affects:
104+
android: >-
105+
Answers `{"result": true}` for a start the app refused. Observed on a
106+
Pixel 3 with a Bluetooth experiment whose device was not yet fully
107+
connected: the app put "The Bluetooth device is not connected. Experiment
108+
can not be started." on screen, `status.measuring` stayed false, and
109+
`/control?cmd=start` reported success.
110+
ios: >-
111+
Same shape - the result reports that the command was accepted rather than
112+
that the measurement began. Not re-verified on hardware for this entry.
113+
verified: >-
114+
2026-08-27, Android development build on a Pixel 3 against an ESP32 running
115+
the Arduino randomNumbers example (phyphox-docs device lab, ble suite).
116+
summary: >-
117+
A client that starts an experiment over the remote interface cannot tell
118+
from the answer whether it is running. The documented meaning of `result`
119+
is "whether the command was accepted", and both apps answer that
120+
literally - a start that the app then refuses, because a Bluetooth device
121+
is not connected or another precondition fails, is still reported as
122+
successful. The maintainer decided (2026-08-28) that the result must
123+
reflect whether the measurement actually started. Until both apps are
124+
fixed, poll `status.measuring` from `/get` to confirm a start rather than
125+
trusting the answer.

tools/lab/ble.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,11 @@ def record_baselines(devices, args):
11621162
remote access on, and then does the measuring and the writing itself.
11631163
Ten scenarios is ten pauses; this happens once per reference release,
11641164
not per run.
1165+
1166+
The wait is for the REMOTE API, not for a keypress: switching remote
1167+
access on is the operator's last step and is precisely what makes the
1168+
phone answer, so the tool needs no terminal of its own and the
1169+
operator needs no second action to say "done".
11651170
"""
11661171
import datetime
11671172
cfg = load_scenarios()
@@ -1198,24 +1203,23 @@ def record_baselines(devices, args):
11981203
print(f" !! {msg}")
11991204
failed.append(f"{label}: {msg}")
12001205
continue
1206+
# The operator's own actions ARE the signal, so nothing is read
1207+
# from stdin: switching remote access on is the last step, and it
1208+
# is exactly what makes the API answer. Waiting for that instead
1209+
# of for a keypress means this runs the same way whether a person
1210+
# is at a terminal or driving it from somewhere else.
12011211
print(f" On {dev_id}, by hand:\n"
12021212
f" 1. add an experiment for a Bluetooth device and pick "
12031213
f"{name!r}\n"
12041214
f" 2. let it load, then switch remote access on from the "
12051215
f"menu\n"
1206-
f" Enter to record, or 's' to skip this scenario: ", end="",
1207-
flush=True)
1208-
try:
1209-
if (input().strip().lower() or "") == "s":
1210-
failed.append(f"{label}: skipped by the operator")
1211-
continue
1212-
except EOFError:
1213-
print("\n!! not an interactive terminal - this mode needs one")
1214-
return 1
1216+
f" waiting up to {args.record_wait:.0f} s for the phone to "
1217+
f"start serving...", flush=True)
12151218

1216-
if wait_api(dev.base, args.api_wait) is None:
1217-
print(" !! the phone is not serving the remote API - is remote "
1218-
"access on, and on this network?")
1219+
if wait_api(dev.base, args.record_wait) is None:
1220+
print(" !! nothing served within the wait - skipping this one. "
1221+
"Remote access not switched on, a different network, or "
1222+
"the experiment did not load")
12191223
failed.append(f"{label}: no remote API")
12201224
continue
12211225
meta = {}

tools/lab/run.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,11 @@ def main():
356356
"automation seam, so a human connects the phone "
357357
"and switches remote access on for each scenario. "
358358
"Pass one --devices id")
359+
ap.add_argument("--record-wait", type=float, default=240.0,
360+
help="--record-ble-baseline: seconds to wait per scenario "
361+
"for the operator to connect the phone and switch "
362+
"remote access on. The API answering IS the signal; "
363+
"nothing is read from stdin")
359364
ap.add_argument("--ble-scenario", metavar="[LIB/]EXAMPLE",
360365
help="ble suite: run only this scenario (bring-up and "
361366
"debugging - the report is marked as narrowed)")

0 commit comments

Comments
 (0)