67 lines
3.7 KiB
YAML
67 lines
3.7 KiB
YAML
# Self-contained compose for Sanad Package 2 (Premium Communication).
|
|
# NO sibling folders, NO sanad-base — engine vendored from SanadV3 in ./vendor,
|
|
# the flat BLE Mask lib in ./vendor/mask. This dir is all you need.
|
|
#
|
|
# docker compose up -d --build # build + run -> http://<robot>:8012
|
|
# docker compose logs -f # logs
|
|
# docker compose down # stop
|
|
# # Jetson Docker without buildx: DOCKER_BUILDKIT=0 docker compose up -d --build
|
|
#
|
|
# Audio: SANAD_AUDIO_PROFILE=builtin (G1 chest) | plugged (USB/Anker)
|
|
# Mask: needs the BLE "Shining Mask" paired/in range + freed from the phone app.
|
|
# License: point SANAD_LICENSE_FILE at your signed sanad.lic (default = example).
|
|
services:
|
|
p2:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
args:
|
|
BASE_OS_IMAGE: "${BASE_OS_IMAGE:-python:3.10-slim-bookworm}"
|
|
WITH_UNITREE_SDK: "${WITH_UNITREE_SDK:-1}"
|
|
image: "${SANAD_IMAGE:-sanad-p2:latest}"
|
|
container_name: sanad-p2
|
|
# Host networking REQUIRED — G1 DDS link + Gemini cloud + chest audio + BlueZ.
|
|
network_mode: host
|
|
restart: unless-stopped
|
|
# BlueZ talks over D-Bus; mask BLE needs adapter management.
|
|
cap_add:
|
|
- NET_ADMIN
|
|
environment:
|
|
SANAD_PACKAGE: P2
|
|
SANAD_DASHBOARD_PORT: "8012"
|
|
SANAD_DASHBOARD_HOST: "0.0.0.0"
|
|
SANAD_VOICE_BRAIN: gemini
|
|
# builtin (G1 chest) needs the robot's 192.168.123.x net (network_mode host
|
|
# ON a G1). OFF a G1 the chest-mic discovery crashes the voice subprocess —
|
|
# set plugged on any non-G1 host. On the G1 itself, builtin is correct.
|
|
SANAD_AUDIO_PROFILE: "${SANAD_AUDIO_PROFILE:-builtin}" # builtin (chest) | plugged (USB/Anker)
|
|
SANAD_DDS_INTERFACE: "${SANAD_DDS_INTERFACE:-eth0}"
|
|
# Plugged/Bluetooth audio (Anker USB, JBL BT) route through the HOST
|
|
# PulseAudio server — chest ("builtin") uses DDS and needs none of this.
|
|
PULSE_SERVER: "${PULSE_SERVER:-unix:/run/user/1000/pulse/native}"
|
|
PULSE_COOKIE: "${PULSE_COOKIE:-/run/user/1000/pulse/cookie}" # root→uid-1000 PA auth
|
|
SANAD_MASK_DIR: /app/mask
|
|
SANAD_MASK_ADDRESS: "${SANAD_MASK_ADDRESS:-}" # optional: pin the mask BLE MAC
|
|
SANAD_LICENSE: /etc/sanad/sanad.lic
|
|
SANAD_PUBKEY: /etc/sanad/pubkey.ed25519
|
|
SANAD_LICENSE_BIND: "${SANAD_LICENSE_BIND:-0}"
|
|
SANAD_LANGUAGE: "${SANAD_LANGUAGE:-}" # empty = multilingual auto-detect
|
|
devices:
|
|
- "/dev/snd:/dev/snd" # USB/plugged audio (Anker) via ALSA/Pulse
|
|
- "/dev/bus/usb:/dev/bus/usb" # USB BLE dongle (if the adapter is USB)
|
|
volumes:
|
|
- "${SANAD_LICENSE_FILE:-./license/sanad.lic.example}:/etc/sanad/sanad.lic:ro"
|
|
# Plugged/Bluetooth audio (Anker/JBL): mount the host PulseAudio runtime dir
|
|
# (socket + auth cookie) so the container sets ANY sink's volume/output — the
|
|
# volume slider then drives chest (DDS) AND plugged (PA), exactly like SanadV3.
|
|
# Chest ("builtin") audio uses DDS only and needs none of this. One-time host
|
|
# setup for a stable boot-time socket: `loginctl enable-linger unitree`.
|
|
- "${SANAD_PULSE_DIR:-/run/user/1000/pulse}:/run/user/1000/pulse"
|
|
- "./data:/app/Sanad/data" # persist persona/recordings on host
|
|
# Persist mask face colors (mask_face writes /app/Sanad/config/mask_config.json,
|
|
# otherwise a baked layer lost on recreate). Single-file mount — pre-seeded.
|
|
- "./config/mask_config.json:/app/Sanad/config/mask_config.json"
|
|
- "/var/run/dbus:/var/run/dbus" # host BlueZ/D-Bus for bleak (the LED mask)
|
|
# Bound license (SANAD_LICENSE_BIND=1) also needs the host machine-id:
|
|
# - "/etc/machine-id:/etc/machine-id:ro"
|