From 948077623cc48bbdf53206ee6b812e649488eaff Mon Sep 17 00:00:00 2001 From: Eddy de Vink Date: Tue, 11 Aug 2026 20:34:56 +0200 Subject: [PATCH] docs: breid README uit met operations, configuratie, tests en repo-structuur --- README.md | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 22a6598..85ffbca 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,13 @@ SD-kaart uittrekken → umount /mnt/sdcard (fallback: umount -l) ``` +De triggers worden gedefinieerd in `udev/99-dashcam-trigger.rules`. Udev zelf voert +de scripts niet uit maar start ze via `systemd-run` — in udev-context ontbreken +mount/umount-rechten op Fedora met SELinux in enforcing mode. + ## Robuustheid -Het script is ontworpen tegen de hierboven geziene productie-fout (defecte/flakke +Het script is ontworpen tegen een geziene productie-fout (defecte/flakke SD-kaartlezer die midden in de transfer offline klapt, `I/O error`, `device offline`): - **Echte fout zichtbaar** — kopieerfouten worden als `OSError` met reden gelogd @@ -91,14 +95,125 @@ Bestandsnaam: `YYYYMMDDHHMMSS_.MP4` └── ...B.MP4 ``` +## Operations-handleiding + +### WhatsApp berichten + +Na elke transfer stuurt het script een notificatie naar de beheerder. Er zijn drie +basissituaties: + +| Situatie | Bericht | Actie | +|---|---|---| +| **Geslaagd** | Succesmelding met aantal bestanden en totaal in GB | Geen actie nodig | +| **Voltooid met fouten** | Waarschuwing met aantal bestanden, GB en aantal fouten | De betreffende bestanden blijven op de kaart staan en worden de volgende keer opnieuw geprobeerd. Blijft dit terugkomen → kaart/lezer controleren | +| **Gestopt (abort)** | Afbreekmelding met reden en aantal al overgezette bestanden | Zie onderstaande oorzaken | + +Bij een abort zijn er drie vaste redenen: + +- **SD-kaart onleesbaar** — de lezer of kaart gaf een I/O-fout, of de kaart werd + niet netjes afgemeld (dirty). Geen enkel bronbestand is verwijderd. Controleer de + kaart met `fsck.exfat` en probeer een andere lezer/poort. +- **Te veel opeenvolgende fouten** — 5 fouten achter elkaar tijdens het kopiëren. + Ook hier zijn geen bronbestanden verwijderd; de melding bevat de laatste fout. +- **Onvoldoende vrije ruimte** — de SSD had ook na het automatisch verwijderen van + oudste datum-mappen te weinig ruimte. + +Let op: een abort betekent **niet** dat data verloren is. Het script verwijdert een +bronbestand alleen nadat een kopie is geverifieerd (zelfde byte-grootte). + +### Logging + +Alle transfer-activiteit wordt geschreven naar `/tmp/dashcam-transfer.log` op +nextcloud, in het formaat `[YYYY-MM-DD HH:MM:SS] LEVEL bericht`. De mount- en +cleanup-scripts loggen via `logger` naar syslog met tag `dashcam-transfer`. + +Handige greppatronen voor diagnose: + +```bash +# Laatste transfer-run +tail -50 /tmp/dashcam-transfer.log + +# Mount/cleanup triggers + fsck-uitvoer (syslog) +journalctl -t dashcam-transfer --since today +grep dashcam-transfer /var/log/messages + +# I/O- en USB-fouten van de lezer +dmesg | grep -Ei "usb|sd[a-z]|dided|device offline|I/O error" +``` + +### Troubleshooting + +| Symptoom | Waarschijnlijke oorzaak | Actie | +|---|---|---| +| `GESTOPT: SD-kaart onleesbaar` | Lezer/kaart defect of niet netjes afgemeld | `fsck.exfat -n` draaien, lezer/poort wisselen, kaart opnieuw insteken | +| `device offline` / `DID_ERROR` in dmesg | Flakke USB-verbinding, kaart klapt weg | Lezer vervangen, USB-poort wisselen; het script herstelt automatisch bij een nieuwe udev-trigger | +| `Geen MP4 bestanden gevonden` in log | Kaart leeg (transfer geslaagd) of verkeerde mapstructuur | Niks mis; controleer op de SSD of bestanden er zijn | +| Transfer start niet na insteken | Service draait al (is-active gate) of device verscheen niet binnen 60s | Logs checken; als het device nooit komt, lezer opnieuw insteken | +| Stale mount in `mount`-output | REMOVE-trigger miste (lezer trok in één keer beide devices weg) | Cleanup-script handmatig draaien (zie herstel) | +| `WhatsApp notificatie mislukt` in log | wwebjs-api container down | `docker compose` in `/home/aiaiaiaiagent/wwebjs-api/` controleren | +| Abort: onvoldoende vrije ruimte | SSD vol, opschonen hielp niet | Oude datum-mappen handmatig opschonen of SSD uitbreiden | + +### Herstelprocedures + +```bash +# Handmatige transfer (zonder udev-trigger) +/usr/local/bin/dashcam-transfer + +# Alleen de eerste N bestanden (testen) +/usr/local/bin/dashcam-transfer --limit 10 + +# Read-only health check van de kaart (niet-mounted apparaat nodig) +fsck.exfat -n /dev/sde1 + +# Stale mount opruimen (als de udev-trigger het niet deed) +/usr/local/bin/dashcam-transfer-cleanup +# of handmatig: +umount -l /mnt/sdcard + +# Transfer-service handmatig starten +systemctl start dashcam-transfer +``` + +## Configuratiereferentie + +### `dashcam-transfer.py` + +| Constante | Waarde | Doel | +|---|---|---| +| `SD_CARD` | `/mnt/sdcard` | Mountpoint SD-kaart | +| `SOURCE_DIR` | `/mnt/sdcard/Novatek/Movie` | Locatie MP4-bestanden op de kaart | +| `SSD` | `/mnt/ultratouch` | Mountpoint USB-SSD | +| `TARGET_BASE` | `/mnt/ultratouch/dashcam` | Doelmap voor overgezette opnames | +| `LOG_FILE` | `/tmp/dashcam-transfer.log` | Logbestand | +| `LOCK_FILE` | `/tmp/dashcam-transfer.lock` | Lockbestand tegen dubbele runs | +| `CAMERA_MAP` | `F→front`, `B→back` | Vertaling van naam-suffix naar submap | +| `FILE_PATTERN` | `^\d{8}\d{6}_\d+[FB]\.MP4$` | Herkent geldige dashcam-bestandsnamen | +| `MAX_RETRIES` | `3` | Kopieerpogingen per bestand | +| `RETRY_DELAY` | `2` | Pauze tussen pogingen (seconden) | +| `MAX_CONSECUTIVE_ERRORS` | `5` | Aantal opeenvolgende fouten vóór abort | +| `WHATSAPP_API` | `http://localhost:3001/client/sendMessage/EdGpt` | wwebjs-api endpoint (localhost = nextcloud zelf) | +| `WHATSAPP_CHAT` | `31620248011@c.us` | Ontvanger van notificaties | + +### `dashcam-transfer-mount.sh` + +| Variabele | Waarde | Doel | +|---|---|---| +| `MAX_WAIT` | `60` | Maximaal wachten (s) op het device na trigger | +| `DASHCAM_MAX_WAIT` | — | Omgevingsvariabele om bovenstaande te overschrijven | + +### Systeemconfiguratie + +| Onderdeel | Locatie | +|---|---| +| udev-rules | `/etc/udev/rules.d/99-dashcam-trigger.rules` | +| Mount-script | `/usr/local/bin/dashcam-transfer-mount` | +| Cleanup-script | `/usr/local/bin/dashcam-transfer-cleanup` | +| Transfer-service | `/etc/systemd/system/dashcam-transfer.service` | +| SD-kaart UUID | `00D3-7715` | +| SSD UUID | `3027-8ECA` | + ## WhatsApp notificatie -Na elke transfer stuurt het script een WhatsApp bericht naar de beheerder: - -``` -✅ Dashcam transfer voltooid: 164 bestanden (56.8 GB) overgezet, geen fouten -``` - De API (`wwebjs-api`) draait als Docker container op nextcloud zelf: | Config | Waarde | @@ -108,6 +223,24 @@ De API (`wwebjs-api`) draait als Docker container op nextcloud zelf: | Ontvanger | `31620248011@c.us` (privé chat Eddy) | De container: `docker-compose.yml` in `/home/aiaiaiaiagent/wwebjs-api/`. +De notificatie zelf is een JSON-payload naar het endpoint; een mislukte notificatie +wordt alleen gelogd en breekt de transfer niet af. + +## Repo-structuur + +``` +dashcam-transfer/ +├── dashcam-transfer.py Hoofdscript: transfer + WhatsApp-notificatie +├── dashcam-transfer-mount.sh Udev add-trigger: wachten, mount, fsck, service start +├── dashcam-transfer-cleanup.sh Udev remove-trigger: stale mount opruimen +├── udev/ +│ └── 99-dashcam-trigger.rules Bron van de geïnstalleerde udev-rules +├── tests/ +│ ├── test_dashcam_transfer.py 20 unittest-testen (Python) +│ ├── test_mount_script.sh 7 functionele checks (bash) +│ └── test_cleanup_script.sh 12 functionele checks (bash) +└── README.md Deze documentatie +``` ## Service & triggers @@ -126,8 +259,9 @@ zodat de kaart dynamisch gemount wordt ongeacht het filesystem UUID. Na wijzigin ### Mount script (`/usr/local/bin/dashcam-transfer-mount.sh`) -Wacht tot het doorgegeven device beschikbaar is, unmount eventuele stale mounts, -mount de SD-kaart en start de service. +Wacht tot het device beschikbaar is, unmount eventuele stale mounts, mount de +SD-kaart en start de service. Sluit vroegtijdig af als de service al actief is +(een flakke lezer mag nooit een draaiende transfer onderbreken). ### Cleanup script (`/usr/local/bin/dashcam-transfer-cleanup.sh`) @@ -150,7 +284,25 @@ User=root ### Logging -Alle activiteit wordt gelogd naar `/tmp/dashcam-transfer.log` op nextcloud. +Alle activiteit wordt gelogd naar `/tmp/dashcam-transfer.log` op nextcloud; de +trigger-scripts loggen naar syslog met tag `dashcam-transfer`. + +## Testdocumentatie + +### Overzicht + +| Suite | Commando | Aantal | Dekking | +|---|---|---|---| +| Python unit | `python3 -m unittest discover -s tests` | 20 | Naam-parsing, directory-scans, kopie/retry, bestandsvergelijking, ruimte-opschoning, WhatsApp-berichten | +| Mount-script | `./tests/test_mount_script.sh` | 7 | Skip bij actieve service, mount + service start, fsck-uitvoering, logging | +| Cleanup-script | `./tests/test_cleanup_script.sh` | 12 | Stale-detectie (device weg / naam-match), service stop, umount + lazy-fallback, no-op bij gezonde mount | + +De Python-testen draaien tegen een gefakete omgeving (temp-mappen, gemonteerde +modules) en raken geen echte bestanden of de API aan. De bash-testen plaatsen een +set fake-commando's (`findmnt`, `systemctl`, `umount`, `logger`) op de `PATH` en +verificeren met markerbestanden of het script het juiste gedrag vertoont. Een nieuw +scenario toevoegen betekent: een nieuwe fake-commando/marker-regel in de test en een +`check`-assertie voor het verwachte gedrag. ## Handmatig gebruik