Getting Started

This guide explains how to use pymirokai with the current v2 API model.

Table of Contents

1. Connection Model

pymirokai exposes a single entry point: connect(...).

  • The default API version is v2.

  • Authentication is handled with the API key you pass to connect.

  • Robot automatically keeps the shared JWT fresh for REST, WebSocket, and video usage.

from pymirokai.robot import connect

async with connect(ip="192.168.0.10", api_key="YOUR_API_KEY") as robot:
    # Robot is connected to REST + WebSocket + Video endpoints
    ...

Local vs Remote Endpoints

connect(...) resolves endpoints automatically:

  • ip is None: local UDS mode (/tmp/rest_api.sock) + local WS/RTSPS.

  • ip in {"localhost", "127.0.0.1"}: local TCP mode.

  • other IP/hostname: remote mode using:

    • https://<ip>/rest for REST,

    • wss://<ip>/wss for WebSocket,

    • rtsps://<ip>:8555 for video.

JWT Lifetime and Long-Running Connections

Wizard JWTs are short-lived. pymirokai handles this for normal users:

  • REST responses can return a replacement token, which pymirokai stores automatically.

  • When the connection is idle, pymirokai refreshes the token through the authenticated /auth/refresh/ route before it expires.

  • The refresh delay is computed from the JWT exp claim, not from a hard-coded token lifetime. If the token cannot be decoded, pymirokai falls back to a short retry delay instead of looping continuously.

  • After a successful background refresh, the WebSocket reconnects with the new token and re-subscribes to existing topics.

  • Video streams use the current shared JWT when they open or reconnect, so they do not need a separate refresh loop.

Applications using connect(...) do not need to schedule their own JWT refresh.

2. Two Execution Styles

Robot methods fall into two categories.

Skills (Mission-based)

Skill calls return a Mission object.

mission = robot.say("Hello!")
await mission.started()
await mission.completed()

Abilities / Commands (Immediate response)

Ability calls return direct REST responses.

sound = await robot.set_sound_level(50)
runes = await robot.get_detected_runes()

3. Mission Lifecycle

Mission helpers are available both on Mission and Robot.

  • Wait start: await mission.started()

  • Wait completion: await mission.completed()

  • Cancel: await mission.cancel()

  • Cancel and wait: await mission.cancel_and_complete()

  • Ignore completion exceptions: await mission.completed(ignore_exceptions=True)

Robot-level helpers:

  • await robot.wait_for_mission(mission_id)

  • await robot.cancel_mission(mission_id)

  • await robot.wait_for_mission_started(mission_id)

  • await robot.cancel_and_wait_for_mission(mission_id)

4. v2 Command Transport

Internally, all command-like abilities use explicit v2 REST routes under /api/v2/commands/....

  • Robot.send_get_command(route)

  • Robot.send_post_command(route, value)

  • Robot.send_command(method, route, value) (low-level fallback)

For most client code, prefer high-level ability methods (set_sound_level, is_seeing_human, etc.) instead of direct route calls.

5. WebSocket Topics

def on_navigation(message: dict) -> None:
    print(message)

robot.subscribe("navigation_state")
robot.register_callback("navigation_state", on_navigation)
robot.publish("custom_topic", '{"name":"demo","type":"str","data":"hello"}')
robot.unsubscribe("navigation_state")

6. Video Streams

Access the shared VideoStreamManager through robot.connection.video_stream_manager. The manager uses the current robot JWT automatically when opening streams. Relative stream names resolve against the connection video endpoint, for example rtsps://<ip>:8555/head_color. When a stream is opened or reconnected, the manager appends the current JWT as the jwt query parameter required by MediaMTX.

manager = robot.connection.video_stream_manager
manager.add_stream("head_color", "head_color", display=True)
manager.set_display("head_color", False)
manager.remove_stream("head_color")

Absolute RTSP URLs are also accepted. If a URL already contains a jwt parameter, pymirokai replaces it with the current connection token and preserves any other query parameters.

If OpenCV is unavailable, capture/display features are skipped safely.

7. Skill File Management

Use these methods to manage uploaded custom skills:

  • upload_skill_file(skill_path)

  • remove_skill_file(skill_name)

  • list_skill_files()

  • enable_skill_file(skill_name, enable)

8. Error Handling Notes

  • Connection/auth failures raise from underlying aiohttp calls.

  • Command responses are validated server-side; invalid payloads return HTTP errors.

  • Mission methods raise MissionError on cancellation/failure unless ignored.

Use regular try/except around mission and command calls in production clients.