Wearable Integration
The bot collects physiological data from wearable devices through two mechanisms: webhooks for real-time data delivery, and a daily sync cron job at 00:00 UTC as a safety net to catch any missed data. All wearable data is stored in the device_data table.
Architecture
The wearable system uses a provider-based architecture with a registry pattern (PROVIDER_REGISTRY in src/wearables/). Each provider handles:
- OAuth token management -- tokens are encrypted at rest via Fernet (
cryptographypackage) - Webhook processing -- receives and parses incoming data from device APIs
- Data sync -- periodic pull of historical data via
daily_sync.py
Supported Providers
Withings
Create an app at developer.withings.com and configure the webhook callback URL to point to your server.
Data types: weight, blood_pressure, temperature, glucose, activity, sleep, ecg, bed_in/bed_out events
Required environment variables:
WITHINGS_CLIENT_ID=your_client_id
WITHINGS_CLIENT_SECRET=your_client_secret
Fitbit
Create an app at dev.fitbit.com and configure the webhook callback URL.
Data types: activity (1-min intraday), heartrate, hrv, spo2, breathing_rate, sleep, weight, temperature, nutrition
Required environment variables:
FITBIT_CLIENT_ID=your_client_id
FITBIT_CLIENT_SECRET=your_client_secret
FITBIT_SUBSCRIPTION_VERIFICATION_CODE=your_verification_code
Intraday access (1-minute granularity for activity and heart rate) requires Fitbit premium or explicit API approval. The provider automatically falls back to daily summaries if intraday requests return a 403 error.
Oura
Create an app at cloud.ouraring.com/v2/docs.
Data types: daily_sleep, daily_activity, daily_readiness, daily_spo2, daily_stress, heartrate (5-min intervals), workout, session
Required environment variables:
OURA_CLIENT_ID=your_client_id
OURA_CLIENT_SECRET=your_client_secret
Common Setup
1. Generate an encryption key
All OAuth tokens are encrypted at rest. Generate a Fernet key and add it to your .env:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
DEVICE_TOKEN_ENCRYPTION_KEY=your_generated_fernet_key
2. Set the base URL
Webhooks need to reach your API from the public internet. Set BASE_URL to your server's public URL:
BASE_URL=https://your-server.example.com
For local development, start.sh handles this automatically by creating a localtunnel.
3. Link participant devices
Participants link their wearable devices by sending the /devices command in Telegram. This initiates the OAuth flow for the selected provider. Once authorized, the bot begins receiving webhook data and running daily syncs for that participant.
Rules Engine
The rules engine provides event-driven survey triggering based on incoming wearable data. Rules are evaluated after each webhook data save, allowing you to react to physiological events in near real-time.
Example use cases:
- Send a morning survey when sleep data arrives (indicating the participant has woken up)
- Trigger an activity survey when step count exceeds a threshold
- Deliver a stress check-in when heart rate variability drops
Rules are defined in src/rules/models.py and evaluated by src/rules/engine.py. The engine supports cross-provider data type aliases, so a rule targeting "sleep" data will match both Withings sleep events and Oura daily_sleep events.