Skip to content

SDK Overview

Struct Frame provides high-level SDKs for TypeScript/JavaScript, Python, C++, and C# that simplify sending and receiving framed messages over various transport layers.

Enabling SDK Generation

The SDK is opt-in and not generated by default. To include SDK files during code generation, use one of these flags:

  • --sdk: Generate full SDK with all transports (includes ASIO for C++)
  • --sdk_embedded: Generate minimal embedded SDK (serial transport only, no ASIO, no STL dependencies for C++)
# Generate code without SDK (default)
python -m struct_frame your_messages.proto --build_cpp --cpp_path gen/cpp

# Generate code with full SDK
python -m struct_frame your_messages.proto --build_cpp --cpp_path gen/cpp --sdk

# Generate code with embedded SDK (minimal footprint)
python -m struct_frame your_messages.proto --build_cpp --cpp_path gen/cpp --sdk_embedded

Features

  • Multiple Transport Layers: UDP, TCP, WebSocket, and Serial
  • Automatic Framing: Messages are automatically framed and parsed
  • Type-Safe Message Handling: Subscribe to specific message types
  • Auto-Reconnection: Configurable automatic reconnection on connection loss
  • Cross-Platform: Works across embedded systems, desktop, and mobile platforms
  • Generated SDK Interface (C#): High-level, type-safe send methods for each message type with field-level and struct-level overloads
  • Profile-Based Parsing: BufferReader, BufferWriter, and AccumulatingReader classes for efficient multi-frame parsing across all languages

Available SDKs

Language Sync/Async Transports Observer Pattern SDK Flags
TypeScript/JavaScript Async (Promise-based) UDP, TCP, WebSocket, Serial Callback-based --sdk
Python Both Sync & Async UDP, TCP, WebSocket, Serial Callback-based --sdk
C++ Sync (poll-based) UDP, TCP, WebSocket*, Serial Observer/Subscriber --sdk (full) or --sdk_embedded (minimal)
C# Async (Task-based) UDP, TCP, WebSocket*, Serial Event-based --sdk

*UDP, TCP, WebSocket transports in C++ require ASIO and Simple-WebSocket-Server libraries (included with --sdk). Use --sdk_embedded for serial-only with no external dependencies.

Frame Profile Parsing Classes

All SDKs provide profile-specific classes for efficient frame parsing and encoding:

Class Description
BufferReader Parse multiple frames from a buffer with automatic offset tracking
BufferWriter Encode multiple frames into a buffer with automatic offset tracking
AccumulatingReader Unified parser for buffer and streaming modes, handles partial messages

See individual SDK documentation for language-specific examples.

Quick Start

TypeScript/JavaScript

import {
  StructFrameSdk,
  UdpTransport,
} from './struct_frame_sdk';
import { BasicDefault } from './BasicDefault';
import { MyMessage } from './my_messages';

// Create transport
const transport = new UdpTransport({
  remoteHost: '192.168.1.100',
  remotePort: 5000,
  localPort: 5001,
});

// Create SDK with frame parser
const sdk = new StructFrameSdk({
  transport,
  frameParser: new BasicDefault(),
  debug: true,
});

// Subscribe to messages
sdk.subscribe<MyMessage>(MyMessage.msg_id, (message, msgId) => {
  console.log('Received:', message);
});

// Connect and send
await sdk.connect();
const msg = new MyMessage();
msg.value = 42;
await sdk.send(msg);

Python (Async)

import asyncio
from struct_frame_sdk import AsyncStructFrameSdk, AsyncUdpTransport, AsyncUdpTransportConfig
from basic_default import BasicDefault
from my_messages import MyMessage

async def main():
    # Create transport
    transport = AsyncUdpTransport(AsyncUdpTransportConfig(
        remote_host='192.168.1.100',
        remote_port=5000,
        local_port=5001,
    ))

    # Create SDK with frame parser
    sdk = AsyncStructFrameSdk(AsyncStructFrameSdkConfig(
        transport=transport,
        frame_parser=BasicDefault(),
        debug=True,
    ))

    # Subscribe to messages
    def on_message(message, msg_id):
        print(f'Received: {message}')

    sdk.subscribe(MyMessage.msg_id, on_message)

    # Connect and send
    await sdk.connect()
    msg = MyMessage(value=42)
    await sdk.send(msg)

asyncio.run(main())

C++ (Header-Only)

#include "sdk/sdk.hpp"
#include "BasicDefault.hpp"
#include "my_messages.hpp"

using namespace StructFrame;

// Create custom serial port implementation
class MySerialPort : public ISerialPort {
    // Implement platform-specific serial I/O
};

int main() {
    // Create transport
    MySerialPort serialPort;
    SerialTransport transport(&serialPort);

    // Create SDK
    BasicDefault frameParser;
    StructFrameSdk sdk({
        .transport = &transport,
        .frameParser = &frameParser,
        .debug = true,
    });

    // Subscribe with lambda
    auto subscription = sdk.subscribe<MyMessage>(
        MyMessage::msg_id,
        [](const MyMessage& msg, uint8_t msgId) {
            // Handle message
        }
    );

    // Connect and send
    sdk.connect();
    MyMessage msg;
    msg.value = 42;
    sdk.send(msg);

    // Poll for messages (embedded systems)
    while (true) {
        transport.poll();
    }
}

C

using StructFrame.Sdk;
using System;
using System.Threading.Tasks;

async Task Main()
{
    // Create transport
    var transport = new UdpTransport(new UdpTransportConfig
    {
        RemoteHost = "192.168.1.100",
        RemotePort = 5000,
        LocalPort = 5001,
    });

    // Create SDK
    var sdk = new StructFrameSdk(new StructFrameSdkConfig
    {
        Transport = transport,
        FrameParser = new BasicDefault(),
        Debug = true,
    });

    // Subscribe to messages
    sdk.Subscribe<MyMessage>(MyMessage.MsgId, (message, msgId) =>
    {
        Console.WriteLine($"Received: {message}");
    });

    // Connect and send
    await sdk.ConnectAsync();
    var msg = new MyMessage { Value = 42 };
    await sdk.SendAsync(msg);
}

Next Steps