#!/bin/sh set -eu if [ "$(id -u)" -ne 0 ]; then echo "deploy_walnutpi.sh must run as root" >&2 exit 1 fi SOURCE_ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) PROJECT_ROOT=$(CDPATH= cd -- "$SOURCE_ROOT/.." && pwd) WHEELHOUSE=${WHEELHOUSE:-$PROJECT_ROOT/发布更新相关/其他依赖/aarch64-py311} FRPC_BUNDLE=${FRPC_BUNDLE:-$PROJECT_ROOT/发布更新相关/其他依赖/frp/0.71.0/linux-arm64} DEFER_SERVICE_START=${DEFER_SERVICE_START:-0} MANIFEST=$WHEELHOUSE/SHA256SUMS TARGET=/opt/matrix-screen-controller UNIT=/etc/systemd/system/matrix-screen-controller.service OTA_UNIT=/etc/systemd/system/matrix-screen-controller-ota.service CONVERTER_UNIT=/etc/systemd/system/matrix-screen-converter@.service if [ "$(uname -m)" != "aarch64" ]; then echo "this payload is only for the WalnutPi AArch64 host" >&2 exit 1 fi for command in ffmpeg ffprobe heif-convert flock; do if ! command -v "$command" >/dev/null 2>&1; then echo "required media decoder command is missing: $command" >&2 echo "install Debian packages ffmpeg and libheif-examples before deployment" >&2 exit 1 fi done FILTERS=$(ffmpeg -hide_banner -filters 2>/dev/null) for filter in zscale tonemap; do if ! printf '%s\n' "$FILTERS" | grep -Eq "[[:space:]]$filter[[:space:]]"; then echo "required FFmpeg filter is missing: $filter" >&2 exit 1 fi done if [ ! -f "$MANIFEST" ]; then echo "offline wheel manifest missing: $MANIFEST" >&2 exit 1 fi if [ -e "$TARGET" ]; then if [ "$DEFER_SERVICE_START" != "1" ]; then echo "$TARGET already exists; this fresh-install script will not overwrite it" >&2 exit 1 fi if [ ! -f "$TARGET/VERSION" ] || [ "$(cat "$TARGET/VERSION")" != "$(cat "$SOURCE_ROOT/VERSION")" ]; then echo "$TARGET exists but is not the same software version; refusing first-boot recovery" >&2 exit 1 fi for path in \ "$TARGET/.venv/bin/python" \ "$TARGET/scripts/dedicated_host.py" \ "$TARGET/app/display/native/libh618_hub75.so" \ "$TARGET/app/display/native/hub75_safeoff" \ "$TARGET/systemd/matrix-screen-controller.service" \ "$TARGET/systemd/matrix-screen-controller-ota.service" \ "$TARGET/systemd/matrix-screen-converter@.service"; do if [ ! -e "$path" ]; then echo "incomplete first-boot deployment cannot be recovered: $path" >&2 exit 1 fi done FRPC_BUNDLE="$FRPC_BUNDLE" DEFER_SERVICE_START=1 /bin/sh "$TARGET/scripts/install_frpc_system.sh" "$TARGET/.venv/bin/python" "$TARGET/scripts/dedicated_host.py" check --service install -m 0644 "$TARGET/systemd/matrix-screen-controller.service" "$UNIT" install -m 0644 "$TARGET/systemd/matrix-screen-controller-ota.service" "$OTA_UNIT" install -m 0644 "$TARGET/systemd/matrix-screen-converter@.service" "$CONVERTER_UNIT" systemctl daemon-reload systemctl enable matrix-screen-controller.service systemctl is-enabled --quiet matrix-screen-controller.service echo "Recovered the verified same-version deployment; service start is deferred until reboot" exit 0 fi (cd "$WHEELHOUSE" && sha256sum -c SHA256SUMS) STAGING=$(mktemp -d /opt/matrix-screen-controller.stage.XXXXXX) cleanup() { case ${STAGING:-} in /opt/matrix-screen-controller.stage.*) if [ -d "$STAGING" ]; then rm -rf -- "$STAGING" fi ;; esac } trap cleanup EXIT HUP INT TERM cp -a "$SOURCE_ROOT/." "$STAGING/" python3 -m venv "$STAGING/.venv" "$STAGING/.venv/bin/pip" install \ --no-index \ --find-links "$WHEELHOUSE" \ -r "$STAGING/requirements.txt" make -C "$STAGING/app/display/native" clean all test systemctl set-default multi-user.target systemctl disable --now \ lightdm.service \ gpioc-server.service \ map_device.service DEFER_SERVICE_START="$DEFER_SERVICE_START" /bin/sh "$STAGING/scripts/install_mobile_bluetooth.sh" if [ "$DEFER_SERVICE_START" = "1" ]; then "$STAGING/.venv/bin/python" "$STAGING/scripts/dedicated_host.py" check --service else "$STAGING/.venv/bin/python" "$STAGING/scripts/dedicated_host.py" check fi install -d -m 0711 /var/lib/matrix-screen-controller install -d -m 0750 /run/matrix-screen-controller mv -- "$STAGING" "$TARGET" STAGING= FRPC_BUNDLE="$FRPC_BUNDLE" DEFER_SERVICE_START="$DEFER_SERVICE_START" /bin/sh "$TARGET/scripts/install_frpc_system.sh" install -m 0644 "$TARGET/systemd/matrix-screen-controller.service" "$UNIT" install -m 0644 "$TARGET/systemd/matrix-screen-controller-ota.service" "$OTA_UNIT" install -m 0644 "$TARGET/systemd/matrix-screen-converter@.service" "$CONVERTER_UNIT" systemctl daemon-reload if [ "$DEFER_SERVICE_START" = "1" ]; then systemctl enable matrix-screen-controller.service systemctl is-enabled --quiet matrix-screen-controller.service echo "WalnutPi Matrix Screen Controller installed; service start is deferred until reboot" exit 0 fi systemctl enable --now matrix-screen-controller.service attempt=0 while [ "$attempt" -lt 30 ]; do if curl --fail --silent http://127.0.0.1:8080/api/status >/dev/null; then break fi attempt=$((attempt + 1)) sleep 1 done systemctl --no-pager --full status matrix-screen-controller.service curl --fail --silent --show-error http://127.0.0.1:8080/api/status >/dev/null echo "WalnutPi Matrix Screen Controller deployed successfully"