from vuer import VuerClient# Default: connects to ws://localhost:8012client = VuerClient()# Custom URIclient = VuerClient(uri="ws://192.168.1.100:8012")# With custom max message size (default 256MB)client = VuerClient(uri="ws://localhost:8012", max_size=2**30)# Disable SSL certificate verification (e.g., for ngrok with self-signed certs)client = VuerClient(uri="wss://7.tcp.ngrok.io:26620", ssl_verify=False)
Configuration can also be set via environment variables:
VUER_CLIENT_URI: WebSocket URI (default ws://localhost:8012)
WEBSOCKET_MAX_SIZE: Maximum message size in bytes (default 256MB)
VUER_SSL_VERIFY: Whether to verify SSL certificates (default true)
Context Manager (Recommended)
python
async with VuerClient(uri="ws://localhost:8012") as client: await client.send(event)
Manual Connection
python
client = VuerClient()await client.connect()# ... do work ...await client.close()
INIT Event (Automatic)
When a VuerClient connects, it automatically sends an INIT event with system information. This allows the server to identify the client type and environment.
The INIT event includes:
python
{ # Common fields (shared with browser client) "client": "python", # Always "python" for VuerClient "clientVersion": "0.1.x", # Library version "timezone": "America/Los_Angeles", "timezoneOffset": 480, # Python-specific fields "pythonVersion": "3.11.13", "platform": "Darwin", # or "Linux", "Windows" "platformVersion": "24.2.0", "machine": "arm64",}
On the server, you can await this event to identify the client:
python
@app.spawn(start=True)async def main(session: VuerSession): # Wait for the INIT event e = await session.till("INIT") if e.value.get('client') == 'python': print(f"Python client v{e.value.get('clientVersion')}") else: print(f"Browser client: {e.value.get('userAgent')}") session.set @ DefaultScene() await session.forever()
Sending Events
Define custom event classes by setting etype as a class attribute:
python
from vuer.events import ClientEventclass MyEvent(ClientEvent): etype = "MY_EVENT"# Fire-and-forget with @ syntax (no await needed)client.send @ MyEvent(value={"data": 123})# Awaitable with parenthesesawait client.send(MyEvent(value={"data": 123}))
You can also set a default value:
python
class SetPositionEvent(ClientEvent): etype = "SET_POSITION" value = [0, 0, 0]# Uses default value (fire-and-forget)client.send @ SetPositionEvent()# Override value (awaitable)await client.send(SetPositionEvent(value=[1, 2, 3]))
Receiving Events
python
# Single event with timeoutevent = await client.recv(timeout=5.0)# Iterate over eventsasync for event in client: print(f"Received: {event.etype}")
Complete Example: Remote Control
Here's a complete example where a client remotely controls an animated box using a custom event class:
client.py - Sends animated position updates with a custom event class:
python
import asyncioimport mathfrom vuer import VuerClientfrom vuer.events import ClientEventclass SetPositionEvent(ClientEvent): etype = "SET_POSITION"async def main(): async with VuerClient() as client: # Animate the box by sending position updates for i in range(200): t = i * 0.05 x = math.sin(t) * 2 y = 0.5 + math.sin(t * 2) * 0.3 client.send @ SetPositionEvent(value={"position": [x, y, 0]}) await asyncio.sleep(0.016) # ~60 FPSasyncio.run(main())
Run the server first, then run the client in a separate terminal to see the animated box.
Tips
Define custom events by subclassing ClientEvent with an etype class attribute
The server handles events via @app.add_handler("EVENT_TYPE")
Use client.send @ Event() for fire-and-forget (no await needed)
Use await client.send(Event()) when you need to wait for the send to complete
Use client.connected to check connection status
Reconnect by calling connect() again if disconnected
Configure via environment variables: VUER_CLIENT_URI, WEBSOCKET_MAX_SIZE, VUER_SSL_VERIFY
Use ssl_verify=False when connecting through tunnels with self-signed certificates (e.g., ngrok TCP tunnels)
You can also pass any websockets.connect() kwargs (e.g., a custom ssl= context) through the constructor