Show HN: WiSense – WiFi-based human sensing in Python, no camera required WiSense v0.1.0, an open-source Python library for WiFi-based human sensing using Channel State Information (CSI), has been released on GitHub by developer collabray, enabling presence detection, fall detection, breathing-rate estimation, activity classification, and occupant counting without cameras, cloud APIs, or PyTorch/CUDA at runtime. The statistical detection paths are fully implemented and tested against synthetic CSI data, but the library has not yet been validated on real ESP32 hardware, and no trained ONNX model files ship with the repository. WiFi CSI Channel State Information human sensing for Python -- presence, falls, breathing rate, coarse activity, and occupant count, without a camera, without a cloud API, and without PyTorch/CUDA at runtime. python from wisense.core import FileCSISource, CSIBuffer, calibrate from wisense.presence import PresenceDetector with FileCSISource "capture.csv", realtime=True as source: profile = calibrate source, duration seconds=30 empty-room baseline with FileCSISource "capture.csv" as source: buffer = CSIBuffer capacity=256 buffer.fill from source source, max frames=64 result = PresenceDetector .detect buffer.snapshot , calibration=profile print result.present, result.confidence v0.1.0, alpha. The statistical non-ML detection path for every feature module below is fully implemented, tested, and works without any model file. The optional ONNX inference upgrade path is fully implemented against onnxruntime.InferenceSession , but no trained model files ship with this repository -- see Model Files model-files below. This has been validated with unit and integration tests against synthetic CSI data, but not yet against real ESP32 hardware -- the maintainer doesn't currently have a device to test with. If you try it on real hardware, bug reports especially anything in SerialCSISource /the ESP32-CSI-Tool line parsing, and the fixed thresholds in the statistical baselines are genuinely the most useful thing you can contribute right now. Please open an issue with your board model, firmware version, and, if possible, a short capture file reproducing the problem. pip install -e . Requires Python 3.9+. Core dependencies: numpy , scipy , onnxruntime , pyserial . Install extras for development or visualization tooling: pip install -e ". dev " pytest, ruff, mypy, black pip install -e ". viz " matplotlib See examples/presence demo.py https://github.com/collabray/wisense/blob/main/examples/presence demo.py for a complete, runnable, hardware-free walkthrough it replays a small synthetic capture bundled in tests/fixtures/ . Run it with: python examples/presence demo.py For a real device, see examples/live esp32 demo.py https://github.com/collabray/wisense/blob/main/examples/live esp32 demo.py , which requires a physical ESP32 flashed with ESP32-CSI-Tool https://github.com/StevenMHernandez/ESP32-CSI-Tool -compatible firmware, connected over USB serial. The full walkthrough -- connecting, calibrating, every feature module, event callbacks -- is in docs/usage.md https://github.com/collabray/wisense/blob/main/docs/usage.md . API reference is in . https://github.com/collabray/wisense/blob/main/docs/api.md docs/api.md | Module | What it does | Statistical baseline | ONNX upgrade path | |---|---|---|---| wisense.presence | Binary presence detection | Variance-of-amplitude thresholding against a calibration baseline | Yes | wisense.fall | Fall event detection with severity/confidence | Sudden-amplitude-drop-then-stillness signature | Yes | wisense.vitals | Passive breathing-rate estimation | FFT peak detection in the 0.15-0.5 Hz respiration band | No statistical-only; see docstring | wisense.activity | Coarse activity classification | Variance + periodicity + transient-level-shift heuristics | Yes | wisense.people | Occupant count estimation | Multipath/frequency-diversity clustering | No statistical-only; see docstring | wisense.core | Connection, buffering, filtering, calibration, event callbacks | -- | -- | wisense.models | Model download/cache/checksum/load management | -- | -- | Every detection call returns a structured dataclass never a raw image or unprocessed signal -- see docs/api.md for each result type's fields. Capture Layer Linux host or ESP32 device SerialCSISource / NetworkCSISource / FileCSISource | v wisense.core CSIBuffer ring buffer - calibration - filters | v Feature modules presence / fall / vitals / activity / people -- statistical baseline, or ONNX Runtime inference if a model is configured | v Structured output dataclasses + event callbacks on presence change / on fall detected via wisense.core.events.Monitor -- ESP32 running SerialCSISource ESP32-CSI-Tool https://github.com/StevenMHernandez/ESP32-CSI-Tool -compatible firmware, over USB serial. This is the only capture target this repository has parsing code written and tested against.-- UDP or TCP, using a small newline-delimited JSON protocol WiSense defines itself documented in the class docstring -- there is no single industry-standard network CSI wire format, so bridging a different capture pipeline e.g. a Linux host with a CSI-capable driver to WiSense means emitting frames in this format. NetworkCSISource -- replays a recorded capture from disk in the WiSense CSV format documented in the class docstring, and produced by FileCSISource wisense.core.connection.write capture csv . Works fully offline, no hardware needed -- this is what the tests and examples/presence demo.py use. WiSense ships no pretrained .onnx model weights . This is a deliberate design decision: it keeps the pip install small, and every feature module works fully without any model via its statistical baseline method see the feature table above . The ONNX inference path model path= / use registry model= on each detector/classifier is fully implemented against onnxruntime.InferenceSession , including download/cache/checksum management in wisense.models.registry.ModelRegistry . But training and publishing model weights is out of scope for this repository -- ModelRegistry 's default download URL DEFAULT MODEL BASE URL in wisense/models/registry.py is an intentional, clearly-marked placeholder that will not resolve. If you train your own model: - Point PresenceDetector model path="/path/to/your/model.onnx" or the equivalent on FallDetector / ActivityClassifier directly at a local file, or - Host your own .onnx files somewhere and configure ModelRegistry base url="https://your-host/..." , then use use registry model="yourmodel.onnx" . Each detector's module docstring documents the exact input/output tensor contract your model needs to conform to e.g. presence models must output P absent , P present . No accuracy numbers are claimed anywhere in this repository for the ONNX path, because no benchmarked model exists yet to cite one for. The statistical baseline's behavior is exercised by the test suite see tests/ but has likewise not been benchmarked against a labeled real-world dataset -- treat its outputs as a reasonable engineering default, not a validated accuracy claim, and calibrate wisense.core.calibrate for your specific environment before relying on it. See ROADMAP.md https://github.com/collabray/wisense/blob/main/ROADMAP.md for what's intentionally scoped out of this release and not yet implemented. pip install -e ". dev " pytest Every module has a logging.getLogger "wisense.