How kaizer-1/hrv-stress-wearable works
1. Repository shape
This is a split-stack system: a Python package for ML + backend services, a React/Vite frontend, plus scripts, data artifacts, and reports. The main architectural boundary is between the Python inference service and the browser dashboard.
2. Primary runtime path
The live system is a pipeline from sensor source → feature streamer → inference engine → WebSocket broadcast + SQLite persistence → React UI. The backend is the hub; the frontend is a consumer of both REST APIs and a streaming WebSocket.
3. Hardware / input boundary
The backend does not depend on a single physical device. It uses a SensorSource abstraction with three implementations: serial for the ESP32 wearable, CSV replay for offline/demo use, and TCP for a future networked sensor feed. This makes hardware a replaceable ingress layer rather than part of the core service.
4. Signal processing and ML subsystem
Under src/stress_detection/features, raw 1 Hz multi-sensor samples are cleaned, windowed, and converted into a 22-feature vector on a 30-second window with 5-second stride. That feature pipeline is shared by training and serving, which is important for train/serve parity. The model layer is a scikit-learn SVM pipeline with scaling, probability output, and smoothing in the serving path.
5. Training / offline data pipeline
The scripts/ directory and src/stress_detection/io, features, models packages form the offline ML workflow: load raw CSVs, clean them, generate features, train SVMs, and export joblib models. Model artifacts in data/models/ and evaluation outputs in reports/ are the outputs of that pipeline, not runtime dependencies.
6. Inference and session state
src/stress_detection/service/inference turns streaming windows into predictions, applies calibration offsets when enabled, and smooths stress probability over time. src/stress_detection/service/sessions persists user/session/sample/prediction/calibration data into SQLite. This is where ephemeral stream processing becomes durable session history.
7. Auth and user scoping
The service includes a JWT-based auth subsystem under service/auth. Authentication is used to scope REST data and gate the WebSocket stream. That means user identity is a cross-cutting concern for both persistence and live streaming, not just a login screen feature.
8. WebSocket live delivery
Live updates are pushed through service/ws: the backend broadcasts sample, feature, and prediction messages to connected clients. This is the real-time boundary between backend computation and frontend visualization. The stream is server-driven; the UI mainly subscribes and renders state.
9. Frontend application structure
The React app is organized by route and domain: live monitoring, history, calibration, breathing, settings, auth, and session detail. State is split between local UI components, Zustand stores, and API hooks. The frontend consumes REST for session/auth/calibration operations and WebSocket for live telemetry.
10. Demo and hardware-free operation
Demo mode is a first-class subsystem, not a mock-only afterthought. The backend can replay canned session data, and the frontend can switch into a visible demo state. This allows the full architecture to run without the ESP32 or sensors, which is important for testing, demos, and development.
11. Configuration and deployment surface
Runtime behavior is driven by YAML config under config/, especially input source selection and service settings. scripts/run_service.py is the backend entrypoint, and the project is designed around a local host deployment with the API and WebSocket on the Python service and the UI on the Vite dev server.
12. Evidence and quality subsystem
The repo includes substantial test coverage across backend pytest suites, frontend Vitest tests, and Playwright end-to-end flows. docs/ and reports/ capture architecture, API contracts, hardware protocol, and model results. These artifacts are part of the project’s architecture because they document and validate the live system boundaries and data contracts.
13. Key architectural constraint
The model is trained on a combined dataset because the project hardware’s GSR values differ from WESAD’s units. That domain-shift issue directly influences the deployed model choice and explains why the system includes both public-dataset artifacts and project-specific recording artifacts in the repository.
14. What to draw in a diagram
The most accurate diagram should show: ESP32/sensor inputs or CSV replay feeding the Python service; internal stages for cleaning/windowing/features/inference/smoothing; SQLite as persistence; JWT auth as a gate on REST and WebSocket; and the React dashboard as the live/history/calibration UI consuming those APIs. The offline training scripts and model/report artifacts should appear as a separate build-time pipeline, not part of the runtime request path.
Main entry points: client.ts API client · train_combined.py Training scripts · engine.py Inference engine · manager.py Session store
Components 21
Python service
Online backend runtime, streaming inference, persistence, and auth.
- Service app · Assembles the backend runtime, routes, and lifecycle wiring.
src/stress_detection/service/app.py - Runtime config · Loads YAML/runtime settings for source selection, service options, and deployment behavior.
src/stress_detection/service/config.py - Sensor sources · Replaceable input boundary for serial, CSV replay, and TCP sensor feeds.
src/stress_detection/service/sources - Feature stream · Buffers raw samples, windows them, and emits feature-ready records.
src/stress_detection/service/features/streamer.py - Inference engine · Scores streamed windows, applies calibration, and smooths stress probabilities.
src/stress_detection/service/inference/engine.py - Session store · Persists users, sessions, samples, predictions, and calibration history into SQLite.
src/stress_detection/service/sessions/manager.py - JWT auth · Authenticates users and scopes REST and live-stream access.
src/stress_detection/service/auth - WebSocket hub · Broadcasts sample, feature, and prediction messages to connected clients.
src/stress_detection/service/ws/broadcaster.py - Demo API · Serves canned-session and demo-state behavior for hardware-free operation.
src/stress_detection/service/demo/routes.py
React UI
Browser dashboard consuming REST and WebSocket data.
- Dashboard app · Browser UI shell and route composition for monitoring and control.
frontend/src/App.tsx - API client · Typed REST helpers for auth, sessions, calibration, and demo control.
frontend/src/api/client.ts - Live hooks · Hooks and stores that subscribe to live telemetry and connection state.
frontend/src/hooks/useLiveStream.ts - Route views · Live, history, calibration, breathing, settings, and auth pages.
frontend/src/routes/Live.tsx
Offline ML
Training, feature generation, evaluation, and exported model artifacts.
- Feature pipeline · Shared cleaning, windowing, and feature extraction used by training and serving.
src/stress_detection/features/pipeline.py - Extractors · Computes the 22-feature vector from cleaned sensor windows.
src/stress_detection/features/extractors.py - SVM model · Scaled probabilistic SVM used for stress classification.
src/stress_detection/models/svm.py - Training scripts · Builds interim datasets, trains models, checks transfer, and exports artifacts.
scripts/train_combined.py
Data artifacts
Sample recordings, canned demo sessions, trained models, and stored session data.
- Raw data · Project recordings and WESAD-derived CSV sources used for cleaning and feature generation.
data/raw - Model files · Exported trained models consumed by the backend inference path.
data/models - Session DB · On-disk SQLite database holding durable session history.
data/sessions.sqlite - Reports · Metrics, figures, and narrative outputs from training and validation runs.
reports
Connections 27
- Runtime config → Service app: configures · Runtime settings feed service startup and source selection.
- Service app → Sensor sources: opens · Backend instantiates the selected sensor ingress adapter.
- Sensor sources → Feature stream: streams samples · Raw 1 Hz sensor samples are forwarded into feature buffering.
- Feature stream → Feature pipeline: uses · Serving reuses the shared cleaning/windowing/feature logic.
- Feature pipeline → Extractors: computes · Extractors produce the window-level feature vector.
- Feature stream → Inference engine: emits windows · Feature windows become inference-ready inputs.
- Inference engine → SVM model: scores with · The serving path loads and evaluates the trained SVM pipeline.
- Inference engine → Session store: persists · Predictions and calibration state are written to session storage.
- Session store → Session DB: stores in · SQLite is the durable backing store for session history.
- Inference engine → WebSocket hub: publishes · Live predictions and telemetry are sent to the WebSocket layer.
- JWT auth → Session store: scopes data · Identity determines which sessions and records are accessible.
- JWT auth → WebSocket hub: gates · Authenticated users are allowed into the live stream.
- Demo API → Sensor sources: replays · Demo mode can substitute canned or replayed sensor input.
- Training scripts → Raw data: loads · Offline build scripts ingest project and public-dataset CSVs.
- Training scripts → Feature pipeline: trains on · Training uses the same feature pipeline as serving for parity.
- Training scripts → SVM model: exports · Scripts produce versioned joblib SVM artifacts.
- Training scripts → Reports: evaluates to · Metrics and figures are written as validation outputs.
- SVM model → Model files: saved as · Trained classifiers are stored under the model artifact directory.
- Dashboard app → API client: calls · UI screens use REST helpers for auth, sessions, calibration, and demo control.
- Dashboard app → Live hooks: subscribes via · The dashboard consumes live telemetry and connection state through hooks.
- Live hooks → WebSocket hub: connects to · Frontend listens to the backend WebSocket broadcast stream.
- Route views → Dashboard app: renders · Route-level screens are mounted inside the app shell.
- Route views → API client: fetches · Screens request session, auth, calibration, and demo data via REST.
- Route views → Live hooks: shows live data · Live and history-oriented views render telemetry state from stream hooks.
- API client → JWT auth: authenticates against · Login, register, and token usage flow through the backend auth routes.
- API client → Session store: reads history · Session and calibration endpoints are backed by the SQLite store.
- API client → Demo API: controls demo · Frontend toggles canned demo behavior through the demo API.