Skip to main content
Version: QTrobot V3

Connection

Every luxai-robot program starts the same way: create a Robot client over one of three transports.

  • ZMQ is the most common and recommended choice — use it whenever your code runs on the same local network as the robot. It's the most efficient option and should be your default.
  • MQTT is for when you need a remote connection over the internet, and the robot's qtrobot-service-hub-gateway-mqtt has been configured to use an external/remote broker reachable from outside the local network.
  • WebRTC covers the same kind of remote/internet scenario, but as a peer-to-peer connection — pick it when you need the lowest latency, e.g. live audio/video over the internet. For actual internet use, qtrobot-service-hub-gateway-webrtc needs to be configured with a remote MQTT broker for signaling and, in most cases, STUN/TURN servers.

Setup

As best practice, install into a virtual environment rather than system-wide — for example, on QTPC:

mkdir ~/example
cd ~/example
python -m venv .venv
# or: uv venv .venv

source .venv/bin/activate

pip install luxai-robot
# or: uv pip install luxai-robot

Direct connection to the robot's onboard service hub — the lowest-latency option, and the recommended default for Python.

By robot ID (recommended) — every QTrobot has a serial number printed on a label on the back of the robot (e.g. QTRD000123). Passing it as robot_id lets the SDK find the robot automatically via Zeroconf/mDNS discovery, with no IP address needed — this works from any Linux machine on the robot's network:

from luxai.robot.core import Robot

robot = Robot.connect_zmq(robot_id="QTRD000123")
print(f"connected to {robot.robot_id} ({robot.robot_type})")
robot.close()

By endpoint — skip discovery and connect directly if you already know the address:

  • Running your code on QTPC itself (the robot's onboard computer): use 127.0.0.1, or QTPC's internal Ethernet address 10.231.0.1 (the dedicated LAN link between QTPC and QTRP).
  • Running your code on another machine (e.g. your laptop) on the robot's WiFi network: use QTPC's address on that network instead — 10.231.0.1 is only reachable from QTPC itself, not from other devices on the WiFi.
robot = Robot.connect_zmq(endpoint="tcp://10.231.0.1:50500")   # from QTPC itself
Same addressing for MQTT

This addressing model — robot_id auto-discovery (recommended), 127.0.0.1/10.231.0.1 from QTPC itself, or QTPC's WiFi IP from a remote machine — applies identically to the MQTT broker below, since it also runs on QTPC by default.

Optionally pass connect_timeout to control how long discovery waits, and default_rpc_timeout to set the timeout every RPC call on this client uses unless overridden per-call:

robot = Robot.connect_zmq(robot_id="QTRD000123", connect_timeout=10.0)
robot = Robot.connect_zmq(endpoint="tcp://10.231.0.1:50500", default_rpc_timeout=10.0)

Manual transport — power-user style, construct the ZmqTransport yourself when you need direct control over its lifecycle or want to share it across multiple objects:

from luxai.robot.core.transport import ZmqTransport

transport = ZmqTransport(endpoint="tcp://10.231.0.1:50500")
robot = Robot(transport=transport)

Context manager — closes the connection automatically:

with Robot.connect_zmq(endpoint="tcp://10.231.0.1:50500") as robot:
robot.tts.say_text("Hello from ZMQ!")
# robot.close() is called automatically on exit

Connect with MQTT (remote scenario)

Connects through an MQTT broker and the qtrobot-service-hub-gateway-mqtt bridge — for remote, cloud, or browser-friendly control. By default, the robot's local MQTT broker (Mosquitto) runs on QTPC, so the same addressing applies as in the ZMQ section above: 127.0.0.1/10.231.0.1 from QTPC itself, or QTPC's WiFi address from a remote machine.

pip install "luxai-robot[mqtt]"
note

The robot's default MQTT broker has no authentication or TLS configured — use the Basic example below as-is. The username/password, TLS, and mTLS examples only apply if qtrobot-service-hub-gateway-mqtt has been set up to use a different, external broker that requires them.

Basic — plain TCP, no TLS, no authentication:

from luxai.robot.core import Robot

robot = Robot.connect_mqtt("mqtt://10.231.0.1:1883", "QTRD000320")
robot.close()

Username/password, over plain TCP:

from luxai.robot import MqttOptions, MqttAuthOptions

options = MqttOptions(
auth=MqttAuthOptions(mode="username_password", username="myuser", password="mypassword"),
)
robot = Robot.connect_mqtt("mqtt://10.231.0.1:1883", "QTRD000320", options=options)

TLS (server certificate verification only) — use mqtts:// for TLS over TCP or wss:// for TLS over WebSocket:

from luxai.robot import MqttOptions, MqttTlsOptions

options = MqttOptions(tls=MqttTlsOptions(ca_file="/path/to/ca.crt"))
robot = Robot.connect_mqtt("mqtts://10.231.0.1:8883", "QTRD000320", options=options)

Mutual TLS (mTLS) — the client presents its own certificate; no username/password needed:

options = MqttOptions(
tls=MqttTlsOptions(
ca_file="/path/to/ca.crt",
cert_file="/path/to/client.crt",
key_file="/path/to/client.key",
),
auth=MqttAuthOptions(mode="mtls"),
)
robot = Robot.connect_mqtt("mqtts://10.231.0.1:8883", "QTRD000320", options=options)

TLS over WebSocket — useful when connecting through a web proxy or firewall that only allows HTTP/HTTPS traffic:

options = MqttOptions(
tls=MqttTlsOptions(ca_file="/path/to/ca.crt"),
auth=MqttAuthOptions(mode="username_password", username="myuser", password="mypassword"),
)
robot = Robot.connect_mqtt("wss://broker.example.com:8884/mqtt", "QTRD000320", options=options)

Full options — TLS + auth + a persistent session + custom reconnect backoff:

from luxai.robot import MqttOptions, MqttTlsOptions, MqttAuthOptions, MqttSessionOptions, MqttReconnectOptions

options = MqttOptions(
tls=MqttTlsOptions(
ca_file="/path/to/ca.crt",
cert_file="/path/to/client.crt",
key_file="/path/to/client.key",
),
auth=MqttAuthOptions(mode="mtls"),
session=MqttSessionOptions(
clean_start=False, # resume persistent session on reconnect
session_expiry_sec=3600, # keep session alive for 1 hour
),
reconnect=MqttReconnectOptions(enabled=True, min_delay_sec=1.0, max_delay_sec=60.0),
)
robot = Robot.connect_mqtt(
"mqtts://10.231.0.1:8883", "QTRD000320",
options=options, connect_timeout=15.0, default_rpc_timeout=30.0,
)

Manual transport / context manager — same power-user and auto-cleanup patterns as ZMQ above, just with MqttTransport/Robot.connect_mqtt:

with Robot.connect_mqtt("mqtt://10.231.0.1:1883", "QTRD000320") as robot:
robot.tts.say_text("Hello over MQTT!")

Connect with WebRTC (remote p2p scenario)

A peer-to-peer connection — after a short handshake ("signaling"), all RPC and stream traffic flows directly between your code and the robot, rather than through a broker. Signaling can go over MQTT (works over the internet, behind NAT) or a broker-less ZMQ socket (LAN only).

Unlike the MQTT broker, the WebRTC gateway is not installed by default — install it on QTPC first:

sudo apt install qtrobot-service-hub-gateway-webrtc
Advanced: connecting over the internet

For actual remote use over the internet, qtrobot-service-hub-gateway-webrtc needs to be properly configured with a remote/public MQTT broker for signaling, and in most cases STUN/TURN servers for NAT traversal. This is more advanced setup — see mTLS signaling + STUN/TURN below for the relevant options.

Once running, it's configured to use the robot's default (no-auth) MQTT broker for signaling — the same broker used in the MQTT section above.

pip install "luxai-robot[webrtc]"

Basic, MQTT-signaled:

from luxai.robot.core import Robot
from luxai.robot import WebRTCOptions

robot = Robot.connect_webrtc_mqtt(
"mqtt://10.231.0.1:1883", "QTRD000320",
webrtc_options=WebRTCOptions(stun_servers=[]),
)
robot.close()

MQTT signaling over TLS:

from luxai.robot import MqttOptions, MqttTlsOptions

robot = Robot.connect_webrtc_mqtt(
"mqtts://10.231.0.1:8883", "QTRD000320",
mqtt_options=MqttOptions(tls=MqttTlsOptions(ca_file="/path/to/ca.crt")),
)

mTLS signaling + STUN/TURN — add TURN servers when both peers are behind symmetric NATs:

from luxai.robot import MqttOptions, MqttTlsOptions, MqttAuthOptions, WebRTCOptions, WebRTCTurnServer

robot = Robot.connect_webrtc_mqtt(
"mqtts://10.231.0.1:8883", "QTRD000320",
mqtt_options=MqttOptions(
tls=MqttTlsOptions(ca_file="/path/to/ca.crt", cert_file="/path/to/client.crt", key_file="/path/to/client.key"),
auth=MqttAuthOptions(mode="mtls"),
),
webrtc_options=WebRTCOptions(
stun_servers=["stun:stun.l.google.com:19302"],
turn_servers=[WebRTCTurnServer(url="turn:turn.example.com:3478", username="user", credential="pass")],
),
)

Automatic reconnect — the P2P connection re-establishes itself if it drops, without restarting signaling:

robot = Robot.connect_webrtc_mqtt("mqtt://10.231.0.1:1883", "QTRD000320", reconnect=True, connect_timeout=20.0)

Broker-less, ZMQ-signaled — LAN only, no MQTT needed. The robot side binds, the operator side connects:

# Robot side: Robot.connect_webrtc_zmq("tcp://*:5555", "QTRD000320", bind=True)

# Operator side:
robot = Robot.connect_webrtc_zmq("tcp://192.168.3.152:5555", "QTRD000320")
robot.tts.say_text("Hello over broker-less WebRTC!")
robot.close()

Manual transport / context manager — same patterns as above, with WebRTCTransport/Robot.connect_webrtc_mqtt:

with Robot.connect_webrtc_mqtt("mqtt://10.231.0.1:1883", "QTRD000320") as robot:
robot.tts.say_text("Hello over WebRTC!")

Next steps

Continue with the TTS tutorial, or see the full connection API in the Python API Reference.