docs: design spec for the E-1608 network scan
This commit is contained in:
1 parent
a8e12b26a2
commit
19b7f25b82
1 file changed
+63
@@ -0,0 +1,63 @@
|
||||
# E-1608 network scan -- design
|
||||
|
||||
Date: 2026-11-02. Status: approved in conversation, awaiting written-spec review.
|
||||
|
||||
## Goal
|
||||
|
||||
The E-1608 connection form gets a "Scan network" row that finds boards and fills the address or the
|
||||
MAC from a click. Today a user must already know the address, or give a MAC and rely on a lookup.
|
||||
|
||||
## Finding (tested on a real board, 2026-11-02)
|
||||
|
||||
The board was at 169.254.88.75 on `net0`; the default route is `wlan0`. A `D` probe sent to
|
||||
255.255.255.255 with no binding found nothing (it left through `wlan0`). The same probe sent with
|
||||
`SO_BINDTODEVICE net0`, or bound to the interface address, or sent to a directed broadcast, or by
|
||||
unicast, was answered (64 bytes, first byte `D`). So a single limited broadcast is not enough on a
|
||||
host with several interfaces; the existing "find by MAC" lookup has the same flaw.
|
||||
|
||||
## Discovery layer (`e1608_link.{hpp,cpp}`)
|
||||
|
||||
- `class Scan` (non-blocking, one instance per scan): `Scan(port)` enumerates up, non-loopback IPv4
|
||||
interfaces with `IFF_BROADCAST` (`getifaddrs`), opens one UDP socket per interface bound to it
|
||||
(`SO_BINDTODEVICE`, falling back to binding the interface address if the call is refused), enables
|
||||
`SO_BROADCAST`, and sends `D` to 255.255.255.255 on each. `poll()` drains every socket without
|
||||
blocking and returns the devices found so far (E-1608 product id only, one entry per MAC, the same
|
||||
reply parsing as `discover`). `done(ms)` is not part of the class: the caller owns the clock.
|
||||
- `discover()` keeps its signature. A new overload or helper `discover_broadcast(port, wait_ms)` is
|
||||
`Scan` plus a blocking wait. `E1608Source`'s lookup uses it when the subnet is empty; a given
|
||||
subnet still uses `sweep_targets` + `discover` as today.
|
||||
- An interface that cannot be opened or sent on is skipped, never an error; no interfaces is an empty
|
||||
result.
|
||||
|
||||
## Form (`e1608_kind.cpp`)
|
||||
|
||||
- At the top of the Connection expander, an `AdwActionRow` "Scan network" with a text suffix button
|
||||
"Scan" (widget name `e1608-scan`). The row subtitle reads "Scanning...", "N boards found" or
|
||||
"No board found". No theme icons.
|
||||
- A scan starts a `Scan` on the port in the Port field and a 50 ms `g_timeout_add` poll for about
|
||||
1.5 s. There is no thread: the project has exactly two. The timer is removed when the form is
|
||||
destroyed (`Form::alive` guard plus the destroy hook) and when a new scan starts.
|
||||
- Each device found becomes an `AdwActionRow` in the Connection expander right after the scan row,
|
||||
replacing the previous results. Title: IP. Subtitle: MAC. Activating the row fills Address and
|
||||
clears MAC and Subnet. A suffix text button "Use MAC" (`e1608-use-mac`) fills MAC and clears
|
||||
Address and Subnet. Fill is done under the form's `updating` guard, then `changed` fires once.
|
||||
- Result rows are not read or written by the session: only the filled fields persist.
|
||||
- The description line mentions the scan.
|
||||
|
||||
## Verification
|
||||
|
||||
- A scan probe (env var in the existing pattern): starts against `tools/mock_e1608.py` on a
|
||||
loopback-reachable port, presses the scan button, and prints `[e1608] scan: found=N ip=... mac=...
|
||||
fill_addr=1 fill_mac=1 ok=1`, covering both fills and that the results are replaced on a rescan.
|
||||
If the sandbox refuses the broadcast, the line says so and the limitation is documented, not claimed.
|
||||
- A manual run of the scan against the real board, recorded in the README.
|
||||
- Baselines unchanged: 3 warnings clean, `gtk warnings: 0`, no `Gtk-CRITICAL`.
|
||||
|
||||
## Docs
|
||||
|
||||
`README.md` (E-1608 paragraph), `docs/claude/{build-and-run,verification,probe-readings,architecture}.md`.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Remembering scan results across runs; scanning other subnets than the host's interfaces (the
|
||||
`subnet` sweep field remains for that); a worker thread.
|
||||
Reference in new issue
Block a user