This README documents the Python side of the KōreroNET node that runs on a
Raspberry Pi (or Linux desktop). It covers the GUI/launcher (koreronet-wakeup.py),
the batch pipeline (process.py), and the self-updater (updater.py), including
how to install them and register wakeup.py as a systemd user service.
koreronet-wakeup.py— GUI + orchestrator. Mounts Google Drive via rclone, pullsconfig.ini, runs a short UART session with the STM32, builds aremapped_times.csv, optionally launchesprocess.pyin a terminal, monitors fordone.ini, and manages the self-update workflow. (See inline comments.)process.py— Batch pipeline for BirdNET and KōreroNET (ResNet-34). Copies audio in batches to a RAM-disk, runs analyzers, writes per-file CSVs, creates mapped summaries, backs up positives (CSV + WAV chunks), and dropsdone.inion completion.updater.py— Atomic update applier. Pulls payload from cache (/home/bn15/_update_cache), replaces files in/home/bn15, then either reboots the system or relauncheskoreronet-wakeup.pyif aNO_REBOOTflag is present in the cache.
- Python 3.10+ (venv recommended)
- Packages (pip):
pyserial,librosa,soundfile,numpy,torch,torchvision,tqdm(optional),birdnet-analyzer(the Python API), and any UI deps for Tk (tkis present by default on RPi OS Desktop). rcloneinstalled and a remote named gdrive configured with access to your Drive (service account or OAuth).- A Google Drive folder structure with:
To the node/— incoming control/config and update files/From the node/— outputs uploaded by the nodeFrom the node/Power Logs/(and subfolderraw/) optionally used by wakeup
- A connected STM32 node on
/dev/ttyAMA0(default) or another serial port.
These match the scripts’ constants so your systemd unit does not need extra env:
- *BN15 root
- GUI/logs
- Local OUT (wakeup)`
- Pipeline OUT (process)
- Export (local)
- Google Drive mount
- Drive “To the node”
- Drive “From the node”
- Update pickup / / then applied by
updater.py.
Place your config.ini on Drive at To the node/config.ini. The GUI will copy
it to /home/bn15/config.ini on start. Recognized keys (whitespace and
case ignored; key = value or key: value both OK):
BirdNET & KōreroNET thresholds and assets (used by process.py):
birdnet=1|0— enable/disable BirdNETkoreronet=1|0— enable/disable KōreroNETbirdnetconf=0.70— minimum confidence for BirdNET (legacy fallbacks:conf,confidence,min_confaccepted)koreronetconf=0.60— minimum probability for KōreroNEToverlap=2.5— seconds of overlap for 5 s windows (both pipelines)lat,lon,week— BirdNET geo/temporal params;week=1picks current ISO weekcheckpoint=/path/to/koreronetsonicXX.pth— KōreroNET checkpointclassmap=/path/to/classmap.csv— id→label mapping for KōreroNETbirdnetchunklen=5.0,birdnetprepad=1.0,birdnetpostpad=1.0— BN chunk sizing
Timetable (optional; parsed by the GUI if provided):
timetable={S,U,0,P,...(24 entries)},{rec_seconds,sleep_seconds}
- Ensures folders exist locally; mounts Drive (
rclone mount gdrive:→/mnt/gdrive) and copiesTo the node/config.inilocally if available. - Self-update: if Drive folder
To the node/update files/contains any files (exceptdone.ini), copies them to_update_cache/, purges the Drive folder, writes a completion markerdone.inithere, and spawnsupdater.py, exiting immediately so files can be replaced safely. - UART session: opens
/dev/ttyAMA0@ 115200-8-N-1 and sends a few short commands to the STM32 (power stats, history, timetable request). It logs the responses tobn15/logs/session_*.logand writes each command’s output as a text file inbn15/out/. - Timemap build: constructs
remapped_times.csvinbn15/out/by scanning the removable drive (/media/16GB DRIVE) and aligning files onto the intended timetable windows (or uses the timetable inconfig.iniif present). - Optional run: when
birdnet=1, launchesprocess.pyin a new terminal, otherwise skips analysis. - done.ini monitor: watches
/home/KoreroNET/out/done.ini. When the pipeline drops it, the GUI performs a short wrap-up and removes stale flags.
- Reads
config.ini, computes BirdNET & KōreroNET parameters. - Copies audio in batches to a RAM-disk (
/dev/shm/korero_stage) using big-buffer orsendfile()-based copy for speed. - BirdNET: calls the Python API (
birdnet_analyzer.analyze.core.analyze) with threads, min_conf, geo/temporal args, and optional overlap. Produces per-file CSVs under/home/KoreroNET/out. - KōreroNET (ResNet-34 pipeline matching your training):
- Audio → mono 48 kHz → mel-spectrogram (HTK scale,
n_fft=512,hop=128,n_mels=224,fmin=150,fmax=20000, power=2.0 → dB → z-score), then resize to 224×224; to-RGB if the checkpoint expects it. - Sliding 5 s windows (with
overlapin seconds), softmax, thresholding. - Writes per-file CSVs and backs up positive 5 s chunks into
out/backup/koreronet/with filename format:<audio>__kn_<start>_<end>__<label>__p<prob>.wav(+ a CSV sidecar).
- Audio → mono 48 kHz → mel-spectrogram (HTK scale,
- Backups & indices:
- Copies per-file BirdNET CSVs that do contain detections into
out/backup/birdnet/, prefixing the file with the intended timestamp fromremapped_times.csvwhen available. - Appends rows from per-file CSVs into running index CSVs in
out/backup/.
- Copies per-file BirdNET CSVs that do contain detections into
- Mapped summaries (BN & KN): creates
*_detections_mapped_YYYYMMDD_HHMMSS.csvwith an extraActualTimecolumn derived fromremapped_times.csv. - On completion, writes
/home/KoreroNET/out/done.inifor the GUI.
- Uses
.updater.lockto avoid concurrent runs. - Waits briefly for the GUI to exit, atomically replaces files in BN15
from
_update_cache/(preserves permissions), cleans the cache,syncs FS. - If
NO_REBOOTexists in the cache: skips reboot and relaunches the GUI. Otherwise it tries several reboot commands; if all fail, it relaunches the GUI.
# As user 'amin' on the Pi:
python3 -m venv /home/bn15
/home/bn15/bin/pip install --upgrade pip
/home/bn15/bin/pip install pyserial librosa soundfile numpy torch torchvision birdnet-analyzer tqdm
# (Optional extras you use: matplotlib, pandas, etc.)# Configure a remote called 'gdrive'
rclone config
# Test the remote
rclone lsd gdrive:
# (Optional) Manual mount test:
mkdir -p /mnt/gdrive
rclone mount gdrive: /mnt/gdrive --vfs-cache-mode=writes --allow-other --daemonCreate the unit file at: ~/.config/systemd/user/koreronet-wakeup.service
[Unit]
Description=KōreroNET Wakeup GUI (user)
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
# Use the project venv if present; fall back to system Python otherwise
ExecStart=/home/bn15/bin/python3 -u /home/bn15/koreronet-wakeup.py
WorkingDirectory=/home/bn15
Restart=always
RestartSec=3
# If running on a desktop session with GUI, ensure DISPLAY is available:
Environment=PYTHONUNBUFFERED=1
# Uncomment if you need to force the display/shell
# Environment=DISPLAY=:0
# Environment=XDG_RUNTIME_DIR=/run/user/%U
[Install]
WantedBy=default.target
Enable and start it:
systemctl --user daemon-reload
systemctl --user enable koreronet-wakeup.service
systemctl --user start koreronet-wakeup.service
# View logs
journalctl --user -u koreronet-wakeup.service -fIf running headless (no desktop), you can still keep the service;
the GUI will log to bn15/logs/ and run the UART + pipeline orchestration.
If you require a virtual display for any reason, consider xvfb-run or use
a terminal-only mode (future enhancement).
/home/bn15/bin/python3 -u /home/bn15/koreronet-wakeup.py- User (or automation) drops new audio on the removable drive and updates
To the node/config.inias needed. - Service starts
koreronet-wakeup.pyat login/boot; it mounts Drive, pulls config, checks update files, and spawnsupdater.pyif needed. - GUI runs a short UART session with STM32, logs snapshots & history, and builds remapped_times.csv.
- If
birdnet=1, it launches the process.py pipeline; else you can start it manually later. When the pipeline finishes, it writes done.ini. - GUI sees
done.ini, cleans up stale flags, and you’ll find artifacts under/home/KoreroNET/out/andFrom the node/on Drive.
- Per-file CSVs:
/home/KoreroNET/out/*.csv - Mapped summaries:
/home/KoreroNET/out/*_detections_mapped_*.csv - Backups:
.../out/backup/birdnet/*.BirdNET.results.csv(only those with detections, time-prefixed when mapped).../out/backup/koreronet/*.wav(+ CSV sidecars) for positive chunks
- Indices:
.../out/backup/birdnet_detections_all.csvand/orkoreronet_detections_all.csv - Completion flag:
/home/KoreroNET/out/done.ini - GUI logs:
/home/bn15/logs/ - Update cache:
/home/bn15/_update_cache/
- Service doesn’t start:
journalctl --user -u koreronet-wakeup.service -e. Check Python paths, permissions, and rclone availability on PATH. - Drive not mounted: run
rclone version; verify thegdriveremote; try a manualrclone mount(see above). - UART port not found: adjust
CANDIDATE_PORTSin the script to your device (e.g.,/dev/ttyUSB0). Ensure user is in thedialoutgroup. - No BirdNET outputs: ensure
birdnet=1and threshold is not too high. Confirm thebirdnet-analyzerpackage and its model files are accessible. - KōreroNET checkpoint missing: set
checkpoint=inconfig.iniand ensure the path is readable by the service user. If the model expects RGB, the script will expand 1→3 channels automatically. - Updates not applying: confirm files were dropped to
To the node/update files/and that_update_cache/fills on the Pi. Look atbn15/logs/updater_*.log.
Code is licensed under the Polyform Noncommercial License 1.0.0 (non‑commercial use, attribution required, no warranty). Documentation (this README) may be used under CC BY‑NC 4.0. If you prefer a single license, keep everything under Polyform Noncommercial.
© 2025 KōreroNET Project