Files
arneandClaude Opus 5.5 6466f002e0 Add Baby Tracker client and Home Assistant integration
Python client for the Baby Tracker sync server, reverse engineered from
the Android app (4.53), and a HACS-installable Home Assistant integration
built on it. Each baby gets a log calendar and summary sensors, and actions
add entries that sync back to the group.

Reading has been run against the real server. Uploading and running inside
real Home Assistant have not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 10:04:39 +00:00

77 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Read-only check of the client against the real server, using your own account.
BABYTRACKER_EMAIL=you@example.com BABYTRACKER_PASSWORD=... python3 examples/smoke_test.py
It logs in, lists devices and counts transactions per device, and downloads the
seed to a temporary folder to count babies. It uploads nothing, but logging in
registers this client as a device on the account. The device ID is kept in
~/.config/babytracker-api/device-id so repeat runs reuse that one device.
Output is limited to counts and record types, so it is safe to share.
"""
import collections
import importlib.util
import os
import sys
import tempfile
import uuid
from pathlib import Path
# Loaded by path: the integration folder holds a calendar.py, so putting that
# folder on sys.path would hide Python's own calendar module.
_LIBRARY = Path(__file__).resolve().parent.parent / "custom_components" / "babytracker" / "babytracker_api"
_spec = importlib.util.spec_from_file_location(
"babytracker_api", _LIBRARY / "__init__.py", submodule_search_locations=[str(_LIBRARY)]
)
_module = importlib.util.module_from_spec(_spec)
sys.modules["babytracker_api"] = _module
_spec.loader.exec_module(_module)
from babytracker_api import BabyTrackerClient, extract_seed_db, open_seed_db, read_babies, read_cursors
def device_id() -> str:
path = Path.home() / ".config" / "babytracker-api" / "device-id"
if path.exists():
return path.read_text().strip()
path.parent.mkdir(parents=True, exist_ok=True)
value = str(uuid.uuid4())
path.write_text(value)
return value
def main() -> None:
client = BabyTrackerClient(
os.environ["BABYTRACKER_EMAIL"], os.environ["BABYTRACKER_PASSWORD"], device_uuid=device_id()
)
client.login()
print("login: ok")
devices = client.get_devices()
print(f"devices: {len(devices)}")
for number, device in enumerate(devices, 1):
own = " (this client)" if device.uuid == client.device_uuid else ""
print(f" device {number}: last SyncID {device.last_sync_id}{own}")
with tempfile.TemporaryDirectory() as folder:
seed = client.download_seed(Path(folder) / "seed.zip")
connection = open_seed_db(extract_seed_db(seed, Path(folder) / "seed.db"))
print(f"seed: {len(read_babies(connection))} babies, {len(read_cursors(connection))} merged device cursors")
cursors = read_cursors(connection)
connection.close()
types = collections.Counter()
ops = collections.Counter()
for _, item in client.pull(cursors):
types[item.object_type] += 1
ops[item.op.name] += 1
print("transactions newer than the seed:", sum(types.values()))
print(" by type:", dict(types))
print(" by operation:", dict(ops))
if __name__ == "__main__":
main()