diff --git a/README.md b/README.md index 09153936..8f10e1f6 100644 --- a/README.md +++ b/README.md @@ -34,5 +34,12 @@ npm install npm run start ``` +Deploy a rover by copying the repo + `dist/roverd` to the Pi and running the helper: + +```bash +cd ~/MultiRoombaRover +sudo ./pi/install_roverd.sh --mediamtx +``` + Then point each rover's `/etc/roverd.yaml` at `ws://:8080/rover`, enable the sensor stream from the UI, and drive with WASD. Use the “Restart Camera” button if you enable media management so roverd can bounce the mediamtx service remotely. diff --git a/dist/roverd b/dist/roverd new file mode 100755 index 00000000..117f8af1 Binary files /dev/null and b/dist/roverd differ diff --git a/docs/pi-deployment.md b/docs/pi-deployment.md index 09855f43..1e16ee61 100644 --- a/docs/pi-deployment.md +++ b/docs/pi-deployment.md @@ -18,7 +18,33 @@ make pi-build The binary is placed in `dist/roverd` (relative to the repo root). -## Installing `roverd` +## Automated installation (recommended) + +Once the binary (and repo) are on the Pi, run the helper script from the repo root: + +```bash +cd ~/MultiRoombaRover +sudo ./pi/install_roverd.sh --mediamtx +``` + +What the script does: + +- creates the `roverd` (and optionally `mediamtx`) service users if missing and installs `/usr/local/bin/roverd` +- copies `pi/roverd/roverd.sample.yaml` to `/etc/roverd.yaml` if the file is absent (existing configs are left untouched) +- installs/enables the `roverd.service` systemd unit, restarting it automatically when a config already exists +- when `--mediamtx` is passed, installs the sample mediaMTX config + unit, enables the service, and restarts it + +Flags: + +| Flag | Purpose | +|------|---------| +| `-b PATH` | use a different roverd binary (defaults to `dist/roverd`) | +| `-c PATH` | seed `/etc/roverd.yaml` from another template | +| `--mediamtx` | install the provided mediaMTX config + unit alongside roverd | + +If the script installs the sample config, it will remind you to edit `/etc/roverd.yaml` before manually restarting the service: set `name`, `serverUrl`, serial device, BRC pin, battery thresholds, and the WHEP URL that the central server should expose. + +## Manual installation 1. Copy the binary and config: ```bash diff --git a/pi/install_roverd.sh b/pi/install_roverd.sh new file mode 100755 index 00000000..9326db99 --- /dev/null +++ b/pi/install_roverd.sh @@ -0,0 +1,131 @@ +#!/usr/bin/env bash +# +# Installer for the roverd agent on Raspberry Pi + +set -euo pipefail + +BINARY_SRC="dist/roverd" +CONFIG_SRC="pi/roverd/roverd.sample.yaml" +INSTALL_MEDIAMTX=0 + +usage() { + cat <<'USAGE' +Usage: sudo ./pi/install_roverd.sh [options] + +Options: + -b, --binary Path to the roverd binary (default: dist/roverd) + -c, --config Source config to install if /etc/roverd.yaml is missing + (default: pi/roverd/roverd.sample.yaml) + --mediamtx Also install mediaMTX unit/config (requires pi/mediamtx files) + -h, --help Show this help text + +The script must run from the repository root and as root (sudo). It will: + * create system users/groups if needed + * install /usr/local/bin/roverd and /etc/roverd.yaml + * install /etc/systemd/system/roverd.service and enable the service + * optionally install mediaMTX config/unit when --mediamtx is set +USAGE +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -b|--binary) + BINARY_SRC="${2:-}" + shift 2 + ;; + -c|--config) + CONFIG_SRC="${2:-}" + shift 2 + ;; + --mediamtx) + INSTALL_MEDIAMTX=1 + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage + exit 1 + ;; + esac +done + +if [[ "${EUID}" -ne 0 ]]; then + echo "Please run as root (sudo)" >&2 + exit 1 +fi + +if [[ ! -f "$BINARY_SRC" ]]; then + echo "Binary not found at $BINARY_SRC" >&2 + exit 1 +fi + +if [[ ! -f "$CONFIG_SRC" ]]; then + echo "Config source not found at $CONFIG_SRC" >&2 + exit 1 +fi + +ensure_user() { + local user="$1" + local groups="$2" + if ! id -u "$user" >/dev/null 2>&1; then + useradd -r -s /usr/sbin/nologin -G "$groups" "$user" + fi +} + +log() { + echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" +} + +ensure_user roverd "dialout,gpio" +install -o roverd -g roverd -m 0755 "$BINARY_SRC" /usr/local/bin/roverd +log "Installed roverd binary" + +CONFIG_DEST="/etc/roverd.yaml" +CONFIG_EXISTS=0 +if [[ -f "$CONFIG_DEST" ]]; then + CONFIG_EXISTS=1 + log "Existing $CONFIG_DEST found; leaving it in place" +else + install -D -o roverd -g roverd -m 0640 "$CONFIG_SRC" "$CONFIG_DEST" + log "Installed sample config to $CONFIG_DEST (edit before starting service)" +fi + +install -m 0644 pi/systemd/roverd.service /etc/systemd/system/roverd.service +log "Installed roverd systemd unit" + +systemctl daemon-reload +systemctl enable roverd.service +if [[ $CONFIG_EXISTS -eq 1 ]]; then + systemctl restart roverd.service + log "Restarted roverd.service" +else + log "Skipped auto-start because config is the sample; edit $CONFIG_DEST then run: sudo systemctl restart roverd" +fi + +if [[ $INSTALL_MEDIAMTX -eq 1 ]]; then + if [[ ! -f "pi/mediamtx/mediamtx.yml" ]]; then + echo "pi/mediamtx/mediamtx.yml missing, cannot install mediaMTX config" >&2 + exit 1 + fi + if [[ ! -f "pi/systemd/mediamtx.service" ]]; then + echo "pi/systemd/mediamtx.service missing, cannot install mediaMTX unit" >&2 + exit 1 + fi + + ensure_user mediamtx "" + install -d -o mediamtx -g mediamtx /etc/mediamtx + install -o mediamtx -g mediamtx -m 0644 pi/mediamtx/mediamtx.yml /etc/mediamtx/mediamtx.yml + install -m 0644 pi/systemd/mediamtx.service /etc/systemd/system/mediamtx.service + log "Installed mediamtx config and unit" + + systemctl daemon-reload + systemctl enable mediamtx.service + systemctl restart mediamtx.service + log "Restarted mediamtx.service" +fi + +log "Install complete"