# Setting up P2 (Premium Communication) on a NEW G1 Same shape as P1's [NEW_ROBOT_SETUP](../Sanad_Package_1/NEW_ROBOT_SETUP.md) — self-contained, build on the robot, sign a per-robot license — with **three P2 deltas**: the license must **entitle P2**, the **LED mask** needs BLE, and the port is **:8012**. ## 0. Prerequisites (same as P1) + mask - Docker on the Jetson; your user in the `docker` group. - eth0 linked to the G1 (chest audio + arm over DDS). - **BLE "Shining Mask"** powered, in range, and **freed from the phone app** (BLE allows one central at a time). The host BlueZ stack must be up (`systemctl status bluetooth`). ## 1. Copy the package (self-contained — only this folder) ```bash rsync -az --exclude __pycache__ \ Project/Packages/Sanad_Package_2 \ unitree@:~/sanad_deploy/ ``` ## 2. Build on the robot ```bash cd ~/sanad_deploy/Sanad_Package_2 docker compose build # or: DOCKER_BUILDKIT=0 docker build -t sanad-p2:latest . ``` Builds the vendored SanadV3 engine + the chest-audio Unitree SDK (full CycloneDDS + idlc, `cyclonedds==0.10.2`) + `bleak==0.22.3` + Pillow. First build is a few minutes. ## 3. License THIS robot — must entitle **P2** The bundled `license/sanad.lic.example` entitles P1+P2+P3 for demo. For a real delivery, sign a license for the robot (vendor side, private key off-robot): ```bash # claims.json — set packages.P2=true (+ the features it sells) # "packages": {"P1": false, "P2": true, "P3": false, "P4": false}, # "features": {"multilingual": true, "voice_command_motion": true, "lipsync": true, "mask": true} python licensing/sign_license.py sign --key licensing/privkey.ed25519 \ --in claims.json --out sanad.lic scp sanad.lic unitree@:~/sanad_deploy/Sanad_Package_2/license/sanad.lic ``` Fingerprint binding (`SANAD_LICENSE_BIND=1`) works exactly as P1 — read the fingerprint with `PYTHONPATH=vendor python3 -c 'from sanad_pkg import license as L; print(L.machine_fingerprint())'`, put it in claims, and **uncomment the `/etc/machine-id` mount** in `docker-compose.yml`. ## 4. Configure `.env` and run ```bash cd ~/sanad_deploy/Sanad_Package_2 && cp .env.example .env # edit license/audio/mask docker compose up -d docker compose logs -f # expect "[P2] entitled — lang= … port=8012" ``` Dashboard: **http://<NEWROBOT>:8012**. Optional pin the mask MAC: `SANAD_MASK_ADDRESS=XX:XX:…` in `.env`. ## 5. First-use (per customer) Open `:8012`: paste the **Gemini API key** (keyless ship) → set the **Persona** (bilingual prompt = multilingual) → **Mask** tab connect + lip-sync test → enable **Live-voice** for arm gestures (default OFF) → **Start** and talk. ## 6. Verify ```bash ./test_p2.sh :8012 # expect all PASS curl http://:8012/api/package # license.valid + packages.P2=true + features curl http://:8012/api/mask/status ``` ## 7. Auto-run on boot `sudo systemctl enable docker` (compose already `restart: unless-stopped`), or a systemd unit as in P1's guide (WorkingDirectory `…/Sanad_Package_2`, `docker compose up`/`down`). ### Troubleshooting - **Container exits "not licensed"** — your license doesn't entitle P2; re-sign with `packages.P2=true` (the bundled example already does). - **Mask won't connect** — free it from the phone app; confirm host `bluetooth` service up; check `/var/run/dbus` is mounted + `NET_ADMIN`; `bleak==0.22.3` (3.x fails on BlueZ 5.53). `/api/mask/status` shows `lib_available`/`connected`. - **No chest audio** — `builtin` needs the Unitree SDK (default build) + eth0 to the G1; fallback `SANAD_AUDIO_PROFILE=plugged` (USB/Anker). - **`docker compose build` fails on buildx** — `DOCKER_BUILDKIT=0 docker build -t sanad-p2:latest .`