pi-webrtc

Gamepad

Control the device with a gamepad that is connected to the browser. pi-webrtc sends the gamepad state to a Unix socket on the device, as simple JSON lines. Your program does not need to know anything about WebRTC.

--enable-gamepad turns this on. It also turns on IPC.

The browser sends the gamepad state about 60 times per second, over a lossy DataChannel.

Read the gamepad from Python

The gamepad_socket.py example prints every gamepad state that pi-webrtc receives.

  1. Start pi-webrtc with gamepad support:

    ./pi-webrtc --camera=libcamera:0 ... --use-mqtt ... --enable-gamepad
  2. Run the example, then connect a gamepad in the browser:

    python3 examples/gamepad_socket.py

The socket is /tmp/pi-webrtc-gamepad.sock by default. Change it with --gamepad-socket-path.

To drive a ROS 2 robot with the gamepad, see ROS.

Snapshots

Each line holds the latest state of every connected gamepad:

{"device_monotonic_ns":81234567890123,"gamepads":{"alice":{"sequence":1234,"timestamp":{"monotonic_ns":5023000000},"left_x":0.12,"left_y":-0.5,"right_x":0.0,"right_y":0.0,"left_trigger":0.0,"right_trigger":0.87,"buttons":129,"pressed":["a","rt"],"standard_mapping":true}}}
FieldDescription
device_monotonic_nsWhen pi-webrtc made this snapshot, on the device's monotonic clock. Python's time.monotonic_ns() reads the same clock.
gamepadsOne entry per sender. Empty when no gamepad is sending.
sequenceThe sender's report counter. A gap means some snapshots were dropped.
timestamp.monotonic_nsThe browser's timestamp, when it sends one. Do not compare it with device_monotonic_ns.
left_x, left_y, right_x, right_ySticks, from -1 to 1. +y is down.
left_trigger, right_triggerFrom 0 to 1.
buttonsThe button state, as a bit mask.
pressedThe names of the pressed standard buttons (bits 0 to 16).
standard_mappingfalse when the browser does not know the standard layout. Then the button names may not match the real buttons.

The key of each gamepad is the peer id that pi-webrtc gives each MQTT client, or the LiveKit participant identity. It stays the same across WebRTC reconnects within --peer-timeout.

New fields may be added in later releases, so ignore fields that you do not know.

Button mapping

The browser uses the W3C standard gamepad mapping when it can.

BitNameXboxPlayStation
0aACross
1bBCircle
2xXSquare
3yYTriangle
4lbLBL1
5rbRBR1
6ltLTL2
7rtRTR2
8backViewCreate
9startMenuOptions
10l3Left stick pressL3
11r3Right stick pressR3
12dpad_upD-pad upD-pad up
13dpad_downD-pad downD-pad down
14dpad_leftD-pad leftD-pad left
15dpad_rightD-pad rightD-pad right
16guideXbox buttonPS button

Disconnects and old input

  • A gamepad is removed as soon as pi-webrtc closes its connection.
  • It is also removed when no input arrives from it for 500 ms. For example, the browser tab is in the background, the gamepad is unplugged, or the network is down.
  • When nobody is sending, no new snapshot is made. Check the age of the last one, time.monotonic_ns() - device_monotonic_ns, against your own limit.
Edit on GitHub

On this page