Python SDK Overview & Installation

The USMP Python SDK is an asyncio-based library designed to build high-performance USMP gateways, test clients, and tools.

The USMP Python SDK is an asyncio-based library designed to build high-performance USMP gateways, test clients, and tools.

1. Installation

Explanation

The Python SDK is distributed as a standard Python library and can be installed via any PEP 517 build tool (e.g. pip, pipenv, poetry, or uv).

Implementation

pip install usmp

For development, you can use uv inside the repository:

uv pip install -e ./sdk/python

2. SDK Architecture

Explanation

The SDK is designed using asynchronous I/O (asyncio) to handle multiple concurrent device sessions efficiently.

Key Components:

  • USMPServer: Listens for incoming TCP connections and performs the server-side handshake.
  • USMPClient: Connects to a remote gateway and performs the client-side handshake.
  • USMPSession: Manages an active, authenticated session (encryption, decryption, keepalives, sequence number tracking).

3. Minimal Echo Server Example

Explanation

The following implementation shows how to start a USMP server on port 9000 with a hardcoded pre-shared key, registering a session handler to receive data and respond.

Implementation

import asyncio
from usmp import USMPServer, USMPSession
from usmp.errors import ConnectionClosedError

# Initialize server
server = USMPServer(
    host="0.0.0.0",
    port=9000,
    psk=b"your-secret-psk-here"
)

# Register session handler
@server.on_session
async def handle_session(session: USMPSession):
    print(f"[SERVER] New connection from device: {session.device_id}")
    try:
        while True:
            # Non-blocking async read (automatically handles PING/PONG)
            data = await session.recv()
            print(f"[RX] From {session.device_id}: {data.decode()}")
            
            # Encrypt and send response
            await session.send(b"ACK")
    except ConnectionClosedError:
        print(f"[SERVER] Device {session.device_id} disconnected.")

# Run the event loop
asyncio.run(server.serve())

4. Event Model: Arduino Callbacks vs. Python Async Loops

If you are coming from the Arduino framework, you are likely familiar with registered event callbacks (onMessage, onConnect, onDisconnect). In the Python SDK, these events are handled using structured asyncio loop flows.

Here is how the concepts map between the two platforms:

Arduino CallbackPython Async EquivalentDescription
onConnectCode executing immediately after await client.connect() or at the start of @server.on_session.Runs once the cryptographic handshake succeeds and keys are negotiated.
onMessageReading data from data = await session.recv().Fired whenever a new decrypted payload is reassembled and verified.
onDisconnectCatching ConnectionClosedError (or socket exception) in a try/except block.Triggers when the client or server terminates the session or keepalives time out.
onReconnectCatching a disconnection exception, pausing, and calling connect() again in a loop.Re-establishes a fresh secure session with new ephemeral keys.

Comparison Example: Message Handlers

void onMessage(const uint8_t *data, size_t len) {
    Serial.printf("Received message: %.*s\n", len, data);
}

void setup() {
    usmp.onMessage(onMessage);
    usmp.begin(USMP::TCP("192.168.1.100"));
}

5. API Reference Deep-Dives

  • USMPServer — Accepts and manages multiple concurrent device connections.
  • USMPClient — Establishes client connections to a USMP gateway.
  • USMPSession — Handles frame encryption, decryption, sequence validation, and control packets.