diff --git a/frame/README.md b/frame/README.md index ab1a8d5..8351d66 100644 --- a/frame/README.md +++ b/frame/README.md @@ -65,4 +65,4 @@ Pick how the frame gets its birds: Each one enables SPI + I2C, installs the deps and a systemd timer, writes `~/.birdframe/config.toml`, and reboots once to bring SPI up. Full options live in [`config.example.toml`](config.example.toml). -BirdWeather mode renders on the Pi from this repo's illustrations on GitHub, so there is no image set to copy over. ZIP codes with no station nearby fall back to the closest ones, and an optional `EBIRD_API_KEY` covers the most remote spots. +BirdWeather mode renders on the Pi from this repo's illustrations on GitHub, so there is no image set to copy over. ZIP codes with no station nearby fall back to the closest ones. If you are far from any BirdWeather station, add `--ebird-key ` (a free key from [ebird.org/api/keygen](https://ebird.org/api/keygen)) and the frame fills from eBird sightings instead. diff --git a/frame/install.sh b/frame/install.sh index 1a2644f..da9c442 100755 --- a/frame/install.sh +++ b/frame/install.sh @@ -8,6 +8,7 @@ # ./install.sh --image-url fetch a ready-made frame PNG instead # (e.g. a public Cloudflare Worker) # ./install.sh --bird-weather --zip standalone from BirdWeather, no mic +# (add --ebird-key for remote ZIPs) set -euo pipefail cd "$(dirname "$0")" FRAME="$(pwd)" @@ -15,6 +16,7 @@ FRAME="$(pwd)" MODE=local # local | image | birdweather ZIP="" IMAGE_URL="" +EBIRD_KEY="" while [ $# -gt 0 ]; do case "$1" in --bird-weather) MODE=birdweather; shift ;; @@ -24,6 +26,9 @@ while [ $# -gt 0 ]; do --image-url) [ $# -ge 2 ] || { echo "--image-url needs a URL, e.g. --image-url https://bird.example/frame.png" >&2; exit 1; } MODE=image; IMAGE_URL="$2"; shift 2 ;; --image-url=*) MODE=image; IMAGE_URL="${1#*=}"; shift ;; + --ebird-key) [ $# -ge 2 ] || { echo "--ebird-key needs a value (a free key from ebird.org/api/keygen)" >&2; exit 1; } + EBIRD_KEY="$2"; shift 2 ;; + --ebird-key=*) EBIRD_KEY="${1#*=}"; shift ;; *) echo "unknown argument: $1" >&2; exit 1 ;; esac done @@ -32,6 +37,10 @@ if [ -n "$ZIP" ] && [ "$MODE" != birdweather ]; then echo "--zip only applies with --bird-weather" >&2 exit 1 fi +if [ -n "$EBIRD_KEY" ] && [ "$MODE" != birdweather ]; then + echo "--ebird-key only applies with --bird-weather" >&2 + exit 1 +fi # Validate inputs up front: a bad value would otherwise land in a config file or # a systemd unit verbatim. These checks also reject a flag passed as a value @@ -45,6 +54,10 @@ if [ "$MODE" = birdweather ]; then echo "--zip should look like a postal code, e.g. 94107 or SW1A 1AA" >&2 exit 1 fi + if [ -n "$EBIRD_KEY" ] && ! printf '%s' "$EBIRD_KEY" | LC_ALL=C grep -qE '^[A-Za-z0-9]+$'; then + echo "--ebird-key should be the alphanumeric token from ebird.org/api/keygen" >&2 + exit 1 + fi fi if [ "$MODE" = image ]; then if [ -z "$IMAGE_URL" ]; then @@ -151,6 +164,10 @@ Environment=PYTHONUNBUFFERED=1 Nice=10 TimeoutStartSec=300 SERVICE + # Remote ZIPs with no nearby station fall back to eBird, which needs a key. + if [ -n "$EBIRD_KEY" ]; then + echo "Environment=EBIRD_API_KEY=$EBIRD_KEY" | sudo tee -a /etc/systemd/system/birdframe.service >/dev/null + fi # BirdWeather's recent-species list drifts slowly, so refresh a few times a day. sed 's|OnUnitActiveSec=.*|OnUnitActiveSec=6h|' systemd/birdframe.timer \ | sudo tee /etc/systemd/system/birdframe.timer >/dev/null