3.7 KiB
Setting up P2 (Premium Communication) on a NEW G1
Same shape as P1's NEW_ROBOT_SETUP — 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
dockergroup. - 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)
rsync -az --exclude __pycache__ \
Project/Packages/Sanad_Package_2 \
unitree@<NEWROBOT>:~/sanad_deploy/
2. Build on the robot
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):
# 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@<NEWROBOT>:~/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
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=<multilingual> … 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
./test_p2.sh <NEWROBOT>:8012 # expect all PASS
curl http://<NEWROBOT>:8012/api/package # license.valid + packages.P2=true + features
curl http://<NEWROBOT>: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
bluetoothservice up; check/var/run/dbusis mounted +NET_ADMIN;bleak==0.22.3(3.x fails on BlueZ 5.53)./api/mask/statusshowslib_available/connected. - No chest audio —
builtinneeds the Unitree SDK (default build) + eth0 to the G1; fallbackSANAD_AUDIO_PROFILE=plugged(USB/Anker). docker compose buildfails on buildx —DOCKER_BUILDKIT=0 docker build -t sanad-p2:latest .