Skip to main content

Connect to the Unitree Go2 and G1 with WebRTC

Project description

Unitree WebRTC Connect

Python WebRTC driver for Unitree Go2 and G1 robots. Provides high-level control through the same WebRTC protocol used by the Unitree Go/Unitree Explore mobile apps — no jailbreak or firmware modification required.

Screenshot

PyPI GitHub release (latest SemVer) License: MIT

Supported Models

Model Variants
Go2 AIR, PRO, EDU
G1 AIR, EDU

Supported Firmware

Robot Firmware Versions Auth
Go2 1.1.1 – 1.1.14 (latest), 1.0.19 – 1.0.25 static GCM key (data2=2)
G1 1.2.0 – 1.4.5
1.5.1+ (latest)
static GCM key (data2=2)
per-device AES-128 key (data2=3) — see G1 ≥ 1.5.1 — AES-128 Key

Features

Feature Go2 G1
Data channel (pub/sub, RPC) yes yes
Sport / arm-action control yes yes
Video stream (receive) yes yes
Audio stream (send/receive) yes
LiDAR point cloud decoding yes
VUI (LED, brightness, volume) yes
AudioHub (audio file management) yes
Obstacle avoidance API yes
Multicast device discovery yes
data2=3 per-device key auth yes (G1 ≥ 1.5.1)

Installation

PyPI (recommended)

sudo apt update
sudo apt install -y python3-pip portaudio19-dev
pip install unitree_webrtc_connect

From source

sudo apt update
sudo apt install -y python3-pip portaudio19-dev
git clone https://github.com/legion1581/unitree_webrtc_connect.git
cd unitree_webrtc_connect
pip install -e .

Quick Start

from unitree_webrtc_connect import UnitreeWebRTCConnection, WebRTCConnectionMethod

# Go2 / older G1 firmware — no extra auth needed
conn = UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalSTA, ip="192.168.123.18")
await conn.connect()

# G1 firmware ≥ 1.5.1 — per-device AES-128 key required for the LAN handshake
# (see "G1 ≥ 1.5.1 — AES-128 Key" below for how to fetch it)
conn = UnitreeWebRTCConnection(
    WebRTCConnectionMethod.LocalSTA,
    ip="192.168.10.225",
    aes_128_key="<32-hex-chars>",
)
await conn.connect()

Connection Methods

AP Mode

Robot is in Access Point mode, client connects directly to the robot's WiFi.

UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalAP)

# G1 ≥ 1.5.1 in AP mode
UnitreeWebRTCConnection(
    WebRTCConnectionMethod.LocalAP,
    aes_128_key="<32-hex-chars>",
)

STA-L Mode (Local Network)

Robot and client are on the same local network. Requires IP or serial number.

# By IP
UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalSTA, ip="192.168.8.181")

# By serial number (uses multicast discovery, Go2 only)
UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalSTA, serialNumber="B42D2000XXXXXXXX")

# G1 ≥ 1.5.1 by IP, with per-device key
UnitreeWebRTCConnection(
    WebRTCConnectionMethod.LocalSTA,
    ip="192.168.10.225",
    aes_128_key="<32-hex-chars>",
)

STA-T Mode (Remote)

Remote connection through Unitree's TURN server. Control your robot from a different network. Requires Unitree account credentials.

region and device_type pick the cloud endpoint and the AppName header — Go2 hits global-robot-api.unitree.com with AppName: Go2, G1 does the same host with AppName: G1. Use region="cn" for accounts registered in China.

# Go2 (default)
UnitreeWebRTCConnection(
    WebRTCConnectionMethod.Remote,
    serialNumber="B42D2000XXXXXXXX",
    username="email@gmail.com",
    password="pass",
)

# G1 in China region
UnitreeWebRTCConnection(
    WebRTCConnectionMethod.Remote,
    serialNumber="E21D6000XXXXXXXX",
    username="email@gmail.com",
    password="pass",
    region="cn",
    device_type="G1",
)

G1 ≥ 1.5.1 — AES-128 Key (data2=3)

Starting with G1 firmware 1.5.1, the LAN signaling handshake (con_notify) returns data2=3, which means the embedded RSA public key is wrapped under a per-device AES-128-GCM key. Without that key the WebRTC handshake can't decrypt the public key and the connection never starts. (Older firmware uses a static AES-GCM key — handled automatically.)

The key is per device, stable across re-pairings, stored on the robot at /unitree/etc/key/aes_key.bin (RSA-wrapped), and surfaced to the cloud as dev.key in device/bind/list.

Fetch via the bundled CLI

After pip install unitree_webrtc_connect you get a console script:

# By default: region=global, device family=G1 — fits most users.
unitree-fetch-aes-key --email you@example.com --password '...'

# China region:
unitree-fetch-aes-key --email you@example.com --password '...' --region cn

# Single SN, scriptable (bare key on stdout):
unitree-fetch-aes-key --email you@example.com --sn E21D6000XXXXXXXX --quiet

# Pre-existing access token (skip login):
unitree-fetch-aes-key --token <accessToken> --sn E21D6000XXXXXXXX

Equivalent if you don't have it on $PATH:

python -m unitree_webrtc_connect._cli --help

The interactive output is a labelled panel (SN / alias / online / region / key); --quiet swaps that for a bare key on stdout so you can pipe it:

KEY=$(unitree-fetch-aes-key --email ... --sn E21D... --quiet)

Fetch programmatically

from unitree_webrtc_connect import UnitreeCloud, fetch_aes_key

# One-shot lookup
key = fetch_aes_key("you@example.com", "...", sn="E21D6000XXXXXXXX",
                    region="global", device_type="G1")

# Or keep the cloud client around for other calls
cloud = UnitreeCloud(region="global", device_type="G1")
cloud.login_email("you@example.com", "...")
for d in cloud.list_devices():
    print(d.sn, d.alias, d.key)

Typed errors

When you supply the wrong / missing key, the SDK raises typed exceptions you can catch instead of relying on stack traces:

from unitree_webrtc_connect import (
    AesKeyRequiredError,    # data2=3 robot reached without a key
    AesKeyRejectedError,    # GCM tag check failed (wrong key)
    LocalSignalingPortError, # neither :9991 nor :8081 reachable on the IP
    RobotBusyError,          # robot rejected — another WebRTC client is connected
    NoSdpAnswerError,        # signaling round-trip returned no SDP
    DataChannelTimeoutError, # data channel didn't validate in time
)

try:
    await conn.connect()
except AesKeyRejectedError as e:
    ...

Examples

Examples are organized by robot model under the /examples directory.

All examples default to ip="192.168.8.181" but read the UNITREE_ROBOT_IP environment variable if set, so you can point them at your robot without editing the source:

export UNITREE_ROBOT_IP=192.168.8.181
python examples/go2/data_channel/sportmode/sportmode.py

For G1 examples, also set UNITREE_AES_128_KEY (fetch via unitree-fetch-aes-key) on firmware ≥ 1.5.1.

Go2

Category Example Description
Data Channel data_channel/sportmode/ Sport mode movement commands
data_channel/sportmode_mcf/ Interactive MCF sport menu (firmware ≥ 1.1.7)
data_channel/sportmodestate/ Subscribe to sport mode state
data_channel/lowstate/ Subscribe to low-level state (IMU, motors)
data_channel/multiplestate/ Subscribe to multiple state topics
data_channel/vui/ VUI control (LED, volume, brightness)
data_channel/obstacles_avoid/ Toggle obstacle avoidance + WASD drive
data_channel/lidar/lidar_stream.py LiDAR point cloud subscription
data_channel/lidar/plot_lidar_stream.py LiDAR 3D visualization (Three.js)
Audio audio/live_audio/ Live audio receive
audio/save_audio/ Save audio to file
audio/mp3_player/ Play MP3 through robot speaker
audio/internet_radio/ Stream internet radio
Video video/camera_stream/ Display video stream

G1

Category Example Description
Data Channel data_channel/sport_mode/ Sport mode movement commands
Video video/camera_stream/ Display video stream (requires AES-128 key on firmware ≥ 1.5.1)

Imports

All public classes, helpers and exception types are exported from the package root:

from unitree_webrtc_connect import (
    # Core driver
    UnitreeWebRTCConnection,
    WebRTCConnectionMethod,
    WebRTCDataChannel,
    WebRTCDataChannelPubSub,
    DATA_CHANNEL_TYPE,
    RTC_TOPIC,
    SPORT_CMD,

    # Cloud helpers (data2=3, account / TURN flow, bind list)
    UnitreeCloud,
    UnitreeCloudError,
    RobotDevice,
    fetch_aes_key,

    # Typed errors
    AesKeyRequiredError,
    AesKeyRejectedError,
    DataChannelTimeoutError,
    LocalSignalingPortError,
    NoSdpAnswerError,
    RobotBusyError,
)

Acknowledgements

A big thank you to TheRoboVerse community! Visit us at TheRoboVerse for more information and support.

Special thanks to the tfoldi WebRTC project and abizovnuralem for adding LiDAR support, MrRobotoW for the LiDAR visualization example, and Nico for the aiortc monkey patch.

Support

If you like this project, please consider buying me a coffee:

Buy Me A Coffee

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unitree_webrtc_connect-2.1.1.tar.gz (47.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unitree_webrtc_connect-2.1.1-py3-none-any.whl (52.1 kB view details)

Uploaded Python 3

File details

Details for the file unitree_webrtc_connect-2.1.1.tar.gz.

File metadata

  • Download URL: unitree_webrtc_connect-2.1.1.tar.gz
  • Upload date:
  • Size: 47.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unitree_webrtc_connect-2.1.1.tar.gz
Algorithm Hash digest
SHA256 f37ad377c5e4fc7858c21773aa7a72e2c61c8db79daefb6d00e164f70c86e716
MD5 12e6f5264753bf49b4a6700d00417cb1
BLAKE2b-256 67d0c53521d9e4ca0c4eb70d856e3e15b33ebd06c4b108b345bb62c0b1398422

See more details on using hashes here.

File details

Details for the file unitree_webrtc_connect-2.1.1-py3-none-any.whl.

File metadata

  • Download URL: unitree_webrtc_connect-2.1.1-py3-none-any.whl
  • Upload date:
  • Size: 52.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for unitree_webrtc_connect-2.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2501d3de5e73ee1c27662ee1f88bc23dbc4e28f2d755ab81752752661c2bb06a
MD5 1d0cf099136bdf5e21891f59f250b1c6
BLAKE2b-256 8a08de4ab0aa99b3fe7d0df683e5d02aecc1c8c64963c35ce193bcbe678e37e5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page