deploy/setup_online.sh installs system packages (picamera2, hailo-all best-effort), builds the venv + pip deps, fetches the MoveNet model, writes /etc/move-detect/edge.env (prompting or from env vars), installs the systemd unit and starts the service — one command, no offline bundle. Starts on CPU MoveNet; drop in a HEF for Hailo. numpy left to the system to avoid shadowing picamera2's build. Air-gapped path (deploy/bundle/*) unchanged.
114 lines
4.8 KiB
Bash
114 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
# ONE-COMMAND online installer for an INTERNET-CONNECTED Raspberry Pi 5.
|
|
# Installs everything and starts the service. For AIR-GAPPED Pis use deploy/bundle/*.
|
|
#
|
|
# Run from a clone/copy of this repo, as root:
|
|
# sudo deploy/setup_online.sh
|
|
#
|
|
# Non-interactive: pass values as env vars, e.g.
|
|
# sudo DEVICE_ID=pi-01 DEVICE_SECRET=... CAFE24_URL=https://cloud CAMERAS=csi:0:cam-01,uvc:0:cam-02 \
|
|
# HAILO_HEF=/home/pi/yolov8s_pose.hef deploy/setup_online.sh
|
|
# Interactive (a real terminal): it prompts for anything not passed.
|
|
set -euo pipefail
|
|
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "run as root: sudo $0" >&2
|
|
exit 1
|
|
fi
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
PREFIX=/opt/move-detect
|
|
STATE=/var/lib/move-detect
|
|
ETC=/etc/move-detect
|
|
SVC_USER=movedetect
|
|
|
|
echo ">> [1/8] system packages (CSI camera, venv; Hailo runtime best-effort)"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update
|
|
apt-get install -y python3-picamera2 python3-venv python3-pip
|
|
# hailo-all is the Hailo driver+runtime; only present in Pi repos with a Hailo HAT.
|
|
# Best-effort so a Pi without it still installs and runs on CPU MoveNet.
|
|
apt-get install -y hailo-all || echo " WARN: hailo-all not installed — Hailo accel unavailable, CPU MoveNet will be used."
|
|
|
|
echo ">> [2/8] service account + device groups"
|
|
id -u "$SVC_USER" >/dev/null 2>&1 || useradd --system --no-create-home --shell /usr/sbin/nologin "$SVC_USER"
|
|
for g in video render plugdev hailo; do
|
|
getent group "$g" >/dev/null 2>&1 && usermod -aG "$g" "$SVC_USER" || true
|
|
done
|
|
|
|
echo ">> [3/8] source + dirs under $PREFIX"
|
|
install -d -m 0755 "$PREFIX" "$PREFIX/src" "$PREFIX/models" "$PREFIX/docs"
|
|
rm -rf "$PREFIX/src/edge" # full replace on re-run (no nested edge/edge)
|
|
cp -r "$REPO_ROOT/edge" "$PREFIX/src/edge"
|
|
cp "$REPO_ROOT/pyproject.toml" "$PREFIX/src/" 2>/dev/null || true
|
|
find "$PREFIX/src" -name __pycache__ -type d -prune -exec rm -rf {} +
|
|
cp "$REPO_ROOT/docs/pilot-runbook.md" "$PREFIX/docs/" 2>/dev/null || true
|
|
|
|
echo ">> [4/8] venv (+ system site-packages) + pip runtime deps"
|
|
python3 -m venv --system-site-packages "$PREFIX/venv"
|
|
"$PREFIX/venv/bin/pip" install --upgrade pip >/dev/null
|
|
# numpy is intentionally NOT pinned here: it comes in transitively via onnxruntime, and
|
|
# leaving the system numpy in place (the venv sees it) avoids shadowing the numpy that
|
|
# the apt python3-picamera2 stack was compiled against.
|
|
"$PREFIX/venv/bin/pip" install requests onnxruntime opencv-python-headless
|
|
|
|
echo ">> [5/8] MoveNet CPU model"
|
|
( cd "$REPO_ROOT" && "$PREFIX/venv/bin/python" -m edge.tools.fetch_movenet )
|
|
cp "$REPO_ROOT/models/movenet_lightning.onnx" "$PREFIX/models/" 2>/dev/null || true
|
|
|
|
echo ">> [6/8] pose backend"
|
|
POSE_BACKEND=movenet
|
|
HEF_DEST="$PREFIX/models/yolov8s_pose.hef"
|
|
if [ -n "${HAILO_HEF:-}" ] && [ -f "${HAILO_HEF:-}" ]; then
|
|
cp "$HAILO_HEF" "$HEF_DEST"
|
|
POSE_BACKEND=hailo
|
|
echo " -> Hailo HEF installed; POSE_BACKEND=hailo"
|
|
else
|
|
echo " -> no HAILO_HEF given; starting on CPU MoveNet."
|
|
echo " For Hailo: copy yolov8s_pose.hef to $HEF_DEST, set POSE_BACKEND=hailo in"
|
|
echo " $ETC/edge.env, then: sudo systemctl restart move-detect-edge"
|
|
fi
|
|
|
|
echo ">> [7/8] config -> $ETC/edge.env"
|
|
install -d -m 0750 "$STATE"; chown "$SVC_USER":"$SVC_USER" "$STATE"
|
|
install -d -m 0750 "$ETC"
|
|
if [ -f "$ETC/edge.env" ]; then
|
|
echo " -> $ETC/edge.env already exists; left unchanged"
|
|
else
|
|
: "${DEVICE_ID:=}"; : "${DEVICE_SECRET:=}"; : "${CAFE24_URL:=}"; : "${CAMERAS:=}"
|
|
if [ -t 0 ]; then
|
|
[ -n "$DEVICE_ID" ] || read -rp "DEVICE_ID [pi-01]: " DEVICE_ID
|
|
[ -n "$DEVICE_SECRET" ] || { read -rsp "DEVICE_SECRET (from cloud): " DEVICE_SECRET; echo; }
|
|
[ -n "$CAFE24_URL" ] || read -rp "CAFE24_URL (cloud base URL): " CAFE24_URL
|
|
[ -n "$CAMERAS" ] || read -rp "CAMERAS [csi:0:cam-01,uvc:0:cam-02]: " CAMERAS
|
|
fi
|
|
DEVICE_ID="${DEVICE_ID:-pi-01}"
|
|
CAMERAS="${CAMERAS:-csi:0:cam-01,uvc:0:cam-02}"
|
|
# Every line is a bare KEY=value (systemd EnvironmentFile= keeps inline text literally).
|
|
umask 077
|
|
cat > "$ETC/edge.env" <<EOF
|
|
DEVICE_ID=$DEVICE_ID
|
|
DEVICE_SECRET=$DEVICE_SECRET
|
|
CAFE24_URL=$CAFE24_URL
|
|
CAMERAS=$CAMERAS
|
|
POSE_BACKEND=$POSE_BACKEND
|
|
HAILO_HEF=$HEF_DEST
|
|
MOVENET_ONNX=$PREFIX/models/movenet_lightning.onnx
|
|
QUEUE_DB=$STATE/queue.db
|
|
TARGET_FPS=12
|
|
EOF
|
|
chown root:"$SVC_USER" "$ETC/edge.env"
|
|
chmod 0640 "$ETC/edge.env"
|
|
[ -n "$DEVICE_SECRET" ] || echo " NOTE: DEVICE_SECRET is empty — set it in $ETC/edge.env before the cloud will accept events."
|
|
echo " -> wrote $ETC/edge.env"
|
|
fi
|
|
|
|
echo ">> [8/8] systemd service"
|
|
install -m 0644 "$REPO_ROOT/deploy/systemd/move-detect-edge.service" /etc/systemd/system/
|
|
systemctl daemon-reload
|
|
systemctl enable --now move-detect-edge
|
|
|
|
echo ""
|
|
echo "Done. The edge daemon is installed and started."
|
|
echo " logs: journalctl -u move-detect-edge -f"
|
|
echo " config: sudo nano $ETC/edge.env (then: sudo systemctl restart move-detect-edge)"
|