Documentation
Using the platform
Wi-Fi Channel State Information describes how a room changes a signal crossing it. The platform turns that into recordings you can study and detectors you can run, in four steps that match the workflow menu in the app: collect, analyze, build, deploy.
What you need
Two things: at least one ESP board to receive, and something for it to listen to. A receiver on its own measures nothing — CSI is a property of a link, so there has to be a transmitter whose frames the receiver can see.
- A receiver. One supported ESP board, flashed with the capture firmware and attached by USB to the machine running the device pool.
- A transmitter. Either an ordinary access point the board associates with, or a second board configured as an emitter, which gives you a known and steady frame rate instead of whatever the AP happens to send.
- A host. A machine with the boards plugged into it, running the device pool — which owns the serial ports and is the only thing that talks to a board directly. Everything else, the app and the analysis and the models, talks to the pool. See installing a device pool.
Most supported chips expose their serial port over native USB, where the wire rate is fixed by the hardware. If you attach a board through a USB-to-serial bridge instead, the flash rate becomes a real setting and the register dialog offers it; on a native-USB board that selector is shown disabled, with the reason.
Geometry matters more than hardware. A receiver and a transmitter facing each other across the space you care about will see a person crossing between them; two nodes in the same corner will mostly see each other. Relative measurements across several receivers are the ones that survive — a single absolute number from one link is dominated by per-link hardware offsets that have nothing to do with the room.
Collect
A session is one recording, with the metadata that keeps it meaningful: which boards took part, what each one's role was, the radio settings they used, and any reference sensor you ran alongside. The Collect wizard walks that in order, and a session cannot start until every part of it is answered.
- Claim the boards. A board accepts configuration and run commands only from the client holding its claim, so two operators cannot drive one board into contradictory states.
- Assign roles. Which boards receive, and which one emits. An emitter with no interface named does not radiate — the symptom is a set of receivers that all look broken at once, so the wizard requires it.
- Set the radio. Channel, bandwidth and mode have to agree across every participant. A receiver listening on one bandwidth for an emitter sending on another records nothing at all, and nothing about the empty result says why.
- Add reference data, if you have it. A camera or microphone on the same host records alongside the CSI and gives you something to check an answer against later.
- Record. Frames stream to the browser live while they are being written, so you can see whether the link is actually producing data before you record for an hour.
Watch the per-receiver rate, not the total. A sum across receivers looks healthy while one board contributes nothing, and a silent receiver in a multi-receiver recording quietly removes the cross-receiver comparisons that the analysis depends on.
Analyze
Analyze reads a finished recording: amplitude and phase over time, per subcarrier and per receiver, with the preprocessing chain applied. This is where you find out what the recording contains before asking a detector about it.
Preprocessing is part of the measurement, not a display option. The same algorithm over differently-filtered CSI is a different detector, which is why the filters applied to a recording travel with any model built from it — see the export document under the SDK.
Build
Build produces a detector. There are three kinds, and the difference is what the answer is made of.
- Deterministicclosed form
- A named algorithm over a stated preprocessing chain. It has no weights, so its export is its specification: which algorithm, at which version, with which filters. Reproducible from the document alone.
- Calibratedclosed form + fitted numbers
- The same, plus parameters fitted from a recording — for example a per-class mean and variance. The numbers travel inside the recipe as data rather than being compiled in.
- Learnedtrained weights
- An architecture fitted to labelled windows, exported as ONNX. Every offered architecture is CPU-trainable and CPU-inferable; nothing here needs a GPU.
Whichever kind you build, the result is exportable and importable as a single file. That is what makes a detector something you can move between organizations, archive, review, or hand to somebody else — rather than a row in a database you happen to own.
Deploy
A deployment binds a detector to live input, so it answers continuously instead of once per recording. You can test one before committing it: the platform runs it against a stored session and shows the outputs and the latency it took to produce them.
A detector is not ready just because it finished building. One that needs a baseline — a recording of the room while empty — cannot answer until it has one, and one that needs more receivers than the deployment has reports that rather than guessing.
Presence is the better-measured decision than headcount, and a count is only meaningful where presence has already been established. Reading a headcount from an interval whose presence detector says the room is empty is reading noise.