mirror of
https://github.com/ruvnet/RuView
synced 2026-06-20 12:03:19 +00:00
c84ea39e62d14dcafe61fc80d357dfe0349462cd
17 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0c2b1c16cc |
fix: ESP32 vitals over-count + presence flicker (#998/#996) + Observatory per-person position/motion (#1050) (#1060)
* fix(firmware): gate phantom persons + add presence hysteresis (#998, #996) Two ESP32 edge-vitals logic bugs in edge_processing.c. Both are robustness/logic fixes — NOT validated-accuracy claims. True count/PCK vs labelled ground truth remains hardware/data-gated (COM9 ESP32-S3). #998 — n_persons over-counted (reported 4 for one person): update_multi_person_vitals() split top-K subcarriers into top_k_count/2 groups and marked EVERY group active, so one body's multipath always read the full EDGE_MAX_PERSONS. Added two pure, host-testable helpers: - count_distinct_persons(): per-group energy gate (EDGE_PERSON_MIN_ENERGY_RATIO) + spatial dedup (EDGE_PERSON_MIN_SC_SEP) so weak/adjacent multipath groups don't count as separate bodies. Strongest group always counts (>=1). - person_count_debounce(): a gated count must hold EDGE_PERSON_PERSIST_FRAMES consecutive frames before it's emitted, so a single noisy frame can't promote a phantom. The active flags now mark only the strongest stable_count groups. #996 — presence flag flickered at ~50cm despite high presence_score: the bare `score > threshold` compare chattered on a noisy score (field-observed 2.6-26.7 frame-to-frame). Replaced with a Schmitt trigger + clear-debounce (presence_flag_update): assert above threshold, hold in the dead band down to threshold * EDGE_PRESENCE_HYST_RATIO, clear only after EDGE_PRESENCE_CLEAR_FRAMES consecutive sub-low frames. presence_score itself is unchanged and still emitted for consumer-side thresholding. All thresholds are named, documented constants in edge_processing.h. Firmware builds clean for esp32s3 (idf.py build RC=0). Co-Authored-By: claude-flow <ruv@ruv.net> * test(firmware): host C99 tests for vitals count + presence logic (#998, #996) test/test_vitals_count_presence.c pins the two fixes with deterministic host-buildable tests (no ESP-IDF needed). 13 cases / 22 assertions, all passing under gcc 13 -Wall -Wextra: #998 count gate: single strong signature + multipath -> count==1; two well-separated -> 2; two strong-but-adjacent -> 1 (dedup); no signal -> 0; three well-separated -> 3. #998 debounce: transient spike rejected; sustained change accepted; flapping count stays stable. #996 presence: dithering trace -> stable flag (no flicker); brief dips held by clear-debounce; genuine departure clears within hold window; dead-band holds state. The named tuning constants are #include'd from the real edge_processing.h so the test and firmware can never disagree on thresholds. `make run_vitals` / `make host_tests` added; binaries gitignored. Hardware-gated caveat documented in the test header: these pin the decision LOGIC; the exact energy/separation/hysteresis values that best match a real room vs labelled occupancy remain on-device tuning. Co-Authored-By: claude-flow <ruv@ruv.net> * docs: record ESP32 vitals count/presence fixes (#998, #996) CHANGELOG [Unreleased] Fixed: root cause + fix + named constants + test + explicit hardware/data-gated caveat for both bugs. ADR-021 Implementation Notes: dated 2026-06 entry noting the edge-path person-count + presence-flicker fixes are boolean/count emission-logic fixes, not a validated-accuracy claim; thresholds pending on-device calibration. Co-Authored-By: claude-flow <ruv@ruv.net> * fix(sensing-server): emit real field-derived person position/motion to /ws/sensing (#1050) The Observatory 3D figure never animated because the sensing_update WS frame carried no per-person position/motion_score/pose — only image-space keypoints. The FigurePool/PoseSystem (and demo-data.js's own contract) animate each figure from persons[i].position (room-world), .motion_score (0..100), and .pose; none were on the live stream. Honest scope (Case 2): the pipeline has no calibrated per-person room localizer or per-person skeletal pose. New field_localize module extracts the strongest peak(s) from the real signal_field grid (subcarrier variances x motion-band power) and maps the peak cell to Observatory world coords with the exact _buildSignalField transform. motion_score is the measured motion_band_power passed through; pose is set only from a real aggregate posture estimate, else None (never a fabricated skeleton). Empty/below-threshold field -> persons: [] (no phantom); present person with no resolvable peak keeps position [0,0,0], not invented coords. attach_field_positions runs after the tracker step at all five broadcast sites. New position/motion_score/pose fields added to both PersonDetection structs. No UI change needed — the Observatory already reads these fields. Tests: field_localize peak/coordinate/empty/separation units + observatory_persons_field_position_tests (known-peak -> emitted position, empty-room -> no phantom, pose real-or-None, below-threshold honesty). sensing-server bin 441->451, 0 failed. Co-Authored-By: claude-flow <ruv@ruv.net> * docs(changelog): record #1050 Observatory persons position/motion fix Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
6778c708ff |
chore(gitignore): exclude MM-Fi dataset archives (assets/MM-Fi/*.zip)
The MM-Fi benchmark environment archives (E01-E04.zip) are large data files fetched separately for evaluation — they must never be committed. Also keeps the existing aether-arena/staging/ private-staging exclusion. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
e22a24714a |
firmware/esp32-hello-world: ESP32-C6 target and ESP-IDF v6 build fixes (#524)
- Default sdkconfig.defaults to esp32c6 - Fix removed SOC_* macros for ESP-IDF v6; probe_peripherals split for S3 vs C6. - Banner and WiFi/BLE/power strings are target-aware; add CHIP_ESP32C6 name. - Ignore esp32-hello-world/sdkconfig.old from idf.py set-target. Signed-off-by: Chaitanya Tata <chaitanya@dotstarconsulting.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
7393cc2b73 |
feat(rvcsi): rvcsi-runtime composition + rvcsi-node (napi-rs) + rvcsi-cli + @ruv/rvcsi TS SDK
- rvcsi-runtime — the composition layer (no FFI): CaptureRuntime (CsiSource + validate_frame + SignalPipeline + EventPipeline, with next_validated_frame / next_clean_frame / drain_events / health) plus one-shot helpers (summarize_capture → CaptureSummary, decode_nexmon_records, events_from_capture, export_capture_to_rf_memory, rf_memory_self_check). 10 tests. - rvcsi-node — the napi-rs seam (cdylib+rlib, build.rs runs napi_build::setup): thin #[napi] wrappers over rvcsi-runtime — rvcsiVersion / nexmonShimAbiVersion / nexmonDecodeRecords / inspectCaptureFile / eventsFromCaptureFile / exportCaptureToRfMemory + an RvcsiRuntime streaming class. Everything that crosses the boundary is a validated/normalized rvCSI struct serialized to JSON (D6). deny(clippy::all). - @ruv/rvcsi npm package (package.json + index.js + index.d.ts + README + __test__/api.test.cjs) — curated JS surface that JSON-parses the addon's output into plain CsiFrame/CsiWindow/CsiEvent/SourceHealth/CaptureSummary objects; lazy native-addon load with a helpful "not built" error. - rvcsi-cli — the `rvcsi` binary: record (Nexmon dump → .rvcsi, validating), inspect, replay, stream, events, health, calibrate (v0 baseline), export ruvector. 7 tests exercising every subcommand against in-memory captures. - rvcsi-cli no longer depends on rvcsi-node (a binary can't link the napi addon); the shared logic moved to rvcsi-runtime. .gitignore: ignore the generated *.node / binding.js / binding.d.ts / npm/ under rvcsi-node. All rvcsi crates: build together OK, clippy-clean, 140 unit/integration tests + 2 doctests, 0 failures (core 29, dsp 28, events 18, adapter-file 20+1, adapter-nexmon 9, ruvector 20+1, runtime 10, cli 7). https://claude.ai/code/session_01CdYAPvRTjcch6YrYf42n1z |
||
|
|
0943a32248 |
feat: Real-time dense point cloud from camera + WiFi CSI (#405)
* Add wifi-densepose-pointcloud: real-time dense point cloud from camera + WiFi CSI
New crate with 5 modules:
- depth: monocular depth estimation + 3D backprojection (ONNX-ready, synthetic fallback)
- pointcloud: Point3D/ColorPoint types, PLY export, Gaussian splat conversion
- fusion: WiFi occupancy volume → point cloud + multi-modal voxel fusion
- stream: HTTP + Three.js viewer server (Axum, port 9880)
- main: CLI with serve/capture/demo subcommands
Demo output: 271 WiFi points + 19,200 depth points → 4,886 fused → 1,718 Gaussian splats.
Serves interactive 3D viewer at http://localhost:9880 with Three.js orbit controls.
ADR-SYS-0021 documents the architecture for camera + WiFi CSI dense point cloud pipeline.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Optimize pointcloud: larger splat voxels, smaller responses, faster fusion
- Gaussian splat voxel size: 0.10 → 0.15 (42% fewer splats: 1718 → 994)
- Splat response: 399 KB → 225 KB (44% smaller)
- Pipeline: 22.2ms mean (100 runs, σ=0.3ms)
- Cloud API: 1.11ms avg, 905 req/s
- Splats API: 1.39ms avg, 719 req/s
- Binary: 1.0 MB arm64 (Mac Mini), tested
Co-Authored-By: claude-flow <ruv@ruv.net>
* Complete implementation: camera capture, WiFi CSI receiver, training pipeline
Three new modules added to wifi-densepose-pointcloud:
1. camera.rs — Cross-platform camera capture
- macOS: AVFoundation via Swift, ffmpeg avfoundation
- Linux: V4L2, ffmpeg v4l2
- Camera detection, listing, frame capture to RGB
- Graceful fallback to synthetic data when no camera
2. csi.rs — WiFi CSI receiver for ESP32 nodes
- UDP listener for CSI JSON frames from ESP32
- Per-link attenuation tracking with EMA smoothing
- Simplified RF tomography (backprojection to occupancy grid)
- Test frame sender for development without hardware
- Ready for real ESP32 CSI data from ruvzen
3. training.rs — Calibration and training pipeline
- Depth calibration: grid search over scale/offset/gamma
- Occupancy training: threshold optimization for presence detection
- Ground truth reference points for depth RMSE measurement
- Preference pair export (JSONL) for DPO training on ruOS brain
- Brain integration: submit observations as memories
- Persistent calibration files (JSON)
New CLI commands:
ruview-pointcloud cameras # list available cameras
ruview-pointcloud train # run calibration + training
ruview-pointcloud csi-test # send test CSI frames
ruview-pointcloud serve --csi # serve with live CSI input
All tested: demo, training (10 samples, 4 reference points, 3 pairs),
CSI receiver (50 test frames), server API.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Fix viewer: replace WebSocket with fetch polling
Co-Authored-By: claude-flow <ruv@ruv.net>
* Wire live camera into server — real-time updating point cloud
- Server captures from /dev/video0 at 2fps via ffmpeg
- Background tokio task refreshes cloud + splats every 500ms
- Viewer polls /api/splats every 500ms, only updates on new frame
- Shows 🟢 LIVE / 🔴 DEMO indicator
- Camera position set for first-person view (looking forward into scene)
- Downsample 4x for performance (19,200 points per frame)
- Graceful fallback to demo data if camera capture fails
Co-Authored-By: claude-flow <ruv@ruv.net>
* Add MiDaS GPU depth, serial CSI reader, full sensor fusion
- MiDaS depth server: PyTorch on CUDA, real monocular depth estimation
- Rust server calls MiDaS via HTTP for neural depth (falls back to luminance)
- Serial CSI reader for ESP32 with motion detection + presence estimation
- CSI disabled by default (RUVIEW_CSI=1 to enable) — serial reader needs baud config
- Edge-enhanced depth for better object boundaries
- All sensors wired: camera, ESP32 CSI, mmWave (CSI gated until serial fixed)
Co-Authored-By: claude-flow <ruv@ruv.net>
* Complete 7-component sensor fusion pipeline (all working)
1. ADR-018 binary parser — decodes ESP32 CSI UDP frames, extracts I/Q subcarriers
2. WiFlow pose — 17 COCO keypoints from CSI (186K param model loaded)
3. Camera depth — MiDaS on CUDA + luminance fallback
4. Sensor fusion — camera depth + CSI occupancy grid + skeleton overlay
5. RF tomography — ISTA-inspired backprojection from per-node RSSI
6. Vital signs — breathing rate from CSI phase analysis
7. Motion-adaptive — skip expensive depth when CSI shows no motion
Live results: 510 CSI frames/session, 17 keypoints, 26% motion, 40 BPM breathing.
Both ESP32 nodes provisioned to send CSI to 192.168.1.123:3333.
Magic number fix: supports both 0xC5110001 (v1) and 0xC5110006 (v6) frames.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Add brain bridge — sparse spatial observation sync every 60s
Stores room scan summaries, motion events, and vital signs
in the ruOS brain as memories. Only syncs every 120 frames
(~60 seconds) to keep the brain sparse and optimized.
Categories: spatial-observation, spatial-motion, spatial-vitals.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Update README + user guide with dense point cloud features
Added pointcloud section to README (quick start, CLI, performance).
Added comprehensive user guide section: setup, sensors, commands,
pipeline components, API endpoints, training, output formats,
deep room scan, ESP32 provisioning.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Add ruview-geo: geospatial satellite integration (11 modules, 8/8 tests)
New crate with free satellite imagery, terrain, OSM, weather, and brain integration.
Modules: types, coord, locate, cache, tiles, terrain, osm, register, fuse, brain, temporal
Tests: 8 passed (haversine, ENU roundtrip, tiles, HGT parse, registration)
Validation: real data — 43.49N 79.71W, 4 Sentinel-2 tiles, 2°C weather, brain stored
Data sources (all free, no API keys):
- EOX Sentinel-2 cloudless (10m satellite tiles)
- SRTM GL1 (30m elevation)
- Overpass API (OSM buildings/roads)
- ip-api.com (geolocation)
- Open Meteo (weather)
ADR-044 documents architecture decisions.
README.md in crate subdirectory.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Update ADR-044: add Common Crawl WET, NASA FIRMS, OpenAQ, Overture Maps sources
Extended geospatial data sources leveraging ruvector's existing web_ingest
and Common Crawl support for hyperlocal context.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Fix OSM/SRTM queries, add change detection + night mode
- OSM: use inclusive building filter with relation query and 25s timeout
- SRTM: switch to NASA public mirror with viewfinderpanoramas fallback
- Add detect_tile_changes() for pixel-diff satellite change detection
- Add is_night() solar-declination model for CSI-only night mode
- 6 new unit tests (night mode + tile change detection)
Co-Authored-By: claude-flow <ruv@ruv.net>
* Enhance viewer: skeleton overlay, weather, buildings, better camera
Add COCO skeleton rendering with yellow keypoint spheres and white bone
lines, info panel sections for weather/buildings/CSI rate/confidence,
overhead camera at (0,2,-4), and denser point size with sizeAttenuation.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Add CSI fingerprint DB + night mode detection
Co-Authored-By: claude-flow <ruv@ruv.net>
* Fix ADR-044 numbering conflict, update geo README
Renumbered provisioning tool ADR from 044 to 050 to avoid conflict
with geospatial satellite integration ADR-044.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Clean up warnings: suppress dead_code for conditional pipeline modules
Removes unused imports/variables via cargo fix and adds #[allow(dead_code)]
for modules used conditionally at runtime (CSI, depth, fusion, serial).
Pointcloud: 28 → 0 warnings. Geo: 2 → 0 warnings. 8/8 tests pass.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Fix PR #405 blockers: async runtime panic, crate rename, path traversal, brain URL config
- brain_bridge.rs: replace `Handle::current().block_on(...)` inside async fn
with `.await` (was a guaranteed "runtime within runtime" panic). Brain URL
now read from RUVIEW_BRAIN_URL env var (default http://127.0.0.1:9876),
logged once via OnceLock.
- wifi-densepose-geo: rename Cargo package from `ruview-geo` to
`wifi-densepose-geo` to match directory and workspace conventions. Update
all use sites (tests/examples/README). Same env-var pattern for brain URL
in brain.rs + temporal.rs.
- training.rs: add sanitize_data_path() rejecting `..` components and
safe_join() that canonicalises + enforces base-dir containment on every
write (calibration.json, samples.json, preference_pairs.jsonl,
occupancy_calibration.json). Defence-in-depth check also in main.rs
before TrainingSession::new.
- osm.rs: clamp Overpass radius to MAX_RADIUS_M=5000m; return Err beyond
that. Add parse_overpass_json() that rejects malformed payloads
(missing top-level `elements` array).
Co-Authored-By: claude-flow <ruv@ruv.net>
* csi_pipeline: rename WiFlow stub to heuristic_pose_from_amplitude, decouple UDP
Blocker 3 (PR #405 review): The "WiFlow inference" path was a stub that
built a model from empty weight vectors and synthesised keypoints from
amplitude energy. Presenting this as "WiFlow inference" was misleading.
- Rename WiFlowModel to PoseModelMetadata (empty tag struct; we only care
if the on-disk file exists)
- Rename load_wiflow_model() -> detect_pose_model_metadata() and log
"amplitude-energy heuristic enabled/disabled" (no "WiFlow" claim)
- Rename estimate_pose() -> heuristic_pose_from_amplitude() with
prominent `STUB:` doc comment saying this is NOT a trained model
Blocker 4 (PR #405 review): The UDP receiver held the shared Arc<Mutex>
across a synchronous process_frame() call, starving HTTP handlers.
- Introduce a std::sync::mpsc channel between the UDP thread (which only
parses + pushes) and a dedicated processor thread (which locks only
briefly around a single process_frame). HTTP snapshots via
get_pipeline_output no longer contend with the socket read loop.
Also:
- Move ADR-018 parser to parser.rs (see next commit); csi_pipeline re-exports
- send_test_frames now uses parser::build_test_frame for synthetic frames
- Log a one-line node stats summary every 500 frames (reads every public
CsiFrame field on the runtime path)
Co-Authored-By: claude-flow <ruv@ruv.net>
* Extract ADR-018 parser into parser.rs + wire Fingerprint CLI
File-split (strong concern #9 in PR #405 review): csi_pipeline.rs was 602
LOC; extract the pure-function ADR-018 parser + synthetic frame builder
into src/parser.rs. Inline unit tests in parser.rs cover:
- 0xC5110001 (raw CSI, v1) roundtrip
- 0xC5110006 (feature state, v6) roundtrip
- wrong magic is rejected
- truncated header is rejected
- truncated payload is rejected
main.rs: expose `fingerprint NAME [--seconds N]` subcommand wiring
record_fingerprint() (this was the only caller needed to make the public
API non-dead on the runtime path). Also:
- Replace `--host/--port` + external `--csi` with a single `--bind`
defaulting to loopback (`127.0.0.1:9880`) — addresses strong concern
#7 about exposing camera/CSI/vitals by default.
- Update synthetic `csi-test` to target UDP 3333 (matching the ADR-018
listener) and use the shared parser::build_test_frame.
- Defence-in-depth: call training::sanitize_data_path on the expanded
--data-dir before TrainingSession::new does the same.
Co-Authored-By: claude-flow <ruv@ruv.net>
* stream: extract viewer HTML to viewer.html, default bind to loopback
Strong concern #7 (PR #405): default HTTP bind leaked camera/CSI/vitals
to the LAN. The `serve` fn now takes a single `bind` arg and prints a
loud WARNING when bound outside loopback.
Strong concern #10 (PR #405): embedded HTML+JS was ~220 LOC of the 418
LOC stream.rs. Moved the markup verbatim into viewer.html and inlined
via `include_str!("viewer.html")`. Also:
- Drop the #![allow(dead_code)] crate-level silencing (reviewer point
#11). Remove the now-unused AppState.csi_pipeline field.
- capture_camera_cloud_with_luminance returns the mean luminance of the
captured frame; the background loop feeds that to
CsiPipelineState::set_light_level so the night-mode flag actually
toggles at runtime (previously it could only be set from tests).
Net effect on file size: stream.rs 418 → 232 LOC.
Co-Authored-By: claude-flow <ruv@ruv.net>
* Dead-code cleanup + tests for fusion/depth/OSM/training/fingerprinting
Reviewer point #11 (PR #405): remove the `#![allow(dead_code)]`
silencing added in
|
||
|
|
7a75277d58 |
chore: add data/ and models/ to .gitignore
Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
a4bd2308b7 |
feat: ADR-069 ESP32 CSI → Cognitum Seed RVF pipeline (v0.5.4-esp32)
Hardware-validated pipeline connecting ESP32-S3 CSI sensing to Cognitum Seed (Pi Zero 2 W) edge intelligence appliance via 8-dim feature vectors. Firmware: - New 48-byte feature vector packet (magic 0xC5110003) at 1 Hz with normalized presence, motion, breathing, heart rate, phase variance, person count, fall detection, and RSSI - Compressed frame magic reassigned 0xC5110003 → 0xC5110005 - Guard against uninitialized s_top_k read when count=0 Bridge (scripts/seed_csi_bridge.py): - UDP→HTTPS ingest with bearer token, hash-based vector IDs - --validate (kNN), --stats, --compact, --allowed-sources modes - NaN/inf rejection, retry logic, SEED_TOKEN env var support Validated on live hardware: - 941 vectors ingested, 100% kNN exact match - Witness chain SHA-256 verified (1,325 entries) - 1,463 Rust tests passed, Python proof VERDICT: PASS Research: 26 docs covering Arena Physica, Maxwell's equations in WiFi sensing, SOTA survey 2025-2026, GOAP implementation plan Security: removed hardcoded credentials, added NVS patterns to .gitignore, source IP filtering, NaN validation Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
1d4af7c757 |
chore: add runtime artifacts to .gitignore and untrack them
Remove from index: daemon.pid, vectors.db, memory.db, pending-insights.jsonl, session state, node_modules. These are machine-specific runtime artifacts that should never have been committed. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
8b57a6f64c |
docs: update README with ADR-045–048, Observatory, adaptive classifier, AMOLED display
- Update ADR count from 44 to 48 - Add adaptive classifier (ADR-048) to Intelligence features - Add Observatory visualization (ADR-047) and AMOLED display (ADR-045) to Deployment features - Update screenshot to v2-screen.png - Add ADR-045 (AMOLED), ADR-046 (Android TV), ADR-047 (Observatory), DDD deployment model - Add AMOLED display firmware (display_hal, display_task, display_ui, LVGL config) - Add Observatory UI (13 Three.js modules, CSS, HTML entry point) - Add trained adaptive model JSON - Update .gitignore for managed_components, recordings, .swarm Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
3b74798ba6 |
chore: add CLAUDE.local.md to .gitignore
Contains WiFi credentials and machine-specific paths — must never be committed. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
e94c7056f2 |
feat: add ADR-042 CHCI protocol, 24 new edge modules, README restructure
- ADR-042: Coherent Human Channel Imaging (non-CSI sensing protocol) with DDD domain model (6 bounded contexts) - 24 new WASM edge modules: medical (5), retail (5), security (5), building (5), industrial (5), exotic (8) - README: plain-language rewrites, moved detail sections below TOC, added edge module links to use case tables, firmware release docs - User guide: firmware release table, edge intelligence documentation - .gitignore: added rules for wasm, esp32 temp files, NVS binaries - WASM edge crate: cargo config, integration tests, module registry Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
4b1005524e |
feat: complete vendor repos, add edge intelligence and WASM modules
- Add 154 missing vendor files (gitignore was filtering them) - vendor/midstream: 564 files (was 561) - vendor/sublinear-time-solver: 1190 files (was 1039) - Add ESP32 edge processing (ADR-039): presence, vitals, fall detection - Add WASM programmable sensing (ADR-040/041) with wasm3 runtime - Add firmware CI workflow (.github/workflows/firmware-ci.yml) - Add wifi-densepose-wasm-edge crate for edge WASM modules - Update sensing server, provision.py, UI components Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
915943cef4 |
feat: ESP32 CSI MAC address filtering with NVS/Kconfig support (#101)
* feat: add MAC address filter for ESP32 CSI collection In multi-AP environments, CSI frames from different access points get mixed together, corrupting the sensing signal. Add transmitter MAC filtering so only frames from a specified AP are processed. Implementation: - csi_collector: filter in wifi_csi_callback by comparing info->mac against configured MAC; log transmitter MAC in periodic debug output - csi_collector_set_filter_mac(): runtime API to enable/disable filter - Kconfig: CSI_FILTER_MAC option (format "AA:BB:CC:DD:EE:FF") - NVS: "filter_mac" 6-byte blob overrides Kconfig at runtime - nvs_config: parse Kconfig MAC string at boot, load NVS override - main: apply filter from config after csi_collector_init() When no filter is configured (default), behavior is unchanged — all transmitter MACs are accepted for backward compatibility. Fixes #98 Co-Authored-By: claude-flow <ruv@ruv.net> * chore: add CLAUDE.local.md to .gitignore Local machine configuration (ESP-IDF paths, COM port, build instructions) should not be committed to the repository. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
e2320e8e4b |
feat(wifiscan): add Rust macOS + Linux adapters, fix Python byte counters
- Add MacosCoreWlanScanner (macOS): CoreWLAN Swift helper adapter with synthetic BSSID generation via FNV-1a hash for redacted MACs (ADR-025) - Add LinuxIwScanner (Linux): parses `iw dev <iface> scan` output with freq-to-channel conversion and BSS stanza parsing - Both adapters produce Vec<BssidObservation> compatible with the existing WindowsWifiPipeline 8-stage processing - Platform-gate modules with #[cfg(target_os)] so each adapter only compiles on its target OS - Fix Python MacosWifiCollector: remove synthetic byte counters that produced misleading tx_bytes/rx_bytes data (set to 0) - Add compiled Swift binary (mac_wifi) to .gitignore Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
92a5182dc3 |
feat(adr-018): ESP32-S3 firmware, Rust aggregator, and live CSI pipeline
Complete end-to-end WiFi CSI capture pipeline verified on real hardware: - ESP32-S3 firmware: WiFi STA + promiscuous mode CSI collection, ADR-018 binary serialization, UDP streaming at ~20 Hz - Rust aggregator CLI binary (clap): receives UDP frames, parses with Esp32CsiParser, prints per-frame summary (node, seq, rssi, amp) - UDP aggregator module with per-node sequence tracking and drop detection - CsiFrame bridge to detection pipeline (amplitude/phase/SNR conversion) - Python ESP32 binary parser with UDP reader - Presence detection confirmed: motion score 10/10 from live CSI variance Hardware verified: ESP32-S3-DevKitC-1 (CP2102, MAC 3C:0F:02:EC:C2:28), Docker ESP-IDF v5.2 build, esptool 5.1.0 flash, 20 Rust + 6 Python tests pass. Co-Authored-By: claude-flow <ruv@ruv.net> |
||
|
|
f3c77b1750 |
Add WiFi DensePose implementation and results
- Implemented the WiFi DensePose model in PyTorch, including CSI phase processing, modality translation, and DensePose prediction heads. - Added a comprehensive training utility for the model, including loss functions and training steps. - Created a CSV file to document hardware specifications, architecture details, training parameters, performance metrics, and advantages of the model. |
||
|
|
6cab230908 | Initial commit |