- Add Fitbit authentication flow (save credentials, OAuth callback handling) - Implement Garmin MFA support with successful session/cookie handling - Optimize segment discovery with new sampling and activity query services - Refactor database session management in discovery API for better testability - Enhance activity data parsing for charts and analysis - Update tests to use testcontainers and proper dependency injection - Clean up repository by ignoring and removing tracked transient files (.pyc, .db)
Fitbit-Garmin Local Sync
A standalone Python application designed to synchronize health and fitness data between the Fitbit and Garmin Connect platforms. The primary functions are to transfer weight data from Fitbit to Garmin, archive activity files from Garmin to a local directory, and download a wide range of Garmin health metrics for local storage and analysis.
Features
- Weight Data Synchronization: Fetches weight history from Fitbit API and uploads to Garmin Connect
- Activity File Archiving: Downloads original activity files (.fit, .gpx, .tcx) from Garmin to local storage
- Health Metrics Download: Retrieves comprehensive health metrics from Garmin Connect
- Web Interface: Simple browser-based UI for triggering sync operations
- Local-Only Storage: All sensitive data stored locally with no external cloud services
Prerequisites
- Python 3.11+
- PostgreSQL database
- Docker and Docker Compose (for containerized deployment)
- Fitbit Developer Account (to create an app and get API credentials)
- Garmin Connect Account
Setup
1. Clone and Install Dependencies
# Clone the repository
git clone <repository-url>
cd fitbit-garmin-sync
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
2. Database Setup
# Create PostgreSQL database
createdb fitbit_garmin_sync
# Update database configuration in application
# The application will handle schema creation automatically
3. Environment Configuration
Create a .env file with the following:
DATABASE_URL=postgresql://username:password@localhost:5432/fitbit_garmin_sync
FITBIT_CLIENT_ID=your_fitbit_client_id
FITBIT_CLIENT_SECRET=your_fitbit_client_secret
FITBIT_REDIRECT_URI=http://localhost:8000/api/setup/fitbit/callback
4. Run the Application
# Using uvicorn directly
uvicorn main:app --host 0.0.0.0 --port 8000
# Or using Docker
docker-compose up --build
Initial Configuration
- Open the application in your browser at
http://localhost:8000 - Navigate to the Setup page (
/setup) - Enter your Garmin Connect username and password
- Enter your Fitbit Client ID and Client Secret
- Click the authorization link provided to authenticate with Fitbit
- Copy the full callback URL from your browser after authorizing and paste it into the input field on the setup page
Usage
Sync Weight Data
- Go to the home page (
/) - Click the "Sync Weight" button
- Monitor the sync status in the logs table
Archive Activities
- Go to the home page (
/) - Click the "Sync Activities" button
- Enter the number of days back to look for activities
- Monitor the sync status in the logs table
View Health Metrics
- Use the API endpoints to query health metrics:
/api/metrics/list- List available metric types/api/metrics/query- Query specific metrics/api/health-data/summary- Get aggregated health statistics
API Endpoints
See the full API documentation in the specs/001-fitbit-garmin-sync/contracts/api-contract.yaml file or access the automatic documentation at /docs when running the application.
Docker Deployment
# Build and run with Docker Compose
docker-compose up --build
# The application will be available at http://localhost:8000
# PostgreSQL database will be automatically set up
Architecture
Project Structure
backend/
├── main.py
├── src/
│ ├── api/
│ │ ├── __init__.py
│ │ ├── activities.py
│ │ ├── auth.py # Refactored from setup.py
│ │ ├── config_routes.py # Refactored from setup.py
│ │ ├── logs.py
│ │ ├── metrics.py
│ │ ├── scheduling.py
│ │ ├── status.py
│ │ └── sync.py
│ ├── models/
│ │ ├── __init__.py
│ │ ├── activity.py
│ │ ├── activity_state.py
│ │ ├── api_token.py
│ │ ├── auth_status.py
│ │ ├── base.py
│ │ ├── config.py
│ │ ├── health_metric.py
│ │ ├── health_state.py
│ │ ├── job.py
│ │ ├── scheduled_job.py
│ │ ├── sync_log.py
│ │ └── weight_record.py
│ ├── routers/
│ │ ├── __init__.py
│ │ └── web.py
│ ├── services/
│ │ ├── garmin/
│ │ │ ├── auth.py
│ │ │ ├── client.py
│ │ │ └── data.py
│ │ ├── sync/
│ │ │ ├── activity.py
│ │ │ ├── health.py
│ │ │ ├── utils.py
│ │ │ └── weight.py
│ │ ├── __init__.py
│ │ ├── fitbit_client.py
│ │ ├── garth_helper.py
│ │ ├── job_manager.py
│ │ ├── postgresql_manager.py
│ │ ├── scheduler.py
│ │ └── sync_app.py
│ └── utils/
│ ├── __init__.py
│ ├── config.py
│ ├── helpers.py
│ └── logging_config.py
├── templates/
│ ├── index.html
│ └── setup.html
├── static/
│ ├── css/
│ └── js/
├── requirements.txt
├── Dockerfile
└── docker-compose.yml
tests/
├── unit/
│ ├── test_models/
│ ├── test_services/
│ └── test_api/
├── integration/
│ └── test_sync_flow.py
└── contract/
└── test_api_contracts.py
Development
For development, run the application with auto-reload:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
Security
- All API credentials and tokens are encrypted in the database
- OAuth2 flows are implemented following security best practices
- No external cloud services are used for data storage
- Implements rate limiting to be respectful to API providers