Skip to content

Neubauer-Ralf/weight_sync

Repository files navigation

weight-sync

Automatically sync Withings scale weight and Garmin Connect workout data to a Google Sheet — daily, via a Raspberry Pi (or any always-on Linux box).

What it does

A Python script runs once a day via systemd timer. It:

  1. Fetches your latest weight from the Withings API
  2. Checks Garmin Connect for any logged activity today
  3. Finds today's row in your Google Sheet and writes the weight + an "x" in the workout column

Prerequisites

  • Raspberry Pi (or any always-on Linux box) with Python 3.9+
  • A Withings scale syncing to the Withings app
  • A Garmin watch syncing to Garmin Connect
  • A Google Sheet with pre-filled dates in column A, weight in column B, and a workout marker in column J

Setup

1. Clone and install

git clone https://github.com/YOUR_USER/weight-sync.git
cd weight-sync
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp config.example.yaml config.yaml

2. Google Sheets API

  1. Go to Google Cloud Console
  2. Create a project and enable the Google Sheets API
  3. Go to Credentials → Create Credentials → Service Account
  4. Choose "Application data" when asked
  5. Download the JSON key and save it to the project directory
  6. Share your Google Sheet with the service account email (the client_email in the JSON)
  7. Copy the spreadsheet ID from the URL into config.yaml

3. Withings API

  1. Go to developer.withings.com and create an application
  2. Set the callback URL to http://localhost:8585/callback
  3. Copy the Client ID and Client Secret into config.yaml
  4. Run the authorization flow:
source venv/bin/activate
python3 setup_withings.py

Follow the prompts — open the URL, authorize, paste the code.

4. Garmin Connect

Add your Garmin email and password to config.yaml, then run the one-time login:

source venv/bin/activate
python3 setup_garmin.py

This will prompt for MFA. If the interactive prompt doesn't work, use the hardcoded approach documented in setup_garmin.py.

5. Configure

Edit config.yaml with your credentials, spreadsheet ID, and worksheet name:

withings:
  client_id: "..."
  client_secret: "..."

garmin:
  email: "..."
  password: "..."

google:
  credentials_path: "/path/to/google-credentials.json"
  spreadsheet_id: "..."

sheet: "Sheet1"

6. Test

source venv/bin/activate
python3 sync.py

7. Systemd timer

Edit weight-sync.service and replace YOUR_USER and YOUR_HOME with your actual values, then:

sudo cp weight-sync.service /etc/systemd/system/
sudo cp weight-sync.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now weight-sync.timer

The default schedule is 22:00 daily. Edit weight-sync.timer to change it.

Check status:

systemctl list-timers weight-sync.timer
journalctl -u weight-sync.service -n 30

How it finds the right row

Column A has pre-filled dates. The script reads all of column A, matches today's date, and writes to that row. Weight goes to column B, workout marker to column J. If you rearrange columns, update the column letters in update_sheet().

Token refresh

  • Withings: Tokens auto-refresh on every run.
  • Garmin: Tokens are re-saved after each login. If they expire after extended downtime, re-run setup_garmin.py.

Troubleshooting

Problem Fix
No row found for today Check that column A dates match a supported format (dd.mm.yyyy, yyyy-mm-dd, etc.)
Withings token refresh fails Re-run setup_withings.py
Garmin login fails Re-run setup_garmin.py — MFA tokens may have expired
Sheet not updating Make sure the sheet is shared with the service account email
APIError: 400 Make sure the sheet is a native Google Sheet, not an uploaded .xlsx

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages