diff --git a/.env.example b/.env.example deleted file mode 100644 index 2eb5e8e..0000000 --- a/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -IMMICH_URL=https://immich.example.com -IMMICH_API_KEY=your-immich-api-key -HA_URL=https://homeassistant.example.com -HA_TOKEN=your-home-assistant-long-lived-token diff --git a/.gitignore b/.gitignore index 2f2026c..d55f838 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,3 @@ __pycache__/ *.egg-info/ .ipynb_checkpoints/ photo_history.json -.env - diff --git a/CLAUDE.md b/CLAUDE.md index 489b712..561ca62 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,7 +62,7 @@ former `dither_test/`): - **Display refresh takes 12-15 seconds** — the BUSY pin polling handles this - **No test suite** — this is a hardware project; test by deploying to the Pi - **Dependencies on Pi**: `python3-pil python3-numba python3-smbus spidev gpiozero` -- **Config via `.env`** (gitignored): `IMMICH_URL`, `IMMICH_API_KEY`, `HA_URL`, `HA_TOKEN`. Loaded by `src/lib/env.py` (stdlib-only); `require(key)` raises if a value is missing. Copy `.env.example` to `.env` and fill in. The Pi keeps its own `~/frame/.env` — `sync.sh` excludes it. +- **Config via environment variables**: `IMMICH_URL`, `IMMICH_API_KEY`, `HA_URL`, `HA_TOKEN` (with hardcoded defaults in display.py) - **Uses only stdlib `urllib`** — no requests library; the Immich client uses `urllib.request` directly - **Single-instance lock** at `/tmp/frame.lock` (fcntl) — overlapping cron runs exit cleanly - `sys.path.append` is used to add `lib/` to the path from display.py diff --git a/notebooks/_helpers.py b/notebooks/_helpers.py index d5df9f6..eb85467 100644 --- a/notebooks/_helpers.py +++ b/notebooks/_helpers.py @@ -9,6 +9,7 @@ from __future__ import annotations import contextlib import io +import os import random import sys import tempfile @@ -20,6 +21,8 @@ REPO = Path(__file__).resolve().parent.parent CACHE_DIR = Path(tempfile.gettempdir()) / "frame_notebook" DEFAULT_PEOPLE = ("Me", "Ruby") +DEFAULT_IMMICH_URL = "https://immich.schmelczer.dev" +DEFAULT_IMMICH_API_KEY = "6crxVS1JLTJxsfGlzVhN2kefdL4EP7HPkkoMk9L6ZOE" def bootstrap() -> None: @@ -29,16 +32,15 @@ def bootstrap() -> None: if sp not in sys.path: sys.path.insert(0, sp) sys.modules.setdefault("waveshare_epd.epdconfig", ModuleType("waveshare_epd.epdconfig")) - from env import load_env - - load_env() def immich_client(): - from env import require from immich import ImmichClient - return ImmichClient(require("IMMICH_URL"), require("IMMICH_API_KEY")) + return ImmichClient( + os.environ.get("IMMICH_URL", DEFAULT_IMMICH_URL), + os.environ.get("IMMICH_API_KEY", DEFAULT_IMMICH_API_KEY), + ) def is_landscape(asset: dict) -> bool: diff --git a/src/display.py b/src/display.py index b79558b..22ae920 100644 --- a/src/display.py +++ b/src/display.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse import fcntl +import os import sys from datetime import datetime from pathlib import Path @@ -9,7 +10,6 @@ from PIL import Image sys.path.append(str(Path(__file__).parent / "lib")) from crop import face_aware_crop -from env import load_env, require from homeassistant import HomeAssistantClient from immich import ImmichClient, get_random_photo_from_album, get_random_photo_of_people from overlay import format_age, format_location @@ -18,11 +18,14 @@ from overlay import format_age, format_location # GPIO pins at import time, so two overlapping invocations would both crash # on "GPIO busy" before reaching the flock below. -load_env() -IMMICH_URL = require("IMMICH_URL") -IMMICH_API_KEY = require("IMMICH_API_KEY") -HA_URL = require("HA_URL") -HA_TOKEN = require("HA_TOKEN") +IMMICH_URL = os.environ.get("IMMICH_URL", "https://immich.schmelczer.dev") +IMMICH_API_KEY = os.environ.get("IMMICH_API_KEY", "6crxVS1JLTJxsfGlzVhN2kefdL4EP7HPkkoMk9L6ZOE") + +HA_URL = os.environ.get("HA_URL", "https://homeassistant.schmelczer.dev") +HA_TOKEN = os.environ.get( + "HA_TOKEN", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJmZjk3OTNmOWMzOWU0YjdmYmRjYTc5YmJkMTUyODcyNSIsImlhdCI6MTc2OTIwMjg1NCwiZXhwIjoyMDg0NTYyODU0fQ.IiL_1vTrGMlOoPMksN6lAopE0aInlY_wRnL4Jc-CeBs", +) HA_PRESENCE = {"Andras": "person.andras", "Ruby": "person.ruby"} diff --git a/src/lib/env.py b/src/lib/env.py deleted file mode 100644 index 943617b..0000000 --- a/src/lib/env.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Minimal stdlib .env loader. - -Reads KEY=VALUE lines from a .env file (project root by default) into -`os.environ`, leaving already-set variables untouched. -""" - -from __future__ import annotations - -import os -from pathlib import Path - - -def _find_env() -> Path | None: - # Walk up from this file and from cwd; first .env wins. Handles both the - # dev layout (src/lib/env.py with .env at repo root) and the Pi layout - # (lib/env.py with .env at ~/frame/.env). - for start in (Path(__file__).resolve().parent, Path.cwd().resolve()): - for d in (start, *start.parents): - candidate = d / ".env" - if candidate.is_file(): - return candidate - return None - - -def load_env(path: Path | None = None) -> None: - env_path = path or _find_env() - if env_path is None or not env_path.exists(): - return - for raw in env_path.read_text().splitlines(): - line = raw.strip() - if not line or line.startswith("#") or "=" not in line: - continue - key, _, value = line.partition("=") - key = key.strip() - value = value.strip().strip('"').strip("'") - os.environ.setdefault(key, value) - - -def require(key: str) -> str: - value = os.environ.get(key) - if not value: - raise RuntimeError(f"missing required env var: {key} (set it in .env or the environment)") - return value diff --git a/src/wifi-check.sh b/src/wifi-check.sh index d6dfd03..97fbdff 100755 --- a/src/wifi-check.sh +++ b/src/wifi-check.sh @@ -4,13 +4,7 @@ # brcmfmac chip on the Pi Zero 2W. CONNECTION="netplan-wlan0-HiddenPlace" - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -# shellcheck disable=SC1091 -[ -f "$SCRIPT_DIR/.env" ] && set -a && . "$SCRIPT_DIR/.env" && set +a -PROBE_HOST="${HA_URL#http*://}" -PROBE_HOST="${PROBE_HOST%%/*}" -: "${PROBE_HOST:?HA_URL must be set in .env}" +PROBE_HOST="homeassistant.schmelczer.dev" probe() { ping -c 1 -W 5 192.168.0.1 >/dev/null 2>&1 \ diff --git a/sync.sh b/sync.sh index 8cc6408..e0f8eca 100755 --- a/sync.sh +++ b/sync.sh @@ -1,2 +1,2 @@ #!/bin/bash -rsync -avz --progress --exclude=.env src/ andras@192.168.0.81:~/frame/ +rsync -avz --progress src/ andras@192.168.0.81:~/frame/