diff --git a/README.md b/README.md new file mode 100644 index 0000000..184e1e8 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Monitorink + +Transforme une **Kobo Libra 2** (e-reader e-ink) en écran de monitoring domestique affichant : +**heure**, **météo**, **statuts Home Assistant**, et surtout le **reste de tokens de +l'abonnement Claude**. + +## Architecture + +``` +[Homelab] backend PNG (FastAPI + Playwright, Docker, derrière Caddy) + ├─ Claude : GET /api/oauth/usage (token longue durée `claude setup-token`) + ├─ Météo : Open-Meteo (sans clé) + └─ Home Assistant : API REST /states + │ + └── GET /image.png (1264×1680 niveaux de gris) + │ WiFi à la demande + [Kobo Libra 2] boucle NickelMenu : fetch → fbink → suspend rtcwake +``` + +- **`backend/`** — serveur Python qui agrège les données et génère l'image du dashboard. +- **`kobo/`** — scripts client pour la Kobo (overlay sur `usetrmnl/trmnl-kobo`). +- **`dev/`** — utilitaires de dev (sonde de l'endpoint usage Claude). + +## Le « reste de tokens Claude » + +L'endpoint OAuth `/usage` (celui derrière la commande `/usage` de Claude Code) renvoie des +**pourcentages d'utilisation** des fenêtres glissantes (session 5 h + hebdo), pas un nombre brut +de tokens — Anthropic n'expose pas de compteur absolu côté abonnement. Monitorink affiche donc +le **% restant** (`100 − utilisation`) et le temps avant reset. *(ChatGPT : hors scope, aucune +API officielle de quota restant.)* + +Le backend s'authentifie avec un **token longue durée dédié** généré par `claude setup-token` +(env `MONITORINK_CLAUDE_TOKEN`) — il ne touche jamais aux credentials de Claude Code et ne fait +aucun refresh (le token est valide ~1 an). + +## Démarrage backend (dev, sur Mac) + +```sh +cd backend +python3 -m venv .venv && .venv/bin/pip install -r requirements.txt +.venv/bin/python -m playwright install chromium +cp ../.env.example ../.env # puis compléter +.venv/bin/uvicorn app:app --reload --port 8080 +# -> http://localhost:8080/image.png et /debug.html (itération design) +``` + +## Déploiement (homelab, Docker + Caddy) + +1. Générer le token sur le homelab : `ssh -t homelab claude setup-token`. +2. Créer `.env` (depuis `.env.example`) avec le token, les coords météo, et la config HA. +3. `docker compose up -d --build` (le service s'expose via caddy-docker-proxy sur + `monitorink.homelab.nestor-server.fr`). + +Voir `kobo/README.md` pour l'installation côté Kobo. diff --git a/dev/probe_usage.py b/dev/probe_usage.py old mode 100644 new mode 100755 diff --git a/kobo/README.md b/kobo/README.md new file mode 100644 index 0000000..7ca9cbb --- /dev/null +++ b/kobo/README.md @@ -0,0 +1,54 @@ +# Client Kobo — Monitorink + +Affiche le dashboard Monitorink (`/image.png`) sur une **Kobo Libra 2** (FW 4.38.x) déjà +équipée de **NickelMenu**. Approche : boucle WiFi → fetch image → `fbink` → suspend `rtcwake`. + +Ces scripts sont un **overlay** : ils réutilisent les binaires ARM et les helpers WiFi +pré-compilés/éprouvés du projet [`usetrmnl/trmnl-kobo`](https://github.com/usetrmnl/trmnl-kobo), +afin de ne pas réinventer (et risquer de casser) la gestion WiFi/suspend spécifique au matériel. + +## Contenu de ce dossier +- `monitorink.sh` — point d'entrée (lancé par NickelMenu). +- `monitorinkloop.sh` — boucle d'affichage (réutilise `bin/` et `scripts/` de trmnl-kobo). +- `nm/monitorink` — entrée NickelMenu. + +## Installation (Kobo branchée en USB) + +1. **Récupérer les binaires + helpers WiFi** depuis trmnl-kobo : + ```sh + git clone https://github.com/usetrmnl/trmnl-kobo + ``` + On a besoin de `src/TRMNL/bin/` (fbink, fbdepth, busybox_kobo) et `src/TRMNL/scripts/` + (enable-wifi.sh, disable-wifi.sh, force-wifi-connection.sh, obtain-ip.sh, release-ip.sh, + ledToggle.sh, getrssi.sh). + +2. **Construire le dossier Monitorink** sur la Kobo, à + `/mnt/onboard/.adds/Monitorink/` : + ``` + Monitorink/ + monitorink.sh (ce repo) + monitorinkloop.sh (ce repo) + bin/ (copié depuis trmnl-kobo/src/TRMNL/bin/) + scripts/ (copié depuis trmnl-kobo/src/TRMNL/scripts/) + ``` + +3. **Entrée NickelMenu** : copier `nm/monitorink` dans `/mnt/onboard/.adds/nm/monitorink`. + +4. **Configurer l'URL** dans `monitorink.sh` (`MONITORINK_URL`) et l'intervalle + (`MONITORINK_REFRESH`, en secondes). + +5. **Éjecter proprement** la Kobo → l'entrée « Monitorink » apparaît dans NickelMenu. + +## Utilisation +- Lancer « Monitorink » depuis NickelMenu. La boucle démarre : l'écran se met à jour, puis le + device passe en suspend et se réveille à chaque intervalle. +- Un **swipe** sur l'écran réveille le device et force un rafraîchissement. +- Pour **arrêter** : maintenir le bouton power (le device se réveille sous Nickel). +- Logs : `/tmp/monitorink.log` (effacés au reboot). + +## À valider sur l'appareil (cf. plan, tâche 8) +- Orientation framebuffer : si l'image sort tournée, soit pivoter côté serveur, soit ajouter + `./bin/fbdepth -r 2` avant l'affichage et `-r -1` après. +- Stabilité de `rtcwake -m mem` sur FW 4.38.23171 (sinon le fallback `state-extended` prend le + relais ; en dernier recours `sleep`). +- Autonomie réelle sur 24 h. diff --git a/kobo/monitorink.sh b/kobo/monitorink.sh new file mode 100755 index 0000000..8f504d3 --- /dev/null +++ b/kobo/monitorink.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# Monitorink — point d'entrée lancé par NickelMenu. +# Configure quelques paramètres puis lance la boucle d'affichage. + +BASE="/mnt/onboard/.adds/Monitorink" +cd "$BASE" || exit 1 + +# --- Configuration (adapter au besoin) --- +export MONITORINK_URL="http://monitorink.homelab.nestor-server.fr/image.png" +export MONITORINK_REFRESH=600 + +# Gouverneur CPU économe pendant les phases actives. +for gov in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do + echo ondemand > "$gov" 2>/dev/null +done + +# Lance la boucle (journalisée). exec pour ne pas laisser de process orphelin. +exec sh "$BASE/monitorinkloop.sh" >> /tmp/monitorink.log 2>&1 diff --git a/kobo/monitorinkloop.sh b/kobo/monitorinkloop.sh new file mode 100755 index 0000000..7f2f7d7 --- /dev/null +++ b/kobo/monitorinkloop.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Monitorink — boucle d'affichage e-ink sur Kobo Libra 2. +# +# Conçu comme un OVERLAY sur un checkout de https://github.com/usetrmnl/trmnl-kobo : +# il réutilise ses binaires ARM pré-compilés (bin/fbink, bin/busybox_kobo) et ses +# helpers WiFi éprouvés (scripts/enable-wifi.sh, etc.). On remplace l'appel API TRMNL +# par un simple fetch de notre image de dashboard. +# +# Lancé par monitorink.sh (lui-même lancé via NickelMenu). +# ⚠️ La séquence suspend/rtcwake est à valider sur l'appareil (FW 4.38.23171). + +BASE="$(dirname "$0")" +cd "$BASE" || exit 1 + +IMAGE_URL="${MONITORINK_URL:-http://monitorink.homelab.nestor-server.fr/image.png}" +REFRESH="${MONITORINK_REFRESH:-600}" # secondes entre deux rafraîchissements +TMP="/tmp/monitorink.png" + +FBINK="./bin/fbink/fbink" +BUSYBOX="./bin/busybox_kobo" + +# Ferme les FD hérités pour ne pas bloquer l'éjection USB. +exec 3>&- 2>/dev/null + +display() { + # Affiche l'image plein écran, full refresh (-f) anti-ghosting, clear (-c) avant. + "$FBINK" -g file="$TMP",valign=CENTER,halign=CENTER -c -f +} + +suspend_for() { + # Suspend-to-RAM avec réveil RTC. Si rtcwake échoue (retour < 10 s), fallback + # séquence Kobo (state-extended) puis sleep en dernier recours. + secs="$1" + start=$(date +%s) + "$BUSYBOX" rtcwake -a -s "$secs" -m mem 2>/dev/null + end=$(date +%s) + if [ $((end - start)) -lt 10 ]; then + echo 1 > /sys/power/state-extended 2>/dev/null + sleep 2 + echo mem > /sys/power/state 2>/dev/null + echo 0 > /sys/power/state-extended 2>/dev/null + # Si même ça n'a pas tenu, on dort simplement. + now=$(date +%s) + [ $((now - start)) -lt 10 ] && sleep "$secs" + fi +} + +while true; do + ./scripts/ledToggle.sh on 2>/dev/null + + # WiFi à la demande (ON -> fetch -> OFF) pour préserver la batterie. + ./scripts/enable-wifi.sh + ./scripts/force-wifi-connection.sh + ./scripts/obtain-ip.sh + + if curl -fsS -m 30 -o "$TMP" "$IMAGE_URL"; then + display + else + "$FBINK" -pmh "Monitorink : image indisponible ($(date '+%H:%M'))" + fi + + ./scripts/release-ip.sh + ./scripts/disable-wifi.sh + ./scripts/ledToggle.sh off 2>/dev/null + + suspend_for "$REFRESH" +done diff --git a/kobo/nm/monitorink b/kobo/nm/monitorink new file mode 100644 index 0000000..7220840 --- /dev/null +++ b/kobo/nm/monitorink @@ -0,0 +1,7 @@ +# Entrée NickelMenu pour Monitorink. +# À copier dans /mnt/onboard/.adds/nm/monitorink +# Lance le dashboard en tâche de fond. Pour arrêter : maintenir le bouton power +# (réveil + reprise Nickel), ou tuer le process via une entrée dédiée si besoin. + +menu_item :main :Monitorink :cmd_spawn :exec /mnt/onboard/.adds/Monitorink/monitorink.sh + chain_success :dialog :Monitorink démarré