"Je beschermt wat je kent"
Gedistribueerd biodiversiteitsmonitoringsysteem voor real-time detectie en analyse van vogels, vleermuizen, weer, atmosferische condities en nestkasten in Nijverdal (NL).
Zes Raspberry Pi's, één NAS, één ESP32-touchscreen en één LED-matrix monitoren 24/7 de lokale biodiversiteit:
- Vogeldetectie via BirdNET-Pi op 2 vaste + 1 mobiel station
- Akoestische lokalisatie via stereo microfoons (Noord/Zuid richtingsdetectie op zolder)
- Vocalisatieanalyse via 197 soortspecifieke CNN-modellen (zang / roep / alarm)
- Vleermuisdetectie via BatDetect2 + BattyBirdNET-Bavaria op 200 kHz
- Weermonitoring via Davis Vantage Pro 2
- Hemelmonitoring via HQ Camera IMX477 met 140° FOV (ISS, maan, meteoren, sterren)
- Nestkastcameras via 3 Tuya-camera's met go2rtc-streaming
- Vogeltrek via KNMI FlySafe radar-integratie
- Real-time displays op Ulanzi TC001 LED-matrix + CYD-touchscreen (46 schermen)
- AI-rapporten via Claude API (wekelijks + maandelijks)
- Centrale opslag op Synology NAS met PostgreSQL
- 31 Grafana-dashboards voor visualisatie
| Station | IP | Hardware | Functie |
|---|---|---|---|
| emsn2-zolder | zolder.emsn.lan | RPi 5, Steinberg UR22mkII | BirdNET-Pi, MQTT broker, stereo lokalisatie |
| emsn2-berging | berging.emsn.lan | RPi 5, Steinberg UR44 | BirdNET-Pi, AtmosBird HQ-cam, CYD display |
| emsn2-meteo | meteo.emsn.lan | RPi Zero 2W | Davis Vantage Pro 2 |
| emsn2-mobiel | 192.168.1.80 | RPi 5, WittyPi 5, 4G, GPS | Mobiel veldstation |
| emsn-sonar | sonar.emsn.lan | RPi 5, Dodotronic Ultramic | Vleermuisdetectie (BatDetect2) |
| NAS DS224+ | nas.emsn.lan | Synology | PostgreSQL, Grafana, Loki, go2rtc, Docker |
| Ulanzi TC001 | ulanzi.emsn.lan | ESP32, AWTRIX Light | LED-matrix notificaties |
| CYD Berging | DHCP | ESP32-2432S028R | 320×240 touchscreen, 46 schermen |
┌──────────────────────────────────────────────────────────────┐
│ Zolder Berging Meteo Mobiel Sonar │
│ │ │ │ │ │ │
│ └───────┴───────┼───────┴───────┘ │
│ ▼ │
│ MQTT Broker (zolder) │
│ :1883 plain + :8883 mTLS │
│ │ │
│ ┌─────────┬───┴───┬─────────┬──────────┐ │
│ ▼ ▼ ▼ ▼ ▼ │
│ Postgres Ulanzi CYD go2rtc Loki │
│ :5433 :3100 │
│ │ │
│ Grafana (31) OpenBao (:8200) Uptime Kuma (:3002) │
└──────────────────────────────────────────────────────────────┘
| Map | Inhoud |
|---|---|
scripts/core/ |
Fundament: config, database pool, logging, exception handling, resilience (circuit breaker + retry), secrets manager (OpenBao), mTLS-MQTT, async helpers |
scripts/sync/ |
Lifetime sync BirdNET-Pi → PostgreSQL, hardware metrics, dual-detection matching |
scripts/audio/ |
Stereo richtingsdetectie, audio quality analyzer, CNN distance classifier |
scripts/vocalization/ |
CNN-classificatie zang vs. roep (197 soortmodellen) |
scripts/atmosbird/ |
Hemelmonitoring + 24/7 livestream-relay met filler-frame |
scripts/nestbox/ |
Tuya-camera REST-API + automatische screenshots |
scripts/flysafe/ |
KNMI vogeltrekradar |
scripts/monitoring/ |
Watchdogs, pipeline canary, Uptime Kuma, deep health checks |
scripts/maintenance/ |
Service scaffold, baseline drop-ins, secrets-migratie |
scripts/backup/ |
Gelaagde backups: rsync, SD-image, PostgreSQL → NAS + HiDrive |
scripts/archive/ |
Audio/spectrogram archief met SHA256-verificatie en self-heal |
scripts/reports/ |
AI-rapporten via Claude API |
scripts/ulanzi/ |
LED-matrix bridge met 5-tier zeldzaamheidssysteem |
scripts/display/ |
CYD stats publisher + AtmosBird image server |
cyd-berging/ |
ESP32 PlatformIO firmware (C++, TFT_eSPI, 46 schermen) |
PostgreSQL 15 op de NAS (:5433). Belangrijkste tabellen:
| Tabel | Inhoud |
|---|---|
bird_detections |
Vogeldetecties met richting + vocalisatie + audio-paden |
bat_detections |
Vleermuisdetecties |
sky_observations |
AtmosBird metingen |
weather_data |
Davis VP2 metingen |
nestbox_events + nestbox_media |
Nestkast observaties + screenshots/video's |
dual_detections |
Cross-station matches |
system_health |
Hardware metrics per station |
backup_status |
Backup-status per station/type |
Schema-versioning via 19 SQL-migraties in database/migrations/.
| Topic | Inhoud |
|---|---|
birdnet/{station}/detection |
Live vogeldetectie |
emsn2/{station}/health/metrics |
Hardware status |
emsn2/meteo/weather/current |
Weerdata |
emsn2/dual/detection |
Cross-station match |
emsn2/alerts/rare_species |
Zeldzame soort |
emsn2/stats/today/* …/week/* …/lifetime/* |
Statistieken |
emsn2/berging/atmosbird_stream |
Stream-relay health (retained) |
emsn2/{station}/reboot |
Reboot info (retained) |
emsn2/{station}/unit_watchdog |
Service status |
- Loki (NAS:3100) — centrale logging via Promtail op elke Pi
- Pipeline canary — output-side monitoring, detecteert silent fails per pipeline-stage
- Uptime Kuma (NAS:3002) — visuele statuspagina
- Grafana — 31 dashboards
- Reboot-alerts — MQTT-alert bij elke onverwachte reboot, type-detectie (watchdog/OOM/kernel-panic/power-loss)
- Circuit breakers + tenacity retry voor alle externe calls (Tuya, KNMI, HiDrive, NAS)
- Watchdog heartbeat thread voor alle long-running services
- Hardware watchdog op alle Pi's (BCM2835, 60s timeout)
- Service resource baseline —
LimitNOFILE=4096+TasksMax=128via drop-ins
- mTLS-MQTT op poort 8883 (klassieke 1883 blijft beschikbaar voor migratie)
- OpenBao (Vault-compatible) op NAS:8200 — 33 secrets, KV v2
- Fallback chain:
OpenBao → environment → .secrets
| Type | Frequentie | NAS | HiDrive cloud |
|---|---|---|---|
| Rsync | Dagelijks 02:00 | 7 dagen | 5 dagen |
| SD-image | Maandelijks | 6 maanden | – |
| PostgreSQL | Dagelijks 03:00 | 7 dagen | 7 dagen |
Wekelijkse backup_verify.py controleert integriteit.
emsn2/
├── cyd-berging/ # ESP32 CYD firmware (PlatformIO, C++)
├── database/migrations # 19 SQL-migraties
├── docs/ # Documentatie
│ └── adr/ # 17 Architecture Decision Records
├── grafana/ # Dashboard JSON-exports
├── scripts/ # Python (28 submappen)
├── systemd/ # Service + timer files per station
└── tests/ # Pytest (35 tests)
Vereist Raspberry Pi OS 64-bit (Bookworm), Python 3.13+, PostgreSQL 15+ op NAS, Mosquitto MQTT.
git clone https://github.com/RonnyCHL/emsn2.git
cd emsn2
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
cp .secrets.example .secrets # Vul credentials in
# Units uitrollen via het manifest: eerst kijken, dan pas doen.
./venv/bin/python -m scripts.deploy.sync_systemd_manifest --station <station>
sudo ./venv/bin/python -m scripts.deploy.sync_systemd_manifest --station <station> --apply
sudo python3 -m scripts.maintenance.apply_service_baselineHier stonden tot 8 augustus 2026 twee
cp-regels die uitsystemd/<station>/ensystemd/shared/kopieerden. Die mappen zijn bij de herindeling van 1 juni 2026 verdwenen — de units staan sindsdien insystemd/roles/ensystemd/stations/<station>/units/.cpvan een lege glob kopieert niets en meldt niets, dus wie deze instructie volgde dacht klaar te zijn en had geen enkele unit geïnstalleerd. Dezelfde val alssync_systemd.sh, die om precies die reden is verwijderd.
| Metric | Waarde |
|---|---|
| Python scripts | 268 |
| Regels Python-code | 90.849 |
| Systemd services | 105 |
| Systemd timers | 69 |
| Grafana dashboards | 31 |
| Database migraties | 19 |
| ADR-documenten | 17 |
| Pytest tests | 35 |
| CYD-schermen | 46 |
| CNN-vocalisatiemodellen | 197 |
| Stations | 6 (3 BirdNET + 1 sonar + 1 meteo + 1 mobiel) |
| Nestkast-camera's | 3 |
| Git commits | 837 |
docs/website-overzicht.md— Uitgebreide projectbeschrijvingdocs/adr/— Architecture Decision Recordsdocs/backup-restore-guide.md— Restore-proceduresdocs/degradation-policy.md— Graceful degradation per componentdocs/archive-system.md— Audio/spectrogram-archiefCLAUDE.md— Project-instructies + geleerde lessen
Ontwikkeld door Ronny Hullegie met assistentie van Claude AI (Anthropic). Locatie: Nijverdal, Overijssel — 52,3602° N, 6,4726° O.