diff --git a/.gitea/workflows/build-sd-image.yml b/.gitea/workflows/build-sd-image.yml index 88b4f13..30d2d73 100644 --- a/.gitea/workflows/build-sd-image.yml +++ b/.gitea/workflows/build-sd-image.yml @@ -32,7 +32,7 @@ jobs: - name: Prepare pi-gen stage files run: | - STAGE_FILES="tools/pi-gen-tipote/stage-tipote/01-install-tipote/files" + STAGE_FILES="tools/pi-gen-tipote/stage3/01-install-tipote/files" rm -rf "$STAGE_FILES" mkdir -p "$STAGE_FILES" diff --git a/tools/pi-gen-tipote/Dockerfile b/tools/pi-gen-tipote/Dockerfile index dfa0c78..f6e80c2 100644 --- a/tools/pi-gen-tipote/Dockerfile +++ b/tools/pi-gen-tipote/Dockerfile @@ -19,9 +19,9 @@ RUN git clone --depth 1 --branch bookworm https://github.com/RPi-Distro/pi-gen.g # Copy config and stage COPY config /build/pi-gen/config -COPY stage-tipote/ /build/pi-gen/stage-tipote/ +COPY stage3/ /build/pi-gen/stage3/ -# Skip stage2 image export (we export from stage-tipote) +# Skip stage2 image export (we export from stage3) RUN touch /build/pi-gen/stage2/SKIP_IMAGES # Patch pi-gen for Docker compatibility: diff --git a/tools/pi-gen-tipote/config b/tools/pi-gen-tipote/config index c0f048b..3228172 100644 --- a/tools/pi-gen-tipote/config +++ b/tools/pi-gen-tipote/config @@ -10,4 +10,4 @@ TIMEZONE_DEFAULT=Europe/Paris ENABLE_SSH=1 # Only run base stages + our custom stage (skip desktop/apps) -STAGE_LIST="stage0 stage1 stage2 stage-tipote" +STAGE_LIST="stage0 stage1 stage2 stage3" diff --git a/tools/pi-gen-tipote/deploy.sh b/tools/pi-gen-tipote/deploy.sh index 738f2f5..3268bfb 100755 --- a/tools/pi-gen-tipote/deploy.sh +++ b/tools/pi-gen-tipote/deploy.sh @@ -61,8 +61,9 @@ $SSH "echo 'SSH OK — $(uname -m) — $(cat /etc/os-release | grep PRETTY_NAME echo "▸ [3/7] Installing system dependencies..." $SSH "sudo apt-get update -qq && sudo apt-get install -y -qq \ python3 python3-venv python3-pip \ - portaudio19-dev libatlas-base-dev alsa-utils \ - network-manager curl" + portaudio19-dev alsa-utils \ + network-manager curl \ + libsystemd-dev build-essential" # Install Node.js 22 if not present $SSH "node --version 2>/dev/null | grep -q 'v22' || { diff --git a/tools/pi-gen-tipote/stage-tipote/00-install-deps/00-packages b/tools/pi-gen-tipote/stage3/00-install-deps/00-packages similarity index 100% rename from tools/pi-gen-tipote/stage-tipote/00-install-deps/00-packages rename to tools/pi-gen-tipote/stage3/00-install-deps/00-packages diff --git a/tools/pi-gen-tipote/stage-tipote/00-install-deps/00-run.sh b/tools/pi-gen-tipote/stage3/00-install-deps/00-run.sh similarity index 100% rename from tools/pi-gen-tipote/stage-tipote/00-install-deps/00-run.sh rename to tools/pi-gen-tipote/stage3/00-install-deps/00-run.sh diff --git a/tools/pi-gen-tipote/stage-tipote/01-install-tipote/00-run.sh b/tools/pi-gen-tipote/stage3/01-install-tipote/00-run.sh similarity index 100% rename from tools/pi-gen-tipote/stage-tipote/01-install-tipote/00-run.sh rename to tools/pi-gen-tipote/stage3/01-install-tipote/00-run.sh diff --git a/tools/pi-gen-tipote/stage3/01-install-tipote/files/journald-tipote.conf b/tools/pi-gen-tipote/stage3/01-install-tipote/files/journald-tipote.conf new file mode 100644 index 0000000..dca620a --- /dev/null +++ b/tools/pi-gen-tipote/stage3/01-install-tipote/files/journald-tipote.conf @@ -0,0 +1,6 @@ +# /etc/systemd/journald.conf.d/tipote.conf +# Limit journal size on Pi Zero 2W (32GB SD card) +[Journal] +SystemMaxUse=50M +SystemMaxFileSize=10M +MaxRetentionSec=7day diff --git a/tools/pi-gen-tipote/stage3/01-install-tipote/files/package.json b/tools/pi-gen-tipote/stage3/01-install-tipote/files/package.json new file mode 100644 index 0000000..37ae60b --- /dev/null +++ b/tools/pi-gen-tipote/stage3/01-install-tipote/files/package.json @@ -0,0 +1,41 @@ +{ + "name": "@ti-pote/robot-client", + "version": "0.0.1", + "private": true, + "type": "module", + "description": "Ti-Pote Robot Client — Runs on Raspberry Pi Zero 2W", + "bin": { + "tipote": "./dist/cli.js" + }, + "scripts": { + "dev": "tsx watch src/main.ts", + "build": "tsup src/main.ts src/cli.ts --format esm --dts --clean", + "start": "node dist/main.js", + "lint": "eslint \"src/**/*.ts\" --fix", + "format": "prettier --write \"src/**/*.ts\"", + "test": "vitest run", + "test:watch": "vitest", + "hw:demo": "pnpm exec tsx scripts/hardware-demo.ts", + "audio:loopback": "pnpm exec tsx scripts/audio-loopback.ts", + "audio:beep": "pnpm exec tsx scripts/audio-beep.ts", + "esp:record": "pnpm exec tsx ../robot-hardware/scripts/esp-record.ts", + "esp:play": "pnpm exec tsx ../robot-hardware/scripts/esp-play.ts" + }, + "dependencies": { + "socket.io-client": "^4.8.3", + "dotenv": "^17.3.1", + "pino": "^9.6.0", + "pino-pretty": "^13.0.0", + "serialport": "^12.0.0", + "sd-notify": "^2.8.0" + }, + "devDependencies": { + "typescript": "^5.8.3", + "tsx": "^4.21.0", + "tsup": "^8.5.0", + "@types/node": "^22.15.0", + "vitest": "^3.2.1", + "eslint": "^10.1.0", + "prettier": "^3.8.1" + } +} diff --git a/tools/pi-gen-tipote/stage3/01-install-tipote/files/tipote.service b/tools/pi-gen-tipote/stage3/01-install-tipote/files/tipote.service new file mode 100644 index 0000000..e120fd9 --- /dev/null +++ b/tools/pi-gen-tipote/stage3/01-install-tipote/files/tipote.service @@ -0,0 +1,37 @@ +[Unit] +Description=Ti-Pote Robot Client +After=network.target NetworkManager.service +Wants=NetworkManager.service + +[Service] +Type=notify +ExecStart=/usr/bin/node /opt/tipote/dist/main.js +WorkingDirectory=/opt/tipote +EnvironmentFile=/opt/tipote/.env +User=tipote +Group=tipote + +# Restart policy: max 5 restarts per 5 minutes +Restart=on-failure +RestartSec=5 +StartLimitIntervalSec=300 +StartLimitBurst=5 + +# Watchdog: process must ping every 60s or gets killed +WatchdogSec=60 + +# Logging via journald +StandardOutput=journal +StandardError=journal +SyslogIdentifier=tipote + +# Security: bind port 80 (captive portal) without root +AmbientCapabilities=CAP_NET_BIND_SERVICE +NoNewPrivileges=true + +# Resource limits (Pi Zero 2W has 416MB RAM) +MemoryMax=200M +MemoryHigh=150M + +[Install] +WantedBy=multi-user.target diff --git a/tools/pi-gen-tipote/stage-tipote/prerun.sh b/tools/pi-gen-tipote/stage3/prerun.sh similarity index 100% rename from tools/pi-gen-tipote/stage-tipote/prerun.sh rename to tools/pi-gen-tipote/stage3/prerun.sh