81 lines
3.7 KiB
Markdown
81 lines
3.7 KiB
Markdown
# 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@<NEWROBOT>:~/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@<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
|
|
```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=<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
|
|
```bash
|
|
./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 `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 .`
|