Files
eink/README.md
T

117 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# eink
NixOS-managed Raspberry Pi 4 driving a Waveshare 12.48" e-paper panel as a
calendar / day-planner. CalDAV data comes from the household Stalwart at
`mail.rubenhensen.nl`. The Pi pulls every commit on `main` via
[comin](https://github.com/nlewo/comin) — never touch the SD card after the
first flash.
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────┐
│ Raspberry Pi 4 (NixOS aarch64, hostname: dayplanner) │
│ │
│ systemd: eink-dashboard.service systemd: eink-renderer.service │
│ ┌──────────────────────────┐ ┌──────────────────────────────┐ │
│ │ SvelteKit (Node adapter) │◄──────│ Playwright → Pillow dither │ │
│ │ :3000 │ HTTP │ → Waveshare 12.48" driver │ │
│ │ fetches CalDAV every load│ │ (every REFRESH_SECONDS) │ │
│ └────────────┬─────────────┘ └───────────────┬──────────────┘ │
│ │ │ SPI │
│ ▼ ▼ │
│ mail.rubenhensen.nl Waveshare 12.48" HAT │
│ (Stalwart CalDAV) (1304×984, 4 sub-panels) │
└─────────────────────────────────────────────────────────────────────────┘
Deploy path: laptop → git push → Gitea → comin (60s poll) → Pi
```
## Layout
```
eink/
├── flake.nix # nixpkgs + comin → nixosConfigurations.dayplanner
├── hosts/dayplanner/ # this Pi's NixOS config (users, comin, hardware)
├── modules/ # eink-dashboard.nix + eink-renderer.nix
├── dashboard/ # SvelteKit app rendered headlessly at 1304×984
└── renderer/ # Python loop: screenshot → dither → push
```
## One-time bootstrap
1. **Flash NixOS aarch64 SD image** onto a card and boot the Pi.
- Image: <https://hydra.nixos.org/job/nixos/release-25.11/nixos.sd_image.aarch64-linux/latest>
- On first boot, set a `nixos` user password via the serial console or
monitor + keyboard. Enable SSH manually (`sudo systemctl start sshd`)
and note the Pi's IP.
2. **Add your SSH public key** to `hosts/dayplanner/default.nix` under
`users.users.ruben.openssh.authorizedKeys.keys`.
3. **Push this repo to a Git remote** the Pi can reach (e.g. your Gitea).
Update `services.comin.remotes[0].url` in `hosts/dayplanner/default.nix`
if the URL differs.
4. **First synchronous deploy from your laptop:**
```sh
nix run nixpkgs#nixos-rebuild -- switch \
--flake .#dayplanner \
--target-host nixos@<pi-ip> \
--build-host nixos@<pi-ip> \
--use-remote-sudo
```
(Building on the Pi itself avoids needing a cross-compile setup on your
Mac. Slow but one-time.)
5. **Drop the CalDAV password** on the Pi:
```sh
ssh ruben@<pi-ip> 'sudo install -d -m 700 /var/lib/eink/secrets'
ssh ruben@<pi-ip> 'sudo tee /var/lib/eink/secrets/caldav-password >/dev/null' \
<<< 'your-caldav-app-password'
ssh ruben@<pi-ip> 'sudo chmod 600 /var/lib/eink/secrets/caldav-password'
```
(Long-term replace this with [sops-nix](https://github.com/Mic92/sops-nix)
so the secret lives encrypted in this repo.)
6. **Vendor the Waveshare driver** (see `renderer/waveshare/README.md`).
After this, the steady-state workflow is just:
```sh
git push origin main # comin picks it up within ~60s and switches the Pi
```
## Iterating on the dashboard locally
You don't need the Pi to develop the UI — just open the SvelteKit dev
server in a browser sized to 1304×984:
```sh
cd dashboard
npm install
CALDAV_PASSWORD=... npm run dev -- --host
# open http://localhost:5173 in a browser with viewport 1304×984
```
Chrome devtools → "Toggle device toolbar" → set to 1304×984 to preview
exactly what the panel will see.
## Refresh cadence & panel wear
`eink.renderer.refreshSeconds = 300` (5 min) is the default. The 12.48"
panel has **no partial refresh** — every update is a full flash that
takes ~8s and consumes some panel life. Below 180 s is abusive; 300-600
s is comfortable. Consider scheduling a nightly invert to spread wear.
## Panel variant
Set `eink.renderer.panel = "bwr"` in `hosts/dayplanner/default.nix` if
you have the **12.48inch e-Paper Module (B)** (B/W/Red) instead of the
plain B/W version. The dashboard's red channel is whatever CSS color
matches `rgb(>180, <100, <100)` — see `renderer/render.py:to_bwr`.
## Troubleshooting
- **Comin not pulling:** `journalctl -u comin.service -f` on the Pi.
- **Renderer dry-running:** check `/tmp/eink-last.png` — if it exists,
the screenshot+dither pipeline works and the Waveshare driver is the
remaining piece (see `renderer/waveshare/README.md`).
- **Dashboard 500:** `journalctl -u eink-dashboard.service -f`. Most
common cause: empty `/var/lib/eink/secrets/caldav-password`.