fix(macos-rssi-bridge): make `make start` launch the presence injector too
The 3D Observatory needs an explicit POST to /api/v1/pose/external to render a single coherent figure — without it the UI shows the placeholder five-skeleton fallback that doesn't respond to real RSSI variance, which manifests as a "frozen" figure even when the bridge is emitting frames and the sensing-server is processing them. presence_to_pose.py is the component that closes that loop (polls /aps, POSTs one pose at 10 Hz). `make start` now manages all three children (server, bridge, presence injector) under one trap, and `make stop` kills the trio. New `make run-presence` target for running the injector standalone against an already-running stack. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
82f15c112a
commit
672be201f4
|
|
@ -1,4 +1,4 @@
|
|||
.PHONY: all build build-server clean start stop test scan run run-verbose listen install-helper dashboard help
|
||||
.PHONY: all build build-server clean start stop test scan run run-verbose run-presence listen install-helper dashboard help
|
||||
|
||||
HELPER := mac_wifi
|
||||
BRIDGE := target/release/macos-rssi-bridge
|
||||
|
|
@ -20,13 +20,14 @@ all: build
|
|||
help:
|
||||
@echo "macos-rssi-bridge — Mac WiFi card → RuView sensing-server bridge"
|
||||
@echo ""
|
||||
@echo " make start build + run everything: sensing-server + bridge + open UIs"
|
||||
@echo " make stop kill any running sensing-server / bridge processes"
|
||||
@echo " make start build + run everything: sensing-server + bridge + presence + open UIs"
|
||||
@echo " make stop kill any running sensing-server / bridge / presence processes"
|
||||
@echo " make build compile mac_wifi (Swift) + macos-rssi-bridge (Rust)"
|
||||
@echo " make build-server compile the v2 sensing-server (release)"
|
||||
@echo " make scan run a single multi-BSSID scan, print JSON"
|
||||
@echo " make run start the bridge → udp://$(TARGET_HOST):$(TARGET_PORT) + http://localhost:9090"
|
||||
@echo " make run-verbose same, with per-frame stats on stderr"
|
||||
@echo " make run-presence poll bridge /aps, POST single pose to sensing-server /api/v1/pose/external"
|
||||
@echo " make dashboard open the multistatic RF tomography UI in your browser"
|
||||
@echo " make listen debug: print frames arriving on $(TARGET_PORT) (no sensing-server)"
|
||||
@echo " make test run Rust unit tests"
|
||||
|
|
@ -45,20 +46,27 @@ $(BRIDGE): src/main.rs Cargo.toml
|
|||
build-server:
|
||||
cd $(SENSING_SERVER_DIR) && cargo build --release -p wifi-densepose-sensing-server --no-default-features
|
||||
|
||||
# One-shot: builds everything, starts sensing-server + bridge under a single
|
||||
# process group, opens both UIs, waits for Ctrl-C, and kills both children
|
||||
# cleanly. The sensing-server is run with cwd=v2/ so its default --ui-path of
|
||||
# ../ui resolves; the bridge stays in this directory so ./mac_wifi works.
|
||||
# One-shot: builds everything, starts sensing-server + bridge + presence
|
||||
# injector under a single process group, opens both UIs, waits for Ctrl-C,
|
||||
# and kills all three children cleanly. The sensing-server is run with
|
||||
# cwd=v2/ so its default --ui-path of ../ui resolves; the bridge stays in
|
||||
# this directory so ./mac_wifi works.
|
||||
#
|
||||
# --source esp32 is required: the server's "auto" probe only binds UDP if it
|
||||
# detects frames *before* the bridge starts sending. The bridge IS the ESP32
|
||||
# source (synthetic, but same wire format), so pin it explicitly. Otherwise
|
||||
# the server falls back to `simulate`, never binds UDP, and you get
|
||||
# ECONNREFUSED on the bridge + a UI showing simulated (fake) motion.
|
||||
#
|
||||
# presence_to_pose.py is required for the 3D Observatory: the sensing-server
|
||||
# computes motion stats from CSI frames, but rendering a single coherent
|
||||
# figure (instead of the placeholder five-skeleton fallback) needs an
|
||||
# explicit POST to /api/v1/pose/external. The script polls the bridge's
|
||||
# /aps endpoint and translates per-AP RSSI variance into one honest pose.
|
||||
start: build build-server
|
||||
@$(MAKE) -s stop >/dev/null 2>&1 || true
|
||||
@echo "[start] sensing-server + macos-rssi-bridge → $(SENSING_UI_URL)"
|
||||
@trap 'echo; echo "[start] stopping…"; kill $$SERVER_PID $$BRIDGE_PID 2>/dev/null; wait 2>/dev/null; exit 0' INT TERM; \
|
||||
@echo "[start] sensing-server + macos-rssi-bridge + presence injector → $(SENSING_UI_URL)"
|
||||
@trap 'echo; echo "[start] stopping…"; kill $$SERVER_PID $$BRIDGE_PID $$PRESENCE_PID 2>/dev/null; wait 2>/dev/null; exit 0' INT TERM; \
|
||||
( cd $(SENSING_SERVER_DIR) && ./$(SENSING_SERVER_BIN) \
|
||||
--source esp32 --udp-port $(TARGET_PORT) ) & \
|
||||
SERVER_PID=$$!; \
|
||||
|
|
@ -67,14 +75,20 @@ start: build build-server
|
|||
./$(BRIDGE) --helper ./$(HELPER) --target-host $(TARGET_HOST) \
|
||||
--target-port $(TARGET_PORT) --interval $(INTERVAL) & \
|
||||
BRIDGE_PID=$$!; \
|
||||
echo "[start] bridge pid=$$BRIDGE_PID — dashboard: $(BRIDGE_DASHBOARD)"; \
|
||||
echo "[start] bridge pid=$$BRIDGE_PID — dashboard: $(BRIDGE_DASHBOARD) — waiting 2s for /aps…"; \
|
||||
sleep 2; \
|
||||
python3 presence_to_pose.py --bridge-url http://127.0.0.1:9090/aps \
|
||||
--server-url $(SENSING_UI_URL)/api/v1/pose/external & \
|
||||
PRESENCE_PID=$$!; \
|
||||
echo "[start] presence injector pid=$$PRESENCE_PID — feeding /api/v1/pose/external @ 10 Hz"; \
|
||||
( sleep 2; open $(SENSING_UI_URL) 2>/dev/null; open $(BRIDGE_DASHBOARD) 2>/dev/null ) & \
|
||||
echo "[start] press Ctrl-C to stop both"; \
|
||||
echo "[start] press Ctrl-C to stop all three"; \
|
||||
wait
|
||||
|
||||
stop:
|
||||
-@pkill -f "$(SENSING_SERVER_BIN)" 2>/dev/null && echo "[stop] sensing-server killed" || echo "[stop] no sensing-server"
|
||||
-@pkill -f "$(BRIDGE)" 2>/dev/null && echo "[stop] bridge killed" || echo "[stop] no bridge"
|
||||
-@pkill -f "presence_to_pose.py" 2>/dev/null && echo "[stop] presence injector killed" || echo "[stop] no presence injector"
|
||||
|
||||
test:
|
||||
cargo test --release
|
||||
|
|
@ -90,6 +104,12 @@ run-verbose: build
|
|||
./$(BRIDGE) --helper ./$(HELPER) --target-host $(TARGET_HOST) \
|
||||
--target-port $(TARGET_PORT) --interval $(INTERVAL) --verbose
|
||||
|
||||
# Standalone presence injector. Requires the bridge to already be running
|
||||
# (so /aps responds) and the sensing-server to be up on $(SENSING_UI_URL).
|
||||
run-presence:
|
||||
python3 presence_to_pose.py --bridge-url http://127.0.0.1:9090/aps \
|
||||
--server-url $(SENSING_UI_URL)/api/v1/pose/external --verbose
|
||||
|
||||
# Open the RF tomography dashboard. Assumes the bridge is already running
|
||||
# (start it with `make run` or `make run-verbose` in another terminal).
|
||||
dashboard:
|
||||
|
|
|
|||
|
|
@ -39,19 +39,30 @@ Toolchain: `swiftc` 6.0+ and Cargo 1.80+. Tested on macOS 26 (Tahoe) arm64.
|
|||
|
||||
## Run
|
||||
|
||||
One command — builds both, launches the sensing-server and the bridge,
|
||||
One command — builds everything, launches the full three-process pipeline,
|
||||
opens both UIs, and cleans up on Ctrl-C:
|
||||
|
||||
```bash
|
||||
make start # → sensing-server (:8080) + bridge (:9090/dashboard)
|
||||
make stop # kill any leftover sensing-server / bridge process
|
||||
make start # → sensing-server (:8080) + bridge (:9090/dashboard) + presence injector
|
||||
make stop # kill any leftover process from the trio
|
||||
```
|
||||
|
||||
Or run them manually in two terminals if you want to see logs side-by-side.
|
||||
In one terminal, the sensing-server (provides UI + UDP receiver):
|
||||
The pipeline is three processes:
|
||||
|
||||
1. **sensing-server** — UDP receiver, motion stats, WebSocket stream, UI
|
||||
(pinned to `--source esp32` so it binds UDP and consumes the bridge's
|
||||
frames instead of falling back to its simulation generator).
|
||||
2. **macos-rssi-bridge** — Swift scan → Rust UDP emitter → ESP32 frame format.
|
||||
3. **presence_to_pose.py** — polls the bridge's `/aps` endpoint and POSTs a
|
||||
single honest pose to `/api/v1/pose/external` so the Observatory renders
|
||||
one figure modulated by RSSI variance instead of the placeholder
|
||||
five-skeleton fallback.
|
||||
|
||||
Or run each manually if you want logs side-by-side. In one terminal, the
|
||||
sensing-server (UI + UDP receiver):
|
||||
|
||||
```bash
|
||||
cd ../../v2 && cargo run --release -p wifi-densepose-sensing-server --no-default-features
|
||||
cd ../../v2 && cargo run --release -p wifi-densepose-sensing-server --no-default-features -- --source esp32
|
||||
# UI: http://localhost:8080
|
||||
# WS: ws://localhost:8765/ws/sensing
|
||||
```
|
||||
|
|
@ -63,6 +74,12 @@ make run # default: target 127.0.0.1:5005, 1.5 s scan interval
|
|||
# or: make run-verbose for per-frame stats on stderr
|
||||
```
|
||||
|
||||
In a third, the presence injector (only needed for the 3D Observatory pose):
|
||||
|
||||
```bash
|
||||
make run-presence # polls :9090/aps, posts a pose to :8080/api/v1/pose/external
|
||||
```
|
||||
|
||||
Open http://localhost:8080 and walk around. Motion should register within a
|
||||
few seconds (the pipeline needs ~5 frames of baseline before it'll classify).
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue