#!/usr/bin/env bash # Interactive installer for the AvianVisitors e-ink frame. # Walks you through configuration with prompts and sensible defaults, # then hands off to install.sh with the right flags. set -euo pipefail cd "$(dirname "$0")" # --- helpers ---------------------------------------------------------------- ask() { local prompt="$1" default="$2" var="$3" if [ -n "$default" ]; then printf '%s [%s]: ' "$prompt" "$default" >&2 else printf '%s: ' "$prompt" >&2 fi read -r input eval "$var=\"\${input:-\$default}\"" } pick() { local prompt="$1" var="$2" shift 2 echo "" >&2 echo "$prompt" >&2 local i=1 for opt in "$@"; do printf ' %d) %s\n' "$i" "$opt" >&2 i=$((i + 1)) done printf 'Choice [1]: ' >&2 read -r choice choice="${choice:-1}" eval "$var=\"$choice\"" } confirm() { printf '%s [Y/n]: ' "$1" >&2 read -r yn case "$yn" in [Nn]*) return 1 ;; *) return 0 ;; esac } hr() { echo "────────────────────────────────────────────────" >&2; } # --- start ------------------------------------------------------------------ echo "" echo " ╔═══════════════════════════════════════╗" echo " ║ AvianVisitors e-ink frame setup ║" echo " ╚═══════════════════════════════════════╝" echo "" # --- mode ------------------------------------------------------------------- pick "How will the frame get its birds?" MODE_CHOICE \ "Local BirdNET-Pi on my network (default)" \ "BirdWeather — no mic, uses nearby stations" \ "Image URL — fetch a pre-rendered frame PNG" INSTALL_FLAGS="" MODE="local" BASE_URL="" ZIP="" IMAGE_URL="" EBIRD_KEY="" case "$MODE_CHOICE" in 2) MODE="birdweather" echo "" >&2 ask "ZIP / postal code" "" ZIP if [ -z "$ZIP" ]; then echo "A ZIP code is required for BirdWeather mode." >&2 exit 1 fi INSTALL_FLAGS="--bird-weather --zip $ZIP" echo "" >&2 if confirm "Do you have an eBird API key? (helps if no BirdWeather stations nearby)"; then ask "eBird API key" "" EBIRD_KEY if [ -n "$EBIRD_KEY" ]; then INSTALL_FLAGS="$INSTALL_FLAGS --ebird-key $EBIRD_KEY" fi fi ;; 3) MODE="image" echo "" >&2 ask "Frame image URL" "" IMAGE_URL if [ -z "$IMAGE_URL" ]; then echo "A URL is required for image mode." >&2 exit 1 fi INSTALL_FLAGS="--image-url $IMAGE_URL" ;; *) MODE="local" echo "" >&2 ask "BirdNET-Pi address" "birdnet.local" BASE_URL ;; esac # --- frame & matte ---------------------------------------------------------- hr pick "What frame and matte are you using?" FRAME_CHOICE \ "A4 frame with A5 matte (stock kit)" \ "11×14 frame with 8×10 matte" \ "Full panel, no matte" \ "Custom dimensions" MAT_W=0 MAT_H=0 case "$FRAME_CHOICE" in 2) MAT_W=8; MAT_H=10 ;; 3) MAT_W=8.4; MAT_H=11.2 ;; 4) echo "" >&2 echo "Enter the matte opening size (the visible area, in inches):" >&2 ask " Opening width" "8" MAT_W ask " Opening height" "10" MAT_H ;; *) MAT_W=0; MAT_H=0 ;; esac # --- titles ----------------------------------------------------------------- hr echo "" >&2 TITLE="Avian Visitors" SUBTITLE="Heard Today" if confirm "Customize the frame title? (default: \"Avian Visitors\" / \"Heard Today\")"; then ask "Title (top line)" "Avian Visitors" TITLE ask "Subtitle (large text)" "Heard Today" SUBTITLE fi # --- rotation --------------------------------------------------------------- hr pick "Which way does the display hang?" ROTATE_CHOICE \ "USB cable exits bottom-right (rotate = 90)" \ "USB cable exits top-left (rotate = 270)" ROTATE=90 [ "$ROTATE_CHOICE" = "2" ] && ROTATE=270 # --- quiet hours ------------------------------------------------------------ hr QUIET_START=0 QUIET_END=0 if confirm "Set quiet hours? (skip refreshes overnight to avoid e-ink noise)"; then ask "Quiet start hour (0-23)" "22" QUIET_START ask "Quiet end hour (0-23)" "6" QUIET_END fi # --- basic auth ------------------------------------------------------------- hr BASIC_USER="" BASIC_PASS="" if [ "$MODE" = "local" ]; then if confirm "Is your BirdNET-Pi behind basic auth?"; then ask "Username" "" BASIC_USER ask "Password" "" BASIC_PASS fi fi # --- summary ---------------------------------------------------------------- hr echo "" >&2 echo " Configuration summary:" >&2 echo "" >&2 echo " Mode: $MODE" >&2 case "$MODE" in local) echo " BirdNET URL: http://$BASE_URL" >&2 ;; birdweather) echo " ZIP code: $ZIP" >&2 ;; image) echo " Image URL: $IMAGE_URL" >&2 ;; esac if [ "$MAT_W" != "0" ] && [ "$MAT_H" != "0" ]; then echo " Matte: ${MAT_W}\" × ${MAT_H}\"" >&2 else echo " Matte: A5 (stock)" >&2 fi echo " Title: $TITLE / $SUBTITLE" >&2 echo " Rotation: $ROTATE" >&2 if [ "$QUIET_START" != "0" ] || [ "$QUIET_END" != "0" ]; then echo " Quiet hours: ${QUIET_START}:00 – ${QUIET_END}:00" >&2 fi echo "" >&2 if ! confirm "Proceed with installation?"; then echo "Cancelled." >&2 exit 0 fi # --- run install.sh --------------------------------------------------------- hr echo "" >&2 echo "Running install.sh $INSTALL_FLAGS ..." >&2 echo "" >&2 ./install.sh $INSTALL_FLAGS # --- write extra config on top of what install.sh generated ----------------- CONFIG="$HOME/.birdframe/config.toml" # Patch base_url for local mode if not birdnet.local if [ "$MODE" = "local" ] && [ "$BASE_URL" != "birdnet.local" ]; then sed -i "s|^base_url = .*|base_url = \"http://$BASE_URL\"|" "$CONFIG" fi # Matte opening if [ "$MAT_W" != "0" ] && [ "$MAT_H" != "0" ]; then printf '\n# Matte opening size (inches). Overrides the default A5.\nmat_opening_w = %s\nmat_opening_h = %s\n' \ "$MAT_W" "$MAT_H" >> "$CONFIG" fi # Titles if [ "$TITLE" != "Avian Visitors" ] || [ "$SUBTITLE" != "Heard Today" ]; then sed -i "s|^shoot_title = .*|shoot_title = \"$TITLE\"|" "$CONFIG" sed -i "s|^shoot_subtitle = .*|shoot_subtitle = \"$SUBTITLE\"|" "$CONFIG" fi # Rotation sed -i "s|^rotate = .*|rotate = $ROTATE|" "$CONFIG" # Quiet hours if [ "$QUIET_START" != "0" ] || [ "$QUIET_END" != "0" ]; then if grep -q "^quiet_start" "$CONFIG" 2>/dev/null; then sed -i "s|^quiet_start = .*|quiet_start = $QUIET_START|" "$CONFIG" sed -i "s|^quiet_end = .*|quiet_end = $QUIET_END|" "$CONFIG" else printf '\nquiet_start = %s\nquiet_end = %s\n' "$QUIET_START" "$QUIET_END" >> "$CONFIG" fi fi # Basic auth if [ -n "$BASIC_USER" ]; then printf '\nbasic_user = "%s"\nbasic_pass = "%s"\n' "$BASIC_USER" "$BASIC_PASS" >> "$CONFIG" fi echo "" >&2 echo "Config written to $CONFIG" >&2 echo "Edit it any time: nano $CONFIG" >&2 echo "" >&2