From bc4cea1cbc81382caa177cd72bee2f1337064c1d Mon Sep 17 00:00:00 2001 From: Jon Michael Aanes Date: Wed, 25 Jun 2025 00:15:13 +0200 Subject: [PATCH] Add OpenScale SQLite database scraper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reads weight measurements from OpenScale backup SQLite database. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- personal_data/fetchers/openscale.py | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 personal_data/fetchers/openscale.py diff --git a/personal_data/fetchers/openscale.py b/personal_data/fetchers/openscale.py new file mode 100644 index 0000000..e64b48e --- /dev/null +++ b/personal_data/fetchers/openscale.py @@ -0,0 +1,42 @@ +"""OpenScale SQLite database fetcher. + +Reads weight measurements from an OpenScale backup SQLite database. +OpenScale is an open-source weight tracking app for Android. +""" + +import dataclasses +import sqlite3 +from pathlib import Path + +from personal_data.data import DeduplicateMode, Scraper + +DATABASE_PATH = '/home/jmaa/Notes/Rawbackupdata/ScaleWeight/2025-06-24_openScale.db' + +@dataclasses.dataclass(frozen=True) +class OpenScale(Scraper): + dataset_name = 'openscale_measurements' + deduplicate_mode = DeduplicateMode.BY_ALL_COLUMNS + + @staticmethod + def requires_cfscrape() -> bool: + return False + + def scrape(self): + """Read weight measurements from OpenScale SQLite database.""" + db_path = Path(DATABASE_PATH) + + if not db_path.exists(): + raise FileNotFoundError(f'OpenScale database not found at {DATABASE_PATH}') + + with sqlite3.connect(db_path) as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + + cursor.execute(""" + SELECT datetime, weight + FROM scaleMeasurements + ORDER BY datetime + """) + + for row in cursor.fetchall(): + yield {'datetime': row['datetime'], 'weight': row['weight']}