diff --git a/README.md b/README.md index 18127d3f..be8cb26d 100644 --- a/README.md +++ b/README.md @@ -74,17 +74,30 @@ When sending structured data over a communication channel, you need to: Struct Frame's framing system addresses these challenges with a cross-platform implementation. -### Basic Frame Format +### Framing Architecture -The default frame format uses a simple but effective structure: +The framing system uses a two-level architecture: + +1. **Frame Type** (Framer): Determines the number of start bytes for synchronization + - **Basic**: 2 start bytes `[0x90] [0x70+PayloadType]` + - **Tiny**: 1 start byte `[0x70+PayloadType]` + - **None**: 0 start bytes (relies on external synchronization) + +2. **Payload Type**: Defines the header/footer structure after start bytes + - Minimal, Default, ExtendedMsgIds, ExtendedLength, Extended + - SysComp, Seq, MultiSystemStream, ExtendedMultiSystemStream + +### Basic Default Frame Format (Recommended) + +The recommended frame format uses a simple but effective structure: ``` -[Start Byte] [Message ID] [Payload Data...] [Checksum 1] [Checksum 2] - 0x90 1 byte Variable Length 1 byte 1 byte +[Start1=0x90] [Start2=0x71] [Length] [Message ID] [Payload Data...] [CRC1] [CRC2] ``` **Frame Components:** -- **Start Byte (0x90)**: Synchronization marker to identify frame boundaries +- **Start Bytes (0x90, 0x71)**: Synchronization markers to identify frame boundaries +- **Length**: Payload length (1 byte, up to 255 bytes) - **Message ID**: Unique identifier (0-255) that maps to specific message types - **Payload**: The actual serialized message data (variable length) - **Fletcher Checksum**: 2-byte error detection using Fletcher-16 algorithm @@ -92,10 +105,24 @@ The default frame format uses a simple but effective structure: **Example Frame Breakdown:** ``` Message: vehicle_heartbeat (ID=42) with 4 bytes of data [0x01, 0x02, 0x03, 0x04] -Frame: [0x90] [0x2A] [0x01, 0x02, 0x03, 0x04] [0x7F] [0x8A] - Start ID=42 Payload Data Checksum +Frame: [0x90] [0x71] [0x04] [0x2A] [0x01, 0x02, 0x03, 0x04] [0x7F] [0x8A] + Start1 Start2 Len ID=42 Payload Data Checksum ``` +### Available Payload Types + +| Payload Type | Structure | Overhead | Use Case | +|--------------|-----------|----------|----------| +| Minimal | `[MSG_ID] [PACKET]` | 1 | Fixed-size messages, trusted environments | +| Default | `[LEN] [MSG_ID] [PACKET] [CRC]` | 4 | Standard format (recommended) | +| ExtendedMsgIds | `[PKG_ID] [LEN] [MSG_ID] [PACKET] [CRC]` | 5 | Large systems with many message types | +| ExtendedLength | `[LEN16] [MSG_ID] [PACKET] [CRC]` | 5 | Large payloads (up to 64KB) | +| SysComp | `[SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC]` | 6 | Multi-vehicle networks | +| Seq | `[SEQ] [LEN] [MSG_ID] [PACKET] [CRC]` | 5 | Packet loss detection | +| MultiSystemStream | `[SEQ] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC]` | 7 | Multi-vehicle streaming | + +See [Framing Documentation](docs/framing.md) for the complete frame format reference. + ### Parser State Machine The frame parser implements a state machine to handle partial data and synchronization recovery: @@ -179,16 +206,25 @@ python src/main.py examples/myl_vehicle.proto --build_gql ### Header Structure Details -The Basic Frame format provides a minimal framing protocol: +The BasicDefault frame format (recommended) provides a robust framing protocol: -#### Header Layout (2 bytes) +#### Header Layout (4 bytes) ``` -Byte 0: Start Byte (0x90) +Byte 0: Start Byte 1 (0x90) - Fixed synchronization marker - Allows parser to identify frame boundaries - Recovery point after frame corruption -Byte 1: Message ID (0x00-0xFF) +Byte 1: Start Byte 2 (0x71 for Default payload type) + - Second sync byte encodes payload type + - 0x70 = Minimal, 0x71 = Default, 0x72 = ExtendedMsgIds, etc. + - Allows different frame formats on same channel + +Byte 2: Length (0x00-0xFF) + - Payload length in bytes + - Allows receiver to know frame size + +Byte 3: Message ID (0x00-0xFF) - Maps to specific message types in proto definitions - Used for routing and deserialization - Must match `option msgid = X` in proto message @@ -196,17 +232,19 @@ Byte 1: Message ID (0x00-0xFF) #### Footer Layout (2 bytes) ``` -Byte N+2: Fletcher Checksum Byte 1 -Byte N+3: Fletcher Checksum Byte 2 +Byte N+4: Fletcher Checksum Byte 1 +Byte N+5: Fletcher Checksum Byte 2 - Fletcher-16 checksum algorithm - - Calculated over Message ID + Payload + - Calculated over Length + Message ID + Payload - Provides error detection for corruption ``` ### Frame Size Calculation **Total Frame Size = Header + Payload + Footer** -- **Header**: 2 bytes (start byte + message ID) + +For BasicDefault (recommended): +- **Header**: 4 bytes (2 start bytes + length + message ID) - **Payload**: Variable (depends on message content) - **Footer**: 2 bytes (Fletcher checksum) @@ -217,7 +255,7 @@ message SimpleHeartbeat { uint32 device_id = 1; // 4 bytes bool alive = 2; // 1 byte } -// Total: 2 (header) + 5 (payload) + 2 (footer) = 9 bytes +// Total: 4 (header) + 5 (payload) + 2 (footer) = 11 bytes ``` ### Framing Compatibility Matrix @@ -235,19 +273,21 @@ message SimpleHeartbeat { ### Extended Frame Format Options -While struct-frame currently implements the Basic Frame format, the architecture supports extensible frame types: +Struct Frame supports multiple frame types and payload types for different use cases: + +**Frame Types:** +- **Basic Frame**: 2 start bytes (0x90, 0x70+PayloadType) - Recommended for most applications +- **Tiny Frame**: 1 start byte (0x70+PayloadType) - Constrained environments +- **None Frame**: 0 start bytes - Trusted point-to-point links -**Current Implementation:** -- **Basic Frame**: Simple start byte + message ID + checksum -- **Start Byte**: 0x90 (fixed) -- **Header Length**: 2 bytes -- **Footer Length**: 2 bytes (Fletcher checksum) +**Payload Types:** +- **Default**: Length + Message ID + Payload + CRC - Recommended +- **Minimal**: Message ID + Payload only - Fixed-size messages +- **Extended**: Package ID + 2-byte length + Message ID + Payload + CRC - Large systems +- **SysComp**: System/Component IDs for multi-vehicle networks (MAVLink-style) +- **MultiSystemStream**: Sequence + SysComp for streaming with loss detection -**Potential Extensions** (Framework Ready): -- **Length-Prefixed Frames**: Include explicit length field in header -- **Multi-Byte Start Sequences**: Enhanced synchronization -- **CRC32 Checksums**: Stronger error detection -- **Protocol Versions**: Support multiple frame format versions +See [Framing Documentation](docs/framing.md) for the complete format reference. ## Frame Format Examples and Usage @@ -273,21 +313,22 @@ engine_on = true -> [0x01] Total payload: 9 bytes ``` -**Frame Structure:** +**BasicDefault Frame Structure:** ``` -Position: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] -Data: 90 2A D2 04 00 00 00 00 83 42 01 7E C9 - │ │ └─────── Payload (9 bytes) ──────────┘ │ │ - │ └─ Message ID (42 = 0x2A) │ │ - └─ Start Byte (0x90) └────┘ - Checksum +Position: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] +Data: 90 71 09 2A D2 04 00 00 00 00 83 42 01 7E C9 + │ │ │ │ └─────── Payload (9 bytes) ──────────────┘ │ │ + │ │ │ └─ Message ID (42 = 0x2A) │ │ + │ │ └─ Length (9 = 0x09) │ │ + │ └─ Start Byte 2 (0x71 = Default payload type) │ │ + └─ Start Byte 1 (0x90) └────┘ + Checksum ``` **Checksum Calculation (Fletcher-16):** ``` -Input: [0x2A, 0xD2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x83, 0x42, 0x01] -Byte1 = (0x2A + 0xD2 + 0x04 + ... + 0x01) % 256 = 0x7E -Byte2 = (0x2A + 0xFC + 0x00 + ... + 0xFD) % 256 = 0xC9 +Input: [0x09, 0x2A, 0xD2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x83, 0x42, 0x01] +(calculated over length, message ID, and payload) Result: [0x7E, 0xC9] ``` diff --git a/docs/framing.md b/docs/framing.md index 9cb5a587..ae984d08 100644 --- a/docs/framing.md +++ b/docs/framing.md @@ -2,193 +2,196 @@ Framing wraps messages with headers and checksums so receivers can identify message boundaries and verify integrity. +## Framing Architecture + +The framing system uses a two-level architecture: + +1. **Frame Type** (Framer): Determines the number of start bytes for synchronization + - **Basic**: 2 start bytes `[0x90] [0x70+PayloadType]` + - **Tiny**: 1 start byte `[0x70+PayloadType]` + - **None**: 0 start bytes (relies on external synchronization) + +2. **Payload Type**: Defines the header/footer structure after start bytes + - The second start byte of Basic (or the single start byte of Tiny) encodes the payload type + - Payload type value is added to 0x70 base to get the start byte + ## Frame Format Definitions All supported frame formats are defined in [`examples/frame_formats.proto`](../examples/frame_formats.proto). This file provides: - Protocol Buffer definitions for each frame format -- Enumeration of all frame format types +- Enumeration of frame types and payload types - Configuration message for runtime format selection -## Recommended Frame Formats +## Start Byte Scheme -| Format | Start Bytes | Length | CRC | Total Overhead | Use Case | -|--------|-------------|--------|-----|----------------|----------| -| BasicFrame | 2 (0x90, 0x91) | 0 | 2 | 5 | When all messages are known to both systems | -| TinyFrame | 1 (0x70) | 0 | 2 | 4 | Constrained environments with known messages | -| BasicFrameWithLen | 2 (0x90, 0x92) | 1 | 2 | 6 | When systems may not have matching message definitions | -| TinyFrameWithLen | 1 (0x71) | 1 | 2 | 5 | Constrained environments with variable messages | -| BasicFrameWithLen16 | 2 (0x90, 0x93) | 2 | 2 | 7 | Large payloads up to 64KB | -| BasicFrameWithSysComp | 2 (0x90, 0x94) | 0 | 2 | 7 | Multi-system networks with system and component IDs | +| PayloadType | Offset | Basic START2 / Tiny START | Payload Structure | +|-------------|--------|---------------------------|-------------------| +| Minimal | 0 | 0x70 | `[MSG_ID] [PACKET]` | +| Default | 1 | 0x71 | `[LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| ExtendedMsgIds | 2 | 0x72 | `[LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| ExtendedLength | 3 | 0x73 | `[LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| Extended | 4 | 0x74 | `[LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| SysComp | 5 | 0x75 | `[SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| Seq | 6 | 0x76 | `[SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| MultiSystemStream | 7 | 0x77 | `[SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| ExtendedMultiSystemStream | 8 | 0x78 | `[SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | -## Extended Frame Formats +## Recommended Frame Formats -| Format | Start Bytes | Length | CRC | Total Overhead | Use Case | -|--------|-------------|--------|-----|----------------|----------| -| NoFormat | 0 | 0 | 0 | 0 | Trusted links, nested protocols | -| MinimalFrame | 0 | 0 | 2 | 3 | Minimal framing with CRC | -| MinimalFrameNoCrc | 0 | 0 | 0 | 1 | Minimal framing, trusted link | -| MinimalFrameWithLen | 0 | 1 | 2 | 4 | Variable length, minimal | +| Format | Start Bytes | Overhead | Use Case | +|--------|-------------|----------|----------| +| BasicDefault | 2 (0x90, 0x71) | 6 | **Recommended** - Standard format with length and CRC | +| TinyDefault | 1 (0x71) | 5 | Constrained environments, lower overhead | +| BasicSysComp | 2 (0x90, 0x75) | 8 | Multi-system networks | +| BasicMultiSystemStream | 2 (0x90, 0x77) | 9 | Multi-system with packet loss detection | +| BasicExtendedLength | 2 (0x90, 0x73) | 7 | Large payloads up to 64KB | + +## Payload Types + +### Minimal +**Format**: `[MSG_ID] [PACKET]` +- No length field, no CRC +- Requires known message sizes on both ends +- Minimal overhead (1 byte) +- Use for: Fixed-size messages in trusted environments + +### Default (Recommended) +**Format**: `[LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- 1-byte length field (up to 255 bytes) +- 2-byte Fletcher checksum +- Overhead: 4 bytes +- Use for: Most applications with variable-length messages + +### ExtendedMsgIds +**Format**: `[LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- Adds package ID for message namespace separation +- Allows 256 packages × 256 message IDs = 65536 message types +- Overhead: 5 bytes +- Use for: Large systems with many message types + +### ExtendedLength +**Format**: `[LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- 2-byte length field (up to 65535 bytes) +- Overhead: 5 bytes +- Use for: Large payloads, firmware updates, bulk transfers + +### Extended +**Format**: `[LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- Combines ExtendedMsgIds + ExtendedLength +- Overhead: 6 bytes +- Use for: Large systems with large payloads + +### SysComp +**Format**: `[SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- System ID identifies the vehicle/ground station (0-255) +- Component ID identifies the component (autopilot, camera, etc.) +- Overhead: 6 bytes +- Use for: Multi-vehicle networks, MAVLink-style routing -## Parametric Frame Formats +### Seq +**Format**: `[SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- 1-byte sequence number for packet loss detection +- Overhead: 5 bytes +- Use for: Unreliable links where packet loss matters -| Format | Start Bytes | Length | CRC | Total Overhead | Use Case | -|--------|-------------|--------|-----|----------------|----------| -| BasicFrameNoCrc | 2 (0x90, 0x95) | 0 | 0 | 3 | Sync recovery, no CRC | -| BasicFrameWithLenNoCrc | 2 (0x90, 0x96) | 1 | 0 | 4 | Variable length, no CRC | -| BasicFrameWithLen16NoCrc | 2 (0x90, 0x97) | 2 | 0 | 5 | Large payloads, no CRC | -| TinyFrameNoCrc | 1 (0x72) | 0 | 0 | 2 | Minimal overhead | -| TinyFrameWithLenNoCrc | 1 (0x73) | 1 | 0 | 3 | Variable, minimal overhead | -| TinyFrameWithLen16 | 1 (0x74) | 2 | 2 | 6 | Large payloads, constrained | -| TinyFrameWithLen16NoCrc | 1 (0x75) | 2 | 0 | 4 | Large, minimal overhead | -| MinimalFrameWithLenNoCrc | 0 | 1 | 0 | 2 | Variable length, no CRC | -| MinimalFrameWithLen16 | 0 | 2 | 2 | 5 | Large payloads, minimal | -| MinimalFrameWithLen16NoCrc | 0 | 2 | 0 | 3 | Large payloads, no CRC | +### MultiSystemStream +**Format**: `[SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- Combines Seq + SysComp +- Overhead: 7 bytes +- Use for: Multi-vehicle streaming with loss detection -## No Frame Format +### ExtendedMultiSystemStream +**Format**: `[SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` +- Full-featured format with all extensions +- Overhead: 9 bytes +- Use for: Complex multi-system networks with large payloads -For trusted point-to-point links where you control both ends, you can skip framing entirely. Messages are sent as raw bytes with no header or checksum. +## Frame Types + +### None Frame (0 start bytes) +For trusted point-to-point links where you control both ends. Use cases: - Direct function calls between components - Shared memory between processes -- When another protocol already handles framing and packeting +- When another protocol already handles framing Limitations: - No message boundary detection -- No error detection -- Must know message type externally - -## Basic Frame Format +- Must synchronize externally -The default frame format used by Struct Frame: +### Tiny Frame (1 start byte) +Low overhead framing for constrained environments. ``` -[Start Byte 1] [Start Byte 2] [Message ID] [Payload Data...] [Checksum 1] [Checksum 2] - 0x90 0x91 1 byte Variable Length 1 byte 1 byte +[START=0x70+PayloadType] [PAYLOAD...] ``` -### Components - -**Start Bytes (0x90, 0x91)** -- Two-byte marker to identify frame boundaries -- Parser scans for this sequence to synchronize -- Second byte varies by frame type (0x91=Basic, 0x92=WithLen, etc.) - -**Message ID (1 byte)** -- Maps to specific message type defined in proto -- Range 0-255 -- Must match `option msgid = X` in proto definition - -**Payload** -- Raw serialized message data -- Variable length depending on message type -- Little-endian byte order - -**Fletcher Checksum (2 bytes)** -- Fletcher-16 algorithm -- Calculated over Message ID + Payload -- Detects single-bit errors and most multi-bit errors - -### Example +- 1 byte header overhead +- Suitable for: Battery-powered devices, high message rates -Message: VehicleHeartbeat (ID=42) with payload [0x01, 0x02, 0x03, 0x04] +### Basic Frame (2 start bytes) +The recommended frame format for most applications: ``` -Frame: [0x90] [0x91] [0x2A] [0x01, 0x02, 0x03, 0x04] [0x7F] [0x8A] - Start1 Start2 ID Payload Checksum +[START1=0x90] [START2=0x70+PayloadType] [PAYLOAD...] ``` -### Frame Size - -Total bytes = 3 (header) + payload size + 2 (checksum) - -For a message with 5 bytes of data: 3 + 5 + 2 = 10 bytes total - -## Minimal Frame Variants - -Minimal framing with just message ID and optional CRC (0 start bytes): - -**MinimalFrame**: `[MSG_ID (1)] [PAYLOAD] [CRC (2)]` -- 3 bytes overhead -- For synchronized links with error detection - -**MinimalFrameNoCrc**: `[MSG_ID (1)] [PAYLOAD]` -- 1 byte overhead -- For trusted, synchronized links - -## Tiny Frame Variants - -Low overhead framing for constrained environments (1 start byte): - -**TinyFrame**: `[START (0x70)] [MSG_ID (1)] [PAYLOAD] [CRC (2)]` -- 4 bytes overhead -- Battery-powered devices, high message rates +- 2 bytes header overhead +- Better synchronization recovery than Tiny +- Recommended for: Most serial and network communication -**TinyFrameNoCrc**: `[START (0x72)] [MSG_ID (1)] [PAYLOAD]` -- 2 bytes overhead -- Minimal overhead with sync recovery +## Basic Default Frame Example -## Length-Prefixed Variants +The most common frame format (BasicDefault): -All frame formats have variants with explicit length fields: - -**1-byte length (WithLen)**: Supports payloads up to 255 bytes -- Adds 1 byte to header -- Use for variable-length messages - -**2-byte length (WithLen16)**: Supports payloads up to 65,535 bytes -- Adds 2 bytes to header (little-endian) -- Use for large data transfers, firmware updates - -Example: `BasicFrameWithLen16` ``` -[START1 (0x90)] [START2 (0x93)] [MSG_ID (1)] [LEN_LO (1)] [LEN_HI (1)] [PAYLOAD] [CRC (2)] +[0x90] [0x71] [LEN] [MSG_ID] [Payload Data...] [CRC1] [CRC2] + ^ ^ ^ ^ ^ ^ ^ + | | | | | | | +Start1 Start2 Length MsgID Variable Fletcher-16 ``` -## System/Component ID Variant +### Example + +Message: VehicleHeartbeat (ID=42) with 4-byte payload [0x01, 0x02, 0x03, 0x04] -**BasicFrameWithSysComp**: For multi-system networks ``` -[START1 (0x90)] [START2 (0x94)] [SYS_ID (1)] [COMP_ID (1)] [MSG_ID (1)] [PAYLOAD] [CRC (2)] +Frame: [0x90] [0x71] [0x04] [0x2A] [0x01, 0x02, 0x03, 0x04] [0x7F] [0x8A] + Start1 Start2 Len ID Payload Checksum ``` -- 7 bytes overhead -- System ID identifies the vehicle/ground station -- Component ID identifies the component (autopilot, camera, etc.) + +Total bytes = 2 (start) + 1 (len) + 1 (id) + 4 (payload) + 2 (crc) = 10 bytes ## Parser State Machine -The parser implements a state machine to handle partial data and recover from corruption: +The parser implements a state machine for Basic/Tiny frames: ``` States: - LOOKING_FOR_START_BYTE -> GETTING_HEADER -> GETTING_PAYLOAD - ^ | - |__________________________________| + LOOKING_FOR_START -> GETTING_HEADER -> GETTING_PAYLOAD + ^ | + |____________________________| (on complete or error) ``` -**LOOKING_FOR_START_BYTE** -- Scans incoming bytes for 0x90 -- Discards all other bytes -- Transitions to GETTING_HEADER on match +**LOOKING_FOR_START** (Basic/Tiny only) +- Scans incoming bytes for start byte(s) +- Basic: looks for 0x90 then 0x7X +- Tiny: looks for 0x7X +- Discards other bytes **GETTING_HEADER** -- Reads message ID -- Looks up expected message size +- Reads header fields (length, msg_id, etc.) +- Validates values - Transitions to GETTING_PAYLOAD if valid -- Returns to LOOKING_FOR_START_BYTE if invalid **GETTING_PAYLOAD** - Collects payload bytes -- Collects checksum bytes +- Collects CRC bytes (if applicable) - Validates checksum on completion -- Returns to LOOKING_FOR_START_BYTE - -This handles: -- Partial frame reception (data arrives in chunks) -- Frame corruption (invalid start bytes, bad checksums) -- Synchronization loss (automatic recovery) +- Returns to LOOKING_FOR_START ## CRC Check @@ -197,7 +200,7 @@ The Fletcher-16 checksum provides error detection: ``` sum1 = 0 sum2 = 0 -for each byte in (message_id + payload): +for each byte in (header_after_start + payload): sum1 = (sum1 + byte) % 256 sum2 = (sum2 + sum1) % 256 checksum = [sum1, sum2] @@ -219,11 +222,6 @@ u-blox proprietary binary protocol for GPS/GNSS receivers: [SYNC1 (0xB5)] [SYNC2 (0x62)] [CLASS (1)] [ID (1)] [LEN (2)] [PAYLOAD] [CK_A] [CK_B] ``` -- 8 bytes overhead -- Class + ID for message routing -- Fletcher-8 checksum -- Use for u-blox GPS integration - ### MAVLink v1 Legacy drone communication protocol: @@ -232,12 +230,6 @@ Legacy drone communication protocol: [STX (0xFE)] [LEN (1)] [SEQ (1)] [SYS (1)] [COMP (1)] [MSG (1)] [PAYLOAD] [CRC (2)] ``` -- 8 bytes overhead -- Sequence counter for packet loss detection -- System ID and Component ID for multi-vehicle networks -- CRC-16/X.25 checksum -- Use for ArduPilot/PX4 compatibility - ### MAVLink v2 Modern drone communication with extended features: @@ -246,21 +238,57 @@ Modern drone communication with extended features: [STX (0xFD)] [LEN (1)] [INCOMPAT (1)] [COMPAT (1)] [SEQ (1)] [SYS (1)] [COMP (1)] [MSG_ID (3)] [PAYLOAD] [CRC (2)] [SIGNATURE (13, optional)] ``` -- 12-25 bytes overhead -- 24-bit message ID (16.7M message types) -- Incompatibility/compatibility flags for version negotiation -- Optional 13-byte signature for authentication -- Use for secure drone communication +## Complete Frame Format Reference + +### None Frames (0 start bytes) + +| Format | Overhead | Structure | +|--------|----------|-----------| +| NoneMinimal | 1 | `[MSG_ID] [PACKET]` | +| NoneDefault | 4 | `[LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneExtendedMsgIds | 5 | `[LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneExtendedLength | 5 | `[LEN16] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneExtended | 6 | `[LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneSysComp | 6 | `[SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneSeq | 5 | `[SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneMultiSystemStream | 7 | `[SEQ] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| NoneExtendedMultiSystemStream | 9 | `[SEQ] [SYS] [COMP] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | + +### Tiny Frames (1 start byte: 0x70+PayloadType) + +| Format | Start | Overhead | Structure | +|--------|-------|----------|-----------| +| TinyMinimal | 0x70 | 2 | `[START] [MSG_ID] [PACKET]` | +| TinyDefault | 0x71 | 5 | `[START] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinyExtendedMsgIds | 0x72 | 6 | `[START] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinyExtendedLength | 0x73 | 6 | `[START] [LEN16] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinyExtended | 0x74 | 7 | `[START] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinySysComp | 0x75 | 7 | `[START] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinySeq | 0x76 | 6 | `[START] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinyMultiSystemStream | 0x77 | 8 | `[START] [SEQ] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| TinyExtendedMultiSystemStream | 0x78 | 10 | `[START] [SEQ] [SYS] [COMP] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | + +### Basic Frames (2 start bytes: 0x90, 0x70+PayloadType) + +| Format | Start2 | Overhead | Structure | +|--------|--------|----------|-----------| +| BasicMinimal | 0x70 | 3 | `[0x90] [START2] [MSG_ID] [PACKET]` | +| BasicDefault | 0x71 | 6 | `[0x90] [START2] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicExtendedMsgIds | 0x72 | 7 | `[0x90] [START2] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicExtendedLength | 0x73 | 7 | `[0x90] [START2] [LEN16] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicExtended | 0x74 | 8 | `[0x90] [START2] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicSysComp | 0x75 | 8 | `[0x90] [START2] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicSeq | 0x76 | 7 | `[0x90] [START2] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicMultiSystemStream | 0x77 | 9 | `[0x90] [START2] [SEQ] [SYS] [COMP] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2]` | +| BasicExtendedMultiSystemStream | 0x78 | 11 | `[0x90] [START2] [SEQ] [SYS] [COMP] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2]` | ## Framing Compatibility | Frame Format | C | C++ | TypeScript | Python | |--------------|---|-----|------------|--------| -| No Header (No Framing) | Yes | Yes | Yes | Yes | -| Basic Frame Format | Yes | Yes | Yes | Yes | -| MSG ID Frames | Defined | Defined | Defined | Defined | -| Tiny Frames | Defined | Defined | Defined | Defined | -| Length-Prefixed | Defined | Defined | Defined | Defined | +| None Frames | Yes | Yes | Yes | Yes | +| Basic Frames | Yes | Yes | Yes | Yes | +| Tiny Frames | Yes | Yes | Yes | Yes | | UBX | Defined | Defined | Defined | Defined | | Mavlink v1 | Defined | Defined | Defined | Defined | | Mavlink v2 | Defined | Defined | Defined | Defined | diff --git a/examples/frame_formats.proto b/examples/frame_formats.proto index 89ffe90b..0e1c848e 100644 --- a/examples/frame_formats.proto +++ b/examples/frame_formats.proto @@ -1,250 +1,466 @@ // Frame Format Definitions for struct-frame // Defines message framing formats for communication over serial, network, or byte streams. +// +// FRAMING ARCHITECTURE: +// The framing system has two levels: +// 1. FRAMER (Basic/Tiny/None): Determines start bytes for synchronization +// - Basic: 2 start bytes [0x90] [0x70+payload_type] +// - Tiny: 1 start byte [0x70+payload_type] +// - None: 0 start bytes (relies on external sync) +// +// 2. PAYLOAD TYPE: Defines the header/footer structure of the payload +// The second start byte of Basic (or the single start byte of Tiny) encodes the payload type. +// +// Start byte 1 (Basic only): 0x90 +// Start byte 2 (Basic) or Start byte (Tiny): 0x70 + PayloadType offset package frame_formats; -// Frame format type enumeration -enum FrameFormatType { - NO_FORMAT = 0; - MINIMAL_FRAME = 1; - MINIMAL_FRAME_NO_CRC = 2; - BASIC_FRAME = 3; - BASIC_FRAME_NO_CRC = 4; - TINY_FRAME = 5; - TINY_FRAME_NO_CRC = 6; - MINIMAL_FRAME_WITH_LEN = 7; - MINIMAL_FRAME_WITH_LEN_NO_CRC = 8; - MINIMAL_FRAME_WITH_LEN16 = 9; - MINIMAL_FRAME_WITH_LEN16_NO_CRC = 10; - BASIC_FRAME_WITH_LEN = 11; - BASIC_FRAME_WITH_LEN_NO_CRC = 12; - BASIC_FRAME_WITH_LEN16 = 13; - BASIC_FRAME_WITH_LEN16_NO_CRC = 14; - TINY_FRAME_WITH_LEN = 15; - TINY_FRAME_WITH_LEN_NO_CRC = 16; - TINY_FRAME_WITH_LEN16 = 17; - TINY_FRAME_WITH_LEN16_NO_CRC = 18; - BASIC_FRAME_WITH_SYS_COMP = 19; - UBX = 20; - MAVLINK_V1 = 21; - MAVLINK_V2 = 22; -} +// ============================================================================ +// PAYLOAD TYPE ENUMERATION +// ============================================================================ +// PayloadType defines how the payload is structured (header fields + CRC) +// The start byte encodes this: 0x70 + PayloadType value -// Basic message payload included in all frame formats -message BasicMessage { - uint8 msg_id = 1; +enum PayloadType { + // Minimal: [MSG_ID] [PACKET] + // No length field, no CRC. Requires known message sizes. + PAYLOAD_MINIMAL = 0; + + // Default: [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // 1-byte length, 2-byte CRC. Standard format. + PAYLOAD_DEFAULT = 1; + + // ExtendedMsgIds: [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds package ID for message namespace separation. + PAYLOAD_EXTENDED_MSG_IDS = 2; + + // ExtendedLength: [LEN16] [MSG_ID] [PACKET] [CRC1] [CRC2] + // 2-byte length for payloads up to 65535 bytes. + PAYLOAD_EXTENDED_LENGTH = 3; + + // Extended: [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Extended message IDs + 2-byte length. + PAYLOAD_EXTENDED = 4; + + // SysComp: [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds system and component IDs for multi-system networks. + PAYLOAD_SYS_COMP = 5; + + // Seq: [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds sequence number for packet loss detection. + PAYLOAD_SEQ = 6; + + // MultiSystemStream: [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Combines Seq + SysComp for multi-system streaming. + PAYLOAD_MULTI_SYSTEM_STREAM = 7; + + // ExtendedMultiSystemStream: [SEQ] [SYS_ID] [COMP_ID] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Full featured format with all extensions. + PAYLOAD_EXTENDED_MULTI_SYSTEM_STREAM = 8; } // ============================================================================ -// NO FORMAT - Raw message, no framing -// Format: [MSG] -// Overhead: 0 bytes -message NoFormat { - BasicMessage payload = 1; +// FRAME TYPE ENUMERATION +// ============================================================================ +// FrameType defines the framing level (number of start bytes) + +enum FrameType { + // None: No start bytes, relies on external synchronization + FRAME_NONE = 0; + + // Tiny: 1 start byte [0x70+PayloadType] + FRAME_TINY = 1; + + // Basic: 2 start bytes [0x90] [0x70+PayloadType] + FRAME_BASIC = 2; } -// ============================================================================ -// MINIMAL FRAME - No start bytes, just MSG_ID with CRC -// Format: [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 3 bytes -message MinimalFrame { - BasicMessage payload = 1; - uint8 crc_byte1 = 2; - uint8 crc_byte2 = 3; +// Legacy frame format type enumeration (for backward compatibility) +enum FrameFormatType { + // None frames (0 start bytes) + NONE_MINIMAL = 0; + NONE_DEFAULT = 1; + NONE_EXTENDED_MSG_IDS = 2; + NONE_EXTENDED_LENGTH = 3; + NONE_EXTENDED = 4; + NONE_SYS_COMP = 5; + NONE_SEQ = 6; + NONE_MULTI_SYSTEM_STREAM = 7; + NONE_EXTENDED_MULTI_SYSTEM_STREAM = 8; + + // Tiny frames (1 start byte at 0x70+PayloadType) + TINY_MINIMAL = 10; + TINY_DEFAULT = 11; + TINY_EXTENDED_MSG_IDS = 12; + TINY_EXTENDED_LENGTH = 13; + TINY_EXTENDED = 14; + TINY_SYS_COMP = 15; + TINY_SEQ = 16; + TINY_MULTI_SYSTEM_STREAM = 17; + TINY_EXTENDED_MULTI_SYSTEM_STREAM = 18; + + // Basic frames (2 start bytes: 0x90, 0x70+PayloadType) + BASIC_MINIMAL = 20; + BASIC_DEFAULT = 21; + BASIC_EXTENDED_MSG_IDS = 22; + BASIC_EXTENDED_LENGTH = 23; + BASIC_EXTENDED = 24; + BASIC_SYS_COMP = 25; + BASIC_SEQ = 26; + BASIC_MULTI_SYSTEM_STREAM = 27; + BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 28; + + // Third party protocols + UBX = 100; + MAVLINK_V1 = 101; + MAVLINK_V2 = 102; } -// MINIMAL FRAME NO CRC -// Format: [MSG_ID] [MSG] +// ============================================================================ +// FRAME FORMAT CONSTANTS +// ============================================================================ + +// Start byte values +// Basic frame start byte 1 is always 0x90 +// Basic frame start byte 2 and Tiny frame start byte are 0x70 + PayloadType + +// ============================================================================ +// NONE FRAME FORMATS (0 start bytes) +// ============================================================================ + +// NONE_MINIMAL - Minimal payload with no framing +// Format: [MSG_ID] [PACKET] // Overhead: 1 byte -message MinimalFrameNoCrc { +message NoneMinimal { BasicMessage payload = 1; } -// ============================================================================ -// BASIC FRAME - 2 start bytes with CRC (Recommended) -// Format: [START1=0x90] [START2=0x91] [MSG_ID] [MSG] [CRC1] [CRC2] +// NONE_DEFAULT - Default payload with no framing +// Format: [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 4 bytes +message NoneDefault { + uint8 length = 1; + BasicMessage payload = 2; + uint8 crc_byte1 = 3; + uint8 crc_byte2 = 4; +} + +// NONE_EXTENDED_MSG_IDS - Extended message IDs payload with no framing +// Format: [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] // Overhead: 5 bytes -message BasicFrame { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x91]; +message NoneExtendedMsgIds { + uint8 length = 1; + uint8 package_id = 2; BasicMessage payload = 3; uint8 crc_byte1 = 4; uint8 crc_byte2 = 5; } -// BASIC FRAME NO CRC -// Format: [START1=0x90] [START2=0x95] [MSG_ID] [MSG] -// Overhead: 3 bytes -message BasicFrameNoCrc { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x95]; - BasicMessage payload = 3; -} - -// ============================================================================ -// TINY FRAME - 1 start byte with CRC (Recommended) -// Format: [START=0x70] [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 4 bytes -message TinyFrame { - uint8 start_byte = 1 [(hex) = 0x70]; +// NONE_EXTENDED_LENGTH - Extended length payload with no framing +// Format: [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message NoneExtendedLength { + uint16 length = 1; BasicMessage payload = 2; uint8 crc_byte1 = 3; uint8 crc_byte2 = 4; } -// TINY FRAME NO CRC -// Format: [START=0x72] [MSG_ID] [MSG] -// Overhead: 2 bytes -message TinyFrameNoCrc { - uint8 start_byte = 1 [(hex) = 0x72]; - BasicMessage payload = 2; +// NONE_EXTENDED - Extended payload with no framing +// Format: [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message NoneExtended { + uint16 length = 1; + uint8 package_id = 2; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// NONE_SYS_COMP - System/Component ID payload with no framing +// Format: [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message NoneSysComp { + uint8 system_id = 1; + uint8 component_id = 2; + uint8 length = 3; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; +} + +// NONE_SEQ - Sequence number payload with no framing +// Format: [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message NoneSeq { + uint8 sequence = 1; + uint8 length = 2; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// NONE_MULTI_SYSTEM_STREAM - Multi-system stream payload with no framing +// Format: [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message NoneMultiSystemStream { + uint8 sequence = 1; + uint8 system_id = 2; + uint8 component_id = 3; + uint8 length = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; +} + +// NONE_EXTENDED_MULTI_SYSTEM_STREAM - Extended multi-system stream payload with no framing +// Format: [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 9 bytes +message NoneExtendedMultiSystemStream { + uint8 sequence = 1; + uint8 system_id = 2; + uint8 component_id = 3; + uint16 length = 4; + uint8 package_id = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; } // ============================================================================ -// LENGTH-PREFIXED VARIANTS (1-byte length, up to 255 bytes) +// TINY FRAME FORMATS (1 start byte at 0x70+PayloadType) // ============================================================================ -// MINIMAL FRAME WITH LEN -// Format: [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] -// Overhead: 4 bytes -message MinimalFrameWithLen { - BasicMessage payload = 1; +// TINY_MINIMAL - Tiny frame with minimal payload +// Format: [START=0x70] [MSG_ID] [PACKET] +// Overhead: 2 bytes +message TinyMinimal { + uint8 start_byte = 1 [(hex) = 0x70]; + BasicMessage payload = 2; +} + +// TINY_DEFAULT - Tiny frame with default payload (Recommended) +// Format: [START=0x71] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message TinyDefault { + uint8 start_byte = 1 [(hex) = 0x71]; uint8 length = 2; - uint8 crc_byte1 = 3; - uint8 crc_byte2 = 4; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; } -// MINIMAL FRAME WITH LEN NO CRC -// Format: [MSG_ID] [LEN] [MSG] -// Overhead: 2 bytes -message MinimalFrameWithLenNoCrc { - BasicMessage payload = 1; +// TINY_EXTENDED_MSG_IDS - Tiny frame with extended message IDs +// Format: [START=0x72] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message TinyExtendedMsgIds { + uint8 start_byte = 1 [(hex) = 0x72]; uint8 length = 2; + uint8 package_id = 3; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN (Recommended for variable length) -// Format: [START1=0x90] [START2=0x92] [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] +// TINY_EXTENDED_LENGTH - Tiny frame with extended length +// Format: [START=0x73] [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] // Overhead: 6 bytes -message BasicFrameWithLen { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x92]; +message TinyExtendedLength { + uint8 start_byte = 1 [(hex) = 0x73]; + uint16 length = 2; BasicMessage payload = 3; - uint8 length = 4; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// TINY_EXTENDED - Tiny frame with extended payload +// Format: [START=0x74] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message TinyExtended { + uint8 start_byte = 1 [(hex) = 0x74]; + uint16 length = 2; + uint8 package_id = 3; + BasicMessage payload = 4; uint8 crc_byte1 = 5; uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN NO CRC -// Format: [START1=0x90] [START2=0x96] [MSG_ID] [LEN] [MSG] -// Overhead: 4 bytes -message BasicFrameWithLenNoCrc { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x96]; - BasicMessage payload = 3; +// TINY_SYS_COMP - Tiny frame with system/component IDs +// Format: [START=0x75] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message TinySysComp { + uint8 start_byte = 1 [(hex) = 0x75]; + uint8 system_id = 2; + uint8 component_id = 3; uint8 length = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// TINY FRAME WITH LEN (Recommended) -// Format: [START=0x71] [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] -// Overhead: 5 bytes -message TinyFrameWithLen { - uint8 start_byte = 1 [(hex) = 0x71]; - BasicMessage payload = 2; +// TINY_SEQ - Tiny frame with sequence number +// Format: [START=0x76] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message TinySeq { + uint8 start_byte = 1 [(hex) = 0x76]; + uint8 sequence = 2; uint8 length = 3; - uint8 crc_byte1 = 4; - uint8 crc_byte2 = 5; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// TINY FRAME WITH LEN NO CRC -// Format: [START=0x73] [MSG_ID] [LEN] [MSG] -// Overhead: 3 bytes -message TinyFrameWithLenNoCrc { - uint8 start_byte = 1 [(hex) = 0x73]; - BasicMessage payload = 2; - uint8 length = 3; +// TINY_MULTI_SYSTEM_STREAM - Tiny frame with multi-system stream +// Format: [START=0x77] [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message TinyMultiSystemStream { + uint8 start_byte = 1 [(hex) = 0x77]; + uint8 sequence = 2; + uint8 system_id = 3; + uint8 component_id = 4; + uint8 length = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; +} + +// TINY_EXTENDED_MULTI_SYSTEM_STREAM - Tiny frame with extended multi-system stream +// Format: [START=0x78] [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 10 bytes +message TinyExtendedMultiSystemStream { + uint8 start_byte = 1 [(hex) = 0x78]; + uint8 sequence = 2; + uint8 system_id = 3; + uint8 component_id = 4; + uint16 length = 5; + uint8 package_id = 6; + BasicMessage payload = 7; + uint8 crc_byte1 = 8; + uint8 crc_byte2 = 9; } // ============================================================================ -// LENGTH-PREFIXED VARIANTS (2-byte length, up to 65535 bytes) +// BASIC FRAME FORMATS (2 start bytes: 0x90, 0x70+PayloadType) // ============================================================================ -// MINIMAL FRAME WITH LEN16 -// Format: [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 5 bytes -message MinimalFrameWithLen16 { - BasicMessage payload = 1; - uint16 length = 2; - uint8 crc_byte1 = 3; - uint8 crc_byte2 = 4; -} - -// MINIMAL FRAME WITH LEN16 NO CRC -// Format: [MSG_ID] [LEN_LO] [LEN_HI] [MSG] +// BASIC_MINIMAL - Basic frame with minimal payload +// Format: [START1=0x90] [START2=0x70] [MSG_ID] [PACKET] // Overhead: 3 bytes -message MinimalFrameWithLen16NoCrc { - BasicMessage payload = 1; - uint16 length = 2; +message BasicMinimal { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x70]; + BasicMessage payload = 3; } -// BASIC FRAME WITH LEN16 (Recommended for large payloads) -// Format: [START1=0x90] [START2=0x93] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 7 bytes -message BasicFrameWithLen16 { +// BASIC_DEFAULT - Basic frame with default payload (Recommended) +// Format: [START1=0x90] [START2=0x71] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message BasicDefault { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x93]; - BasicMessage payload = 3; - uint16 length = 4; + uint8 start_byte2 = 2 [(hex) = 0x71]; + uint8 length = 3; + BasicMessage payload = 4; uint8 crc_byte1 = 5; uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN16 NO CRC -// Format: [START1=0x90] [START2=0x97] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] -// Overhead: 5 bytes -message BasicFrameWithLen16NoCrc { +// BASIC_EXTENDED_MSG_IDS - Basic frame with extended message IDs +// Format: [START1=0x90] [START2=0x72] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicExtendedMsgIds { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x97]; - BasicMessage payload = 3; - uint16 length = 4; + uint8 start_byte2 = 2 [(hex) = 0x72]; + uint8 length = 3; + uint8 package_id = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// TINY FRAME WITH LEN16 -// Format: [START=0x74] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 6 bytes -message TinyFrameWithLen16 { - uint8 start_byte = 1 [(hex) = 0x74]; - BasicMessage payload = 2; +// BASIC_EXTENDED_LENGTH - Basic frame with extended length +// Format: [START1=0x90] [START2=0x73] [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicExtendedLength { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x73]; uint16 length = 3; - uint8 crc_byte1 = 4; - uint8 crc_byte2 = 5; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// TINY FRAME WITH LEN16 NO CRC -// Format: [START=0x75] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] -// Overhead: 4 bytes -message TinyFrameWithLen16NoCrc { - uint8 start_byte = 1 [(hex) = 0x75]; - BasicMessage payload = 2; +// BASIC_EXTENDED - Basic frame with extended payload +// Format: [START1=0x90] [START2=0x74] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message BasicExtended { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x74]; uint16 length = 3; + uint8 package_id = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// ============================================================================ -// SYSTEM/COMPONENT ID VARIANT (Recommended for multi-system networks) -// ============================================================================ - -// BASIC FRAME WITH SYS COMP -// Format: [START1=0x90] [START2=0x94] [SYS_ID] [COMP_ID] [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 7 bytes -message BasicFrameWithSysComp { +// BASIC_SYS_COMP - Basic frame with system/component IDs +// Format: [START1=0x90] [START2=0x75] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message BasicSysComp { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x94]; + uint8 start_byte2 = 2 [(hex) = 0x75]; uint8 system_id = 3; uint8 component_id = 4; + uint8 length = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; +} + +// BASIC_SEQ - Basic frame with sequence number +// Format: [START1=0x90] [START2=0x76] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicSeq { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x76]; + uint8 sequence = 3; + uint8 length = 4; BasicMessage payload = 5; uint8 crc_byte1 = 6; uint8 crc_byte2 = 7; } +// BASIC_MULTI_SYSTEM_STREAM - Basic frame with multi-system stream +// Format: [START1=0x90] [START2=0x77] [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 9 bytes +message BasicMultiSystemStream { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x77]; + uint8 sequence = 3; + uint8 system_id = 4; + uint8 component_id = 5; + uint8 length = 6; + BasicMessage payload = 7; + uint8 crc_byte1 = 8; + uint8 crc_byte2 = 9; +} + +// BASIC_EXTENDED_MULTI_SYSTEM_STREAM - Basic frame with extended multi-system stream +// Format: [START1=0x90] [START2=0x78] [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 11 bytes +message BasicExtendedMultiSystemStream { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x78]; + uint8 sequence = 3; + uint8 system_id = 4; + uint8 component_id = 5; + uint16 length = 6; + uint8 package_id = 7; + BasicMessage payload = 8; + uint8 crc_byte1 = 9; + uint8 crc_byte2 = 10; +} + // ============================================================================ // THIRD PARTY PROTOCOLS // ============================================================================ @@ -312,15 +528,24 @@ message MavlinkV2Signature { uint8 signature_5 = 13; } +// ============================================================================ +// HELPER MESSAGES +// ============================================================================ + +// Basic message payload included in all frame formats +message BasicMessage { + uint8 msg_id = 1; +} + // ============================================================================ // CONFIGURATION // ============================================================================ // Runtime frame format configuration message FrameFormatConfig { - FrameFormatType format_type = 1; - uint8 start_byte1 = 2 [(hex) = 0x90]; - uint8 start_byte2 = 3 [(hex) = 0x91]; - bool crc_enabled = 4; - bool signing_enabled = 5; + FrameType frame_type = 1; + PayloadType payload_type = 2; + uint8 start_byte1 = 3 [(hex) = 0x90]; + uint8 start_byte2 = 4 [(hex) = 0x71]; + bool crc_enabled = 5; } diff --git a/src/struct_frame/boilerplate/c/basic_default.h b/src/struct_frame/boilerplate/c/basic_default.h new file mode 100644 index 00000000..62adde4b --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_default.h @@ -0,0 +1,209 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicDefault Frame Format + *===========================================================================*/ + +/* BasicDefault constants */ +#define BASIC_DEFAULT_START_BYTE1 0x90 +#define BASIC_DEFAULT_START_BYTE2 0x71 +#define BASIC_DEFAULT_HEADER_SIZE 4 /* start_byte1 + start_byte2 + msg_id + length(1) */ +#define BASIC_DEFAULT_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_DEFAULT_OVERHEAD (BASIC_DEFAULT_HEADER_SIZE + BASIC_DEFAULT_FOOTER_SIZE) + +/* BasicDefault parser states */ +typedef enum basic_default_parser_state { + BASIC_DEFAULT_LOOKING_FOR_START1 = 0, + BASIC_DEFAULT_LOOKING_FOR_START2 = 1, + BASIC_DEFAULT_GETTING_MSG_ID = 2, + BASIC_DEFAULT_GETTING_LENGTH = 3, + BASIC_DEFAULT_GETTING_PAYLOAD = 4 +} basic_default_parser_state_t; + +/* BasicDefault parser state structure */ +typedef struct basic_default_parser { + basic_default_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_default_parser_t; + +/* BasicDefault encode buffer structure */ +typedef struct basic_default_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_default_encode_buffer_t; + +/** + * Initialize a BasicDefault parser + */ +static inline void basic_default_parser_init(basic_default_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_DEFAULT_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicDefault parser state + */ +static inline void basic_default_parser_reset(basic_default_parser_t* parser) { + parser->state = BASIC_DEFAULT_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicDefault format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_default_parse_byte(basic_default_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_DEFAULT_LOOKING_FOR_START1: + if (byte == BASIC_DEFAULT_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_DEFAULT_LOOKING_FOR_START2; + } + break; + + case BASIC_DEFAULT_LOOKING_FOR_START2: + if (byte == BASIC_DEFAULT_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_DEFAULT_GETTING_MSG_ID; + } else if (byte == BASIC_DEFAULT_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_DEFAULT_LOOKING_FOR_START2; + } else { + parser->state = BASIC_DEFAULT_LOOKING_FOR_START1; + } + break; + + case BASIC_DEFAULT_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_DEFAULT_GETTING_LENGTH; + break; + + case BASIC_DEFAULT_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = BASIC_DEFAULT_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_DEFAULT_GETTING_PAYLOAD; + } else { + parser->state = BASIC_DEFAULT_LOOKING_FOR_START1; + } + break; + + case BASIC_DEFAULT_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_DEFAULT_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_DEFAULT_HEADER_SIZE; + } + parser->state = BASIC_DEFAULT_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicDefault format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_default_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_DEFAULT_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_DEFAULT_START_BYTE1; + buffer[1] = BASIC_DEFAULT_START_BYTE2; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicDefault packet in a buffer + */ +static inline frame_msg_info_t basic_default_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_DEFAULT_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_DEFAULT_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_DEFAULT_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_DEFAULT_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_DEFAULT_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_extended.h b/src/struct_frame/boilerplate/c/basic_extended.h new file mode 100644 index 00000000..5ac00d94 --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_extended.h @@ -0,0 +1,216 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicExtended Frame Format + *===========================================================================*/ + +/* BasicExtended constants */ +#define BASIC_EXTENDED_START_BYTE1 0x90 +#define BASIC_EXTENDED_START_BYTE2 0x74 +#define BASIC_EXTENDED_HEADER_SIZE 6 /* start_byte1 + start_byte2 + msg_id + length(2) */ +#define BASIC_EXTENDED_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_EXTENDED_OVERHEAD (BASIC_EXTENDED_HEADER_SIZE + BASIC_EXTENDED_FOOTER_SIZE) + +/* BasicExtended parser states */ +typedef enum basic_extended_parser_state { + BASIC_EXTENDED_LOOKING_FOR_START1 = 0, + BASIC_EXTENDED_LOOKING_FOR_START2 = 1, + BASIC_EXTENDED_GETTING_MSG_ID = 2, + BASIC_EXTENDED_GETTING_LENGTH = 3, + BASIC_EXTENDED_GETTING_PAYLOAD = 4 +} basic_extended_parser_state_t; + +/* BasicExtended parser state structure */ +typedef struct basic_extended_parser { + basic_extended_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + uint8_t length_lo; /* Low byte for 16-bit length */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_extended_parser_t; + +/* BasicExtended encode buffer structure */ +typedef struct basic_extended_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_extended_encode_buffer_t; + +/** + * Initialize a BasicExtended parser + */ +static inline void basic_extended_parser_init(basic_extended_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_EXTENDED_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->length_lo = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicExtended parser state + */ +static inline void basic_extended_parser_reset(basic_extended_parser_t* parser) { + parser->state = BASIC_EXTENDED_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicExtended format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_extended_parse_byte(basic_extended_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_EXTENDED_LOOKING_FOR_START1: + if (byte == BASIC_EXTENDED_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_LOOKING_FOR_START2; + } + break; + + case BASIC_EXTENDED_LOOKING_FOR_START2: + if (byte == BASIC_EXTENDED_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_EXTENDED_GETTING_MSG_ID; + } else if (byte == BASIC_EXTENDED_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_LOOKING_FOR_START2; + } else { + parser->state = BASIC_EXTENDED_LOOKING_FOR_START1; + } + break; + + case BASIC_EXTENDED_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_EXTENDED_GETTING_LENGTH; + break; + + case BASIC_EXTENDED_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + if (parser->buffer_index == 4) { + parser->length_lo = byte; + } else { + parser->msg_length = parser->length_lo | ((size_t)byte << 8); + parser->packet_size = BASIC_EXTENDED_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_EXTENDED_GETTING_PAYLOAD; + } else { + parser->state = BASIC_EXTENDED_LOOKING_FOR_START1; + } + } + break; + + case BASIC_EXTENDED_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_EXTENDED_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 2); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_EXTENDED_HEADER_SIZE; + } + parser->state = BASIC_EXTENDED_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicExtended format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_extended_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_EXTENDED_START_BYTE1; + buffer[1] = BASIC_EXTENDED_START_BYTE2; + buffer[2] = (uint8_t)(msg_size & 0xFF); + buffer[3] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtended packet in a buffer + */ +static inline frame_msg_info_t basic_extended_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_EXTENDED_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_EXTENDED_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_EXTENDED_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_EXTENDED_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_EXTENDED_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_extended_length.h b/src/struct_frame/boilerplate/c/basic_extended_length.h new file mode 100644 index 00000000..4354a0e2 --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_extended_length.h @@ -0,0 +1,216 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicExtendedLength Frame Format + *===========================================================================*/ + +/* BasicExtendedLength constants */ +#define BASIC_EXTENDED_LENGTH_START_BYTE1 0x90 +#define BASIC_EXTENDED_LENGTH_START_BYTE2 0x73 +#define BASIC_EXTENDED_LENGTH_HEADER_SIZE 5 /* start_byte1 + start_byte2 + msg_id + length(2) */ +#define BASIC_EXTENDED_LENGTH_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_EXTENDED_LENGTH_OVERHEAD (BASIC_EXTENDED_LENGTH_HEADER_SIZE + BASIC_EXTENDED_LENGTH_FOOTER_SIZE) + +/* BasicExtendedLength parser states */ +typedef enum basic_extended_length_parser_state { + BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1 = 0, + BASIC_EXTENDED_LENGTH_LOOKING_FOR_START2 = 1, + BASIC_EXTENDED_LENGTH_GETTING_MSG_ID = 2, + BASIC_EXTENDED_LENGTH_GETTING_LENGTH = 3, + BASIC_EXTENDED_LENGTH_GETTING_PAYLOAD = 4 +} basic_extended_length_parser_state_t; + +/* BasicExtendedLength parser state structure */ +typedef struct basic_extended_length_parser { + basic_extended_length_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + uint8_t length_lo; /* Low byte for 16-bit length */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_extended_length_parser_t; + +/* BasicExtendedLength encode buffer structure */ +typedef struct basic_extended_length_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_extended_length_encode_buffer_t; + +/** + * Initialize a BasicExtendedLength parser + */ +static inline void basic_extended_length_parser_init(basic_extended_length_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->length_lo = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicExtendedLength parser state + */ +static inline void basic_extended_length_parser_reset(basic_extended_length_parser_t* parser) { + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicExtendedLength format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_extended_length_parse_byte(basic_extended_length_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1: + if (byte == BASIC_EXTENDED_LENGTH_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START2; + } + break; + + case BASIC_EXTENDED_LENGTH_LOOKING_FOR_START2: + if (byte == BASIC_EXTENDED_LENGTH_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_EXTENDED_LENGTH_GETTING_MSG_ID; + } else if (byte == BASIC_EXTENDED_LENGTH_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START2; + } else { + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1; + } + break; + + case BASIC_EXTENDED_LENGTH_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_EXTENDED_LENGTH_GETTING_LENGTH; + break; + + case BASIC_EXTENDED_LENGTH_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + if (parser->buffer_index == 4) { + parser->length_lo = byte; + } else { + parser->msg_length = parser->length_lo | ((size_t)byte << 8); + parser->packet_size = BASIC_EXTENDED_LENGTH_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_EXTENDED_LENGTH_GETTING_PAYLOAD; + } else { + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1; + } + } + break; + + case BASIC_EXTENDED_LENGTH_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_EXTENDED_LENGTH_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 2); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_EXTENDED_LENGTH_HEADER_SIZE; + } + parser->state = BASIC_EXTENDED_LENGTH_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicExtendedLength format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_extended_length_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_LENGTH_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_EXTENDED_LENGTH_START_BYTE1; + buffer[1] = BASIC_EXTENDED_LENGTH_START_BYTE2; + buffer[2] = (uint8_t)(msg_size & 0xFF); + buffer[3] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedLength packet in a buffer + */ +static inline frame_msg_info_t basic_extended_length_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_EXTENDED_LENGTH_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_EXTENDED_LENGTH_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_EXTENDED_LENGTH_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_EXTENDED_LENGTH_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_EXTENDED_LENGTH_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h b/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h new file mode 100644 index 00000000..129f3deb --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_extended_msg_ids.h @@ -0,0 +1,209 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicExtendedMsgIds Frame Format + *===========================================================================*/ + +/* BasicExtendedMsgIds constants */ +#define BASIC_EXTENDED_MSG_IDS_START_BYTE1 0x90 +#define BASIC_EXTENDED_MSG_IDS_START_BYTE2 0x72 +#define BASIC_EXTENDED_MSG_IDS_HEADER_SIZE 5 /* start_byte1 + start_byte2 + msg_id + length(1) */ +#define BASIC_EXTENDED_MSG_IDS_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_EXTENDED_MSG_IDS_OVERHEAD (BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + BASIC_EXTENDED_MSG_IDS_FOOTER_SIZE) + +/* BasicExtendedMsgIds parser states */ +typedef enum basic_extended_msg_ids_parser_state { + BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1 = 0, + BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START2 = 1, + BASIC_EXTENDED_MSG_IDS_GETTING_MSG_ID = 2, + BASIC_EXTENDED_MSG_IDS_GETTING_LENGTH = 3, + BASIC_EXTENDED_MSG_IDS_GETTING_PAYLOAD = 4 +} basic_extended_msg_ids_parser_state_t; + +/* BasicExtendedMsgIds parser state structure */ +typedef struct basic_extended_msg_ids_parser { + basic_extended_msg_ids_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_extended_msg_ids_parser_t; + +/* BasicExtendedMsgIds encode buffer structure */ +typedef struct basic_extended_msg_ids_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_extended_msg_ids_encode_buffer_t; + +/** + * Initialize a BasicExtendedMsgIds parser + */ +static inline void basic_extended_msg_ids_parser_init(basic_extended_msg_ids_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicExtendedMsgIds parser state + */ +static inline void basic_extended_msg_ids_parser_reset(basic_extended_msg_ids_parser_t* parser) { + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicExtendedMsgIds format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_extended_msg_ids_parse_byte(basic_extended_msg_ids_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1: + if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START2; + } + break; + + case BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START2: + if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_EXTENDED_MSG_IDS_GETTING_MSG_ID; + } else if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START2; + } else { + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1; + } + break; + + case BASIC_EXTENDED_MSG_IDS_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_EXTENDED_MSG_IDS_GETTING_LENGTH; + break; + + case BASIC_EXTENDED_MSG_IDS_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = BASIC_EXTENDED_MSG_IDS_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_EXTENDED_MSG_IDS_GETTING_PAYLOAD; + } else { + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1; + } + break; + + case BASIC_EXTENDED_MSG_IDS_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_EXTENDED_MSG_IDS_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE; + } + parser->state = BASIC_EXTENDED_MSG_IDS_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicExtendedMsgIds format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_extended_msg_ids_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_EXTENDED_MSG_IDS_START_BYTE1; + buffer[1] = BASIC_EXTENDED_MSG_IDS_START_BYTE2; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedMsgIds packet in a buffer + */ +static inline frame_msg_info_t basic_extended_msg_ids_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_EXTENDED_MSG_IDS_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_EXTENDED_MSG_IDS_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_EXTENDED_MSG_IDS_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_EXTENDED_MSG_IDS_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h b/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h new file mode 100644 index 00000000..f7230a86 --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_extended_multi_system_stream.h @@ -0,0 +1,216 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicExtendedMultiSystemStream Frame Format + *===========================================================================*/ + +/* BasicExtendedMultiSystemStream constants */ +#define BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1 0x90 +#define BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2 0x78 +#define BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE 9 /* start_byte1 + start_byte2 + msg_id + length(2) */ +#define BASIC_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD (BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE) + +/* BasicExtendedMultiSystemStream parser states */ +typedef enum basic_extended_multi_system_stream_parser_state { + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1 = 0, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2 = 1, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID = 2, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH = 3, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD = 4 +} basic_extended_multi_system_stream_parser_state_t; + +/* BasicExtendedMultiSystemStream parser state structure */ +typedef struct basic_extended_multi_system_stream_parser { + basic_extended_multi_system_stream_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + uint8_t length_lo; /* Low byte for 16-bit length */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_extended_multi_system_stream_parser_t; + +/* BasicExtendedMultiSystemStream encode buffer structure */ +typedef struct basic_extended_multi_system_stream_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_extended_multi_system_stream_encode_buffer_t; + +/** + * Initialize a BasicExtendedMultiSystemStream parser + */ +static inline void basic_extended_multi_system_stream_parser_init(basic_extended_multi_system_stream_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->length_lo = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicExtendedMultiSystemStream parser state + */ +static inline void basic_extended_multi_system_stream_parser_reset(basic_extended_multi_system_stream_parser_t* parser) { + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicExtendedMultiSystemStream format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_extended_multi_system_stream_parse_byte(basic_extended_multi_system_stream_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1: + if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2; + } + break; + + case BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2: + if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID; + } else if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2; + } else { + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + break; + + case BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH; + break; + + case BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + if (parser->buffer_index == 4) { + parser->length_lo = byte; + } else { + parser->msg_length = parser->length_lo | ((size_t)byte << 8); + parser->packet_size = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD; + } else { + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + } + break; + + case BASIC_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 2); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + parser->state = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicExtendedMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_extended_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1; + buffer[1] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2; + buffer[2] = (uint8_t)(msg_size & 0xFF); + buffer[3] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedMultiSystemStream packet in a buffer + */ +static inline frame_msg_info_t basic_extended_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_frame.h b/src/struct_frame/boilerplate/c/basic_frame.h deleted file mode 100644 index 25ad9b47..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame.h +++ /dev/null @@ -1,205 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrame Frame Format - *===========================================================================*/ - -/* BasicFrame constants */ -#define BASIC_FRAME_START_BYTE1 0x90 -#define BASIC_FRAME_START_BYTE2 0x91 -#define BASIC_FRAME_HEADER_SIZE 3 /* start_byte1 + start_byte2 + msg_id */ -#define BASIC_FRAME_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define BASIC_FRAME_OVERHEAD (BASIC_FRAME_HEADER_SIZE + BASIC_FRAME_FOOTER_SIZE) - -/* BasicFrame parser states */ -typedef enum basic_frame_parser_state { - BASIC_FRAME_LOOKING_FOR_START1 = 0, - BASIC_FRAME_LOOKING_FOR_START2 = 1, - BASIC_FRAME_GETTING_MSG_ID = 2, - BASIC_FRAME_GETTING_PAYLOAD = 3 -} basic_frame_parser_state_t; - -/* BasicFrame parser state structure */ -typedef struct basic_frame_parser { - basic_frame_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_parser_t; - -/* BasicFrame encode buffer structure */ -typedef struct basic_frame_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_encode_buffer_t; - -/** - * Initialize a BasicFrame parser - */ -static inline void basic_frame_parser_init(basic_frame_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrame parser state - */ -static inline void basic_frame_parser_reset(basic_frame_parser_t* parser) { - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with BasicFrame format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_parse_byte(basic_frame_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = BASIC_FRAME_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - } - } else { - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - } - } - break; - - case BASIC_FRAME_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - BASIC_FRAME_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 2, msg_length + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + BASIC_FRAME_HEADER_SIZE; - } - parser->state = BASIC_FRAME_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrame format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_START_BYTE1; - buffer[1] = BASIC_FRAME_START_BYTE2; - buffer[2] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1); - buffer[BASIC_FRAME_HEADER_SIZE + msg_size] = ck.byte1; - buffer[BASIC_FRAME_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete BasicFrame packet in a buffer - */ -static inline frame_msg_info_t basic_frame_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_no_crc.h b/src/struct_frame/boilerplate/c/basic_frame_no_crc.h deleted file mode 100644 index c445a0f3..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_no_crc.h +++ /dev/null @@ -1,189 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameNoCrc Frame Format - *===========================================================================*/ - -/* BasicFrameNoCrc constants */ -#define BASIC_FRAME_NO_CRC_START_BYTE1 0x90 -#define BASIC_FRAME_NO_CRC_START_BYTE2 0x95 -#define BASIC_FRAME_NO_CRC_HEADER_SIZE 3 /* start_byte1 + start_byte2 + msg_id */ -#define BASIC_FRAME_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define BASIC_FRAME_NO_CRC_OVERHEAD (BASIC_FRAME_NO_CRC_HEADER_SIZE + BASIC_FRAME_NO_CRC_FOOTER_SIZE) - -/* BasicFrameNoCrc parser states */ -typedef enum basic_frame_no_crc_parser_state { - BASIC_FRAME_NO_CRC_LOOKING_FOR_START1 = 0, - BASIC_FRAME_NO_CRC_LOOKING_FOR_START2 = 1, - BASIC_FRAME_NO_CRC_GETTING_MSG_ID = 2, - BASIC_FRAME_NO_CRC_GETTING_PAYLOAD = 3 -} basic_frame_no_crc_parser_state_t; - -/* BasicFrameNoCrc parser state structure */ -typedef struct basic_frame_no_crc_parser { - basic_frame_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_no_crc_parser_t; - -/* BasicFrameNoCrc encode buffer structure */ -typedef struct basic_frame_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_no_crc_encode_buffer_t; - -/** - * Initialize a BasicFrameNoCrc parser - */ -static inline void basic_frame_no_crc_parser_init(basic_frame_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameNoCrc parser state - */ -static inline void basic_frame_no_crc_parser_reset(basic_frame_no_crc_parser_t* parser) { - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with BasicFrameNoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_no_crc_parse_byte(basic_frame_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_NO_CRC_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_NO_CRC_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_NO_CRC_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_NO_CRC_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = BASIC_FRAME_NO_CRC_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - } - } else { - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - } - } - break; - - case BASIC_FRAME_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - BASIC_FRAME_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + BASIC_FRAME_NO_CRC_HEADER_SIZE; - parser->state = BASIC_FRAME_NO_CRC_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameNoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_NO_CRC_START_BYTE1; - buffer[1] = BASIC_FRAME_NO_CRC_START_BYTE2; - buffer[2] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete BasicFrameNoCrc packet in a buffer - */ -static inline frame_msg_info_t basic_frame_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_NO_CRC_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_NO_CRC_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_with_len.h b/src/struct_frame/boilerplate/c/basic_frame_with_len.h deleted file mode 100644 index 8b93c9c7..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_with_len.h +++ /dev/null @@ -1,209 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameWithLen Frame Format - *===========================================================================*/ - -/* BasicFrameWithLen constants */ -#define BASIC_FRAME_WITH_LEN_START_BYTE1 0x90 -#define BASIC_FRAME_WITH_LEN_START_BYTE2 0x92 -#define BASIC_FRAME_WITH_LEN_HEADER_SIZE 4 /* start_byte1 + start_byte2 + msg_id + length(1) */ -#define BASIC_FRAME_WITH_LEN_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define BASIC_FRAME_WITH_LEN_OVERHEAD (BASIC_FRAME_WITH_LEN_HEADER_SIZE + BASIC_FRAME_WITH_LEN_FOOTER_SIZE) - -/* BasicFrameWithLen parser states */ -typedef enum basic_frame_with_len_parser_state { - BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1 = 0, - BASIC_FRAME_WITH_LEN_LOOKING_FOR_START2 = 1, - BASIC_FRAME_WITH_LEN_GETTING_MSG_ID = 2, - BASIC_FRAME_WITH_LEN_GETTING_LENGTH = 3, - BASIC_FRAME_WITH_LEN_GETTING_PAYLOAD = 4 -} basic_frame_with_len_parser_state_t; - -/* BasicFrameWithLen parser state structure */ -typedef struct basic_frame_with_len_parser { - basic_frame_with_len_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_with_len_parser_t; - -/* BasicFrameWithLen encode buffer structure */ -typedef struct basic_frame_with_len_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_with_len_encode_buffer_t; - -/** - * Initialize a BasicFrameWithLen parser - */ -static inline void basic_frame_with_len_parser_init(basic_frame_with_len_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameWithLen parser state - */ -static inline void basic_frame_with_len_parser_reset(basic_frame_with_len_parser_t* parser) { - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with BasicFrameWithLen format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_with_len_parse_byte(basic_frame_with_len_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_WITH_LEN_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_WITH_LEN_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_WITH_LEN_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_WITH_LEN_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_WITH_LEN_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = BASIC_FRAME_WITH_LEN_GETTING_LENGTH; - break; - - case BASIC_FRAME_WITH_LEN_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_length = byte; - parser->packet_size = BASIC_FRAME_WITH_LEN_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_WITH_LEN_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - BASIC_FRAME_WITH_LEN_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 2, msg_length + 1 + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + BASIC_FRAME_WITH_LEN_HEADER_SIZE; - } - parser->state = BASIC_FRAME_WITH_LEN_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameWithLen format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_with_len_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_WITH_LEN_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_WITH_LEN_START_BYTE1; - buffer[1] = BASIC_FRAME_WITH_LEN_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = (uint8_t)msg_size; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_WITH_LEN_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); - buffer[BASIC_FRAME_WITH_LEN_HEADER_SIZE + msg_size] = ck.byte1; - buffer[BASIC_FRAME_WITH_LEN_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete BasicFrameWithLen packet in a buffer - */ -static inline frame_msg_info_t basic_frame_with_len_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_WITH_LEN_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_WITH_LEN_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_WITH_LEN_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_WITH_LEN_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_WITH_LEN_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_with_len16.h b/src/struct_frame/boilerplate/c/basic_frame_with_len16.h deleted file mode 100644 index 24292554..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_with_len16.h +++ /dev/null @@ -1,216 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameWithLen16 Frame Format - *===========================================================================*/ - -/* BasicFrameWithLen16 constants */ -#define BASIC_FRAME_WITH_LEN16_START_BYTE1 0x90 -#define BASIC_FRAME_WITH_LEN16_START_BYTE2 0x93 -#define BASIC_FRAME_WITH_LEN16_HEADER_SIZE 5 /* start_byte1 + start_byte2 + msg_id + length(2) */ -#define BASIC_FRAME_WITH_LEN16_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define BASIC_FRAME_WITH_LEN16_OVERHEAD (BASIC_FRAME_WITH_LEN16_HEADER_SIZE + BASIC_FRAME_WITH_LEN16_FOOTER_SIZE) - -/* BasicFrameWithLen16 parser states */ -typedef enum basic_frame_with_len16_parser_state { - BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1 = 0, - BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START2 = 1, - BASIC_FRAME_WITH_LEN16_GETTING_MSG_ID = 2, - BASIC_FRAME_WITH_LEN16_GETTING_LENGTH = 3, - BASIC_FRAME_WITH_LEN16_GETTING_PAYLOAD = 4 -} basic_frame_with_len16_parser_state_t; - -/* BasicFrameWithLen16 parser state structure */ -typedef struct basic_frame_with_len16_parser { - basic_frame_with_len16_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - uint8_t length_lo; /* Low byte for 16-bit length */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_with_len16_parser_t; - -/* BasicFrameWithLen16 encode buffer structure */ -typedef struct basic_frame_with_len16_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_with_len16_encode_buffer_t; - -/** - * Initialize a BasicFrameWithLen16 parser - */ -static inline void basic_frame_with_len16_parser_init(basic_frame_with_len16_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->length_lo = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameWithLen16 parser state - */ -static inline void basic_frame_with_len16_parser_reset(basic_frame_with_len16_parser_t* parser) { - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with BasicFrameWithLen16 format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_with_len16_parse_byte(basic_frame_with_len16_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_WITH_LEN16_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_WITH_LEN16_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_WITH_LEN16_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_WITH_LEN16_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN16_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = BASIC_FRAME_WITH_LEN16_GETTING_LENGTH; - break; - - case BASIC_FRAME_WITH_LEN16_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - if (parser->buffer_index == 4) { - parser->length_lo = byte; - } else { - parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = BASIC_FRAME_WITH_LEN16_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_WITH_LEN16_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1; - } - } - break; - - case BASIC_FRAME_WITH_LEN16_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - BASIC_FRAME_WITH_LEN16_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 2, msg_length + 1 + 2); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + BASIC_FRAME_WITH_LEN16_HEADER_SIZE; - } - parser->state = BASIC_FRAME_WITH_LEN16_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameWithLen16 format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_with_len16_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_WITH_LEN16_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_WITH_LEN16_START_BYTE1; - buffer[1] = BASIC_FRAME_WITH_LEN16_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = (uint8_t)(msg_size & 0xFF); - buffer[4] = (uint8_t)((msg_size >> 8) & 0xFF); - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_WITH_LEN16_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 2); - buffer[BASIC_FRAME_WITH_LEN16_HEADER_SIZE + msg_size] = ck.byte1; - buffer[BASIC_FRAME_WITH_LEN16_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete BasicFrameWithLen16 packet in a buffer - */ -static inline frame_msg_info_t basic_frame_with_len16_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_WITH_LEN16_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_WITH_LEN16_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_WITH_LEN16_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_WITH_LEN16_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 2); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_WITH_LEN16_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_with_len16_no_crc.h b/src/struct_frame/boilerplate/c/basic_frame_with_len16_no_crc.h deleted file mode 100644 index 7827dae9..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_with_len16_no_crc.h +++ /dev/null @@ -1,200 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameWithLen16NoCrc Frame Format - *===========================================================================*/ - -/* BasicFrameWithLen16NoCrc constants */ -#define BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE1 0x90 -#define BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE2 0x97 -#define BASIC_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE 5 /* start_byte1 + start_byte2 + msg_id + length(2) */ -#define BASIC_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD (BASIC_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE + BASIC_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE) - -/* BasicFrameWithLen16NoCrc parser states */ -typedef enum basic_frame_with_len16_no_crc_parser_state { - BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1 = 0, - BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START2 = 1, - BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID = 2, - BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH = 3, - BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD = 4 -} basic_frame_with_len16_no_crc_parser_state_t; - -/* BasicFrameWithLen16NoCrc parser state structure */ -typedef struct basic_frame_with_len16_no_crc_parser { - basic_frame_with_len16_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - uint8_t length_lo; /* Low byte for 16-bit length */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_with_len16_no_crc_parser_t; - -/* BasicFrameWithLen16NoCrc encode buffer structure */ -typedef struct basic_frame_with_len16_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_with_len16_no_crc_encode_buffer_t; - -/** - * Initialize a BasicFrameWithLen16NoCrc parser - */ -static inline void basic_frame_with_len16_no_crc_parser_init(basic_frame_with_len16_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->length_lo = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameWithLen16NoCrc parser state - */ -static inline void basic_frame_with_len16_no_crc_parser_reset(basic_frame_with_len16_no_crc_parser_t* parser) { - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with BasicFrameWithLen16NoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_with_len16_no_crc_parse_byte(basic_frame_with_len16_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH; - break; - - case BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - if (parser->buffer_index == 4) { - parser->length_lo = byte; - } else { - parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1; - } - } - break; - - case BASIC_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + BASIC_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE; - parser->state = BASIC_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameWithLen16NoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_with_len16_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE1; - buffer[1] = BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = (uint8_t)(msg_size & 0xFF); - buffer[4] = (uint8_t)((msg_size >> 8) & 0xFF); - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete BasicFrameWithLen16NoCrc packet in a buffer - */ -static inline frame_msg_info_t basic_frame_with_len16_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_WITH_LEN16_NO_CRC_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_with_len_no_crc.h b/src/struct_frame/boilerplate/c/basic_frame_with_len_no_crc.h deleted file mode 100644 index 7c1dbb5d..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_with_len_no_crc.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameWithLenNoCrc Frame Format - *===========================================================================*/ - -/* BasicFrameWithLenNoCrc constants */ -#define BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE1 0x90 -#define BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE2 0x96 -#define BASIC_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE 4 /* start_byte1 + start_byte2 + msg_id + length(1) */ -#define BASIC_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD (BASIC_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE + BASIC_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE) - -/* BasicFrameWithLenNoCrc parser states */ -typedef enum basic_frame_with_len_no_crc_parser_state { - BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1 = 0, - BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START2 = 1, - BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID = 2, - BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH = 3, - BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD = 4 -} basic_frame_with_len_no_crc_parser_state_t; - -/* BasicFrameWithLenNoCrc parser state structure */ -typedef struct basic_frame_with_len_no_crc_parser { - basic_frame_with_len_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_with_len_no_crc_parser_t; - -/* BasicFrameWithLenNoCrc encode buffer structure */ -typedef struct basic_frame_with_len_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_with_len_no_crc_encode_buffer_t; - -/** - * Initialize a BasicFrameWithLenNoCrc parser - */ -static inline void basic_frame_with_len_no_crc_parser_init(basic_frame_with_len_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameWithLenNoCrc parser state - */ -static inline void basic_frame_with_len_no_crc_parser_reset(basic_frame_with_len_no_crc_parser_t* parser) { - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with BasicFrameWithLenNoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_with_len_no_crc_parse_byte(basic_frame_with_len_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH; - break; - - case BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_length = byte; - parser->packet_size = BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + BASIC_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE; - parser->state = BASIC_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameWithLenNoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_with_len_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE1; - buffer[1] = BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = (uint8_t)msg_size; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete BasicFrameWithLenNoCrc packet in a buffer - */ -static inline frame_msg_info_t basic_frame_with_len_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_WITH_LEN_NO_CRC_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_frame_with_sys_comp.h b/src/struct_frame/boilerplate/c/basic_frame_with_sys_comp.h deleted file mode 100644 index 3a14d937..00000000 --- a/src/struct_frame/boilerplate/c/basic_frame_with_sys_comp.h +++ /dev/null @@ -1,205 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * BasicFrameWithSysComp Frame Format - *===========================================================================*/ - -/* BasicFrameWithSysComp constants */ -#define BASIC_FRAME_WITH_SYS_COMP_START_BYTE1 0x90 -#define BASIC_FRAME_WITH_SYS_COMP_START_BYTE2 0x94 -#define BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE 3 /* start_byte1 + start_byte2 + msg_id */ -#define BASIC_FRAME_WITH_SYS_COMP_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define BASIC_FRAME_WITH_SYS_COMP_OVERHEAD (BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE + BASIC_FRAME_WITH_SYS_COMP_FOOTER_SIZE) - -/* BasicFrameWithSysComp parser states */ -typedef enum basic_frame_with_sys_comp_parser_state { - BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1 = 0, - BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START2 = 1, - BASIC_FRAME_WITH_SYS_COMP_GETTING_MSG_ID = 2, - BASIC_FRAME_WITH_SYS_COMP_GETTING_PAYLOAD = 3 -} basic_frame_with_sys_comp_parser_state_t; - -/* BasicFrameWithSysComp parser state structure */ -typedef struct basic_frame_with_sys_comp_parser { - basic_frame_with_sys_comp_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} basic_frame_with_sys_comp_parser_t; - -/* BasicFrameWithSysComp encode buffer structure */ -typedef struct basic_frame_with_sys_comp_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} basic_frame_with_sys_comp_encode_buffer_t; - -/** - * Initialize a BasicFrameWithSysComp parser - */ -static inline void basic_frame_with_sys_comp_parser_init(basic_frame_with_sys_comp_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset BasicFrameWithSysComp parser state - */ -static inline void basic_frame_with_sys_comp_parser_reset(basic_frame_with_sys_comp_parser_t* parser) { - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with BasicFrameWithSysComp format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t basic_frame_with_sys_comp_parse_byte(basic_frame_with_sys_comp_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1: - if (byte == BASIC_FRAME_WITH_SYS_COMP_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START2; - } - break; - - case BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START2: - if (byte == BASIC_FRAME_WITH_SYS_COMP_START_BYTE2) { - parser->buffer[1] = byte; - parser->buffer_index = 2; - parser->state = BASIC_FRAME_WITH_SYS_COMP_GETTING_MSG_ID; - } else if (byte == BASIC_FRAME_WITH_SYS_COMP_START_BYTE1) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START2; - } else { - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - } - break; - - case BASIC_FRAME_WITH_SYS_COMP_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = BASIC_FRAME_WITH_SYS_COMP_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = BASIC_FRAME_WITH_SYS_COMP_GETTING_PAYLOAD; - } else { - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - } - } else { - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - } - } - break; - - case BASIC_FRAME_WITH_SYS_COMP_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - BASIC_FRAME_WITH_SYS_COMP_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 2, msg_length + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE; - } - parser->state = BASIC_FRAME_WITH_SYS_COMP_LOOKING_FOR_START1; - } - break; - } - - return result; -} - -/** - * Encode a message with BasicFrameWithSysComp format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t basic_frame_with_sys_comp_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = BASIC_FRAME_WITH_SYS_COMP_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = BASIC_FRAME_WITH_SYS_COMP_START_BYTE1; - buffer[1] = BASIC_FRAME_WITH_SYS_COMP_START_BYTE2; - buffer[2] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1); - buffer[BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; - buffer[BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete BasicFrameWithSysComp packet in a buffer - */ -static inline frame_msg_info_t basic_frame_with_sys_comp_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < BASIC_FRAME_WITH_SYS_COMP_OVERHEAD) { - return result; - } - - if (buffer[0] != BASIC_FRAME_WITH_SYS_COMP_START_BYTE1) { - return result; - } - if (buffer[1] != BASIC_FRAME_WITH_SYS_COMP_START_BYTE2) { - return result; - } - - size_t msg_length = length - BASIC_FRAME_WITH_SYS_COMP_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[2]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + BASIC_FRAME_WITH_SYS_COMP_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/basic_minimal.h b/src/struct_frame/boilerplate/c/basic_minimal.h new file mode 100644 index 00000000..3694785c --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_minimal.h @@ -0,0 +1,189 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicMinimal Frame Format + *===========================================================================*/ + +/* BasicMinimal constants */ +#define BASIC_MINIMAL_START_BYTE1 0x90 +#define BASIC_MINIMAL_START_BYTE2 0x70 +#define BASIC_MINIMAL_HEADER_SIZE 3 /* start_byte1 + start_byte2 + msg_id */ +#define BASIC_MINIMAL_FOOTER_SIZE 0 /* no footer */ +#define BASIC_MINIMAL_OVERHEAD (BASIC_MINIMAL_HEADER_SIZE + BASIC_MINIMAL_FOOTER_SIZE) + +/* BasicMinimal parser states */ +typedef enum basic_minimal_parser_state { + BASIC_MINIMAL_LOOKING_FOR_START1 = 0, + BASIC_MINIMAL_LOOKING_FOR_START2 = 1, + BASIC_MINIMAL_GETTING_MSG_ID = 2, + BASIC_MINIMAL_GETTING_PAYLOAD = 3 +} basic_minimal_parser_state_t; + +/* BasicMinimal parser state structure */ +typedef struct basic_minimal_parser { + basic_minimal_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_minimal_parser_t; + +/* BasicMinimal encode buffer structure */ +typedef struct basic_minimal_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_minimal_encode_buffer_t; + +/** + * Initialize a BasicMinimal parser + */ +static inline void basic_minimal_parser_init(basic_minimal_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicMinimal parser state + */ +static inline void basic_minimal_parser_reset(basic_minimal_parser_t* parser) { + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; +} + +/** + * Parse a single byte with BasicMinimal format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_minimal_parse_byte(basic_minimal_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_MINIMAL_LOOKING_FOR_START1: + if (byte == BASIC_MINIMAL_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_MINIMAL_LOOKING_FOR_START2; + } + break; + + case BASIC_MINIMAL_LOOKING_FOR_START2: + if (byte == BASIC_MINIMAL_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_MINIMAL_GETTING_MSG_ID; + } else if (byte == BASIC_MINIMAL_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_MINIMAL_LOOKING_FOR_START2; + } else { + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + } + break; + + case BASIC_MINIMAL_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + { + size_t msg_length = 0; + if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { + parser->packet_size = BASIC_MINIMAL_OVERHEAD + msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_MINIMAL_GETTING_PAYLOAD; + } else { + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + } + } else { + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + } + } + break; + + case BASIC_MINIMAL_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = parser->packet_size - BASIC_MINIMAL_OVERHEAD; + result.msg_data = parser->buffer + BASIC_MINIMAL_HEADER_SIZE; + parser->state = BASIC_MINIMAL_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicMinimal format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_minimal_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_MINIMAL_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_MINIMAL_START_BYTE1; + buffer[1] = BASIC_MINIMAL_START_BYTE2; + buffer[2] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + return total_size; +} + +/** + * Validate a complete BasicMinimal packet in a buffer + */ +static inline frame_msg_info_t basic_minimal_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_MINIMAL_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_MINIMAL_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_MINIMAL_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_MINIMAL_OVERHEAD; + + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_MINIMAL_HEADER_SIZE); + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_multi_system_stream.h b/src/struct_frame/boilerplate/c/basic_multi_system_stream.h new file mode 100644 index 00000000..8f1cb66b --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_multi_system_stream.h @@ -0,0 +1,209 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicMultiSystemStream Frame Format + *===========================================================================*/ + +/* BasicMultiSystemStream constants */ +#define BASIC_MULTI_SYSTEM_STREAM_START_BYTE1 0x90 +#define BASIC_MULTI_SYSTEM_STREAM_START_BYTE2 0x77 +#define BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE 7 /* start_byte1 + start_byte2 + msg_id + length(1) */ +#define BASIC_MULTI_SYSTEM_STREAM_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_MULTI_SYSTEM_STREAM_OVERHEAD (BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + BASIC_MULTI_SYSTEM_STREAM_FOOTER_SIZE) + +/* BasicMultiSystemStream parser states */ +typedef enum basic_multi_system_stream_parser_state { + BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1 = 0, + BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2 = 1, + BASIC_MULTI_SYSTEM_STREAM_GETTING_MSG_ID = 2, + BASIC_MULTI_SYSTEM_STREAM_GETTING_LENGTH = 3, + BASIC_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD = 4 +} basic_multi_system_stream_parser_state_t; + +/* BasicMultiSystemStream parser state structure */ +typedef struct basic_multi_system_stream_parser { + basic_multi_system_stream_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_multi_system_stream_parser_t; + +/* BasicMultiSystemStream encode buffer structure */ +typedef struct basic_multi_system_stream_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_multi_system_stream_encode_buffer_t; + +/** + * Initialize a BasicMultiSystemStream parser + */ +static inline void basic_multi_system_stream_parser_init(basic_multi_system_stream_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicMultiSystemStream parser state + */ +static inline void basic_multi_system_stream_parser_reset(basic_multi_system_stream_parser_t* parser) { + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicMultiSystemStream format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_multi_system_stream_parse_byte(basic_multi_system_stream_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1: + if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2; + } + break; + + case BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2: + if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_MULTI_SYSTEM_STREAM_GETTING_MSG_ID; + } else if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START2; + } else { + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + break; + + case BASIC_MULTI_SYSTEM_STREAM_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_MULTI_SYSTEM_STREAM_GETTING_LENGTH; + break; + + case BASIC_MULTI_SYSTEM_STREAM_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = BASIC_MULTI_SYSTEM_STREAM_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD; + } else { + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + break; + + case BASIC_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_MULTI_SYSTEM_STREAM_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + parser->state = BASIC_MULTI_SYSTEM_STREAM_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE1; + buffer[1] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE2; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicMultiSystemStream packet in a buffer + */ +static inline frame_msg_info_t basic_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_MULTI_SYSTEM_STREAM_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_MULTI_SYSTEM_STREAM_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_MULTI_SYSTEM_STREAM_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_seq.h b/src/struct_frame/boilerplate/c/basic_seq.h new file mode 100644 index 00000000..efb5e586 --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_seq.h @@ -0,0 +1,209 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicSeq Frame Format + *===========================================================================*/ + +/* BasicSeq constants */ +#define BASIC_SEQ_START_BYTE1 0x90 +#define BASIC_SEQ_START_BYTE2 0x76 +#define BASIC_SEQ_HEADER_SIZE 5 /* start_byte1 + start_byte2 + msg_id + length(1) */ +#define BASIC_SEQ_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_SEQ_OVERHEAD (BASIC_SEQ_HEADER_SIZE + BASIC_SEQ_FOOTER_SIZE) + +/* BasicSeq parser states */ +typedef enum basic_seq_parser_state { + BASIC_SEQ_LOOKING_FOR_START1 = 0, + BASIC_SEQ_LOOKING_FOR_START2 = 1, + BASIC_SEQ_GETTING_MSG_ID = 2, + BASIC_SEQ_GETTING_LENGTH = 3, + BASIC_SEQ_GETTING_PAYLOAD = 4 +} basic_seq_parser_state_t; + +/* BasicSeq parser state structure */ +typedef struct basic_seq_parser { + basic_seq_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_seq_parser_t; + +/* BasicSeq encode buffer structure */ +typedef struct basic_seq_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_seq_encode_buffer_t; + +/** + * Initialize a BasicSeq parser + */ +static inline void basic_seq_parser_init(basic_seq_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_SEQ_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicSeq parser state + */ +static inline void basic_seq_parser_reset(basic_seq_parser_t* parser) { + parser->state = BASIC_SEQ_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicSeq format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_seq_parse_byte(basic_seq_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_SEQ_LOOKING_FOR_START1: + if (byte == BASIC_SEQ_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_SEQ_LOOKING_FOR_START2; + } + break; + + case BASIC_SEQ_LOOKING_FOR_START2: + if (byte == BASIC_SEQ_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_SEQ_GETTING_MSG_ID; + } else if (byte == BASIC_SEQ_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_SEQ_LOOKING_FOR_START2; + } else { + parser->state = BASIC_SEQ_LOOKING_FOR_START1; + } + break; + + case BASIC_SEQ_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_SEQ_GETTING_LENGTH; + break; + + case BASIC_SEQ_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = BASIC_SEQ_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_SEQ_GETTING_PAYLOAD; + } else { + parser->state = BASIC_SEQ_LOOKING_FOR_START1; + } + break; + + case BASIC_SEQ_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_SEQ_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_SEQ_HEADER_SIZE; + } + parser->state = BASIC_SEQ_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicSeq format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_seq_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_SEQ_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_SEQ_START_BYTE1; + buffer[1] = BASIC_SEQ_START_BYTE2; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_SEQ_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicSeq packet in a buffer + */ +static inline frame_msg_info_t basic_seq_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_SEQ_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_SEQ_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_SEQ_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_SEQ_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_SEQ_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/basic_sys_comp.h b/src/struct_frame/boilerplate/c/basic_sys_comp.h new file mode 100644 index 00000000..224cc9b3 --- /dev/null +++ b/src/struct_frame/boilerplate/c/basic_sys_comp.h @@ -0,0 +1,209 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * BasicSysComp Frame Format + *===========================================================================*/ + +/* BasicSysComp constants */ +#define BASIC_SYS_COMP_START_BYTE1 0x90 +#define BASIC_SYS_COMP_START_BYTE2 0x75 +#define BASIC_SYS_COMP_HEADER_SIZE 6 /* start_byte1 + start_byte2 + msg_id + length(1) */ +#define BASIC_SYS_COMP_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define BASIC_SYS_COMP_OVERHEAD (BASIC_SYS_COMP_HEADER_SIZE + BASIC_SYS_COMP_FOOTER_SIZE) + +/* BasicSysComp parser states */ +typedef enum basic_sys_comp_parser_state { + BASIC_SYS_COMP_LOOKING_FOR_START1 = 0, + BASIC_SYS_COMP_LOOKING_FOR_START2 = 1, + BASIC_SYS_COMP_GETTING_MSG_ID = 2, + BASIC_SYS_COMP_GETTING_LENGTH = 3, + BASIC_SYS_COMP_GETTING_PAYLOAD = 4 +} basic_sys_comp_parser_state_t; + +/* BasicSysComp parser state structure */ +typedef struct basic_sys_comp_parser { + basic_sys_comp_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} basic_sys_comp_parser_t; + +/* BasicSysComp encode buffer structure */ +typedef struct basic_sys_comp_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} basic_sys_comp_encode_buffer_t; + +/** + * Initialize a BasicSysComp parser + */ +static inline void basic_sys_comp_parser_init(basic_sys_comp_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START1; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset BasicSysComp parser state + */ +static inline void basic_sys_comp_parser_reset(basic_sys_comp_parser_t* parser) { + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START1; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with BasicSysComp format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t basic_sys_comp_parse_byte(basic_sys_comp_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case BASIC_SYS_COMP_LOOKING_FOR_START1: + if (byte == BASIC_SYS_COMP_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START2; + } + break; + + case BASIC_SYS_COMP_LOOKING_FOR_START2: + if (byte == BASIC_SYS_COMP_START_BYTE2) { + parser->buffer[1] = byte; + parser->buffer_index = 2; + parser->state = BASIC_SYS_COMP_GETTING_MSG_ID; + } else if (byte == BASIC_SYS_COMP_START_BYTE1) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START2; + } else { + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START1; + } + break; + + case BASIC_SYS_COMP_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = BASIC_SYS_COMP_GETTING_LENGTH; + break; + + case BASIC_SYS_COMP_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = BASIC_SYS_COMP_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = BASIC_SYS_COMP_GETTING_PAYLOAD; + } else { + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START1; + } + break; + + case BASIC_SYS_COMP_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - BASIC_SYS_COMP_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 2, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + BASIC_SYS_COMP_HEADER_SIZE; + } + parser->state = BASIC_SYS_COMP_LOOKING_FOR_START1; + } + break; + } + + return result; +} + +/** + * Encode a message with BasicSysComp format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t basic_sys_comp_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_SYS_COMP_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = BASIC_SYS_COMP_START_BYTE1; + buffer[1] = BASIC_SYS_COMP_START_BYTE2; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + BASIC_SYS_COMP_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicSysComp packet in a buffer + */ +static inline frame_msg_info_t basic_sys_comp_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < BASIC_SYS_COMP_OVERHEAD) { + return result; + } + + if (buffer[0] != BASIC_SYS_COMP_START_BYTE1) { + return result; + } + if (buffer[1] != BASIC_SYS_COMP_START_BYTE2) { + return result; + } + + size_t msg_length = length - BASIC_SYS_COMP_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + BASIC_SYS_COMP_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/frame_base.h b/src/struct_frame/boilerplate/c/frame_base.h index ab54be3b..909c2551 100644 --- a/src/struct_frame/boilerplate/c/frame_base.h +++ b/src/struct_frame/boilerplate/c/frame_base.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser base utilities */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -10,24 +10,24 @@ /* Frame format type enumeration */ typedef enum FrameFormatType { - FRAME_FORMAT_MINIMAL_FRAME = 0, - FRAME_FORMAT_BASIC_FRAME = 1, - FRAME_FORMAT_BASIC_FRAME_NO_CRC = 2, - FRAME_FORMAT_TINY_FRAME = 3, - FRAME_FORMAT_TINY_FRAME_NO_CRC = 4, - FRAME_FORMAT_MINIMAL_FRAME_WITH_LEN = 5, - FRAME_FORMAT_MINIMAL_FRAME_WITH_LEN_NO_CRC = 6, - FRAME_FORMAT_BASIC_FRAME_WITH_LEN = 7, - FRAME_FORMAT_BASIC_FRAME_WITH_LEN_NO_CRC = 8, - FRAME_FORMAT_TINY_FRAME_WITH_LEN = 9, - FRAME_FORMAT_TINY_FRAME_WITH_LEN_NO_CRC = 10, - FRAME_FORMAT_MINIMAL_FRAME_WITH_LEN16 = 11, - FRAME_FORMAT_MINIMAL_FRAME_WITH_LEN16_NO_CRC = 12, - FRAME_FORMAT_BASIC_FRAME_WITH_LEN16 = 13, - FRAME_FORMAT_BASIC_FRAME_WITH_LEN16_NO_CRC = 14, - FRAME_FORMAT_TINY_FRAME_WITH_LEN16 = 15, - FRAME_FORMAT_TINY_FRAME_WITH_LEN16_NO_CRC = 16, - FRAME_FORMAT_BASIC_FRAME_WITH_SYS_COMP = 17, + FRAME_FORMAT_TINY_MINIMAL = 0, + FRAME_FORMAT_TINY_DEFAULT = 1, + FRAME_FORMAT_TINY_EXTENDED_MSG_IDS = 2, + FRAME_FORMAT_TINY_EXTENDED_LENGTH = 3, + FRAME_FORMAT_TINY_EXTENDED = 4, + FRAME_FORMAT_TINY_SYS_COMP = 5, + FRAME_FORMAT_TINY_SEQ = 6, + FRAME_FORMAT_TINY_MULTI_SYSTEM_STREAM = 7, + FRAME_FORMAT_TINY_EXTENDED_MULTI_SYSTEM_STREAM = 8, + FRAME_FORMAT_BASIC_MINIMAL = 9, + FRAME_FORMAT_BASIC_DEFAULT = 10, + FRAME_FORMAT_BASIC_EXTENDED_MSG_IDS = 11, + FRAME_FORMAT_BASIC_EXTENDED_LENGTH = 12, + FRAME_FORMAT_BASIC_EXTENDED = 13, + FRAME_FORMAT_BASIC_SYS_COMP = 14, + FRAME_FORMAT_BASIC_SEQ = 15, + FRAME_FORMAT_BASIC_MULTI_SYSTEM_STREAM = 16, + FRAME_FORMAT_BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 17, FRAME_FORMAT_UBX_FRAME = 18, FRAME_FORMAT_MAVLINK_V1_FRAME = 19, FRAME_FORMAT_MAVLINK_V2_FRAME = 20, diff --git a/src/struct_frame/boilerplate/c/frame_format_config.h b/src/struct_frame/boilerplate/c/frame_format_config.h index 0ed59a2d..b8980421 100644 --- a/src/struct_frame/boilerplate/c/frame_format_config.h +++ b/src/struct_frame/boilerplate/c/frame_format_config.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -11,7 +11,7 @@ /* FrameFormatConfig constants */ #define FRAME_FORMAT_CONFIG_START_BYTE1 0x90 -#define FRAME_FORMAT_CONFIG_START_BYTE2 0x91 +#define FRAME_FORMAT_CONFIG_START_BYTE2 0x71 #define FRAME_FORMAT_CONFIG_HEADER_SIZE 2 /* start_byte1 + start_byte2 + msg_id */ #define FRAME_FORMAT_CONFIG_FOOTER_SIZE 1 /* crc(1 bytes) */ #define FRAME_FORMAT_CONFIG_OVERHEAD (FRAME_FORMAT_CONFIG_HEADER_SIZE + FRAME_FORMAT_CONFIG_FOOTER_SIZE) diff --git a/src/struct_frame/boilerplate/c/frame_parsers.h b/src/struct_frame/boilerplate/c/frame_parsers.h index 5f5db21d..755b2684 100644 --- a/src/struct_frame/boilerplate/c/frame_parsers.h +++ b/src/struct_frame/boilerplate/c/frame_parsers.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser main header */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -7,24 +7,24 @@ #include "frame_base.h" /* Individual frame format parsers */ -#include "minimal_frame.h" -#include "basic_frame.h" -#include "basic_frame_no_crc.h" -#include "tiny_frame.h" -#include "tiny_frame_no_crc.h" -#include "minimal_frame_with_len.h" -#include "minimal_frame_with_len_no_crc.h" -#include "basic_frame_with_len.h" -#include "basic_frame_with_len_no_crc.h" -#include "tiny_frame_with_len.h" -#include "tiny_frame_with_len_no_crc.h" -#include "minimal_frame_with_len16.h" -#include "minimal_frame_with_len16_no_crc.h" -#include "basic_frame_with_len16.h" -#include "basic_frame_with_len16_no_crc.h" -#include "tiny_frame_with_len16.h" -#include "tiny_frame_with_len16_no_crc.h" -#include "basic_frame_with_sys_comp.h" +#include "tiny_minimal.h" +#include "tiny_default.h" +#include "tiny_extended_msg_ids.h" +#include "tiny_extended_length.h" +#include "tiny_extended.h" +#include "tiny_sys_comp.h" +#include "tiny_seq.h" +#include "tiny_multi_system_stream.h" +#include "tiny_extended_multi_system_stream.h" +#include "basic_minimal.h" +#include "basic_default.h" +#include "basic_extended_msg_ids.h" +#include "basic_extended_length.h" +#include "basic_extended.h" +#include "basic_sys_comp.h" +#include "basic_seq.h" +#include "basic_multi_system_stream.h" +#include "basic_extended_multi_system_stream.h" #include "ubx_frame.h" #include "mavlink_v1_frame.h" #include "mavlink_v2_frame.h" diff --git a/src/struct_frame/boilerplate/c/mavlink_v1_frame.h b/src/struct_frame/boilerplate/c/mavlink_v1_frame.h index a359ae8b..30797371 100644 --- a/src/struct_frame/boilerplate/c/mavlink_v1_frame.h +++ b/src/struct_frame/boilerplate/c/mavlink_v1_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -11,7 +11,7 @@ /* MavlinkV1Frame constants */ #define MAVLINK_V1_FRAME_START_BYTE 0xFE -#define MAVLINK_V1_FRAME_HEADER_SIZE 3 /* stx + msg_id + length(1) */ +#define MAVLINK_V1_FRAME_HEADER_SIZE 6 /* stx + msg_id + length(1) */ #define MAVLINK_V1_FRAME_FOOTER_SIZE 2 /* crc(2 bytes) */ #define MAVLINK_V1_FRAME_OVERHEAD (MAVLINK_V1_FRAME_HEADER_SIZE + MAVLINK_V1_FRAME_FOOTER_SIZE) @@ -143,8 +143,8 @@ static inline size_t mavlink_v1_frame_encode(uint8_t* buffer, size_t buffer_size } buffer[0] = MAVLINK_V1_FRAME_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)msg_size; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; /* Write message data */ if (msg_size > 0 && msg != NULL) { @@ -179,7 +179,7 @@ static inline frame_msg_info_t mavlink_v1_frame_validate_packet(const uint8_t* b frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[2]; result.msg_len = msg_length; result.msg_data = (uint8_t*)(buffer + MAVLINK_V1_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/c/mavlink_v2_frame.h b/src/struct_frame/boilerplate/c/mavlink_v2_frame.h index 73c05c03..44ccb177 100644 --- a/src/struct_frame/boilerplate/c/mavlink_v2_frame.h +++ b/src/struct_frame/boilerplate/c/mavlink_v2_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -11,7 +11,7 @@ /* MavlinkV2Frame constants */ #define MAVLINK_V2_FRAME_START_BYTE 0xFD -#define MAVLINK_V2_FRAME_HEADER_SIZE 5 /* stx + msg_id + length(1) */ +#define MAVLINK_V2_FRAME_HEADER_SIZE 8 /* stx + msg_id + length(1) */ #define MAVLINK_V2_FRAME_FOOTER_SIZE 2 /* crc(2 bytes) */ #define MAVLINK_V2_FRAME_OVERHEAD (MAVLINK_V2_FRAME_HEADER_SIZE + MAVLINK_V2_FRAME_FOOTER_SIZE) @@ -143,8 +143,8 @@ static inline size_t mavlink_v2_frame_encode(uint8_t* buffer, size_t buffer_size } buffer[0] = MAVLINK_V2_FRAME_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)msg_size; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; /* Write message data */ if (msg_size > 0 && msg != NULL) { @@ -179,7 +179,7 @@ static inline frame_msg_info_t mavlink_v2_frame_validate_packet(const uint8_t* b frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[2]; result.msg_len = msg_length; result.msg_data = (uint8_t*)(buffer + MAVLINK_V2_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/c/minimal_frame.h b/src/struct_frame/boilerplate/c/minimal_frame.h deleted file mode 100644 index 1e827448..00000000 --- a/src/struct_frame/boilerplate/c/minimal_frame.h +++ /dev/null @@ -1,171 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * MinimalFrame Frame Format - *===========================================================================*/ - -/* MinimalFrame constants */ -#define MINIMAL_FRAME_HEADER_SIZE 1 /* msg_id */ -#define MINIMAL_FRAME_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define MINIMAL_FRAME_OVERHEAD (MINIMAL_FRAME_HEADER_SIZE + MINIMAL_FRAME_FOOTER_SIZE) - -/* MinimalFrame parser states */ -typedef enum minimal_frame_parser_state { - MINIMAL_FRAME_GETTING_MSG_ID = 0, - MINIMAL_FRAME_GETTING_PAYLOAD = 1 -} minimal_frame_parser_state_t; - -/* MinimalFrame parser state structure */ -typedef struct minimal_frame_parser { - minimal_frame_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} minimal_frame_parser_t; - -/* MinimalFrame encode buffer structure */ -typedef struct minimal_frame_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} minimal_frame_encode_buffer_t; - -/** - * Initialize a MinimalFrame parser - */ -static inline void minimal_frame_parser_init(minimal_frame_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = MINIMAL_FRAME_GETTING_MSG_ID; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset MinimalFrame parser state - */ -static inline void minimal_frame_parser_reset(minimal_frame_parser_t* parser) { - parser->state = MINIMAL_FRAME_GETTING_MSG_ID; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with MinimalFrame format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t minimal_frame_parse_byte(minimal_frame_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case MINIMAL_FRAME_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = MINIMAL_FRAME_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = MINIMAL_FRAME_GETTING_PAYLOAD; - } else { - parser->state = MINIMAL_FRAME_GETTING_MSG_ID; - } - } else { - parser->state = MINIMAL_FRAME_GETTING_MSG_ID; - } - } - break; - - case MINIMAL_FRAME_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - MINIMAL_FRAME_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 0, msg_length + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + MINIMAL_FRAME_HEADER_SIZE; - } - parser->state = MINIMAL_FRAME_GETTING_MSG_ID; - } - break; - } - - return result; -} - -/** - * Encode a message with MinimalFrame format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t minimal_frame_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = MINIMAL_FRAME_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + MINIMAL_FRAME_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_size + 1); - buffer[MINIMAL_FRAME_HEADER_SIZE + msg_size] = ck.byte1; - buffer[MINIMAL_FRAME_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete MinimalFrame packet in a buffer - */ -static inline frame_msg_info_t minimal_frame_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < MINIMAL_FRAME_OVERHEAD) { - return result; - } - - - size_t msg_length = length - MINIMAL_FRAME_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_length + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[0]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + MINIMAL_FRAME_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/minimal_frame_with_len.h b/src/struct_frame/boilerplate/c/minimal_frame_with_len.h deleted file mode 100644 index 189105ac..00000000 --- a/src/struct_frame/boilerplate/c/minimal_frame_with_len.h +++ /dev/null @@ -1,175 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * MinimalFrameWithLen Frame Format - *===========================================================================*/ - -/* MinimalFrameWithLen constants */ -#define MINIMAL_FRAME_WITH_LEN_HEADER_SIZE 2 /* msg_id + length(1) */ -#define MINIMAL_FRAME_WITH_LEN_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define MINIMAL_FRAME_WITH_LEN_OVERHEAD (MINIMAL_FRAME_WITH_LEN_HEADER_SIZE + MINIMAL_FRAME_WITH_LEN_FOOTER_SIZE) - -/* MinimalFrameWithLen parser states */ -typedef enum minimal_frame_with_len_parser_state { - MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID = 0, - MINIMAL_FRAME_WITH_LEN_GETTING_LENGTH = 1, - MINIMAL_FRAME_WITH_LEN_GETTING_PAYLOAD = 2 -} minimal_frame_with_len_parser_state_t; - -/* MinimalFrameWithLen parser state structure */ -typedef struct minimal_frame_with_len_parser { - minimal_frame_with_len_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} minimal_frame_with_len_parser_t; - -/* MinimalFrameWithLen encode buffer structure */ -typedef struct minimal_frame_with_len_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} minimal_frame_with_len_encode_buffer_t; - -/** - * Initialize a MinimalFrameWithLen parser - */ -static inline void minimal_frame_with_len_parser_init(minimal_frame_with_len_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset MinimalFrameWithLen parser state - */ -static inline void minimal_frame_with_len_parser_reset(minimal_frame_with_len_parser_t* parser) { - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with MinimalFrameWithLen format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t minimal_frame_with_len_parse_byte(minimal_frame_with_len_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_LENGTH; - break; - - case MINIMAL_FRAME_WITH_LEN_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_length = byte; - parser->packet_size = MINIMAL_FRAME_WITH_LEN_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_PAYLOAD; - } else { - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID; - } - break; - - case MINIMAL_FRAME_WITH_LEN_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - MINIMAL_FRAME_WITH_LEN_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 0, msg_length + 1 + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + MINIMAL_FRAME_WITH_LEN_HEADER_SIZE; - } - parser->state = MINIMAL_FRAME_WITH_LEN_GETTING_MSG_ID; - } - break; - } - - return result; -} - -/** - * Encode a message with MinimalFrameWithLen format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t minimal_frame_with_len_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = MINIMAL_FRAME_WITH_LEN_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = msg_id; - buffer[1] = (uint8_t)msg_size; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + MINIMAL_FRAME_WITH_LEN_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_size + 1 + 1); - buffer[MINIMAL_FRAME_WITH_LEN_HEADER_SIZE + msg_size] = ck.byte1; - buffer[MINIMAL_FRAME_WITH_LEN_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete MinimalFrameWithLen packet in a buffer - */ -static inline frame_msg_info_t minimal_frame_with_len_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < MINIMAL_FRAME_WITH_LEN_OVERHEAD) { - return result; - } - - - size_t msg_length = length - MINIMAL_FRAME_WITH_LEN_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_length + 1 + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[0]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + MINIMAL_FRAME_WITH_LEN_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/minimal_frame_with_len16.h b/src/struct_frame/boilerplate/c/minimal_frame_with_len16.h deleted file mode 100644 index f2fffe72..00000000 --- a/src/struct_frame/boilerplate/c/minimal_frame_with_len16.h +++ /dev/null @@ -1,182 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * MinimalFrameWithLen16 Frame Format - *===========================================================================*/ - -/* MinimalFrameWithLen16 constants */ -#define MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE 3 /* msg_id + length(2) */ -#define MINIMAL_FRAME_WITH_LEN16_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define MINIMAL_FRAME_WITH_LEN16_OVERHEAD (MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE + MINIMAL_FRAME_WITH_LEN16_FOOTER_SIZE) - -/* MinimalFrameWithLen16 parser states */ -typedef enum minimal_frame_with_len16_parser_state { - MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID = 0, - MINIMAL_FRAME_WITH_LEN16_GETTING_LENGTH = 1, - MINIMAL_FRAME_WITH_LEN16_GETTING_PAYLOAD = 2 -} minimal_frame_with_len16_parser_state_t; - -/* MinimalFrameWithLen16 parser state structure */ -typedef struct minimal_frame_with_len16_parser { - minimal_frame_with_len16_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - uint8_t length_lo; /* Low byte for 16-bit length */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} minimal_frame_with_len16_parser_t; - -/* MinimalFrameWithLen16 encode buffer structure */ -typedef struct minimal_frame_with_len16_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} minimal_frame_with_len16_encode_buffer_t; - -/** - * Initialize a MinimalFrameWithLen16 parser - */ -static inline void minimal_frame_with_len16_parser_init(minimal_frame_with_len16_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->length_lo = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset MinimalFrameWithLen16 parser state - */ -static inline void minimal_frame_with_len16_parser_reset(minimal_frame_with_len16_parser_t* parser) { - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with MinimalFrameWithLen16 format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t minimal_frame_with_len16_parse_byte(minimal_frame_with_len16_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_LENGTH; - break; - - case MINIMAL_FRAME_WITH_LEN16_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - if (parser->buffer_index == 2) { - parser->length_lo = byte; - } else { - parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = MINIMAL_FRAME_WITH_LEN16_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_PAYLOAD; - } else { - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID; - } - } - break; - - case MINIMAL_FRAME_WITH_LEN16_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - MINIMAL_FRAME_WITH_LEN16_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 0, msg_length + 1 + 2); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE; - } - parser->state = MINIMAL_FRAME_WITH_LEN16_GETTING_MSG_ID; - } - break; - } - - return result; -} - -/** - * Encode a message with MinimalFrameWithLen16 format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t minimal_frame_with_len16_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = MINIMAL_FRAME_WITH_LEN16_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = msg_id; - buffer[1] = (uint8_t)(msg_size & 0xFF); - buffer[2] = (uint8_t)((msg_size >> 8) & 0xFF); - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_size + 1 + 2); - buffer[MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE + msg_size] = ck.byte1; - buffer[MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete MinimalFrameWithLen16 packet in a buffer - */ -static inline frame_msg_info_t minimal_frame_with_len16_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < MINIMAL_FRAME_WITH_LEN16_OVERHEAD) { - return result; - } - - - size_t msg_length = length - MINIMAL_FRAME_WITH_LEN16_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 0, msg_length + 1 + 2); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[0]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + MINIMAL_FRAME_WITH_LEN16_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/minimal_frame_with_len16_no_crc.h b/src/struct_frame/boilerplate/c/minimal_frame_with_len16_no_crc.h deleted file mode 100644 index 6ddcdaa8..00000000 --- a/src/struct_frame/boilerplate/c/minimal_frame_with_len16_no_crc.h +++ /dev/null @@ -1,166 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * MinimalFrameWithLen16NoCrc Frame Format - *===========================================================================*/ - -/* MinimalFrameWithLen16NoCrc constants */ -#define MINIMAL_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE 3 /* msg_id + length(2) */ -#define MINIMAL_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD (MINIMAL_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE + MINIMAL_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE) - -/* MinimalFrameWithLen16NoCrc parser states */ -typedef enum minimal_frame_with_len16_no_crc_parser_state { - MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID = 0, - MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH = 1, - MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD = 2 -} minimal_frame_with_len16_no_crc_parser_state_t; - -/* MinimalFrameWithLen16NoCrc parser state structure */ -typedef struct minimal_frame_with_len16_no_crc_parser { - minimal_frame_with_len16_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - uint8_t length_lo; /* Low byte for 16-bit length */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} minimal_frame_with_len16_no_crc_parser_t; - -/* MinimalFrameWithLen16NoCrc encode buffer structure */ -typedef struct minimal_frame_with_len16_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} minimal_frame_with_len16_no_crc_encode_buffer_t; - -/** - * Initialize a MinimalFrameWithLen16NoCrc parser - */ -static inline void minimal_frame_with_len16_no_crc_parser_init(minimal_frame_with_len16_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->length_lo = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset MinimalFrameWithLen16NoCrc parser state - */ -static inline void minimal_frame_with_len16_no_crc_parser_reset(minimal_frame_with_len16_no_crc_parser_t* parser) { - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with MinimalFrameWithLen16NoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t minimal_frame_with_len16_no_crc_parse_byte(minimal_frame_with_len16_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH; - break; - - case MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - if (parser->buffer_index == 2) { - parser->length_lo = byte; - } else { - parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - } - } - break; - - case MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + MINIMAL_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE; - parser->state = MINIMAL_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - } - break; - } - - return result; -} - -/** - * Encode a message with MinimalFrameWithLen16NoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t minimal_frame_with_len16_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = msg_id; - buffer[1] = (uint8_t)(msg_size & 0xFF); - buffer[2] = (uint8_t)((msg_size >> 8) & 0xFF); - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + MINIMAL_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete MinimalFrameWithLen16NoCrc packet in a buffer - */ -static inline frame_msg_info_t minimal_frame_with_len16_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD) { - return result; - } - - - size_t msg_length = length - MINIMAL_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[0]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + MINIMAL_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/minimal_frame_with_len_no_crc.h b/src/struct_frame/boilerplate/c/minimal_frame_with_len_no_crc.h deleted file mode 100644 index 970420c9..00000000 --- a/src/struct_frame/boilerplate/c/minimal_frame_with_len_no_crc.h +++ /dev/null @@ -1,159 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * MinimalFrameWithLenNoCrc Frame Format - *===========================================================================*/ - -/* MinimalFrameWithLenNoCrc constants */ -#define MINIMAL_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE 2 /* msg_id + length(1) */ -#define MINIMAL_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD (MINIMAL_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE + MINIMAL_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE) - -/* MinimalFrameWithLenNoCrc parser states */ -typedef enum minimal_frame_with_len_no_crc_parser_state { - MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID = 0, - MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH = 1, - MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD = 2 -} minimal_frame_with_len_no_crc_parser_state_t; - -/* MinimalFrameWithLenNoCrc parser state structure */ -typedef struct minimal_frame_with_len_no_crc_parser { - minimal_frame_with_len_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} minimal_frame_with_len_no_crc_parser_t; - -/* MinimalFrameWithLenNoCrc encode buffer structure */ -typedef struct minimal_frame_with_len_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} minimal_frame_with_len_no_crc_encode_buffer_t; - -/** - * Initialize a MinimalFrameWithLenNoCrc parser - */ -static inline void minimal_frame_with_len_no_crc_parser_init(minimal_frame_with_len_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset MinimalFrameWithLenNoCrc parser state - */ -static inline void minimal_frame_with_len_no_crc_parser_reset(minimal_frame_with_len_no_crc_parser_t* parser) { - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with MinimalFrameWithLenNoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t minimal_frame_with_len_no_crc_parse_byte(minimal_frame_with_len_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH; - break; - - case MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_length = byte; - parser->packet_size = MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - } - break; - - case MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + MINIMAL_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE; - parser->state = MINIMAL_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - } - break; - } - - return result; -} - -/** - * Encode a message with MinimalFrameWithLenNoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t minimal_frame_with_len_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = msg_id; - buffer[1] = (uint8_t)msg_size; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + MINIMAL_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete MinimalFrameWithLenNoCrc packet in a buffer - */ -static inline frame_msg_info_t minimal_frame_with_len_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD) { - return result; - } - - - size_t msg_length = length - MINIMAL_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[0]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + MINIMAL_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/tiny_default.h b/src/struct_frame/boilerplate/c/tiny_default.h new file mode 100644 index 00000000..2a021639 --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_default.h @@ -0,0 +1,189 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyDefault Frame Format + *===========================================================================*/ + +/* TinyDefault constants */ +#define TINY_DEFAULT_START_BYTE 0x71 +#define TINY_DEFAULT_HEADER_SIZE 3 /* start_byte + msg_id + length(1) */ +#define TINY_DEFAULT_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_DEFAULT_OVERHEAD (TINY_DEFAULT_HEADER_SIZE + TINY_DEFAULT_FOOTER_SIZE) + +/* TinyDefault parser states */ +typedef enum tiny_default_parser_state { + TINY_DEFAULT_LOOKING_FOR_START = 0, + TINY_DEFAULT_GETTING_MSG_ID = 1, + TINY_DEFAULT_GETTING_LENGTH = 2, + TINY_DEFAULT_GETTING_PAYLOAD = 3 +} tiny_default_parser_state_t; + +/* TinyDefault parser state structure */ +typedef struct tiny_default_parser { + tiny_default_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_default_parser_t; + +/* TinyDefault encode buffer structure */ +typedef struct tiny_default_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_default_encode_buffer_t; + +/** + * Initialize a TinyDefault parser + */ +static inline void tiny_default_parser_init(tiny_default_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_DEFAULT_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyDefault parser state + */ +static inline void tiny_default_parser_reset(tiny_default_parser_t* parser) { + parser->state = TINY_DEFAULT_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinyDefault format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_default_parse_byte(tiny_default_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_DEFAULT_LOOKING_FOR_START: + if (byte == TINY_DEFAULT_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_DEFAULT_GETTING_MSG_ID; + } + break; + + case TINY_DEFAULT_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_DEFAULT_GETTING_LENGTH; + break; + + case TINY_DEFAULT_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = TINY_DEFAULT_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_DEFAULT_GETTING_PAYLOAD; + } else { + parser->state = TINY_DEFAULT_LOOKING_FOR_START; + } + break; + + case TINY_DEFAULT_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_DEFAULT_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_DEFAULT_HEADER_SIZE; + } + parser->state = TINY_DEFAULT_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyDefault format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_default_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_DEFAULT_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_DEFAULT_START_BYTE; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyDefault packet in a buffer + */ +static inline frame_msg_info_t tiny_default_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_DEFAULT_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_DEFAULT_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_DEFAULT_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_DEFAULT_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_extended.h b/src/struct_frame/boilerplate/c/tiny_extended.h new file mode 100644 index 00000000..7c82a727 --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_extended.h @@ -0,0 +1,196 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyExtended Frame Format + *===========================================================================*/ + +/* TinyExtended constants */ +#define TINY_EXTENDED_START_BYTE 0x74 +#define TINY_EXTENDED_HEADER_SIZE 5 /* start_byte + msg_id + length(2) */ +#define TINY_EXTENDED_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_EXTENDED_OVERHEAD (TINY_EXTENDED_HEADER_SIZE + TINY_EXTENDED_FOOTER_SIZE) + +/* TinyExtended parser states */ +typedef enum tiny_extended_parser_state { + TINY_EXTENDED_LOOKING_FOR_START = 0, + TINY_EXTENDED_GETTING_MSG_ID = 1, + TINY_EXTENDED_GETTING_LENGTH = 2, + TINY_EXTENDED_GETTING_PAYLOAD = 3 +} tiny_extended_parser_state_t; + +/* TinyExtended parser state structure */ +typedef struct tiny_extended_parser { + tiny_extended_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + uint8_t length_lo; /* Low byte for 16-bit length */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_extended_parser_t; + +/* TinyExtended encode buffer structure */ +typedef struct tiny_extended_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_extended_encode_buffer_t; + +/** + * Initialize a TinyExtended parser + */ +static inline void tiny_extended_parser_init(tiny_extended_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_EXTENDED_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->length_lo = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyExtended parser state + */ +static inline void tiny_extended_parser_reset(tiny_extended_parser_t* parser) { + parser->state = TINY_EXTENDED_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinyExtended format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_extended_parse_byte(tiny_extended_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_EXTENDED_LOOKING_FOR_START: + if (byte == TINY_EXTENDED_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_EXTENDED_GETTING_MSG_ID; + } + break; + + case TINY_EXTENDED_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_EXTENDED_GETTING_LENGTH; + break; + + case TINY_EXTENDED_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + if (parser->buffer_index == 3) { + parser->length_lo = byte; + } else { + parser->msg_length = parser->length_lo | ((size_t)byte << 8); + parser->packet_size = TINY_EXTENDED_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_EXTENDED_GETTING_PAYLOAD; + } else { + parser->state = TINY_EXTENDED_LOOKING_FOR_START; + } + } + break; + + case TINY_EXTENDED_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_EXTENDED_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 2); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_EXTENDED_HEADER_SIZE; + } + parser->state = TINY_EXTENDED_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyExtended format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_extended_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_EXTENDED_START_BYTE; + buffer[1] = (uint8_t)(msg_size & 0xFF); + buffer[2] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 2); + buffer[TINY_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtended packet in a buffer + */ +static inline frame_msg_info_t tiny_extended_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_EXTENDED_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_EXTENDED_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_EXTENDED_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_EXTENDED_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_frame_with_len16.h b/src/struct_frame/boilerplate/c/tiny_extended_length.h similarity index 50% rename from src/struct_frame/boilerplate/c/tiny_frame_with_len16.h rename to src/struct_frame/boilerplate/c/tiny_extended_length.h index 9b8335df..616f0bdc 100644 --- a/src/struct_frame/boilerplate/c/tiny_frame_with_len16.h +++ b/src/struct_frame/boilerplate/c/tiny_extended_length.h @@ -1,31 +1,31 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once #include "frame_base.h" /*=========================================================================== - * TinyFrameWithLen16 Frame Format + * TinyExtendedLength Frame Format *===========================================================================*/ -/* TinyFrameWithLen16 constants */ -#define TINY_FRAME_WITH_LEN16_START_BYTE 0x74 -#define TINY_FRAME_WITH_LEN16_HEADER_SIZE 4 /* start_byte + msg_id + length(2) */ -#define TINY_FRAME_WITH_LEN16_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define TINY_FRAME_WITH_LEN16_OVERHEAD (TINY_FRAME_WITH_LEN16_HEADER_SIZE + TINY_FRAME_WITH_LEN16_FOOTER_SIZE) - -/* TinyFrameWithLen16 parser states */ -typedef enum tiny_frame_with_len16_parser_state { - TINY_FRAME_WITH_LEN16_LOOKING_FOR_START = 0, - TINY_FRAME_WITH_LEN16_GETTING_MSG_ID = 1, - TINY_FRAME_WITH_LEN16_GETTING_LENGTH = 2, - TINY_FRAME_WITH_LEN16_GETTING_PAYLOAD = 3 -} tiny_frame_with_len16_parser_state_t; - -/* TinyFrameWithLen16 parser state structure */ -typedef struct tiny_frame_with_len16_parser { - tiny_frame_with_len16_parser_state_t state; +/* TinyExtendedLength constants */ +#define TINY_EXTENDED_LENGTH_START_BYTE 0x73 +#define TINY_EXTENDED_LENGTH_HEADER_SIZE 4 /* start_byte + msg_id + length(2) */ +#define TINY_EXTENDED_LENGTH_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_EXTENDED_LENGTH_OVERHEAD (TINY_EXTENDED_LENGTH_HEADER_SIZE + TINY_EXTENDED_LENGTH_FOOTER_SIZE) + +/* TinyExtendedLength parser states */ +typedef enum tiny_extended_length_parser_state { + TINY_EXTENDED_LENGTH_LOOKING_FOR_START = 0, + TINY_EXTENDED_LENGTH_GETTING_MSG_ID = 1, + TINY_EXTENDED_LENGTH_GETTING_LENGTH = 2, + TINY_EXTENDED_LENGTH_GETTING_PAYLOAD = 3 +} tiny_extended_length_parser_state_t; + +/* TinyExtendedLength parser state structure */ +typedef struct tiny_extended_length_parser { + tiny_extended_length_parser_state_t state; uint8_t* buffer; size_t buffer_max_size; size_t buffer_index; @@ -35,24 +35,24 @@ typedef struct tiny_frame_with_len16_parser { uint8_t length_lo; /* Low byte for 16-bit length */ /* User-provided function to get message length from msg_id (for non-length frames) */ bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_with_len16_parser_t; +} tiny_extended_length_parser_t; -/* TinyFrameWithLen16 encode buffer structure */ -typedef struct tiny_frame_with_len16_encode_buffer { +/* TinyExtendedLength encode buffer structure */ +typedef struct tiny_extended_length_encode_buffer { uint8_t* data; size_t max_size; size_t size; bool in_progress; size_t reserved_msg_size; -} tiny_frame_with_len16_encode_buffer_t; +} tiny_extended_length_encode_buffer_t; /** - * Initialize a TinyFrameWithLen16 parser + * Initialize a TinyExtendedLength parser */ -static inline void tiny_frame_with_len16_parser_init(tiny_frame_with_len16_parser_t* parser, +static inline void tiny_extended_length_parser_init(tiny_extended_length_parser_t* parser, uint8_t* buffer, size_t buffer_size, bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_WITH_LEN16_LOOKING_FOR_START; + parser->state = TINY_EXTENDED_LENGTH_LOOKING_FOR_START; parser->buffer = buffer; parser->buffer_max_size = buffer_size; parser->buffer_index = 0; @@ -64,10 +64,10 @@ static inline void tiny_frame_with_len16_parser_init(tiny_frame_with_len16_parse } /** - * Reset TinyFrameWithLen16 parser state + * Reset TinyExtendedLength parser state */ -static inline void tiny_frame_with_len16_parser_reset(tiny_frame_with_len16_parser_t* parser) { - parser->state = TINY_FRAME_WITH_LEN16_LOOKING_FOR_START; +static inline void tiny_extended_length_parser_reset(tiny_extended_length_parser_t* parser) { + parser->state = TINY_EXTENDED_LENGTH_LOOKING_FOR_START; parser->buffer_index = 0; parser->packet_size = 0; parser->msg_id = 0; @@ -75,50 +75,50 @@ static inline void tiny_frame_with_len16_parser_reset(tiny_frame_with_len16_pars } /** - * Parse a single byte with TinyFrameWithLen16 format + * Parse a single byte with TinyExtendedLength format * Returns frame_msg_info_t with valid=true when a complete valid message is received */ -static inline frame_msg_info_t tiny_frame_with_len16_parse_byte(tiny_frame_with_len16_parser_t* parser, uint8_t byte) { +static inline frame_msg_info_t tiny_extended_length_parse_byte(tiny_extended_length_parser_t* parser, uint8_t byte) { frame_msg_info_t result = {false, 0, 0, NULL}; switch (parser->state) { - case TINY_FRAME_WITH_LEN16_LOOKING_FOR_START: - if (byte == TINY_FRAME_WITH_LEN16_START_BYTE) { + case TINY_EXTENDED_LENGTH_LOOKING_FOR_START: + if (byte == TINY_EXTENDED_LENGTH_START_BYTE) { parser->buffer[0] = byte; parser->buffer_index = 1; - parser->state = TINY_FRAME_WITH_LEN16_GETTING_MSG_ID; + parser->state = TINY_EXTENDED_LENGTH_GETTING_MSG_ID; } break; - case TINY_FRAME_WITH_LEN16_GETTING_MSG_ID: + case TINY_EXTENDED_LENGTH_GETTING_MSG_ID: parser->buffer[parser->buffer_index++] = byte; parser->msg_id = byte; - parser->state = TINY_FRAME_WITH_LEN16_GETTING_LENGTH; + parser->state = TINY_EXTENDED_LENGTH_GETTING_LENGTH; break; - case TINY_FRAME_WITH_LEN16_GETTING_LENGTH: + case TINY_EXTENDED_LENGTH_GETTING_LENGTH: parser->buffer[parser->buffer_index++] = byte; if (parser->buffer_index == 3) { parser->length_lo = byte; } else { parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = TINY_FRAME_WITH_LEN16_OVERHEAD + parser->msg_length; + parser->packet_size = TINY_EXTENDED_LENGTH_OVERHEAD + parser->msg_length; if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_WITH_LEN16_GETTING_PAYLOAD; + parser->state = TINY_EXTENDED_LENGTH_GETTING_PAYLOAD; } else { - parser->state = TINY_FRAME_WITH_LEN16_LOOKING_FOR_START; + parser->state = TINY_EXTENDED_LENGTH_LOOKING_FOR_START; } } break; - case TINY_FRAME_WITH_LEN16_GETTING_PAYLOAD: + case TINY_EXTENDED_LENGTH_GETTING_PAYLOAD: if (parser->buffer_index < parser->buffer_max_size) { parser->buffer[parser->buffer_index++] = byte; } if (parser->buffer_index >= parser->packet_size) { /* Validate checksum */ - size_t msg_length = parser->packet_size - TINY_FRAME_WITH_LEN16_OVERHEAD; + size_t msg_length = parser->packet_size - TINY_EXTENDED_LENGTH_OVERHEAD; frame_checksum_t ck = frame_fletcher_checksum( parser->buffer + 1, msg_length + 1 + 2); @@ -127,9 +127,9 @@ static inline frame_msg_info_t tiny_frame_with_len16_parse_byte(tiny_frame_with_ result.valid = true; result.msg_id = parser->msg_id; result.msg_len = msg_length; - result.msg_data = parser->buffer + TINY_FRAME_WITH_LEN16_HEADER_SIZE; + result.msg_data = parser->buffer + TINY_EXTENDED_LENGTH_HEADER_SIZE; } - parser->state = TINY_FRAME_WITH_LEN16_LOOKING_FOR_START; + parser->state = TINY_EXTENDED_LENGTH_LOOKING_FOR_START; } break; } @@ -138,57 +138,57 @@ static inline frame_msg_info_t tiny_frame_with_len16_parse_byte(tiny_frame_with_ } /** - * Encode a message with TinyFrameWithLen16 format + * Encode a message with TinyExtendedLength format * Returns the number of bytes written, or 0 on failure */ -static inline size_t tiny_frame_with_len16_encode(uint8_t* buffer, size_t buffer_size, +static inline size_t tiny_extended_length_encode(uint8_t* buffer, size_t buffer_size, uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_WITH_LEN16_OVERHEAD + msg_size; + size_t total_size = TINY_EXTENDED_LENGTH_OVERHEAD + msg_size; if (buffer_size < total_size) { return 0; } - buffer[0] = TINY_FRAME_WITH_LEN16_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)(msg_size & 0xFF); - buffer[3] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[0] = TINY_EXTENDED_LENGTH_START_BYTE; + buffer[1] = (uint8_t)(msg_size & 0xFF); + buffer[2] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; /* Write message data */ if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_WITH_LEN16_HEADER_SIZE, msg, msg_size); + memcpy(buffer + TINY_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); } /* Calculate checksum */ frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 2); - buffer[TINY_FRAME_WITH_LEN16_HEADER_SIZE + msg_size] = ck.byte1; - buffer[TINY_FRAME_WITH_LEN16_HEADER_SIZE + msg_size + 1] = ck.byte2; + buffer[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; return total_size; } /** - * Validate a complete TinyFrameWithLen16 packet in a buffer + * Validate a complete TinyExtendedLength packet in a buffer */ -static inline frame_msg_info_t tiny_frame_with_len16_validate_packet(const uint8_t* buffer, size_t length) { +static inline frame_msg_info_t tiny_extended_length_validate_packet(const uint8_t* buffer, size_t length) { frame_msg_info_t result = {false, 0, 0, NULL}; - if (length < TINY_FRAME_WITH_LEN16_OVERHEAD) { + if (length < TINY_EXTENDED_LENGTH_OVERHEAD) { return result; } - if (buffer[0] != TINY_FRAME_WITH_LEN16_START_BYTE) { + if (buffer[0] != TINY_EXTENDED_LENGTH_START_BYTE) { return result; } - size_t msg_length = length - TINY_FRAME_WITH_LEN16_OVERHEAD; + size_t msg_length = length - TINY_EXTENDED_LENGTH_OVERHEAD; /* Validate checksum */ frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 2); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[3]; result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_WITH_LEN16_HEADER_SIZE); + result.msg_data = (uint8_t*)(buffer + TINY_EXTENDED_LENGTH_HEADER_SIZE); } return result; diff --git a/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h b/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h new file mode 100644 index 00000000..1f45c76c --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_extended_msg_ids.h @@ -0,0 +1,189 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyExtendedMsgIds Frame Format + *===========================================================================*/ + +/* TinyExtendedMsgIds constants */ +#define TINY_EXTENDED_MSG_IDS_START_BYTE 0x72 +#define TINY_EXTENDED_MSG_IDS_HEADER_SIZE 4 /* start_byte + msg_id + length(1) */ +#define TINY_EXTENDED_MSG_IDS_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_EXTENDED_MSG_IDS_OVERHEAD (TINY_EXTENDED_MSG_IDS_HEADER_SIZE + TINY_EXTENDED_MSG_IDS_FOOTER_SIZE) + +/* TinyExtendedMsgIds parser states */ +typedef enum tiny_extended_msg_ids_parser_state { + TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START = 0, + TINY_EXTENDED_MSG_IDS_GETTING_MSG_ID = 1, + TINY_EXTENDED_MSG_IDS_GETTING_LENGTH = 2, + TINY_EXTENDED_MSG_IDS_GETTING_PAYLOAD = 3 +} tiny_extended_msg_ids_parser_state_t; + +/* TinyExtendedMsgIds parser state structure */ +typedef struct tiny_extended_msg_ids_parser { + tiny_extended_msg_ids_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_extended_msg_ids_parser_t; + +/* TinyExtendedMsgIds encode buffer structure */ +typedef struct tiny_extended_msg_ids_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_extended_msg_ids_encode_buffer_t; + +/** + * Initialize a TinyExtendedMsgIds parser + */ +static inline void tiny_extended_msg_ids_parser_init(tiny_extended_msg_ids_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyExtendedMsgIds parser state + */ +static inline void tiny_extended_msg_ids_parser_reset(tiny_extended_msg_ids_parser_t* parser) { + parser->state = TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinyExtendedMsgIds format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_extended_msg_ids_parse_byte(tiny_extended_msg_ids_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START: + if (byte == TINY_EXTENDED_MSG_IDS_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_EXTENDED_MSG_IDS_GETTING_MSG_ID; + } + break; + + case TINY_EXTENDED_MSG_IDS_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_EXTENDED_MSG_IDS_GETTING_LENGTH; + break; + + case TINY_EXTENDED_MSG_IDS_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = TINY_EXTENDED_MSG_IDS_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_EXTENDED_MSG_IDS_GETTING_PAYLOAD; + } else { + parser->state = TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START; + } + break; + + case TINY_EXTENDED_MSG_IDS_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_EXTENDED_MSG_IDS_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_EXTENDED_MSG_IDS_HEADER_SIZE; + } + parser->state = TINY_EXTENDED_MSG_IDS_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyExtendedMsgIds format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_extended_msg_ids_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_EXTENDED_MSG_IDS_START_BYTE; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtendedMsgIds packet in a buffer + */ +static inline frame_msg_info_t tiny_extended_msg_ids_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_EXTENDED_MSG_IDS_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_EXTENDED_MSG_IDS_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_EXTENDED_MSG_IDS_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_EXTENDED_MSG_IDS_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h b/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h new file mode 100644 index 00000000..e6e4d0bd --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_extended_multi_system_stream.h @@ -0,0 +1,196 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyExtendedMultiSystemStream Frame Format + *===========================================================================*/ + +/* TinyExtendedMultiSystemStream constants */ +#define TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE 0x78 +#define TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE 8 /* start_byte + msg_id + length(2) */ +#define TINY_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD (TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + TINY_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE) + +/* TinyExtendedMultiSystemStream parser states */ +typedef enum tiny_extended_multi_system_stream_parser_state { + TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START = 0, + TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID = 1, + TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH = 2, + TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD = 3 +} tiny_extended_multi_system_stream_parser_state_t; + +/* TinyExtendedMultiSystemStream parser state structure */ +typedef struct tiny_extended_multi_system_stream_parser { + tiny_extended_multi_system_stream_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + uint8_t length_lo; /* Low byte for 16-bit length */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_extended_multi_system_stream_parser_t; + +/* TinyExtendedMultiSystemStream encode buffer structure */ +typedef struct tiny_extended_multi_system_stream_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_extended_multi_system_stream_encode_buffer_t; + +/** + * Initialize a TinyExtendedMultiSystemStream parser + */ +static inline void tiny_extended_multi_system_stream_parser_init(tiny_extended_multi_system_stream_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->length_lo = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyExtendedMultiSystemStream parser state + */ +static inline void tiny_extended_multi_system_stream_parser_reset(tiny_extended_multi_system_stream_parser_t* parser) { + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinyExtendedMultiSystemStream format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_extended_multi_system_stream_parse_byte(tiny_extended_multi_system_stream_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START: + if (byte == TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID; + } + break; + + case TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH; + break; + + case TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + if (parser->buffer_index == 3) { + parser->length_lo = byte; + } else { + parser->msg_length = parser->length_lo | ((size_t)byte << 8); + parser->packet_size = TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD; + } else { + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + } + } + break; + + case TINY_EXTENDED_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 2); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + parser->state = TINY_EXTENDED_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyExtendedMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_extended_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE; + buffer[1] = (uint8_t)(msg_size & 0xFF); + buffer[2] = (uint8_t)((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 2); + buffer[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtendedMultiSystemStream packet in a buffer + */ +static inline frame_msg_info_t tiny_extended_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_frame.h b/src/struct_frame/boilerplate/c/tiny_frame.h deleted file mode 100644 index 6963f65a..00000000 --- a/src/struct_frame/boilerplate/c/tiny_frame.h +++ /dev/null @@ -1,185 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * TinyFrame Frame Format - *===========================================================================*/ - -/* TinyFrame constants */ -#define TINY_FRAME_START_BYTE 0x70 -#define TINY_FRAME_HEADER_SIZE 2 /* start_byte + msg_id */ -#define TINY_FRAME_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define TINY_FRAME_OVERHEAD (TINY_FRAME_HEADER_SIZE + TINY_FRAME_FOOTER_SIZE) - -/* TinyFrame parser states */ -typedef enum tiny_frame_parser_state { - TINY_FRAME_LOOKING_FOR_START = 0, - TINY_FRAME_GETTING_MSG_ID = 1, - TINY_FRAME_GETTING_PAYLOAD = 2 -} tiny_frame_parser_state_t; - -/* TinyFrame parser state structure */ -typedef struct tiny_frame_parser { - tiny_frame_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_parser_t; - -/* TinyFrame encode buffer structure */ -typedef struct tiny_frame_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} tiny_frame_encode_buffer_t; - -/** - * Initialize a TinyFrame parser - */ -static inline void tiny_frame_parser_init(tiny_frame_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_LOOKING_FOR_START; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset TinyFrame parser state - */ -static inline void tiny_frame_parser_reset(tiny_frame_parser_t* parser) { - parser->state = TINY_FRAME_LOOKING_FOR_START; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with TinyFrame format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t tiny_frame_parse_byte(tiny_frame_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case TINY_FRAME_LOOKING_FOR_START: - if (byte == TINY_FRAME_START_BYTE) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = TINY_FRAME_GETTING_MSG_ID; - } - break; - - case TINY_FRAME_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = TINY_FRAME_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_GETTING_PAYLOAD; - } else { - parser->state = TINY_FRAME_LOOKING_FOR_START; - } - } else { - parser->state = TINY_FRAME_LOOKING_FOR_START; - } - } - break; - - case TINY_FRAME_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - /* Validate checksum */ - size_t msg_length = parser->packet_size - TINY_FRAME_OVERHEAD; - frame_checksum_t ck = frame_fletcher_checksum( - parser->buffer + 1, msg_length + 1); - - if (ck.byte1 == parser->buffer[parser->packet_size - 2] && - ck.byte2 == parser->buffer[parser->packet_size - 1]) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = msg_length; - result.msg_data = parser->buffer + TINY_FRAME_HEADER_SIZE; - } - parser->state = TINY_FRAME_LOOKING_FOR_START; - } - break; - } - - return result; -} - -/** - * Encode a message with TinyFrame format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t tiny_frame_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = TINY_FRAME_START_BYTE; - buffer[1] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_HEADER_SIZE, msg, msg_size); - } - - /* Calculate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1); - buffer[TINY_FRAME_HEADER_SIZE + msg_size] = ck.byte1; - buffer[TINY_FRAME_HEADER_SIZE + msg_size + 1] = ck.byte2; - - return total_size; -} - -/** - * Validate a complete TinyFrame packet in a buffer - */ -static inline frame_msg_info_t tiny_frame_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < TINY_FRAME_OVERHEAD) { - return result; - } - - if (buffer[0] != TINY_FRAME_START_BYTE) { - return result; - } - - size_t msg_length = length - TINY_FRAME_OVERHEAD; - - /* Validate checksum */ - frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1); - if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { - result.valid = true; - result.msg_id = buffer[1]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_HEADER_SIZE); - } - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/tiny_frame_no_crc.h b/src/struct_frame/boilerplate/c/tiny_frame_no_crc.h deleted file mode 100644 index bc6e2711..00000000 --- a/src/struct_frame/boilerplate/c/tiny_frame_no_crc.h +++ /dev/null @@ -1,169 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * TinyFrameNoCrc Frame Format - *===========================================================================*/ - -/* TinyFrameNoCrc constants */ -#define TINY_FRAME_NO_CRC_START_BYTE 0x72 -#define TINY_FRAME_NO_CRC_HEADER_SIZE 2 /* start_byte + msg_id */ -#define TINY_FRAME_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define TINY_FRAME_NO_CRC_OVERHEAD (TINY_FRAME_NO_CRC_HEADER_SIZE + TINY_FRAME_NO_CRC_FOOTER_SIZE) - -/* TinyFrameNoCrc parser states */ -typedef enum tiny_frame_no_crc_parser_state { - TINY_FRAME_NO_CRC_LOOKING_FOR_START = 0, - TINY_FRAME_NO_CRC_GETTING_MSG_ID = 1, - TINY_FRAME_NO_CRC_GETTING_PAYLOAD = 2 -} tiny_frame_no_crc_parser_state_t; - -/* TinyFrameNoCrc parser state structure */ -typedef struct tiny_frame_no_crc_parser { - tiny_frame_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_no_crc_parser_t; - -/* TinyFrameNoCrc encode buffer structure */ -typedef struct tiny_frame_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} tiny_frame_no_crc_encode_buffer_t; - -/** - * Initialize a TinyFrameNoCrc parser - */ -static inline void tiny_frame_no_crc_parser_init(tiny_frame_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_NO_CRC_LOOKING_FOR_START; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset TinyFrameNoCrc parser state - */ -static inline void tiny_frame_no_crc_parser_reset(tiny_frame_no_crc_parser_t* parser) { - parser->state = TINY_FRAME_NO_CRC_LOOKING_FOR_START; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; -} - -/** - * Parse a single byte with TinyFrameNoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t tiny_frame_no_crc_parse_byte(tiny_frame_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case TINY_FRAME_NO_CRC_LOOKING_FOR_START: - if (byte == TINY_FRAME_NO_CRC_START_BYTE) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = TINY_FRAME_NO_CRC_GETTING_MSG_ID; - } - break; - - case TINY_FRAME_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - { - size_t msg_length = 0; - if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { - parser->packet_size = TINY_FRAME_NO_CRC_OVERHEAD + msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = TINY_FRAME_NO_CRC_LOOKING_FOR_START; - } - } else { - parser->state = TINY_FRAME_NO_CRC_LOOKING_FOR_START; - } - } - break; - - case TINY_FRAME_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - TINY_FRAME_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + TINY_FRAME_NO_CRC_HEADER_SIZE; - parser->state = TINY_FRAME_NO_CRC_LOOKING_FOR_START; - } - break; - } - - return result; -} - -/** - * Encode a message with TinyFrameNoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t tiny_frame_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = TINY_FRAME_NO_CRC_START_BYTE; - buffer[1] = msg_id; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete TinyFrameNoCrc packet in a buffer - */ -static inline frame_msg_info_t tiny_frame_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < TINY_FRAME_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != TINY_FRAME_NO_CRC_START_BYTE) { - return result; - } - - size_t msg_length = length - TINY_FRAME_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[1]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/tiny_frame_with_len16_no_crc.h b/src/struct_frame/boilerplate/c/tiny_frame_with_len16_no_crc.h deleted file mode 100644 index 32324b1f..00000000 --- a/src/struct_frame/boilerplate/c/tiny_frame_with_len16_no_crc.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * TinyFrameWithLen16NoCrc Frame Format - *===========================================================================*/ - -/* TinyFrameWithLen16NoCrc constants */ -#define TINY_FRAME_WITH_LEN16_NO_CRC_START_BYTE 0x75 -#define TINY_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE 4 /* start_byte + msg_id + length(2) */ -#define TINY_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD (TINY_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE + TINY_FRAME_WITH_LEN16_NO_CRC_FOOTER_SIZE) - -/* TinyFrameWithLen16NoCrc parser states */ -typedef enum tiny_frame_with_len16_no_crc_parser_state { - TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START = 0, - TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID = 1, - TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH = 2, - TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD = 3 -} tiny_frame_with_len16_no_crc_parser_state_t; - -/* TinyFrameWithLen16NoCrc parser state structure */ -typedef struct tiny_frame_with_len16_no_crc_parser { - tiny_frame_with_len16_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - uint8_t length_lo; /* Low byte for 16-bit length */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_with_len16_no_crc_parser_t; - -/* TinyFrameWithLen16NoCrc encode buffer structure */ -typedef struct tiny_frame_with_len16_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} tiny_frame_with_len16_no_crc_encode_buffer_t; - -/** - * Initialize a TinyFrameWithLen16NoCrc parser - */ -static inline void tiny_frame_with_len16_no_crc_parser_init(tiny_frame_with_len16_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->length_lo = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset TinyFrameWithLen16NoCrc parser state - */ -static inline void tiny_frame_with_len16_no_crc_parser_reset(tiny_frame_with_len16_no_crc_parser_t* parser) { - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with TinyFrameWithLen16NoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t tiny_frame_with_len16_no_crc_parse_byte(tiny_frame_with_len16_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START: - if (byte == TINY_FRAME_WITH_LEN16_NO_CRC_START_BYTE) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID; - } - break; - - case TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH; - break; - - case TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - if (parser->buffer_index == 3) { - parser->length_lo = byte; - } else { - parser->msg_length = parser->length_lo | ((size_t)byte << 8); - parser->packet_size = TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START; - } - } - break; - - case TINY_FRAME_WITH_LEN16_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + TINY_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE; - parser->state = TINY_FRAME_WITH_LEN16_NO_CRC_LOOKING_FOR_START; - } - break; - } - - return result; -} - -/** - * Encode a message with TinyFrameWithLen16NoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t tiny_frame_with_len16_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = TINY_FRAME_WITH_LEN16_NO_CRC_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)(msg_size & 0xFF); - buffer[3] = (uint8_t)((msg_size >> 8) & 0xFF); - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete TinyFrameWithLen16NoCrc packet in a buffer - */ -static inline frame_msg_info_t tiny_frame_with_len16_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != TINY_FRAME_WITH_LEN16_NO_CRC_START_BYTE) { - return result; - } - - size_t msg_length = length - TINY_FRAME_WITH_LEN16_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[1]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_WITH_LEN16_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/tiny_frame_with_len_no_crc.h b/src/struct_frame/boilerplate/c/tiny_frame_with_len_no_crc.h deleted file mode 100644 index 8404e082..00000000 --- a/src/struct_frame/boilerplate/c/tiny_frame_with_len_no_crc.h +++ /dev/null @@ -1,173 +0,0 @@ -/* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ - -#pragma once - -#include "frame_base.h" - -/*=========================================================================== - * TinyFrameWithLenNoCrc Frame Format - *===========================================================================*/ - -/* TinyFrameWithLenNoCrc constants */ -#define TINY_FRAME_WITH_LEN_NO_CRC_START_BYTE 0x73 -#define TINY_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE 3 /* start_byte + msg_id + length(1) */ -#define TINY_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE 0 /* no footer */ -#define TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD (TINY_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE + TINY_FRAME_WITH_LEN_NO_CRC_FOOTER_SIZE) - -/* TinyFrameWithLenNoCrc parser states */ -typedef enum tiny_frame_with_len_no_crc_parser_state { - TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START = 0, - TINY_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID = 1, - TINY_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH = 2, - TINY_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD = 3 -} tiny_frame_with_len_no_crc_parser_state_t; - -/* TinyFrameWithLenNoCrc parser state structure */ -typedef struct tiny_frame_with_len_no_crc_parser { - tiny_frame_with_len_no_crc_parser_state_t state; - uint8_t* buffer; - size_t buffer_max_size; - size_t buffer_index; - size_t packet_size; - uint8_t msg_id; - size_t msg_length; /* From length field */ - /* User-provided function to get message length from msg_id (for non-length frames) */ - bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_with_len_no_crc_parser_t; - -/* TinyFrameWithLenNoCrc encode buffer structure */ -typedef struct tiny_frame_with_len_no_crc_encode_buffer { - uint8_t* data; - size_t max_size; - size_t size; - bool in_progress; - size_t reserved_msg_size; -} tiny_frame_with_len_no_crc_encode_buffer_t; - -/** - * Initialize a TinyFrameWithLenNoCrc parser - */ -static inline void tiny_frame_with_len_no_crc_parser_init(tiny_frame_with_len_no_crc_parser_t* parser, - uint8_t* buffer, size_t buffer_size, - bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START; - parser->buffer = buffer; - parser->buffer_max_size = buffer_size; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; - parser->get_msg_length = get_msg_length; -} - -/** - * Reset TinyFrameWithLenNoCrc parser state - */ -static inline void tiny_frame_with_len_no_crc_parser_reset(tiny_frame_with_len_no_crc_parser_t* parser) { - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START; - parser->buffer_index = 0; - parser->packet_size = 0; - parser->msg_id = 0; - parser->msg_length = 0; -} - -/** - * Parse a single byte with TinyFrameWithLenNoCrc format - * Returns frame_msg_info_t with valid=true when a complete valid message is received - */ -static inline frame_msg_info_t tiny_frame_with_len_no_crc_parse_byte(tiny_frame_with_len_no_crc_parser_t* parser, uint8_t byte) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - switch (parser->state) { - case TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START: - if (byte == TINY_FRAME_WITH_LEN_NO_CRC_START_BYTE) { - parser->buffer[0] = byte; - parser->buffer_index = 1; - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID; - } - break; - - case TINY_FRAME_WITH_LEN_NO_CRC_GETTING_MSG_ID: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_id = byte; - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH; - break; - - case TINY_FRAME_WITH_LEN_NO_CRC_GETTING_LENGTH: - parser->buffer[parser->buffer_index++] = byte; - parser->msg_length = byte; - parser->packet_size = TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD + parser->msg_length; - if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD; - } else { - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START; - } - break; - - case TINY_FRAME_WITH_LEN_NO_CRC_GETTING_PAYLOAD: - if (parser->buffer_index < parser->buffer_max_size) { - parser->buffer[parser->buffer_index++] = byte; - } - - if (parser->buffer_index >= parser->packet_size) { - result.valid = true; - result.msg_id = parser->msg_id; - result.msg_len = parser->packet_size - TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - result.msg_data = parser->buffer + TINY_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE; - parser->state = TINY_FRAME_WITH_LEN_NO_CRC_LOOKING_FOR_START; - } - break; - } - - return result; -} - -/** - * Encode a message with TinyFrameWithLenNoCrc format - * Returns the number of bytes written, or 0 on failure - */ -static inline size_t tiny_frame_with_len_no_crc_encode(uint8_t* buffer, size_t buffer_size, - uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD + msg_size; - if (buffer_size < total_size) { - return 0; - } - - buffer[0] = TINY_FRAME_WITH_LEN_NO_CRC_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)msg_size; - - /* Write message data */ - if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE, msg, msg_size); - } - - - return total_size; -} - -/** - * Validate a complete TinyFrameWithLenNoCrc packet in a buffer - */ -static inline frame_msg_info_t tiny_frame_with_len_no_crc_validate_packet(const uint8_t* buffer, size_t length) { - frame_msg_info_t result = {false, 0, 0, NULL}; - - if (length < TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD) { - return result; - } - - if (buffer[0] != TINY_FRAME_WITH_LEN_NO_CRC_START_BYTE) { - return result; - } - - size_t msg_length = length - TINY_FRAME_WITH_LEN_NO_CRC_OVERHEAD; - - result.valid = true; - result.msg_id = buffer[1]; - result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_WITH_LEN_NO_CRC_HEADER_SIZE); - - return result; -} - diff --git a/src/struct_frame/boilerplate/c/tiny_minimal.h b/src/struct_frame/boilerplate/c/tiny_minimal.h new file mode 100644 index 00000000..d9c5d3e5 --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_minimal.h @@ -0,0 +1,169 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyMinimal Frame Format + *===========================================================================*/ + +/* TinyMinimal constants */ +#define TINY_MINIMAL_START_BYTE 0x70 +#define TINY_MINIMAL_HEADER_SIZE 2 /* start_byte + msg_id */ +#define TINY_MINIMAL_FOOTER_SIZE 0 /* no footer */ +#define TINY_MINIMAL_OVERHEAD (TINY_MINIMAL_HEADER_SIZE + TINY_MINIMAL_FOOTER_SIZE) + +/* TinyMinimal parser states */ +typedef enum tiny_minimal_parser_state { + TINY_MINIMAL_LOOKING_FOR_START = 0, + TINY_MINIMAL_GETTING_MSG_ID = 1, + TINY_MINIMAL_GETTING_PAYLOAD = 2 +} tiny_minimal_parser_state_t; + +/* TinyMinimal parser state structure */ +typedef struct tiny_minimal_parser { + tiny_minimal_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_minimal_parser_t; + +/* TinyMinimal encode buffer structure */ +typedef struct tiny_minimal_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_minimal_encode_buffer_t; + +/** + * Initialize a TinyMinimal parser + */ +static inline void tiny_minimal_parser_init(tiny_minimal_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_MINIMAL_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyMinimal parser state + */ +static inline void tiny_minimal_parser_reset(tiny_minimal_parser_t* parser) { + parser->state = TINY_MINIMAL_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; +} + +/** + * Parse a single byte with TinyMinimal format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_minimal_parse_byte(tiny_minimal_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_MINIMAL_LOOKING_FOR_START: + if (byte == TINY_MINIMAL_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_MINIMAL_GETTING_MSG_ID; + } + break; + + case TINY_MINIMAL_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + { + size_t msg_length = 0; + if (parser->get_msg_length && parser->get_msg_length(byte, &msg_length)) { + parser->packet_size = TINY_MINIMAL_OVERHEAD + msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_MINIMAL_GETTING_PAYLOAD; + } else { + parser->state = TINY_MINIMAL_LOOKING_FOR_START; + } + } else { + parser->state = TINY_MINIMAL_LOOKING_FOR_START; + } + } + break; + + case TINY_MINIMAL_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = parser->packet_size - TINY_MINIMAL_OVERHEAD; + result.msg_data = parser->buffer + TINY_MINIMAL_HEADER_SIZE; + parser->state = TINY_MINIMAL_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyMinimal format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_minimal_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_MINIMAL_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_MINIMAL_START_BYTE; + buffer[1] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + return total_size; +} + +/** + * Validate a complete TinyMinimal packet in a buffer + */ +static inline frame_msg_info_t tiny_minimal_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_MINIMAL_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_MINIMAL_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_MINIMAL_OVERHEAD; + + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_MINIMAL_HEADER_SIZE); + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h b/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h new file mode 100644 index 00000000..26cccd16 --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_multi_system_stream.h @@ -0,0 +1,189 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinyMultiSystemStream Frame Format + *===========================================================================*/ + +/* TinyMultiSystemStream constants */ +#define TINY_MULTI_SYSTEM_STREAM_START_BYTE 0x77 +#define TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE 6 /* start_byte + msg_id + length(1) */ +#define TINY_MULTI_SYSTEM_STREAM_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_MULTI_SYSTEM_STREAM_OVERHEAD (TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + TINY_MULTI_SYSTEM_STREAM_FOOTER_SIZE) + +/* TinyMultiSystemStream parser states */ +typedef enum tiny_multi_system_stream_parser_state { + TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START = 0, + TINY_MULTI_SYSTEM_STREAM_GETTING_MSG_ID = 1, + TINY_MULTI_SYSTEM_STREAM_GETTING_LENGTH = 2, + TINY_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD = 3 +} tiny_multi_system_stream_parser_state_t; + +/* TinyMultiSystemStream parser state structure */ +typedef struct tiny_multi_system_stream_parser { + tiny_multi_system_stream_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_multi_system_stream_parser_t; + +/* TinyMultiSystemStream encode buffer structure */ +typedef struct tiny_multi_system_stream_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_multi_system_stream_encode_buffer_t; + +/** + * Initialize a TinyMultiSystemStream parser + */ +static inline void tiny_multi_system_stream_parser_init(tiny_multi_system_stream_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinyMultiSystemStream parser state + */ +static inline void tiny_multi_system_stream_parser_reset(tiny_multi_system_stream_parser_t* parser) { + parser->state = TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinyMultiSystemStream format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_multi_system_stream_parse_byte(tiny_multi_system_stream_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START: + if (byte == TINY_MULTI_SYSTEM_STREAM_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_MULTI_SYSTEM_STREAM_GETTING_MSG_ID; + } + break; + + case TINY_MULTI_SYSTEM_STREAM_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_MULTI_SYSTEM_STREAM_GETTING_LENGTH; + break; + + case TINY_MULTI_SYSTEM_STREAM_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = TINY_MULTI_SYSTEM_STREAM_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD; + } else { + parser->state = TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + } + break; + + case TINY_MULTI_SYSTEM_STREAM_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_MULTI_SYSTEM_STREAM_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + parser->state = TINY_MULTI_SYSTEM_STREAM_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinyMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_MULTI_SYSTEM_STREAM_START_BYTE; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyMultiSystemStream packet in a buffer + */ +static inline frame_msg_info_t tiny_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_MULTI_SYSTEM_STREAM_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_MULTI_SYSTEM_STREAM_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_MULTI_SYSTEM_STREAM_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_seq.h b/src/struct_frame/boilerplate/c/tiny_seq.h new file mode 100644 index 00000000..35f97bc2 --- /dev/null +++ b/src/struct_frame/boilerplate/c/tiny_seq.h @@ -0,0 +1,189 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.h" + +/*=========================================================================== + * TinySeq Frame Format + *===========================================================================*/ + +/* TinySeq constants */ +#define TINY_SEQ_START_BYTE 0x76 +#define TINY_SEQ_HEADER_SIZE 4 /* start_byte + msg_id + length(1) */ +#define TINY_SEQ_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_SEQ_OVERHEAD (TINY_SEQ_HEADER_SIZE + TINY_SEQ_FOOTER_SIZE) + +/* TinySeq parser states */ +typedef enum tiny_seq_parser_state { + TINY_SEQ_LOOKING_FOR_START = 0, + TINY_SEQ_GETTING_MSG_ID = 1, + TINY_SEQ_GETTING_LENGTH = 2, + TINY_SEQ_GETTING_PAYLOAD = 3 +} tiny_seq_parser_state_t; + +/* TinySeq parser state structure */ +typedef struct tiny_seq_parser { + tiny_seq_parser_state_t state; + uint8_t* buffer; + size_t buffer_max_size; + size_t buffer_index; + size_t packet_size; + uint8_t msg_id; + size_t msg_length; /* From length field */ + /* User-provided function to get message length from msg_id (for non-length frames) */ + bool (*get_msg_length)(uint8_t msg_id, size_t* length); +} tiny_seq_parser_t; + +/* TinySeq encode buffer structure */ +typedef struct tiny_seq_encode_buffer { + uint8_t* data; + size_t max_size; + size_t size; + bool in_progress; + size_t reserved_msg_size; +} tiny_seq_encode_buffer_t; + +/** + * Initialize a TinySeq parser + */ +static inline void tiny_seq_parser_init(tiny_seq_parser_t* parser, + uint8_t* buffer, size_t buffer_size, + bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { + parser->state = TINY_SEQ_LOOKING_FOR_START; + parser->buffer = buffer; + parser->buffer_max_size = buffer_size; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; + parser->get_msg_length = get_msg_length; +} + +/** + * Reset TinySeq parser state + */ +static inline void tiny_seq_parser_reset(tiny_seq_parser_t* parser) { + parser->state = TINY_SEQ_LOOKING_FOR_START; + parser->buffer_index = 0; + parser->packet_size = 0; + parser->msg_id = 0; + parser->msg_length = 0; +} + +/** + * Parse a single byte with TinySeq format + * Returns frame_msg_info_t with valid=true when a complete valid message is received + */ +static inline frame_msg_info_t tiny_seq_parse_byte(tiny_seq_parser_t* parser, uint8_t byte) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + switch (parser->state) { + case TINY_SEQ_LOOKING_FOR_START: + if (byte == TINY_SEQ_START_BYTE) { + parser->buffer[0] = byte; + parser->buffer_index = 1; + parser->state = TINY_SEQ_GETTING_MSG_ID; + } + break; + + case TINY_SEQ_GETTING_MSG_ID: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_id = byte; + parser->state = TINY_SEQ_GETTING_LENGTH; + break; + + case TINY_SEQ_GETTING_LENGTH: + parser->buffer[parser->buffer_index++] = byte; + parser->msg_length = byte; + parser->packet_size = TINY_SEQ_OVERHEAD + parser->msg_length; + if (parser->packet_size <= parser->buffer_max_size) { + parser->state = TINY_SEQ_GETTING_PAYLOAD; + } else { + parser->state = TINY_SEQ_LOOKING_FOR_START; + } + break; + + case TINY_SEQ_GETTING_PAYLOAD: + if (parser->buffer_index < parser->buffer_max_size) { + parser->buffer[parser->buffer_index++] = byte; + } + + if (parser->buffer_index >= parser->packet_size) { + /* Validate checksum */ + size_t msg_length = parser->packet_size - TINY_SEQ_OVERHEAD; + frame_checksum_t ck = frame_fletcher_checksum( + parser->buffer + 1, msg_length + 1 + 1); + + if (ck.byte1 == parser->buffer[parser->packet_size - 2] && + ck.byte2 == parser->buffer[parser->packet_size - 1]) { + result.valid = true; + result.msg_id = parser->msg_id; + result.msg_len = msg_length; + result.msg_data = parser->buffer + TINY_SEQ_HEADER_SIZE; + } + parser->state = TINY_SEQ_LOOKING_FOR_START; + } + break; + } + + return result; +} + +/** + * Encode a message with TinySeq format + * Returns the number of bytes written, or 0 on failure + */ +static inline size_t tiny_seq_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_SEQ_OVERHEAD + msg_size; + if (buffer_size < total_size) { + return 0; + } + + buffer[0] = TINY_SEQ_START_BYTE; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; + + /* Write message data */ + if (msg_size > 0 && msg != NULL) { + memcpy(buffer + TINY_SEQ_HEADER_SIZE, msg, msg_size); + } + + /* Calculate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinySeq packet in a buffer + */ +static inline frame_msg_info_t tiny_seq_validate_packet(const uint8_t* buffer, size_t length) { + frame_msg_info_t result = {false, 0, 0, NULL}; + + if (length < TINY_SEQ_OVERHEAD) { + return result; + } + + if (buffer[0] != TINY_SEQ_START_BYTE) { + return result; + } + + size_t msg_length = length - TINY_SEQ_OVERHEAD; + + /* Validate checksum */ + frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = (uint8_t*)(buffer + TINY_SEQ_HEADER_SIZE); + } + + return result; +} + diff --git a/src/struct_frame/boilerplate/c/tiny_frame_with_len.h b/src/struct_frame/boilerplate/c/tiny_sys_comp.h similarity index 50% rename from src/struct_frame/boilerplate/c/tiny_frame_with_len.h rename to src/struct_frame/boilerplate/c/tiny_sys_comp.h index 046de60a..a1a5dfc0 100644 --- a/src/struct_frame/boilerplate/c/tiny_frame_with_len.h +++ b/src/struct_frame/boilerplate/c/tiny_sys_comp.h @@ -1,31 +1,31 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once #include "frame_base.h" /*=========================================================================== - * TinyFrameWithLen Frame Format + * TinySysComp Frame Format *===========================================================================*/ -/* TinyFrameWithLen constants */ -#define TINY_FRAME_WITH_LEN_START_BYTE 0x71 -#define TINY_FRAME_WITH_LEN_HEADER_SIZE 3 /* start_byte + msg_id + length(1) */ -#define TINY_FRAME_WITH_LEN_FOOTER_SIZE 2 /* crc(2 bytes) */ -#define TINY_FRAME_WITH_LEN_OVERHEAD (TINY_FRAME_WITH_LEN_HEADER_SIZE + TINY_FRAME_WITH_LEN_FOOTER_SIZE) - -/* TinyFrameWithLen parser states */ -typedef enum tiny_frame_with_len_parser_state { - TINY_FRAME_WITH_LEN_LOOKING_FOR_START = 0, - TINY_FRAME_WITH_LEN_GETTING_MSG_ID = 1, - TINY_FRAME_WITH_LEN_GETTING_LENGTH = 2, - TINY_FRAME_WITH_LEN_GETTING_PAYLOAD = 3 -} tiny_frame_with_len_parser_state_t; - -/* TinyFrameWithLen parser state structure */ -typedef struct tiny_frame_with_len_parser { - tiny_frame_with_len_parser_state_t state; +/* TinySysComp constants */ +#define TINY_SYS_COMP_START_BYTE 0x75 +#define TINY_SYS_COMP_HEADER_SIZE 5 /* start_byte + msg_id + length(1) */ +#define TINY_SYS_COMP_FOOTER_SIZE 2 /* crc(2 bytes) */ +#define TINY_SYS_COMP_OVERHEAD (TINY_SYS_COMP_HEADER_SIZE + TINY_SYS_COMP_FOOTER_SIZE) + +/* TinySysComp parser states */ +typedef enum tiny_sys_comp_parser_state { + TINY_SYS_COMP_LOOKING_FOR_START = 0, + TINY_SYS_COMP_GETTING_MSG_ID = 1, + TINY_SYS_COMP_GETTING_LENGTH = 2, + TINY_SYS_COMP_GETTING_PAYLOAD = 3 +} tiny_sys_comp_parser_state_t; + +/* TinySysComp parser state structure */ +typedef struct tiny_sys_comp_parser { + tiny_sys_comp_parser_state_t state; uint8_t* buffer; size_t buffer_max_size; size_t buffer_index; @@ -34,24 +34,24 @@ typedef struct tiny_frame_with_len_parser { size_t msg_length; /* From length field */ /* User-provided function to get message length from msg_id (for non-length frames) */ bool (*get_msg_length)(uint8_t msg_id, size_t* length); -} tiny_frame_with_len_parser_t; +} tiny_sys_comp_parser_t; -/* TinyFrameWithLen encode buffer structure */ -typedef struct tiny_frame_with_len_encode_buffer { +/* TinySysComp encode buffer structure */ +typedef struct tiny_sys_comp_encode_buffer { uint8_t* data; size_t max_size; size_t size; bool in_progress; size_t reserved_msg_size; -} tiny_frame_with_len_encode_buffer_t; +} tiny_sys_comp_encode_buffer_t; /** - * Initialize a TinyFrameWithLen parser + * Initialize a TinySysComp parser */ -static inline void tiny_frame_with_len_parser_init(tiny_frame_with_len_parser_t* parser, +static inline void tiny_sys_comp_parser_init(tiny_sys_comp_parser_t* parser, uint8_t* buffer, size_t buffer_size, bool (*get_msg_length)(uint8_t msg_id, size_t* length)) { - parser->state = TINY_FRAME_WITH_LEN_LOOKING_FOR_START; + parser->state = TINY_SYS_COMP_LOOKING_FOR_START; parser->buffer = buffer; parser->buffer_max_size = buffer_size; parser->buffer_index = 0; @@ -62,10 +62,10 @@ static inline void tiny_frame_with_len_parser_init(tiny_frame_with_len_parser_t* } /** - * Reset TinyFrameWithLen parser state + * Reset TinySysComp parser state */ -static inline void tiny_frame_with_len_parser_reset(tiny_frame_with_len_parser_t* parser) { - parser->state = TINY_FRAME_WITH_LEN_LOOKING_FOR_START; +static inline void tiny_sys_comp_parser_reset(tiny_sys_comp_parser_t* parser) { + parser->state = TINY_SYS_COMP_LOOKING_FOR_START; parser->buffer_index = 0; parser->packet_size = 0; parser->msg_id = 0; @@ -73,46 +73,46 @@ static inline void tiny_frame_with_len_parser_reset(tiny_frame_with_len_parser_t } /** - * Parse a single byte with TinyFrameWithLen format + * Parse a single byte with TinySysComp format * Returns frame_msg_info_t with valid=true when a complete valid message is received */ -static inline frame_msg_info_t tiny_frame_with_len_parse_byte(tiny_frame_with_len_parser_t* parser, uint8_t byte) { +static inline frame_msg_info_t tiny_sys_comp_parse_byte(tiny_sys_comp_parser_t* parser, uint8_t byte) { frame_msg_info_t result = {false, 0, 0, NULL}; switch (parser->state) { - case TINY_FRAME_WITH_LEN_LOOKING_FOR_START: - if (byte == TINY_FRAME_WITH_LEN_START_BYTE) { + case TINY_SYS_COMP_LOOKING_FOR_START: + if (byte == TINY_SYS_COMP_START_BYTE) { parser->buffer[0] = byte; parser->buffer_index = 1; - parser->state = TINY_FRAME_WITH_LEN_GETTING_MSG_ID; + parser->state = TINY_SYS_COMP_GETTING_MSG_ID; } break; - case TINY_FRAME_WITH_LEN_GETTING_MSG_ID: + case TINY_SYS_COMP_GETTING_MSG_ID: parser->buffer[parser->buffer_index++] = byte; parser->msg_id = byte; - parser->state = TINY_FRAME_WITH_LEN_GETTING_LENGTH; + parser->state = TINY_SYS_COMP_GETTING_LENGTH; break; - case TINY_FRAME_WITH_LEN_GETTING_LENGTH: + case TINY_SYS_COMP_GETTING_LENGTH: parser->buffer[parser->buffer_index++] = byte; parser->msg_length = byte; - parser->packet_size = TINY_FRAME_WITH_LEN_OVERHEAD + parser->msg_length; + parser->packet_size = TINY_SYS_COMP_OVERHEAD + parser->msg_length; if (parser->packet_size <= parser->buffer_max_size) { - parser->state = TINY_FRAME_WITH_LEN_GETTING_PAYLOAD; + parser->state = TINY_SYS_COMP_GETTING_PAYLOAD; } else { - parser->state = TINY_FRAME_WITH_LEN_LOOKING_FOR_START; + parser->state = TINY_SYS_COMP_LOOKING_FOR_START; } break; - case TINY_FRAME_WITH_LEN_GETTING_PAYLOAD: + case TINY_SYS_COMP_GETTING_PAYLOAD: if (parser->buffer_index < parser->buffer_max_size) { parser->buffer[parser->buffer_index++] = byte; } if (parser->buffer_index >= parser->packet_size) { /* Validate checksum */ - size_t msg_length = parser->packet_size - TINY_FRAME_WITH_LEN_OVERHEAD; + size_t msg_length = parser->packet_size - TINY_SYS_COMP_OVERHEAD; frame_checksum_t ck = frame_fletcher_checksum( parser->buffer + 1, msg_length + 1 + 1); @@ -121,9 +121,9 @@ static inline frame_msg_info_t tiny_frame_with_len_parse_byte(tiny_frame_with_le result.valid = true; result.msg_id = parser->msg_id; result.msg_len = msg_length; - result.msg_data = parser->buffer + TINY_FRAME_WITH_LEN_HEADER_SIZE; + result.msg_data = parser->buffer + TINY_SYS_COMP_HEADER_SIZE; } - parser->state = TINY_FRAME_WITH_LEN_LOOKING_FOR_START; + parser->state = TINY_SYS_COMP_LOOKING_FOR_START; } break; } @@ -132,56 +132,56 @@ static inline frame_msg_info_t tiny_frame_with_len_parse_byte(tiny_frame_with_le } /** - * Encode a message with TinyFrameWithLen format + * Encode a message with TinySysComp format * Returns the number of bytes written, or 0 on failure */ -static inline size_t tiny_frame_with_len_encode(uint8_t* buffer, size_t buffer_size, +static inline size_t tiny_sys_comp_encode(uint8_t* buffer, size_t buffer_size, uint8_t msg_id, const uint8_t* msg, size_t msg_size) { - size_t total_size = TINY_FRAME_WITH_LEN_OVERHEAD + msg_size; + size_t total_size = TINY_SYS_COMP_OVERHEAD + msg_size; if (buffer_size < total_size) { return 0; } - buffer[0] = TINY_FRAME_WITH_LEN_START_BYTE; - buffer[1] = msg_id; - buffer[2] = (uint8_t)msg_size; + buffer[0] = TINY_SYS_COMP_START_BYTE; + buffer[1] = (uint8_t)msg_size; + buffer[2] = msg_id; /* Write message data */ if (msg_size > 0 && msg != NULL) { - memcpy(buffer + TINY_FRAME_WITH_LEN_HEADER_SIZE, msg, msg_size); + memcpy(buffer + TINY_SYS_COMP_HEADER_SIZE, msg, msg_size); } /* Calculate checksum */ frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_size + 1 + 1); - buffer[TINY_FRAME_WITH_LEN_HEADER_SIZE + msg_size] = ck.byte1; - buffer[TINY_FRAME_WITH_LEN_HEADER_SIZE + msg_size + 1] = ck.byte2; + buffer[TINY_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; return total_size; } /** - * Validate a complete TinyFrameWithLen packet in a buffer + * Validate a complete TinySysComp packet in a buffer */ -static inline frame_msg_info_t tiny_frame_with_len_validate_packet(const uint8_t* buffer, size_t length) { +static inline frame_msg_info_t tiny_sys_comp_validate_packet(const uint8_t* buffer, size_t length) { frame_msg_info_t result = {false, 0, 0, NULL}; - if (length < TINY_FRAME_WITH_LEN_OVERHEAD) { + if (length < TINY_SYS_COMP_OVERHEAD) { return result; } - if (buffer[0] != TINY_FRAME_WITH_LEN_START_BYTE) { + if (buffer[0] != TINY_SYS_COMP_START_BYTE) { return result; } - size_t msg_length = length - TINY_FRAME_WITH_LEN_OVERHEAD; + size_t msg_length = length - TINY_SYS_COMP_OVERHEAD; /* Validate checksum */ frame_checksum_t ck = frame_fletcher_checksum(buffer + 1, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[2]; result.msg_len = msg_length; - result.msg_data = (uint8_t*)(buffer + TINY_FRAME_WITH_LEN_HEADER_SIZE); + result.msg_data = (uint8_t*)(buffer + TINY_SYS_COMP_HEADER_SIZE); } return result; diff --git a/src/struct_frame/boilerplate/c/ubx_frame.h b/src/struct_frame/boilerplate/c/ubx_frame.h index 4006db69..ed52c85f 100644 --- a/src/struct_frame/boilerplate/c/ubx_frame.h +++ b/src/struct_frame/boilerplate/c/ubx_frame.h @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -160,8 +160,8 @@ static inline size_t ubx_frame_encode(uint8_t* buffer, size_t buffer_size, buffer[0] = UBX_FRAME_START_BYTE1; buffer[1] = UBX_FRAME_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = (uint8_t)msg_size; + buffer[2] = (uint8_t)msg_size; + buffer[3] = msg_id; /* Write message data */ if (msg_size > 0 && msg != NULL) { @@ -199,7 +199,7 @@ static inline frame_msg_info_t ubx_frame_validate_packet(const uint8_t* buffer, frame_checksum_t ck = frame_fletcher_checksum(buffer + 2, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[2]; + result.msg_id = buffer[3]; result.msg_len = msg_length; result.msg_data = (uint8_t*)(buffer + UBX_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/cpp/BasicDefault.hpp b/src/struct_frame/boilerplate/cpp/BasicDefault.hpp new file mode 100644 index 00000000..e991754e --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicDefault.hpp @@ -0,0 +1,246 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicDefault Frame Format +// ============================================================================= + +enum class BasicDefaultParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicDefault constants +constexpr uint8_t BASIC_DEFAULT_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_DEFAULT_START_BYTE2 = 0x71; +constexpr size_t BASIC_DEFAULT_HEADER_SIZE = 4; +constexpr size_t BASIC_DEFAULT_FOOTER_SIZE = 2; +constexpr size_t BASIC_DEFAULT_OVERHEAD = BASIC_DEFAULT_HEADER_SIZE + BASIC_DEFAULT_FOOTER_SIZE; +constexpr size_t BASIC_DEFAULT_LENGTH_BYTES = 1; + +/** + * BasicDefault Encode Buffer + */ +class BasicDefaultEncodeBuffer { +public: + BasicDefaultEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_DEFAULT_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_DEFAULT_START_BYTE1; + packet_start[1] = BASIC_DEFAULT_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 1); + packet_start[BASIC_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicDefault Frame Parser + */ +class BasicDefaultParser { +public: + using MsgLengthCallback = std::function; + + BasicDefaultParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicDefaultParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicDefaultParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicDefaultParserState::LookingForStart1: + if (byte == BASIC_DEFAULT_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicDefaultParserState::LookingForStart2; + } + break; + + case BasicDefaultParserState::LookingForStart2: + if (byte == BASIC_DEFAULT_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicDefaultParserState::GettingMsgId; + } else if (byte == BASIC_DEFAULT_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicDefaultParserState::LookingForStart2; + } else { + state_ = BasicDefaultParserState::LookingForStart1; + } + break; + + case BasicDefaultParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicDefaultParserState::GettingLength; + break; + } + + case BasicDefaultParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = BASIC_DEFAULT_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicDefaultParserState::GettingPayload; + } else { + state_ = BasicDefaultParserState::LookingForStart1; + } + break; + + case BasicDefaultParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_DEFAULT_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_DEFAULT_HEADER_SIZE; + } + state_ = BasicDefaultParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicDefaultParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicDefault format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_default_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_DEFAULT_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_DEFAULT_START_BYTE1; + buffer[1] = BASIC_DEFAULT_START_BYTE2; + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicDefault packet in a buffer + */ +inline FrameMsgInfo basic_default_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_DEFAULT_OVERHEAD) return result; + + if (buffer[0] != BASIC_DEFAULT_START_BYTE1) return result; + if (buffer[1] != BASIC_DEFAULT_START_BYTE2) return result; + + size_t msg_length = length - BASIC_DEFAULT_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_DEFAULT_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicExtended.hpp b/src/struct_frame/boilerplate/cpp/BasicExtended.hpp new file mode 100644 index 00000000..c90eae00 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicExtended.hpp @@ -0,0 +1,254 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicExtended Frame Format +// ============================================================================= + +enum class BasicExtendedParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicExtended constants +constexpr uint8_t BASIC_EXTENDED_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_EXTENDED_START_BYTE2 = 0x74; +constexpr size_t BASIC_EXTENDED_HEADER_SIZE = 6; +constexpr size_t BASIC_EXTENDED_FOOTER_SIZE = 2; +constexpr size_t BASIC_EXTENDED_OVERHEAD = BASIC_EXTENDED_HEADER_SIZE + BASIC_EXTENDED_FOOTER_SIZE; +constexpr size_t BASIC_EXTENDED_LENGTH_BYTES = 2; + +/** + * BasicExtended Encode Buffer + */ +class BasicExtendedEncodeBuffer { +public: + BasicExtendedEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_EXTENDED_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_EXTENDED_START_BYTE1; + packet_start[1] = BASIC_EXTENDED_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size & 0xFF); + packet_start[4] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 2); + packet_start[BASIC_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicExtended Frame Parser + */ +class BasicExtendedParser { +public: + using MsgLengthCallback = std::function; + + BasicExtendedParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicExtendedParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicExtendedParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicExtendedParserState::LookingForStart1: + if (byte == BASIC_EXTENDED_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedParserState::LookingForStart2; + } + break; + + case BasicExtendedParserState::LookingForStart2: + if (byte == BASIC_EXTENDED_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicExtendedParserState::GettingMsgId; + } else if (byte == BASIC_EXTENDED_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedParserState::LookingForStart2; + } else { + state_ = BasicExtendedParserState::LookingForStart1; + } + break; + + case BasicExtendedParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicExtendedParserState::GettingLength; + break; + } + + case BasicExtendedParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 4) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = BASIC_EXTENDED_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicExtendedParserState::GettingPayload; + } else { + state_ = BasicExtendedParserState::LookingForStart1; + } + } + break; + + case BasicExtendedParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_EXTENDED_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_EXTENDED_HEADER_SIZE; + } + state_ = BasicExtendedParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicExtendedParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicExtended format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_extended_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_EXTENDED_START_BYTE1; + buffer[1] = BASIC_EXTENDED_START_BYTE2; + buffer[2] = static_cast(msg_size & 0xFF); + buffer[3] = static_cast((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtended packet in a buffer + */ +inline FrameMsgInfo basic_extended_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_EXTENDED_OVERHEAD) return result; + + if (buffer[0] != BASIC_EXTENDED_START_BYTE1) return result; + if (buffer[1] != BASIC_EXTENDED_START_BYTE2) return result; + + size_t msg_length = length - BASIC_EXTENDED_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_EXTENDED_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp new file mode 100644 index 00000000..0e0600de --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedLength.hpp @@ -0,0 +1,254 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicExtendedLength Frame Format +// ============================================================================= + +enum class BasicExtendedLengthParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicExtendedLength constants +constexpr uint8_t BASIC_EXTENDED_LENGTH_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_EXTENDED_LENGTH_START_BYTE2 = 0x73; +constexpr size_t BASIC_EXTENDED_LENGTH_HEADER_SIZE = 5; +constexpr size_t BASIC_EXTENDED_LENGTH_FOOTER_SIZE = 2; +constexpr size_t BASIC_EXTENDED_LENGTH_OVERHEAD = BASIC_EXTENDED_LENGTH_HEADER_SIZE + BASIC_EXTENDED_LENGTH_FOOTER_SIZE; +constexpr size_t BASIC_EXTENDED_LENGTH_LENGTH_BYTES = 2; + +/** + * BasicExtendedLength Encode Buffer + */ +class BasicExtendedLengthEncodeBuffer { +public: + BasicExtendedLengthEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_EXTENDED_LENGTH_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_EXTENDED_LENGTH_START_BYTE1; + packet_start[1] = BASIC_EXTENDED_LENGTH_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size & 0xFF); + packet_start[4] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 2); + packet_start[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicExtendedLength Frame Parser + */ +class BasicExtendedLengthParser { +public: + using MsgLengthCallback = std::function; + + BasicExtendedLengthParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicExtendedLengthParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicExtendedLengthParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicExtendedLengthParserState::LookingForStart1: + if (byte == BASIC_EXTENDED_LENGTH_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedLengthParserState::LookingForStart2; + } + break; + + case BasicExtendedLengthParserState::LookingForStart2: + if (byte == BASIC_EXTENDED_LENGTH_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicExtendedLengthParserState::GettingMsgId; + } else if (byte == BASIC_EXTENDED_LENGTH_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedLengthParserState::LookingForStart2; + } else { + state_ = BasicExtendedLengthParserState::LookingForStart1; + } + break; + + case BasicExtendedLengthParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicExtendedLengthParserState::GettingLength; + break; + } + + case BasicExtendedLengthParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 4) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = BASIC_EXTENDED_LENGTH_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicExtendedLengthParserState::GettingPayload; + } else { + state_ = BasicExtendedLengthParserState::LookingForStart1; + } + } + break; + + case BasicExtendedLengthParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_EXTENDED_LENGTH_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_EXTENDED_LENGTH_HEADER_SIZE; + } + state_ = BasicExtendedLengthParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicExtendedLengthParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicExtendedLength format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_extended_length_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_LENGTH_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_EXTENDED_LENGTH_START_BYTE1; + buffer[1] = BASIC_EXTENDED_LENGTH_START_BYTE2; + buffer[2] = static_cast(msg_size & 0xFF); + buffer[3] = static_cast((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedLength packet in a buffer + */ +inline FrameMsgInfo basic_extended_length_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_EXTENDED_LENGTH_OVERHEAD) return result; + + if (buffer[0] != BASIC_EXTENDED_LENGTH_START_BYTE1) return result; + if (buffer[1] != BASIC_EXTENDED_LENGTH_START_BYTE2) return result; + + size_t msg_length = length - BASIC_EXTENDED_LENGTH_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_EXTENDED_LENGTH_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp new file mode 100644 index 00000000..3386728b --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedMsgIds.hpp @@ -0,0 +1,246 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicExtendedMsgIds Frame Format +// ============================================================================= + +enum class BasicExtendedMsgIdsParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicExtendedMsgIds constants +constexpr uint8_t BASIC_EXTENDED_MSG_IDS_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_EXTENDED_MSG_IDS_START_BYTE2 = 0x72; +constexpr size_t BASIC_EXTENDED_MSG_IDS_HEADER_SIZE = 5; +constexpr size_t BASIC_EXTENDED_MSG_IDS_FOOTER_SIZE = 2; +constexpr size_t BASIC_EXTENDED_MSG_IDS_OVERHEAD = BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + BASIC_EXTENDED_MSG_IDS_FOOTER_SIZE; +constexpr size_t BASIC_EXTENDED_MSG_IDS_LENGTH_BYTES = 1; + +/** + * BasicExtendedMsgIds Encode Buffer + */ +class BasicExtendedMsgIdsEncodeBuffer { +public: + BasicExtendedMsgIdsEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_EXTENDED_MSG_IDS_START_BYTE1; + packet_start[1] = BASIC_EXTENDED_MSG_IDS_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 1); + packet_start[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicExtendedMsgIds Frame Parser + */ +class BasicExtendedMsgIdsParser { +public: + using MsgLengthCallback = std::function; + + BasicExtendedMsgIdsParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicExtendedMsgIdsParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicExtendedMsgIdsParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicExtendedMsgIdsParserState::LookingForStart1: + if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedMsgIdsParserState::LookingForStart2; + } + break; + + case BasicExtendedMsgIdsParserState::LookingForStart2: + if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicExtendedMsgIdsParserState::GettingMsgId; + } else if (byte == BASIC_EXTENDED_MSG_IDS_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedMsgIdsParserState::LookingForStart2; + } else { + state_ = BasicExtendedMsgIdsParserState::LookingForStart1; + } + break; + + case BasicExtendedMsgIdsParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicExtendedMsgIdsParserState::GettingLength; + break; + } + + case BasicExtendedMsgIdsParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = BASIC_EXTENDED_MSG_IDS_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicExtendedMsgIdsParserState::GettingPayload; + } else { + state_ = BasicExtendedMsgIdsParserState::LookingForStart1; + } + break; + + case BasicExtendedMsgIdsParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_EXTENDED_MSG_IDS_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE; + } + state_ = BasicExtendedMsgIdsParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicExtendedMsgIdsParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicExtendedMsgIds format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_extended_msg_ids_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_EXTENDED_MSG_IDS_START_BYTE1; + buffer[1] = BASIC_EXTENDED_MSG_IDS_START_BYTE2; + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedMsgIds packet in a buffer + */ +inline FrameMsgInfo basic_extended_msg_ids_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_EXTENDED_MSG_IDS_OVERHEAD) return result; + + if (buffer[0] != BASIC_EXTENDED_MSG_IDS_START_BYTE1) return result; + if (buffer[1] != BASIC_EXTENDED_MSG_IDS_START_BYTE2) return result; + + size_t msg_length = length - BASIC_EXTENDED_MSG_IDS_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_EXTENDED_MSG_IDS_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp new file mode 100644 index 00000000..0ee19a50 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicExtendedMultiSystemStream.hpp @@ -0,0 +1,254 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicExtendedMultiSystemStream Frame Format +// ============================================================================= + +enum class BasicExtendedMultiSystemStreamParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicExtendedMultiSystemStream constants +constexpr uint8_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2 = 0x78; +constexpr size_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE = 9; +constexpr size_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE = 2; +constexpr size_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE; +constexpr size_t BASIC_EXTENDED_MULTI_SYSTEM_STREAM_LENGTH_BYTES = 2; + +/** + * BasicExtendedMultiSystemStream Encode Buffer + */ +class BasicExtendedMultiSystemStreamEncodeBuffer { +public: + BasicExtendedMultiSystemStreamEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1; + packet_start[1] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size & 0xFF); + packet_start[4] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 2); + packet_start[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicExtendedMultiSystemStream Frame Parser + */ +class BasicExtendedMultiSystemStreamParser { +public: + using MsgLengthCallback = std::function; + + BasicExtendedMultiSystemStreamParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicExtendedMultiSystemStreamParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicExtendedMultiSystemStreamParserState::LookingForStart1: + if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart2; + } + break; + + case BasicExtendedMultiSystemStreamParserState::LookingForStart2: + if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicExtendedMultiSystemStreamParserState::GettingMsgId; + } else if (byte == BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart2; + } else { + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart1; + } + break; + + case BasicExtendedMultiSystemStreamParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicExtendedMultiSystemStreamParserState::GettingLength; + break; + } + + case BasicExtendedMultiSystemStreamParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 4) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicExtendedMultiSystemStreamParserState::GettingPayload; + } else { + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart1; + } + } + break; + + case BasicExtendedMultiSystemStreamParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + state_ = BasicExtendedMultiSystemStreamParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicExtendedMultiSystemStreamParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicExtendedMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_extended_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1; + buffer[1] = BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2; + buffer[2] = static_cast(msg_size & 0xFF); + buffer[3] = static_cast((msg_size >> 8) & 0xFF); + buffer[4] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 2); + buffer[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicExtendedMultiSystemStream packet in a buffer + */ +inline FrameMsgInfo basic_extended_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD) return result; + + if (buffer[0] != BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE1) return result; + if (buffer[1] != BASIC_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE2) return result; + + size_t msg_length = length - BASIC_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[4]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp b/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp new file mode 100644 index 00000000..a3eefc1b --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicMinimal.hpp @@ -0,0 +1,221 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicMinimal Frame Format +// ============================================================================= + +enum class BasicMinimalParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingPayload = 3 +}; + +// BasicMinimal constants +constexpr uint8_t BASIC_MINIMAL_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_MINIMAL_START_BYTE2 = 0x70; +constexpr size_t BASIC_MINIMAL_HEADER_SIZE = 3; +constexpr size_t BASIC_MINIMAL_FOOTER_SIZE = 0; +constexpr size_t BASIC_MINIMAL_OVERHEAD = BASIC_MINIMAL_HEADER_SIZE + BASIC_MINIMAL_FOOTER_SIZE; + +/** + * BasicMinimal Encode Buffer + */ +class BasicMinimalEncodeBuffer { +public: + BasicMinimalEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_MINIMAL_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_MINIMAL_START_BYTE1; + packet_start[1] = BASIC_MINIMAL_START_BYTE2; + packet_start[2] = msg_id; + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicMinimal Frame Parser + */ +class BasicMinimalParser { +public: + using MsgLengthCallback = std::function; + + BasicMinimalParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicMinimalParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicMinimalParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicMinimalParserState::LookingForStart1: + if (byte == BASIC_MINIMAL_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicMinimalParserState::LookingForStart2; + } + break; + + case BasicMinimalParserState::LookingForStart2: + if (byte == BASIC_MINIMAL_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicMinimalParserState::GettingMsgId; + } else if (byte == BASIC_MINIMAL_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicMinimalParserState::LookingForStart2; + } else { + state_ = BasicMinimalParserState::LookingForStart1; + } + break; + + case BasicMinimalParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + size_t msg_length = 0; + if (get_msg_length_ && get_msg_length_(byte, &msg_length)) { + packet_size_ = BASIC_MINIMAL_OVERHEAD + msg_length; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicMinimalParserState::GettingPayload; + } else { + state_ = BasicMinimalParserState::LookingForStart1; + } + } else { + state_ = BasicMinimalParserState::LookingForStart1; + } + break; + } + + case BasicMinimalParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = packet_size_ - BASIC_MINIMAL_OVERHEAD; + result.msg_data = buffer_ + BASIC_MINIMAL_HEADER_SIZE; + state_ = BasicMinimalParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicMinimalParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicMinimal format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_minimal_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_MINIMAL_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_MINIMAL_START_BYTE1; + buffer[1] = BASIC_MINIMAL_START_BYTE2; + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + return total_size; +} + +/** + * Validate a complete BasicMinimal packet in a buffer + */ +inline FrameMsgInfo basic_minimal_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_MINIMAL_OVERHEAD) return result; + + if (buffer[0] != BASIC_MINIMAL_START_BYTE1) return result; + if (buffer[1] != BASIC_MINIMAL_START_BYTE2) return result; + + size_t msg_length = length - BASIC_MINIMAL_OVERHEAD; + + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_MINIMAL_HEADER_SIZE); + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp new file mode 100644 index 00000000..a6cc9dd4 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicMultiSystemStream.hpp @@ -0,0 +1,246 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicMultiSystemStream Frame Format +// ============================================================================= + +enum class BasicMultiSystemStreamParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicMultiSystemStream constants +constexpr uint8_t BASIC_MULTI_SYSTEM_STREAM_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_MULTI_SYSTEM_STREAM_START_BYTE2 = 0x77; +constexpr size_t BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE = 7; +constexpr size_t BASIC_MULTI_SYSTEM_STREAM_FOOTER_SIZE = 2; +constexpr size_t BASIC_MULTI_SYSTEM_STREAM_OVERHEAD = BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + BASIC_MULTI_SYSTEM_STREAM_FOOTER_SIZE; +constexpr size_t BASIC_MULTI_SYSTEM_STREAM_LENGTH_BYTES = 1; + +/** + * BasicMultiSystemStream Encode Buffer + */ +class BasicMultiSystemStreamEncodeBuffer { +public: + BasicMultiSystemStreamEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE1; + packet_start[1] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 1); + packet_start[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicMultiSystemStream Frame Parser + */ +class BasicMultiSystemStreamParser { +public: + using MsgLengthCallback = std::function; + + BasicMultiSystemStreamParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicMultiSystemStreamParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicMultiSystemStreamParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicMultiSystemStreamParserState::LookingForStart1: + if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicMultiSystemStreamParserState::LookingForStart2; + } + break; + + case BasicMultiSystemStreamParserState::LookingForStart2: + if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicMultiSystemStreamParserState::GettingMsgId; + } else if (byte == BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicMultiSystemStreamParserState::LookingForStart2; + } else { + state_ = BasicMultiSystemStreamParserState::LookingForStart1; + } + break; + + case BasicMultiSystemStreamParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicMultiSystemStreamParserState::GettingLength; + break; + } + + case BasicMultiSystemStreamParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = BASIC_MULTI_SYSTEM_STREAM_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicMultiSystemStreamParserState::GettingPayload; + } else { + state_ = BasicMultiSystemStreamParserState::LookingForStart1; + } + break; + + case BasicMultiSystemStreamParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_MULTI_SYSTEM_STREAM_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + state_ = BasicMultiSystemStreamParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicMultiSystemStreamParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE1; + buffer[1] = BASIC_MULTI_SYSTEM_STREAM_START_BYTE2; + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicMultiSystemStream packet in a buffer + */ +inline FrameMsgInfo basic_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_MULTI_SYSTEM_STREAM_OVERHEAD) return result; + + if (buffer[0] != BASIC_MULTI_SYSTEM_STREAM_START_BYTE1) return result; + if (buffer[1] != BASIC_MULTI_SYSTEM_STREAM_START_BYTE2) return result; + + size_t msg_length = length - BASIC_MULTI_SYSTEM_STREAM_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicSeq.hpp b/src/struct_frame/boilerplate/cpp/BasicSeq.hpp new file mode 100644 index 00000000..32003090 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicSeq.hpp @@ -0,0 +1,246 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicSeq Frame Format +// ============================================================================= + +enum class BasicSeqParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicSeq constants +constexpr uint8_t BASIC_SEQ_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_SEQ_START_BYTE2 = 0x76; +constexpr size_t BASIC_SEQ_HEADER_SIZE = 5; +constexpr size_t BASIC_SEQ_FOOTER_SIZE = 2; +constexpr size_t BASIC_SEQ_OVERHEAD = BASIC_SEQ_HEADER_SIZE + BASIC_SEQ_FOOTER_SIZE; +constexpr size_t BASIC_SEQ_LENGTH_BYTES = 1; + +/** + * BasicSeq Encode Buffer + */ +class BasicSeqEncodeBuffer { +public: + BasicSeqEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_SEQ_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_SEQ_START_BYTE1; + packet_start[1] = BASIC_SEQ_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_SEQ_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 1); + packet_start[BASIC_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicSeq Frame Parser + */ +class BasicSeqParser { +public: + using MsgLengthCallback = std::function; + + BasicSeqParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicSeqParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicSeqParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicSeqParserState::LookingForStart1: + if (byte == BASIC_SEQ_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicSeqParserState::LookingForStart2; + } + break; + + case BasicSeqParserState::LookingForStart2: + if (byte == BASIC_SEQ_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicSeqParserState::GettingMsgId; + } else if (byte == BASIC_SEQ_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicSeqParserState::LookingForStart2; + } else { + state_ = BasicSeqParserState::LookingForStart1; + } + break; + + case BasicSeqParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicSeqParserState::GettingLength; + break; + } + + case BasicSeqParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = BASIC_SEQ_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicSeqParserState::GettingPayload; + } else { + state_ = BasicSeqParserState::LookingForStart1; + } + break; + + case BasicSeqParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_SEQ_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_SEQ_HEADER_SIZE; + } + state_ = BasicSeqParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicSeqParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicSeq format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_seq_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_SEQ_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_SEQ_START_BYTE1; + buffer[1] = BASIC_SEQ_START_BYTE2; + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_SEQ_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicSeq packet in a buffer + */ +inline FrameMsgInfo basic_seq_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_SEQ_OVERHEAD) return result; + + if (buffer[0] != BASIC_SEQ_START_BYTE1) return result; + if (buffer[1] != BASIC_SEQ_START_BYTE2) return result; + + size_t msg_length = length - BASIC_SEQ_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_SEQ_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp b/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp new file mode 100644 index 00000000..2e7b101d --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/BasicSysComp.hpp @@ -0,0 +1,246 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// BasicSysComp Frame Format +// ============================================================================= + +enum class BasicSysCompParserState : uint8_t { + LookingForStart1 = 0, + LookingForStart2 = 1, + GettingMsgId = 2, + GettingLength = 3, + GettingPayload = 4 +}; + +// BasicSysComp constants +constexpr uint8_t BASIC_SYS_COMP_START_BYTE1 = 0x90; +constexpr uint8_t BASIC_SYS_COMP_START_BYTE2 = 0x75; +constexpr size_t BASIC_SYS_COMP_HEADER_SIZE = 6; +constexpr size_t BASIC_SYS_COMP_FOOTER_SIZE = 2; +constexpr size_t BASIC_SYS_COMP_OVERHEAD = BASIC_SYS_COMP_HEADER_SIZE + BASIC_SYS_COMP_FOOTER_SIZE; +constexpr size_t BASIC_SYS_COMP_LENGTH_BYTES = 1; + +/** + * BasicSysComp Encode Buffer + */ +class BasicSysCompEncodeBuffer { +public: + BasicSysCompEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = BASIC_SYS_COMP_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = BASIC_SYS_COMP_START_BYTE1; + packet_start[1] = BASIC_SYS_COMP_START_BYTE2; + packet_start[2] = msg_id; + packet_start[3] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + BASIC_SYS_COMP_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 2, msg_size + 1 + 1); + packet_start[BASIC_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[BASIC_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * BasicSysComp Frame Parser + */ +class BasicSysCompParser { +public: + using MsgLengthCallback = std::function; + + BasicSysCompParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(BasicSysCompParserState::LookingForStart1), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = BasicSysCompParserState::LookingForStart1; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case BasicSysCompParserState::LookingForStart1: + if (byte == BASIC_SYS_COMP_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicSysCompParserState::LookingForStart2; + } + break; + + case BasicSysCompParserState::LookingForStart2: + if (byte == BASIC_SYS_COMP_START_BYTE2) { + buffer_[1] = byte; + buffer_index_ = 2; + state_ = BasicSysCompParserState::GettingMsgId; + } else if (byte == BASIC_SYS_COMP_START_BYTE1) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = BasicSysCompParserState::LookingForStart2; + } else { + state_ = BasicSysCompParserState::LookingForStart1; + } + break; + + case BasicSysCompParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = BasicSysCompParserState::GettingLength; + break; + } + + case BasicSysCompParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = BASIC_SYS_COMP_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = BasicSysCompParserState::GettingPayload; + } else { + state_ = BasicSysCompParserState::LookingForStart1; + } + break; + + case BasicSysCompParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - BASIC_SYS_COMP_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 2, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + BASIC_SYS_COMP_HEADER_SIZE; + } + state_ = BasicSysCompParserState::LookingForStart1; + } + break; + } + + return result; + } + +private: + BasicSysCompParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with BasicSysComp format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t basic_sys_comp_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = BASIC_SYS_COMP_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = BASIC_SYS_COMP_START_BYTE1; + buffer[1] = BASIC_SYS_COMP_START_BYTE2; + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + BASIC_SYS_COMP_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_size + 1 + 1); + buffer[BASIC_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + buffer[BASIC_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete BasicSysComp packet in a buffer + */ +inline FrameMsgInfo basic_sys_comp_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < BASIC_SYS_COMP_OVERHEAD) return result; + + if (buffer[0] != BASIC_SYS_COMP_START_BYTE1) return result; + if (buffer[1] != BASIC_SYS_COMP_START_BYTE2) return result; + + size_t msg_length = length - BASIC_SYS_COMP_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + BASIC_SYS_COMP_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp b/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp index e56d684b..909757db 100644 --- a/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp +++ b/src/struct_frame/boilerplate/cpp/FrameFormatConfig.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -20,7 +20,7 @@ enum class FrameFormatConfigParserState : uint8_t { // FrameFormatConfig constants constexpr uint8_t FRAME_FORMAT_CONFIG_START_BYTE1 = 0x90; -constexpr uint8_t FRAME_FORMAT_CONFIG_START_BYTE2 = 0x91; +constexpr uint8_t FRAME_FORMAT_CONFIG_START_BYTE2 = 0x71; constexpr size_t FRAME_FORMAT_CONFIG_HEADER_SIZE = 2; constexpr size_t FRAME_FORMAT_CONFIG_FOOTER_SIZE = 1; constexpr size_t FRAME_FORMAT_CONFIG_OVERHEAD = FRAME_FORMAT_CONFIG_HEADER_SIZE + FRAME_FORMAT_CONFIG_FOOTER_SIZE; diff --git a/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp b/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp index de7146da..72e0c354 100644 --- a/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp +++ b/src/struct_frame/boilerplate/cpp/MavlinkV1Frame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -20,7 +20,7 @@ enum class MavlinkV1FrameParserState : uint8_t { // MavlinkV1Frame constants constexpr uint8_t MAVLINK_V1_FRAME_START_BYTE = 0xFE; -constexpr size_t MAVLINK_V1_FRAME_HEADER_SIZE = 3; +constexpr size_t MAVLINK_V1_FRAME_HEADER_SIZE = 6; constexpr size_t MAVLINK_V1_FRAME_FOOTER_SIZE = 2; constexpr size_t MAVLINK_V1_FRAME_OVERHEAD = MAVLINK_V1_FRAME_HEADER_SIZE + MAVLINK_V1_FRAME_FOOTER_SIZE; constexpr size_t MAVLINK_V1_FRAME_LENGTH_BYTES = 1; @@ -187,8 +187,8 @@ inline size_t mavlink_v1_frame_encode(uint8_t* buffer, size_t buffer_size, if (buffer_size < total_size) return 0; buffer[0] = MAVLINK_V1_FRAME_START_BYTE; - buffer[1] = msg_id; - buffer[2] = static_cast(msg_size); + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; if (msg_size > 0 && msg != nullptr) { std::memcpy(buffer + MAVLINK_V1_FRAME_HEADER_SIZE, msg, msg_size); @@ -216,7 +216,7 @@ inline FrameMsgInfo mavlink_v1_frame_validate_packet(const uint8_t* buffer, size FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[2]; result.msg_len = msg_length; result.msg_data = const_cast(buffer + MAVLINK_V1_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp b/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp index 0e2c7ff4..204d0076 100644 --- a/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp +++ b/src/struct_frame/boilerplate/cpp/MavlinkV2Frame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -20,7 +20,7 @@ enum class MavlinkV2FrameParserState : uint8_t { // MavlinkV2Frame constants constexpr uint8_t MAVLINK_V2_FRAME_START_BYTE = 0xFD; -constexpr size_t MAVLINK_V2_FRAME_HEADER_SIZE = 5; +constexpr size_t MAVLINK_V2_FRAME_HEADER_SIZE = 8; constexpr size_t MAVLINK_V2_FRAME_FOOTER_SIZE = 2; constexpr size_t MAVLINK_V2_FRAME_OVERHEAD = MAVLINK_V2_FRAME_HEADER_SIZE + MAVLINK_V2_FRAME_FOOTER_SIZE; constexpr size_t MAVLINK_V2_FRAME_LENGTH_BYTES = 1; @@ -187,8 +187,8 @@ inline size_t mavlink_v2_frame_encode(uint8_t* buffer, size_t buffer_size, if (buffer_size < total_size) return 0; buffer[0] = MAVLINK_V2_FRAME_START_BYTE; - buffer[1] = msg_id; - buffer[2] = static_cast(msg_size); + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; if (msg_size > 0 && msg != nullptr) { std::memcpy(buffer + MAVLINK_V2_FRAME_HEADER_SIZE, msg, msg_size); @@ -216,7 +216,7 @@ inline FrameMsgInfo mavlink_v2_frame_validate_packet(const uint8_t* buffer, size FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[1]; + result.msg_id = buffer[2]; result.msg_len = msg_length; result.msg_data = const_cast(buffer + MAVLINK_V2_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/cpp/TinyDefault.hpp b/src/struct_frame/boilerplate/cpp/TinyDefault.hpp new file mode 100644 index 00000000..eb2ecb06 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyDefault.hpp @@ -0,0 +1,227 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyDefault Frame Format +// ============================================================================= + +enum class TinyDefaultParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyDefault constants +constexpr uint8_t TINY_DEFAULT_START_BYTE = 0x71; +constexpr size_t TINY_DEFAULT_HEADER_SIZE = 3; +constexpr size_t TINY_DEFAULT_FOOTER_SIZE = 2; +constexpr size_t TINY_DEFAULT_OVERHEAD = TINY_DEFAULT_HEADER_SIZE + TINY_DEFAULT_FOOTER_SIZE; +constexpr size_t TINY_DEFAULT_LENGTH_BYTES = 1; + +/** + * TinyDefault Encode Buffer + */ +class TinyDefaultEncodeBuffer { +public: + TinyDefaultEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_DEFAULT_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_DEFAULT_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 1); + packet_start[TINY_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyDefault Frame Parser + */ +class TinyDefaultParser { +public: + using MsgLengthCallback = std::function; + + TinyDefaultParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyDefaultParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyDefaultParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyDefaultParserState::LookingForStart: + if (byte == TINY_DEFAULT_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyDefaultParserState::GettingMsgId; + } + break; + + case TinyDefaultParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyDefaultParserState::GettingLength; + break; + } + + case TinyDefaultParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = TINY_DEFAULT_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyDefaultParserState::GettingPayload; + } else { + state_ = TinyDefaultParserState::LookingForStart; + } + break; + + case TinyDefaultParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_DEFAULT_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_DEFAULT_HEADER_SIZE; + } + state_ = TinyDefaultParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyDefaultParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyDefault format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_default_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_DEFAULT_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_DEFAULT_START_BYTE; + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_DEFAULT_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_DEFAULT_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_DEFAULT_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyDefault packet in a buffer + */ +inline FrameMsgInfo tiny_default_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_DEFAULT_OVERHEAD) return result; + + if (buffer[0] != TINY_DEFAULT_START_BYTE) return result; + + size_t msg_length = length - TINY_DEFAULT_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_DEFAULT_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyExtended.hpp b/src/struct_frame/boilerplate/cpp/TinyExtended.hpp new file mode 100644 index 00000000..91db333c --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyExtended.hpp @@ -0,0 +1,235 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyExtended Frame Format +// ============================================================================= + +enum class TinyExtendedParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyExtended constants +constexpr uint8_t TINY_EXTENDED_START_BYTE = 0x74; +constexpr size_t TINY_EXTENDED_HEADER_SIZE = 5; +constexpr size_t TINY_EXTENDED_FOOTER_SIZE = 2; +constexpr size_t TINY_EXTENDED_OVERHEAD = TINY_EXTENDED_HEADER_SIZE + TINY_EXTENDED_FOOTER_SIZE; +constexpr size_t TINY_EXTENDED_LENGTH_BYTES = 2; + +/** + * TinyExtended Encode Buffer + */ +class TinyExtendedEncodeBuffer { +public: + TinyExtendedEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_EXTENDED_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_EXTENDED_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size & 0xFF); + packet_start[3] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 2); + packet_start[TINY_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyExtended Frame Parser + */ +class TinyExtendedParser { +public: + using MsgLengthCallback = std::function; + + TinyExtendedParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyExtendedParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyExtendedParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyExtendedParserState::LookingForStart: + if (byte == TINY_EXTENDED_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyExtendedParserState::GettingMsgId; + } + break; + + case TinyExtendedParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyExtendedParserState::GettingLength; + break; + } + + case TinyExtendedParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 3) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = TINY_EXTENDED_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyExtendedParserState::GettingPayload; + } else { + state_ = TinyExtendedParserState::LookingForStart; + } + } + break; + + case TinyExtendedParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_EXTENDED_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_EXTENDED_HEADER_SIZE; + } + state_ = TinyExtendedParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyExtendedParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyExtended format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_extended_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_EXTENDED_START_BYTE; + buffer[1] = static_cast(msg_size & 0xFF); + buffer[2] = static_cast((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_EXTENDED_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 2); + buffer[TINY_EXTENDED_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtended packet in a buffer + */ +inline FrameMsgInfo tiny_extended_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_EXTENDED_OVERHEAD) return result; + + if (buffer[0] != TINY_EXTENDED_START_BYTE) return result; + + size_t msg_length = length - TINY_EXTENDED_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_EXTENDED_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp new file mode 100644 index 00000000..83fefcd0 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedLength.hpp @@ -0,0 +1,235 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyExtendedLength Frame Format +// ============================================================================= + +enum class TinyExtendedLengthParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyExtendedLength constants +constexpr uint8_t TINY_EXTENDED_LENGTH_START_BYTE = 0x73; +constexpr size_t TINY_EXTENDED_LENGTH_HEADER_SIZE = 4; +constexpr size_t TINY_EXTENDED_LENGTH_FOOTER_SIZE = 2; +constexpr size_t TINY_EXTENDED_LENGTH_OVERHEAD = TINY_EXTENDED_LENGTH_HEADER_SIZE + TINY_EXTENDED_LENGTH_FOOTER_SIZE; +constexpr size_t TINY_EXTENDED_LENGTH_LENGTH_BYTES = 2; + +/** + * TinyExtendedLength Encode Buffer + */ +class TinyExtendedLengthEncodeBuffer { +public: + TinyExtendedLengthEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_EXTENDED_LENGTH_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_EXTENDED_LENGTH_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size & 0xFF); + packet_start[3] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 2); + packet_start[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyExtendedLength Frame Parser + */ +class TinyExtendedLengthParser { +public: + using MsgLengthCallback = std::function; + + TinyExtendedLengthParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyExtendedLengthParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyExtendedLengthParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyExtendedLengthParserState::LookingForStart: + if (byte == TINY_EXTENDED_LENGTH_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyExtendedLengthParserState::GettingMsgId; + } + break; + + case TinyExtendedLengthParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyExtendedLengthParserState::GettingLength; + break; + } + + case TinyExtendedLengthParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 3) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = TINY_EXTENDED_LENGTH_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyExtendedLengthParserState::GettingPayload; + } else { + state_ = TinyExtendedLengthParserState::LookingForStart; + } + } + break; + + case TinyExtendedLengthParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_EXTENDED_LENGTH_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_EXTENDED_LENGTH_HEADER_SIZE; + } + state_ = TinyExtendedLengthParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyExtendedLengthParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyExtendedLength format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_extended_length_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_LENGTH_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_EXTENDED_LENGTH_START_BYTE; + buffer[1] = static_cast(msg_size & 0xFF); + buffer[2] = static_cast((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_EXTENDED_LENGTH_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 2); + buffer[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_LENGTH_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtendedLength packet in a buffer + */ +inline FrameMsgInfo tiny_extended_length_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_EXTENDED_LENGTH_OVERHEAD) return result; + + if (buffer[0] != TINY_EXTENDED_LENGTH_START_BYTE) return result; + + size_t msg_length = length - TINY_EXTENDED_LENGTH_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_EXTENDED_LENGTH_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp new file mode 100644 index 00000000..a41477dd --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedMsgIds.hpp @@ -0,0 +1,227 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyExtendedMsgIds Frame Format +// ============================================================================= + +enum class TinyExtendedMsgIdsParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyExtendedMsgIds constants +constexpr uint8_t TINY_EXTENDED_MSG_IDS_START_BYTE = 0x72; +constexpr size_t TINY_EXTENDED_MSG_IDS_HEADER_SIZE = 4; +constexpr size_t TINY_EXTENDED_MSG_IDS_FOOTER_SIZE = 2; +constexpr size_t TINY_EXTENDED_MSG_IDS_OVERHEAD = TINY_EXTENDED_MSG_IDS_HEADER_SIZE + TINY_EXTENDED_MSG_IDS_FOOTER_SIZE; +constexpr size_t TINY_EXTENDED_MSG_IDS_LENGTH_BYTES = 1; + +/** + * TinyExtendedMsgIds Encode Buffer + */ +class TinyExtendedMsgIdsEncodeBuffer { +public: + TinyExtendedMsgIdsEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_EXTENDED_MSG_IDS_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 1); + packet_start[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyExtendedMsgIds Frame Parser + */ +class TinyExtendedMsgIdsParser { +public: + using MsgLengthCallback = std::function; + + TinyExtendedMsgIdsParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyExtendedMsgIdsParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyExtendedMsgIdsParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyExtendedMsgIdsParserState::LookingForStart: + if (byte == TINY_EXTENDED_MSG_IDS_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyExtendedMsgIdsParserState::GettingMsgId; + } + break; + + case TinyExtendedMsgIdsParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyExtendedMsgIdsParserState::GettingLength; + break; + } + + case TinyExtendedMsgIdsParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = TINY_EXTENDED_MSG_IDS_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyExtendedMsgIdsParserState::GettingPayload; + } else { + state_ = TinyExtendedMsgIdsParserState::LookingForStart; + } + break; + + case TinyExtendedMsgIdsParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_EXTENDED_MSG_IDS_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_EXTENDED_MSG_IDS_HEADER_SIZE; + } + state_ = TinyExtendedMsgIdsParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyExtendedMsgIdsParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyExtendedMsgIds format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_extended_msg_ids_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_MSG_IDS_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_EXTENDED_MSG_IDS_START_BYTE; + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_EXTENDED_MSG_IDS_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_MSG_IDS_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtendedMsgIds packet in a buffer + */ +inline FrameMsgInfo tiny_extended_msg_ids_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_EXTENDED_MSG_IDS_OVERHEAD) return result; + + if (buffer[0] != TINY_EXTENDED_MSG_IDS_START_BYTE) return result; + + size_t msg_length = length - TINY_EXTENDED_MSG_IDS_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_EXTENDED_MSG_IDS_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp new file mode 100644 index 00000000..8c31e4e9 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyExtendedMultiSystemStream.hpp @@ -0,0 +1,235 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyExtendedMultiSystemStream Frame Format +// ============================================================================= + +enum class TinyExtendedMultiSystemStreamParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyExtendedMultiSystemStream constants +constexpr uint8_t TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE = 0x78; +constexpr size_t TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE = 8; +constexpr size_t TINY_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE = 2; +constexpr size_t TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD = TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + TINY_EXTENDED_MULTI_SYSTEM_STREAM_FOOTER_SIZE; +constexpr size_t TINY_EXTENDED_MULTI_SYSTEM_STREAM_LENGTH_BYTES = 2; + +/** + * TinyExtendedMultiSystemStream Encode Buffer + */ +class TinyExtendedMultiSystemStreamEncodeBuffer { +public: + TinyExtendedMultiSystemStreamEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size & 0xFF); + packet_start[3] = static_cast((msg_size >> 8) & 0xFF); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 2); + packet_start[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyExtendedMultiSystemStream Frame Parser + */ +class TinyExtendedMultiSystemStreamParser { +public: + using MsgLengthCallback = std::function; + + TinyExtendedMultiSystemStreamParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyExtendedMultiSystemStreamParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + length_lo_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyExtendedMultiSystemStreamParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyExtendedMultiSystemStreamParserState::LookingForStart: + if (byte == TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyExtendedMultiSystemStreamParserState::GettingMsgId; + } + break; + + case TinyExtendedMultiSystemStreamParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyExtendedMultiSystemStreamParserState::GettingLength; + break; + } + + case TinyExtendedMultiSystemStreamParserState::GettingLength: + buffer_[buffer_index_++] = byte; + if (buffer_index_ == 3) { + length_lo_ = byte; + } else { + msg_length_ = length_lo_ | (static_cast(byte) << 8); + packet_size_ = TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyExtendedMultiSystemStreamParserState::GettingPayload; + } else { + state_ = TinyExtendedMultiSystemStreamParserState::LookingForStart; + } + } + break; + + case TinyExtendedMultiSystemStreamParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 2); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + state_ = TinyExtendedMultiSystemStreamParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyExtendedMultiSystemStreamParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + uint8_t length_lo_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyExtendedMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_extended_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE; + buffer[1] = static_cast(msg_size & 0xFF); + buffer[2] = static_cast((msg_size >> 8) & 0xFF); + buffer[3] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 2); + buffer[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyExtendedMultiSystemStream packet in a buffer + */ +inline FrameMsgInfo tiny_extended_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD) return result; + + if (buffer[0] != TINY_EXTENDED_MULTI_SYSTEM_STREAM_START_BYTE) return result; + + size_t msg_length = length - TINY_EXTENDED_MULTI_SYSTEM_STREAM_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 2); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[3]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_EXTENDED_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp b/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp new file mode 100644 index 00000000..c3eb8164 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyMinimal.hpp @@ -0,0 +1,202 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyMinimal Frame Format +// ============================================================================= + +enum class TinyMinimalParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingPayload = 2 +}; + +// TinyMinimal constants +constexpr uint8_t TINY_MINIMAL_START_BYTE = 0x70; +constexpr size_t TINY_MINIMAL_HEADER_SIZE = 2; +constexpr size_t TINY_MINIMAL_FOOTER_SIZE = 0; +constexpr size_t TINY_MINIMAL_OVERHEAD = TINY_MINIMAL_HEADER_SIZE + TINY_MINIMAL_FOOTER_SIZE; + +/** + * TinyMinimal Encode Buffer + */ +class TinyMinimalEncodeBuffer { +public: + TinyMinimalEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_MINIMAL_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_MINIMAL_START_BYTE; + packet_start[1] = msg_id; + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyMinimal Frame Parser + */ +class TinyMinimalParser { +public: + using MsgLengthCallback = std::function; + + TinyMinimalParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyMinimalParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyMinimalParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyMinimalParserState::LookingForStart: + if (byte == TINY_MINIMAL_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyMinimalParserState::GettingMsgId; + } + break; + + case TinyMinimalParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + size_t msg_length = 0; + if (get_msg_length_ && get_msg_length_(byte, &msg_length)) { + packet_size_ = TINY_MINIMAL_OVERHEAD + msg_length; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyMinimalParserState::GettingPayload; + } else { + state_ = TinyMinimalParserState::LookingForStart; + } + } else { + state_ = TinyMinimalParserState::LookingForStart; + } + break; + } + + case TinyMinimalParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = packet_size_ - TINY_MINIMAL_OVERHEAD; + result.msg_data = buffer_ + TINY_MINIMAL_HEADER_SIZE; + state_ = TinyMinimalParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyMinimalParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyMinimal format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_minimal_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_MINIMAL_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_MINIMAL_START_BYTE; + buffer[1] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_MINIMAL_HEADER_SIZE, msg, msg_size); + } + + + return total_size; +} + +/** + * Validate a complete TinyMinimal packet in a buffer + */ +inline FrameMsgInfo tiny_minimal_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_MINIMAL_OVERHEAD) return result; + + if (buffer[0] != TINY_MINIMAL_START_BYTE) return result; + + size_t msg_length = length - TINY_MINIMAL_OVERHEAD; + + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_MINIMAL_HEADER_SIZE); + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp b/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp new file mode 100644 index 00000000..7a39970e --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinyMultiSystemStream.hpp @@ -0,0 +1,227 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinyMultiSystemStream Frame Format +// ============================================================================= + +enum class TinyMultiSystemStreamParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinyMultiSystemStream constants +constexpr uint8_t TINY_MULTI_SYSTEM_STREAM_START_BYTE = 0x77; +constexpr size_t TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE = 6; +constexpr size_t TINY_MULTI_SYSTEM_STREAM_FOOTER_SIZE = 2; +constexpr size_t TINY_MULTI_SYSTEM_STREAM_OVERHEAD = TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + TINY_MULTI_SYSTEM_STREAM_FOOTER_SIZE; +constexpr size_t TINY_MULTI_SYSTEM_STREAM_LENGTH_BYTES = 1; + +/** + * TinyMultiSystemStream Encode Buffer + */ +class TinyMultiSystemStreamEncodeBuffer { +public: + TinyMultiSystemStreamEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_MULTI_SYSTEM_STREAM_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 1); + packet_start[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinyMultiSystemStream Frame Parser + */ +class TinyMultiSystemStreamParser { +public: + using MsgLengthCallback = std::function; + + TinyMultiSystemStreamParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinyMultiSystemStreamParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinyMultiSystemStreamParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinyMultiSystemStreamParserState::LookingForStart: + if (byte == TINY_MULTI_SYSTEM_STREAM_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinyMultiSystemStreamParserState::GettingMsgId; + } + break; + + case TinyMultiSystemStreamParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinyMultiSystemStreamParserState::GettingLength; + break; + } + + case TinyMultiSystemStreamParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = TINY_MULTI_SYSTEM_STREAM_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinyMultiSystemStreamParserState::GettingPayload; + } else { + state_ = TinyMultiSystemStreamParserState::LookingForStart; + } + break; + + case TinyMultiSystemStreamParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_MULTI_SYSTEM_STREAM_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE; + } + state_ = TinyMultiSystemStreamParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinyMultiSystemStreamParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinyMultiSystemStream format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_multi_system_stream_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_MULTI_SYSTEM_STREAM_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_MULTI_SYSTEM_STREAM_START_BYTE; + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinyMultiSystemStream packet in a buffer + */ +inline FrameMsgInfo tiny_multi_system_stream_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_MULTI_SYSTEM_STREAM_OVERHEAD) return result; + + if (buffer[0] != TINY_MULTI_SYSTEM_STREAM_START_BYTE) return result; + + size_t msg_length = length - TINY_MULTI_SYSTEM_STREAM_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_MULTI_SYSTEM_STREAM_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinySeq.hpp b/src/struct_frame/boilerplate/cpp/TinySeq.hpp new file mode 100644 index 00000000..a5b9eed8 --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinySeq.hpp @@ -0,0 +1,227 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinySeq Frame Format +// ============================================================================= + +enum class TinySeqParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinySeq constants +constexpr uint8_t TINY_SEQ_START_BYTE = 0x76; +constexpr size_t TINY_SEQ_HEADER_SIZE = 4; +constexpr size_t TINY_SEQ_FOOTER_SIZE = 2; +constexpr size_t TINY_SEQ_OVERHEAD = TINY_SEQ_HEADER_SIZE + TINY_SEQ_FOOTER_SIZE; +constexpr size_t TINY_SEQ_LENGTH_BYTES = 1; + +/** + * TinySeq Encode Buffer + */ +class TinySeqEncodeBuffer { +public: + TinySeqEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_SEQ_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_SEQ_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_SEQ_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 1); + packet_start[TINY_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinySeq Frame Parser + */ +class TinySeqParser { +public: + using MsgLengthCallback = std::function; + + TinySeqParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinySeqParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinySeqParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinySeqParserState::LookingForStart: + if (byte == TINY_SEQ_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinySeqParserState::GettingMsgId; + } + break; + + case TinySeqParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinySeqParserState::GettingLength; + break; + } + + case TinySeqParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = TINY_SEQ_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinySeqParserState::GettingPayload; + } else { + state_ = TinySeqParserState::LookingForStart; + } + break; + + case TinySeqParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_SEQ_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_SEQ_HEADER_SIZE; + } + state_ = TinySeqParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinySeqParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinySeq format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_seq_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_SEQ_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_SEQ_START_BYTE; + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_SEQ_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_SEQ_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_SEQ_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinySeq packet in a buffer + */ +inline FrameMsgInfo tiny_seq_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_SEQ_OVERHEAD) return result; + + if (buffer[0] != TINY_SEQ_START_BYTE) return result; + + size_t msg_length = length - TINY_SEQ_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_SEQ_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/TinySysComp.hpp b/src/struct_frame/boilerplate/cpp/TinySysComp.hpp new file mode 100644 index 00000000..903b94dc --- /dev/null +++ b/src/struct_frame/boilerplate/cpp/TinySysComp.hpp @@ -0,0 +1,227 @@ +/* Automatically generated frame parser */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ + +#pragma once + +#include "frame_base.hpp" + +namespace FrameParsers { + +// ============================================================================= +// TinySysComp Frame Format +// ============================================================================= + +enum class TinySysCompParserState : uint8_t { + LookingForStart = 0, + GettingMsgId = 1, + GettingLength = 2, + GettingPayload = 3 +}; + +// TinySysComp constants +constexpr uint8_t TINY_SYS_COMP_START_BYTE = 0x75; +constexpr size_t TINY_SYS_COMP_HEADER_SIZE = 5; +constexpr size_t TINY_SYS_COMP_FOOTER_SIZE = 2; +constexpr size_t TINY_SYS_COMP_OVERHEAD = TINY_SYS_COMP_HEADER_SIZE + TINY_SYS_COMP_FOOTER_SIZE; +constexpr size_t TINY_SYS_COMP_LENGTH_BYTES = 1; + +/** + * TinySysComp Encode Buffer + */ +class TinySysCompEncodeBuffer { +public: + TinySysCompEncodeBuffer(uint8_t* data, size_t max_size) + : data_(data), max_size_(max_size), size_(0), in_progress_(false) {} + + void reset() { + size_ = 0; + in_progress_ = false; + } + + uint8_t* data() { return data_; } + const uint8_t* data() const { return data_; } + size_t size() const { return size_; } + size_t max_size() const { return max_size_; } + bool in_progress() const { return in_progress_; } + + /** + * Encode a message into the buffer + */ + bool encode(uint8_t msg_id, const void* msg, size_t msg_size) { + if (in_progress_) return false; + + size_t total_size = TINY_SYS_COMP_OVERHEAD + msg_size; + if (size_ + total_size > max_size_) return false; + + uint8_t* packet_start = data_ + size_; + + // Write header + packet_start[0] = TINY_SYS_COMP_START_BYTE; + packet_start[1] = msg_id; + packet_start[2] = static_cast(msg_size); + + // Write message data + if (msg_size > 0 && msg != nullptr) { + std::memcpy(packet_start + TINY_SYS_COMP_HEADER_SIZE, msg, msg_size); + } + + // Calculate checksum + FrameChecksum ck = fletcher_checksum(packet_start + 1, msg_size + 1 + 1); + packet_start[TINY_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + packet_start[TINY_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; + + size_ += total_size; + return true; + } + +private: + uint8_t* data_; + size_t max_size_; + size_t size_; + bool in_progress_; +}; + +/** + * TinySysComp Frame Parser + */ +class TinySysCompParser { +public: + using MsgLengthCallback = std::function; + + TinySysCompParser(uint8_t* buffer, size_t buffer_size, MsgLengthCallback msg_length_cb = nullptr) + : state_(TinySysCompParserState::LookingForStart), + buffer_(buffer), + buffer_max_size_(buffer_size), + buffer_index_(0), + packet_size_(0), + msg_id_(0), + msg_length_(0), + get_msg_length_(std::move(msg_length_cb)) {} + + void reset() { + state_ = TinySysCompParserState::LookingForStart; + buffer_index_ = 0; + packet_size_ = 0; + msg_id_ = 0; + msg_length_ = 0; + } + + /** + * Parse a single byte + * Returns FrameMsgInfo with valid=true when a complete valid message is received + */ + FrameMsgInfo parse_byte(uint8_t byte) { + FrameMsgInfo result; + + switch (state_) { + case TinySysCompParserState::LookingForStart: + if (byte == TINY_SYS_COMP_START_BYTE) { + buffer_[0] = byte; + buffer_index_ = 1; + state_ = TinySysCompParserState::GettingMsgId; + } + break; + + case TinySysCompParserState::GettingMsgId: { + buffer_[buffer_index_++] = byte; + msg_id_ = byte; + + state_ = TinySysCompParserState::GettingLength; + break; + } + + case TinySysCompParserState::GettingLength: + buffer_[buffer_index_++] = byte; + msg_length_ = byte; + packet_size_ = TINY_SYS_COMP_OVERHEAD + msg_length_; + if (packet_size_ <= buffer_max_size_) { + state_ = TinySysCompParserState::GettingPayload; + } else { + state_ = TinySysCompParserState::LookingForStart; + } + break; + + case TinySysCompParserState::GettingPayload: + if (buffer_index_ < buffer_max_size_) { + buffer_[buffer_index_++] = byte; + } + + if (buffer_index_ >= packet_size_) { + // Validate checksum + size_t msg_length = packet_size_ - TINY_SYS_COMP_OVERHEAD; + FrameChecksum ck = fletcher_checksum(buffer_ + 1, msg_length + 1 + 1); + + if (ck.byte1 == buffer_[packet_size_ - 2] && + ck.byte2 == buffer_[packet_size_ - 1]) { + result.valid = true; + result.msg_id = msg_id_; + result.msg_len = msg_length; + result.msg_data = buffer_ + TINY_SYS_COMP_HEADER_SIZE; + } + state_ = TinySysCompParserState::LookingForStart; + } + break; + } + + return result; + } + +private: + TinySysCompParserState state_; + uint8_t* buffer_; + size_t buffer_max_size_; + size_t buffer_index_; + size_t packet_size_; + uint8_t msg_id_; + size_t msg_length_; + MsgLengthCallback get_msg_length_; +}; + +/** + * Encode a message with TinySysComp format + * Returns the number of bytes written, or 0 on failure + */ +inline size_t tiny_sys_comp_encode(uint8_t* buffer, size_t buffer_size, + uint8_t msg_id, const uint8_t* msg, size_t msg_size) { + size_t total_size = TINY_SYS_COMP_OVERHEAD + msg_size; + if (buffer_size < total_size) return 0; + + buffer[0] = TINY_SYS_COMP_START_BYTE; + buffer[1] = static_cast(msg_size); + buffer[2] = msg_id; + + if (msg_size > 0 && msg != nullptr) { + std::memcpy(buffer + TINY_SYS_COMP_HEADER_SIZE, msg, msg_size); + } + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_size + 1 + 1); + buffer[TINY_SYS_COMP_HEADER_SIZE + msg_size] = ck.byte1; + buffer[TINY_SYS_COMP_HEADER_SIZE + msg_size + 1] = ck.byte2; + + return total_size; +} + +/** + * Validate a complete TinySysComp packet in a buffer + */ +inline FrameMsgInfo tiny_sys_comp_validate_packet(const uint8_t* buffer, size_t length) { + FrameMsgInfo result; + + if (length < TINY_SYS_COMP_OVERHEAD) return result; + + if (buffer[0] != TINY_SYS_COMP_START_BYTE) return result; + + size_t msg_length = length - TINY_SYS_COMP_OVERHEAD; + + FrameChecksum ck = fletcher_checksum(buffer + 1, msg_length + 1 + 1); + if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = const_cast(buffer + TINY_SYS_COMP_HEADER_SIZE); + } + + return result; +} + +} // namespace FrameParsers diff --git a/src/struct_frame/boilerplate/cpp/UbxFrame.hpp b/src/struct_frame/boilerplate/cpp/UbxFrame.hpp index 83bbf9bc..78887236 100644 --- a/src/struct_frame/boilerplate/cpp/UbxFrame.hpp +++ b/src/struct_frame/boilerplate/cpp/UbxFrame.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -205,8 +205,8 @@ inline size_t ubx_frame_encode(uint8_t* buffer, size_t buffer_size, buffer[0] = UBX_FRAME_START_BYTE1; buffer[1] = UBX_FRAME_START_BYTE2; - buffer[2] = msg_id; - buffer[3] = static_cast(msg_size); + buffer[2] = static_cast(msg_size); + buffer[3] = msg_id; if (msg_size > 0 && msg != nullptr) { std::memcpy(buffer + UBX_FRAME_HEADER_SIZE, msg, msg_size); @@ -235,7 +235,7 @@ inline FrameMsgInfo ubx_frame_validate_packet(const uint8_t* buffer, size_t leng FrameChecksum ck = fletcher_checksum(buffer + 2, msg_length + 1 + 1); if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) { result.valid = true; - result.msg_id = buffer[2]; + result.msg_id = buffer[3]; result.msg_len = msg_length; result.msg_data = const_cast(buffer + UBX_FRAME_HEADER_SIZE); } diff --git a/src/struct_frame/boilerplate/cpp/frame_base.hpp b/src/struct_frame/boilerplate/cpp/frame_base.hpp index 27221c56..a7897130 100644 --- a/src/struct_frame/boilerplate/cpp/frame_base.hpp +++ b/src/struct_frame/boilerplate/cpp/frame_base.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser base utilities */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -12,24 +12,24 @@ namespace FrameParsers { // Frame format type enumeration enum class FrameFormatType { - MINIMAL_FRAME = 0, - BASIC_FRAME = 1, - BASIC_FRAME_NO_CRC = 2, - TINY_FRAME = 3, - TINY_FRAME_NO_CRC = 4, - MINIMAL_FRAME_WITH_LEN = 5, - MINIMAL_FRAME_WITH_LEN_NO_CRC = 6, - BASIC_FRAME_WITH_LEN = 7, - BASIC_FRAME_WITH_LEN_NO_CRC = 8, - TINY_FRAME_WITH_LEN = 9, - TINY_FRAME_WITH_LEN_NO_CRC = 10, - MINIMAL_FRAME_WITH_LEN16 = 11, - MINIMAL_FRAME_WITH_LEN16_NO_CRC = 12, - BASIC_FRAME_WITH_LEN16 = 13, - BASIC_FRAME_WITH_LEN16_NO_CRC = 14, - TINY_FRAME_WITH_LEN16 = 15, - TINY_FRAME_WITH_LEN16_NO_CRC = 16, - BASIC_FRAME_WITH_SYS_COMP = 17, + TINY_MINIMAL = 0, + TINY_DEFAULT = 1, + TINY_EXTENDED_MSG_IDS = 2, + TINY_EXTENDED_LENGTH = 3, + TINY_EXTENDED = 4, + TINY_SYS_COMP = 5, + TINY_SEQ = 6, + TINY_MULTI_SYSTEM_STREAM = 7, + TINY_EXTENDED_MULTI_SYSTEM_STREAM = 8, + BASIC_MINIMAL = 9, + BASIC_DEFAULT = 10, + BASIC_EXTENDED_MSG_IDS = 11, + BASIC_EXTENDED_LENGTH = 12, + BASIC_EXTENDED = 13, + BASIC_SYS_COMP = 14, + BASIC_SEQ = 15, + BASIC_MULTI_SYSTEM_STREAM = 16, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 17, UBX_FRAME = 18, MAVLINK_V1_FRAME = 19, MAVLINK_V2_FRAME = 20, diff --git a/src/struct_frame/boilerplate/cpp/frame_parsers.hpp b/src/struct_frame/boilerplate/cpp/frame_parsers.hpp index cd9f1b1e..186bfafa 100644 --- a/src/struct_frame/boilerplate/cpp/frame_parsers.hpp +++ b/src/struct_frame/boilerplate/cpp/frame_parsers.hpp @@ -1,5 +1,5 @@ /* Automatically generated frame parser main header */ -/* Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. */ +/* Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. */ #pragma once @@ -7,24 +7,24 @@ #include "frame_base.hpp" /* Individual frame format parsers */ -#include "MinimalFrame.hpp" -#include "BasicFrame.hpp" -#include "BasicFrameNoCrc.hpp" -#include "TinyFrame.hpp" -#include "TinyFrameNoCrc.hpp" -#include "MinimalFrameWithLen.hpp" -#include "MinimalFrameWithLenNoCrc.hpp" -#include "BasicFrameWithLen.hpp" -#include "BasicFrameWithLenNoCrc.hpp" -#include "TinyFrameWithLen.hpp" -#include "TinyFrameWithLenNoCrc.hpp" -#include "MinimalFrameWithLen16.hpp" -#include "MinimalFrameWithLen16NoCrc.hpp" -#include "BasicFrameWithLen16.hpp" -#include "BasicFrameWithLen16NoCrc.hpp" -#include "TinyFrameWithLen16.hpp" -#include "TinyFrameWithLen16NoCrc.hpp" -#include "BasicFrameWithSysComp.hpp" +#include "TinyMinimal.hpp" +#include "TinyDefault.hpp" +#include "TinyExtendedMsgIds.hpp" +#include "TinyExtendedLength.hpp" +#include "TinyExtended.hpp" +#include "TinySysComp.hpp" +#include "TinySeq.hpp" +#include "TinyMultiSystemStream.hpp" +#include "TinyExtendedMultiSystemStream.hpp" +#include "BasicMinimal.hpp" +#include "BasicDefault.hpp" +#include "BasicExtendedMsgIds.hpp" +#include "BasicExtendedLength.hpp" +#include "BasicExtended.hpp" +#include "BasicSysComp.hpp" +#include "BasicSeq.hpp" +#include "BasicMultiSystemStream.hpp" +#include "BasicExtendedMultiSystemStream.hpp" #include "UbxFrame.hpp" #include "MavlinkV1Frame.hpp" #include "MavlinkV2Frame.hpp" diff --git a/src/struct_frame/boilerplate/js/BasicDefault.js b/src/struct_frame/boilerplate/js/BasicDefault.js new file mode 100644 index 00000000..e5f9517d --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicDefault.js @@ -0,0 +1,148 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicDefault Frame Format +// ============================================================================= + +const BasicDefaultParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicDefault - Frame format parser and encoder + */ +class BasicDefault { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x71; + static HEADER_SIZE = 4; + static FOOTER_SIZE = 2; + static OVERHEAD = 6; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicDefaultParserState.LOOKING_FOR_START1: + if (byte === BasicDefault.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicDefaultParserState.LOOKING_FOR_START2; + } + break; + + case BasicDefaultParserState.LOOKING_FOR_START2: + if (byte === BasicDefault.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicDefaultParserState.GETTING_MSG_ID; + } else if (byte === BasicDefault.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicDefaultParserState.LOOKING_FOR_START2; + } else { + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + } + break; + + case BasicDefaultParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicDefaultParserState.GETTING_LENGTH; + break; + + case BasicDefaultParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicDefault.OVERHEAD + this.msg_length; + this.state = BasicDefaultParserState.GETTING_PAYLOAD; + break; + + case BasicDefaultParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicDefault.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicDefault.HEADER_SIZE, this.packet_size - BasicDefault.FOOTER_SIZE)); + } + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicDefault.START_BYTE1); + output.push(BasicDefault.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicDefault.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicDefault.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicDefault.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicDefault.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicDefault.HEADER_SIZE, buffer.length - BasicDefault.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicDefault, + BasicDefaultParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicExtended.js b/src/struct_frame/boilerplate/js/BasicExtended.js new file mode 100644 index 00000000..b5348339 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicExtended.js @@ -0,0 +1,154 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicExtended Frame Format +// ============================================================================= + +const BasicExtendedParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicExtended - Frame format parser and encoder + */ +class BasicExtended { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x74; + static HEADER_SIZE = 6; + static FOOTER_SIZE = 2; + static OVERHEAD = 8; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedParserState.LOOKING_FOR_START1: + if (byte === BasicExtended.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedParserState.LOOKING_FOR_START2: + if (byte === BasicExtended.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedParserState.GETTING_MSG_ID; + } else if (byte === BasicExtended.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedParserState.GETTING_LENGTH; + break; + + case BasicExtendedParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtended.OVERHEAD + this.msg_length; + this.state = BasicExtendedParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicExtended.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtended.HEADER_SIZE, this.packet_size - BasicExtended.FOOTER_SIZE)); + } + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicExtended.START_BYTE1); + output.push(BasicExtended.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtended.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtended.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtended.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtended.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtended.HEADER_SIZE, buffer.length - BasicExtended.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicExtended, + BasicExtendedParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedLength.js b/src/struct_frame/boilerplate/js/BasicExtendedLength.js new file mode 100644 index 00000000..1462a441 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicExtendedLength.js @@ -0,0 +1,154 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicExtendedLength Frame Format +// ============================================================================= + +const BasicExtendedLengthParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicExtendedLength - Frame format parser and encoder + */ +class BasicExtendedLength { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x73; + static HEADER_SIZE = 5; + static FOOTER_SIZE = 2; + static OVERHEAD = 7; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedLengthParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedLength.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedLengthParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedLength.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedLengthParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedLength.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedLengthParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedLengthParserState.GETTING_LENGTH; + break; + + case BasicExtendedLengthParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtendedLength.OVERHEAD + this.msg_length; + this.state = BasicExtendedLengthParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedLengthParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicExtendedLength.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedLength.HEADER_SIZE, this.packet_size - BasicExtendedLength.FOOTER_SIZE)); + } + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicExtendedLength.START_BYTE1); + output.push(BasicExtendedLength.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedLength.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedLength.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedLength.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedLength.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedLength.HEADER_SIZE, buffer.length - BasicExtendedLength.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicExtendedLength, + BasicExtendedLengthParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js b/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js new file mode 100644 index 00000000..91e2131d --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicExtendedMsgIds.js @@ -0,0 +1,148 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicExtendedMsgIds Frame Format +// ============================================================================= + +const BasicExtendedMsgIdsParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicExtendedMsgIds - Frame format parser and encoder + */ +class BasicExtendedMsgIds { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x72; + static HEADER_SIZE = 5; + static FOOTER_SIZE = 2; + static OVERHEAD = 7; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedMsgIds.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedMsgIds.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedMsgIds.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedMsgIdsParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH; + break; + + case BasicExtendedMsgIdsParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicExtendedMsgIds.OVERHEAD + this.msg_length; + this.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD; + break; + + case BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicExtendedMsgIds.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedMsgIds.HEADER_SIZE, this.packet_size - BasicExtendedMsgIds.FOOTER_SIZE)); + } + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicExtendedMsgIds.START_BYTE1); + output.push(BasicExtendedMsgIds.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedMsgIds.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedMsgIds.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedMsgIds.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedMsgIds.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedMsgIds.HEADER_SIZE, buffer.length - BasicExtendedMsgIds.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicExtendedMsgIds, + BasicExtendedMsgIdsParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js b/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js new file mode 100644 index 00000000..f174c64b --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicExtendedMultiSystemStream.js @@ -0,0 +1,154 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicExtendedMultiSystemStream Frame Format +// ============================================================================= + +const BasicExtendedMultiSystemStreamParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicExtendedMultiSystemStream - Frame format parser and encoder + */ +class BasicExtendedMultiSystemStream { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x78; + static HEADER_SIZE = 9; + static FOOTER_SIZE = 2; + static OVERHEAD = 11; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedMultiSystemStream.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtendedMultiSystemStream.OVERHEAD + this.msg_length; + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicExtendedMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedMultiSystemStream.HEADER_SIZE, this.packet_size - BasicExtendedMultiSystemStream.FOOTER_SIZE)); + } + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicExtendedMultiSystemStream.START_BYTE1); + output.push(BasicExtendedMultiSystemStream.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedMultiSystemStream.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedMultiSystemStream.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedMultiSystemStream.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, buffer.length - BasicExtendedMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicExtendedMultiSystemStream, + BasicExtendedMultiSystemStreamParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicMinimal.js b/src/struct_frame/boilerplate/js/BasicMinimal.js new file mode 100644 index 00000000..3da9d4e2 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicMinimal.js @@ -0,0 +1,136 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicMinimal Frame Format +// ============================================================================= + +const BasicMinimalParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * BasicMinimal - Frame format parser and encoder + */ +class BasicMinimal { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x70; + static HEADER_SIZE = 3; + static FOOTER_SIZE = 0; + static OVERHEAD = 3; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + reset() { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicMinimalParserState.LOOKING_FOR_START1: + if (byte === BasicMinimal.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMinimalParserState.LOOKING_FOR_START2; + } + break; + + case BasicMinimalParserState.LOOKING_FOR_START2: + if (byte === BasicMinimal.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicMinimalParserState.GETTING_MSG_ID; + } else if (byte === BasicMinimal.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMinimalParserState.LOOKING_FOR_START2; + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + + case BasicMinimalParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.get_msg_length) { + const msg_length = this.get_msg_length(byte); + if (msg_length !== undefined) { + this.packet_size = BasicMinimal.OVERHEAD + msg_length; + this.state = BasicMinimalParserState.GETTING_PAYLOAD; + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + + case BasicMinimalParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = this.packet_size - BasicMinimal.OVERHEAD; + result.msg_data = new Uint8Array(this.buffer.slice(BasicMinimal.HEADER_SIZE)); + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicMinimal.START_BYTE1); + output.push(BasicMinimal.START_BYTE2); + output.push(msg_id); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicMinimal.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicMinimal.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicMinimal.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicMinimal.OVERHEAD; + + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicMinimal.HEADER_SIZE)); + + return result; + } +} + +module.exports = { + BasicMinimal, + BasicMinimalParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js b/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js new file mode 100644 index 00000000..cdae4de5 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicMultiSystemStream.js @@ -0,0 +1,148 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicMultiSystemStream Frame Format +// ============================================================================= + +const BasicMultiSystemStreamParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicMultiSystemStream - Frame format parser and encoder + */ +class BasicMultiSystemStream { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x77; + static HEADER_SIZE = 7; + static FOOTER_SIZE = 2; + static OVERHEAD = 9; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicMultiSystemStreamParserState.LOOKING_FOR_START1: + if (byte === BasicMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; + } + break; + + case BasicMultiSystemStreamParserState.LOOKING_FOR_START2: + if (byte === BasicMultiSystemStream.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID; + } else if (byte === BasicMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; + } else { + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + + case BasicMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case BasicMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicMultiSystemStream.OVERHEAD + this.msg_length; + this.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD; + break; + + case BasicMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicMultiSystemStream.HEADER_SIZE, this.packet_size - BasicMultiSystemStream.FOOTER_SIZE)); + } + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicMultiSystemStream.START_BYTE1); + output.push(BasicMultiSystemStream.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicMultiSystemStream.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicMultiSystemStream.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicMultiSystemStream.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicMultiSystemStream.HEADER_SIZE, buffer.length - BasicMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicMultiSystemStream, + BasicMultiSystemStreamParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicSeq.js b/src/struct_frame/boilerplate/js/BasicSeq.js new file mode 100644 index 00000000..752420f2 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicSeq.js @@ -0,0 +1,148 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicSeq Frame Format +// ============================================================================= + +const BasicSeqParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicSeq - Frame format parser and encoder + */ +class BasicSeq { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x76; + static HEADER_SIZE = 5; + static FOOTER_SIZE = 2; + static OVERHEAD = 7; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicSeqParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = BasicSeqParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicSeqParserState.LOOKING_FOR_START1: + if (byte === BasicSeq.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSeqParserState.LOOKING_FOR_START2; + } + break; + + case BasicSeqParserState.LOOKING_FOR_START2: + if (byte === BasicSeq.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicSeqParserState.GETTING_MSG_ID; + } else if (byte === BasicSeq.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSeqParserState.LOOKING_FOR_START2; + } else { + this.state = BasicSeqParserState.LOOKING_FOR_START1; + } + break; + + case BasicSeqParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicSeqParserState.GETTING_LENGTH; + break; + + case BasicSeqParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicSeq.OVERHEAD + this.msg_length; + this.state = BasicSeqParserState.GETTING_PAYLOAD; + break; + + case BasicSeqParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicSeq.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicSeq.HEADER_SIZE, this.packet_size - BasicSeq.FOOTER_SIZE)); + } + this.state = BasicSeqParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicSeq.START_BYTE1); + output.push(BasicSeq.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicSeq.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicSeq.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicSeq.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicSeq.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicSeq.HEADER_SIZE, buffer.length - BasicSeq.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicSeq, + BasicSeqParserState, +}; diff --git a/src/struct_frame/boilerplate/js/BasicSysComp.js b/src/struct_frame/boilerplate/js/BasicSysComp.js new file mode 100644 index 00000000..46d35aa3 --- /dev/null +++ b/src/struct_frame/boilerplate/js/BasicSysComp.js @@ -0,0 +1,148 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// BasicSysComp Frame Format +// ============================================================================= + +const BasicSysCompParserState = { + LOOKING_FOR_START1: 0, + LOOKING_FOR_START2: 1, + GETTING_MSG_ID: 2, + GETTING_LENGTH: 3, + GETTING_PAYLOAD: 4 +}; + +/** + * BasicSysComp - Frame format parser and encoder + */ +class BasicSysComp { + static START_BYTE1 = 0x90; + static START_BYTE2 = 0x75; + static HEADER_SIZE = 6; + static FOOTER_SIZE = 2; + static OVERHEAD = 8; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicSysCompParserState.LOOKING_FOR_START1: + if (byte === BasicSysComp.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSysCompParserState.LOOKING_FOR_START2; + } + break; + + case BasicSysCompParserState.LOOKING_FOR_START2: + if (byte === BasicSysComp.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicSysCompParserState.GETTING_MSG_ID; + } else if (byte === BasicSysComp.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSysCompParserState.LOOKING_FOR_START2; + } else { + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + } + break; + + case BasicSysCompParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicSysCompParserState.GETTING_LENGTH; + break; + + case BasicSysCompParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicSysComp.OVERHEAD + this.msg_length; + this.state = BasicSysCompParserState.GETTING_PAYLOAD; + break; + + case BasicSysCompParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - BasicSysComp.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicSysComp.HEADER_SIZE, this.packet_size - BasicSysComp.FOOTER_SIZE)); + } + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(BasicSysComp.START_BYTE1); + output.push(BasicSysComp.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicSysComp.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicSysComp.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicSysComp.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicSysComp.OVERHEAD; + + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicSysComp.HEADER_SIZE, buffer.length - BasicSysComp.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + BasicSysComp, + BasicSysCompParserState, +}; diff --git a/src/struct_frame/boilerplate/js/FrameFormatConfig.js b/src/struct_frame/boilerplate/js/FrameFormatConfig.js index 30759814..6e5b3794 100644 --- a/src/struct_frame/boilerplate/js/FrameFormatConfig.js +++ b/src/struct_frame/boilerplate/js/FrameFormatConfig.js @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); @@ -19,7 +19,7 @@ const FrameFormatConfigParserState = { */ class FrameFormatConfig { static START_BYTE1 = 0x90; - static START_BYTE2 = 0x91; + static START_BYTE2 = 0x71; static HEADER_SIZE = 2; static FOOTER_SIZE = 1; static OVERHEAD = 3; diff --git a/src/struct_frame/boilerplate/js/MavlinkV1Frame.js b/src/struct_frame/boilerplate/js/MavlinkV1Frame.js index 9cdef551..a4156544 100644 --- a/src/struct_frame/boilerplate/js/MavlinkV1Frame.js +++ b/src/struct_frame/boilerplate/js/MavlinkV1Frame.js @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); @@ -19,9 +19,9 @@ const MavlinkV1FrameParserState = { */ class MavlinkV1Frame { static START_BYTE = 0xFE; - static HEADER_SIZE = 3; + static HEADER_SIZE = 6; static FOOTER_SIZE = 2; - static OVERHEAD = 5; + static OVERHEAD = 8; static LENGTH_BYTES = 1; constructor(get_msg_length) { diff --git a/src/struct_frame/boilerplate/js/MavlinkV2Frame.js b/src/struct_frame/boilerplate/js/MavlinkV2Frame.js index f5065f32..4ea88ea7 100644 --- a/src/struct_frame/boilerplate/js/MavlinkV2Frame.js +++ b/src/struct_frame/boilerplate/js/MavlinkV2Frame.js @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); @@ -19,9 +19,9 @@ const MavlinkV2FrameParserState = { */ class MavlinkV2Frame { static START_BYTE = 0xFD; - static HEADER_SIZE = 5; + static HEADER_SIZE = 8; static FOOTER_SIZE = 2; - static OVERHEAD = 7; + static OVERHEAD = 10; static LENGTH_BYTES = 1; constructor(get_msg_length) { diff --git a/src/struct_frame/boilerplate/js/TinyDefault.js b/src/struct_frame/boilerplate/js/TinyDefault.js new file mode 100644 index 00000000..fc81430c --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyDefault.js @@ -0,0 +1,130 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyDefault Frame Format +// ============================================================================= + +const TinyDefaultParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyDefault - Frame format parser and encoder + */ +class TinyDefault { + static START_BYTE = 0x71; + static HEADER_SIZE = 3; + static FOOTER_SIZE = 2; + static OVERHEAD = 5; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyDefaultParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = TinyDefaultParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyDefaultParserState.LOOKING_FOR_START: + if (byte === TinyDefault.START_BYTE) { + this.buffer = [byte]; + this.state = TinyDefaultParserState.GETTING_MSG_ID; + } + break; + + case TinyDefaultParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyDefaultParserState.GETTING_LENGTH; + break; + + case TinyDefaultParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyDefault.OVERHEAD + this.msg_length; + this.state = TinyDefaultParserState.GETTING_PAYLOAD; + break; + + case TinyDefaultParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyDefault.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyDefault.HEADER_SIZE, this.packet_size - TinyDefault.FOOTER_SIZE)); + } + this.state = TinyDefaultParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyDefault.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyDefault.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyDefault.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyDefault.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyDefault.HEADER_SIZE, buffer.length - TinyDefault.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyDefault, + TinyDefaultParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyExtended.js b/src/struct_frame/boilerplate/js/TinyExtended.js new file mode 100644 index 00000000..f63ebfce --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyExtended.js @@ -0,0 +1,136 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyExtended Frame Format +// ============================================================================= + +const TinyExtendedParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyExtended - Frame format parser and encoder + */ +class TinyExtended { + static START_BYTE = 0x74; + static HEADER_SIZE = 5; + static FOOTER_SIZE = 2; + static OVERHEAD = 7; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = TinyExtendedParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedParserState.LOOKING_FOR_START: + if (byte === TinyExtended.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedParserState.GETTING_LENGTH; + break; + + case TinyExtendedParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtended.OVERHEAD + this.msg_length; + this.state = TinyExtendedParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyExtended.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtended.HEADER_SIZE, this.packet_size - TinyExtended.FOOTER_SIZE)); + } + this.state = TinyExtendedParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyExtended.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtended.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtended.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtended.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtended.HEADER_SIZE, buffer.length - TinyExtended.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyExtended, + TinyExtendedParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedLength.js b/src/struct_frame/boilerplate/js/TinyExtendedLength.js new file mode 100644 index 00000000..db63e046 --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyExtendedLength.js @@ -0,0 +1,136 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyExtendedLength Frame Format +// ============================================================================= + +const TinyExtendedLengthParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyExtendedLength - Frame format parser and encoder + */ +class TinyExtendedLength { + static START_BYTE = 0x73; + static HEADER_SIZE = 4; + static FOOTER_SIZE = 2; + static OVERHEAD = 6; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedLengthParserState.LOOKING_FOR_START: + if (byte === TinyExtendedLength.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedLengthParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedLengthParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedLengthParserState.GETTING_LENGTH; + break; + + case TinyExtendedLengthParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtendedLength.OVERHEAD + this.msg_length; + this.state = TinyExtendedLengthParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedLengthParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyExtendedLength.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedLength.HEADER_SIZE, this.packet_size - TinyExtendedLength.FOOTER_SIZE)); + } + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyExtendedLength.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedLength.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedLength.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedLength.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedLength.HEADER_SIZE, buffer.length - TinyExtendedLength.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyExtendedLength, + TinyExtendedLengthParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js b/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js new file mode 100644 index 00000000..88c0ff0a --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyExtendedMsgIds.js @@ -0,0 +1,130 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyExtendedMsgIds Frame Format +// ============================================================================= + +const TinyExtendedMsgIdsParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyExtendedMsgIds - Frame format parser and encoder + */ +class TinyExtendedMsgIds { + static START_BYTE = 0x72; + static HEADER_SIZE = 4; + static FOOTER_SIZE = 2; + static OVERHEAD = 6; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedMsgIdsParserState.LOOKING_FOR_START: + if (byte === TinyExtendedMsgIds.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedMsgIdsParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH; + break; + + case TinyExtendedMsgIdsParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyExtendedMsgIds.OVERHEAD + this.msg_length; + this.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD; + break; + + case TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyExtendedMsgIds.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedMsgIds.HEADER_SIZE, this.packet_size - TinyExtendedMsgIds.FOOTER_SIZE)); + } + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyExtendedMsgIds.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedMsgIds.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedMsgIds.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedMsgIds.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedMsgIds.HEADER_SIZE, buffer.length - TinyExtendedMsgIds.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyExtendedMsgIds, + TinyExtendedMsgIdsParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js b/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js new file mode 100644 index 00000000..e4a76f65 --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyExtendedMultiSystemStream.js @@ -0,0 +1,136 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyExtendedMultiSystemStream Frame Format +// ============================================================================= + +const TinyExtendedMultiSystemStreamParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyExtendedMultiSystemStream - Frame format parser and encoder + */ +class TinyExtendedMultiSystemStream { + static START_BYTE = 0x78; + static HEADER_SIZE = 8; + static FOOTER_SIZE = 2; + static OVERHEAD = 10; + static LENGTH_BYTES = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + reset() { + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: + if (byte === TinyExtendedMultiSystemStream.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtendedMultiSystemStream.OVERHEAD + this.msg_length; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyExtendedMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedMultiSystemStream.HEADER_SIZE, this.packet_size - TinyExtendedMultiSystemStream.FOOTER_SIZE)); + } + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyExtendedMultiSystemStream.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedMultiSystemStream.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedMultiSystemStream.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, buffer.length - TinyExtendedMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyExtendedMultiSystemStream, + TinyExtendedMultiSystemStreamParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyMinimal.js b/src/struct_frame/boilerplate/js/TinyMinimal.js new file mode 100644 index 00000000..814e4321 --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyMinimal.js @@ -0,0 +1,118 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyMinimal Frame Format +// ============================================================================= + +const TinyMinimalParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_PAYLOAD: 2 +}; + +/** + * TinyMinimal - Frame format parser and encoder + */ +class TinyMinimal { + static START_BYTE = 0x70; + static HEADER_SIZE = 2; + static FOOTER_SIZE = 0; + static OVERHEAD = 2; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyMinimalParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + reset() { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyMinimalParserState.LOOKING_FOR_START: + if (byte === TinyMinimal.START_BYTE) { + this.buffer = [byte]; + this.state = TinyMinimalParserState.GETTING_MSG_ID; + } + break; + + case TinyMinimalParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.get_msg_length) { + const msg_length = this.get_msg_length(byte); + if (msg_length !== undefined) { + this.packet_size = TinyMinimal.OVERHEAD + msg_length; + this.state = TinyMinimalParserState.GETTING_PAYLOAD; + } else { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + } else { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + break; + + case TinyMinimalParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = this.packet_size - TinyMinimal.OVERHEAD; + result.msg_data = new Uint8Array(this.buffer.slice(TinyMinimal.HEADER_SIZE)); + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyMinimal.START_BYTE); + output.push(msg_id); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyMinimal.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyMinimal.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyMinimal.OVERHEAD; + + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyMinimal.HEADER_SIZE)); + + return result; + } +} + +module.exports = { + TinyMinimal, + TinyMinimalParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js b/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js new file mode 100644 index 00000000..73926c16 --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinyMultiSystemStream.js @@ -0,0 +1,130 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinyMultiSystemStream Frame Format +// ============================================================================= + +const TinyMultiSystemStreamParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinyMultiSystemStream - Frame format parser and encoder + */ +class TinyMultiSystemStream { + static START_BYTE = 0x77; + static HEADER_SIZE = 6; + static FOOTER_SIZE = 2; + static OVERHEAD = 8; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyMultiSystemStreamParserState.LOOKING_FOR_START: + if (byte === TinyMultiSystemStream.START_BYTE) { + this.buffer = [byte]; + this.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID; + } + break; + + case TinyMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case TinyMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyMultiSystemStream.OVERHEAD + this.msg_length; + this.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD; + break; + + case TinyMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinyMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyMultiSystemStream.HEADER_SIZE, this.packet_size - TinyMultiSystemStream.FOOTER_SIZE)); + } + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinyMultiSystemStream.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyMultiSystemStream.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyMultiSystemStream.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyMultiSystemStream.HEADER_SIZE, buffer.length - TinyMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinyMultiSystemStream, + TinyMultiSystemStreamParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinySeq.js b/src/struct_frame/boilerplate/js/TinySeq.js new file mode 100644 index 00000000..7585fe35 --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinySeq.js @@ -0,0 +1,130 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinySeq Frame Format +// ============================================================================= + +const TinySeqParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinySeq - Frame format parser and encoder + */ +class TinySeq { + static START_BYTE = 0x76; + static HEADER_SIZE = 4; + static FOOTER_SIZE = 2; + static OVERHEAD = 6; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinySeqParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = TinySeqParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinySeqParserState.LOOKING_FOR_START: + if (byte === TinySeq.START_BYTE) { + this.buffer = [byte]; + this.state = TinySeqParserState.GETTING_MSG_ID; + } + break; + + case TinySeqParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinySeqParserState.GETTING_LENGTH; + break; + + case TinySeqParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinySeq.OVERHEAD + this.msg_length; + this.state = TinySeqParserState.GETTING_PAYLOAD; + break; + + case TinySeqParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinySeq.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinySeq.HEADER_SIZE, this.packet_size - TinySeq.FOOTER_SIZE)); + } + this.state = TinySeqParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinySeq.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinySeq.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinySeq.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinySeq.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinySeq.HEADER_SIZE, buffer.length - TinySeq.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinySeq, + TinySeqParserState, +}; diff --git a/src/struct_frame/boilerplate/js/TinySysComp.js b/src/struct_frame/boilerplate/js/TinySysComp.js new file mode 100644 index 00000000..9bb54a6a --- /dev/null +++ b/src/struct_frame/boilerplate/js/TinySysComp.js @@ -0,0 +1,130 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); + +// ============================================================================= +// TinySysComp Frame Format +// ============================================================================= + +const TinySysCompParserState = { + LOOKING_FOR_START: 0, + GETTING_MSG_ID: 1, + GETTING_LENGTH: 2, + GETTING_PAYLOAD: 3 +}; + +/** + * TinySysComp - Frame format parser and encoder + */ +class TinySysComp { + static START_BYTE = 0x75; + static HEADER_SIZE = 5; + static FOOTER_SIZE = 2; + static OVERHEAD = 7; + static LENGTH_BYTES = 1; + + constructor(get_msg_length) { + this.get_msg_length = get_msg_length; + this.state = TinySysCompParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + reset() { + this.state = TinySysCompParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + parse_byte(byte) { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinySysCompParserState.LOOKING_FOR_START: + if (byte === TinySysComp.START_BYTE) { + this.buffer = [byte]; + this.state = TinySysCompParserState.GETTING_MSG_ID; + } + break; + + case TinySysCompParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinySysCompParserState.GETTING_LENGTH; + break; + + case TinySysCompParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinySysComp.OVERHEAD + this.msg_length; + this.state = TinySysCompParserState.GETTING_PAYLOAD; + break; + + case TinySysCompParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + const msg_length = this.packet_size - TinySysComp.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinySysComp.HEADER_SIZE, this.packet_size - TinySysComp.FOOTER_SIZE)); + } + this.state = TinySysCompParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + static encode(msg_id, msg) { + const output = []; + output.push(TinySysComp.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + static validate_packet(buffer) { + const result = createFrameMsgInfo(); + + if (buffer.length < TinySysComp.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinySysComp.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinySysComp.OVERHEAD; + + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinySysComp.HEADER_SIZE, buffer.length - TinySysComp.FOOTER_SIZE)); + } + + return result; + } +} + +module.exports = { + TinySysComp, + TinySysCompParserState, +}; diff --git a/src/struct_frame/boilerplate/js/UbxFrame.js b/src/struct_frame/boilerplate/js/UbxFrame.js index 4a1ab410..53c78983 100644 --- a/src/struct_frame/boilerplate/js/UbxFrame.js +++ b/src/struct_frame/boilerplate/js/UbxFrame.js @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. const { createFrameMsgInfo, fletcher_checksum } = require('./frame_base'); diff --git a/src/struct_frame/boilerplate/js/frame_base.js b/src/struct_frame/boilerplate/js/frame_base.js index 4416e5c5..a6cb8c3f 100644 --- a/src/struct_frame/boilerplate/js/frame_base.js +++ b/src/struct_frame/boilerplate/js/frame_base.js @@ -1,26 +1,26 @@ // Automatically generated frame parser base utilities -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. // Frame format type enumeration const FrameFormatType = { - MINIMAL_FRAME: 0, - BASIC_FRAME: 1, - BASIC_FRAME_NO_CRC: 2, - TINY_FRAME: 3, - TINY_FRAME_NO_CRC: 4, - MINIMAL_FRAME_WITH_LEN: 5, - MINIMAL_FRAME_WITH_LEN_NO_CRC: 6, - BASIC_FRAME_WITH_LEN: 7, - BASIC_FRAME_WITH_LEN_NO_CRC: 8, - TINY_FRAME_WITH_LEN: 9, - TINY_FRAME_WITH_LEN_NO_CRC: 10, - MINIMAL_FRAME_WITH_LEN16: 11, - MINIMAL_FRAME_WITH_LEN16_NO_CRC: 12, - BASIC_FRAME_WITH_LEN16: 13, - BASIC_FRAME_WITH_LEN16_NO_CRC: 14, - TINY_FRAME_WITH_LEN16: 15, - TINY_FRAME_WITH_LEN16_NO_CRC: 16, - BASIC_FRAME_WITH_SYS_COMP: 17, + TINY_MINIMAL: 0, + TINY_DEFAULT: 1, + TINY_EXTENDED_MSG_IDS: 2, + TINY_EXTENDED_LENGTH: 3, + TINY_EXTENDED: 4, + TINY_SYS_COMP: 5, + TINY_SEQ: 6, + TINY_MULTI_SYSTEM_STREAM: 7, + TINY_EXTENDED_MULTI_SYSTEM_STREAM: 8, + BASIC_MINIMAL: 9, + BASIC_DEFAULT: 10, + BASIC_EXTENDED_MSG_IDS: 11, + BASIC_EXTENDED_LENGTH: 12, + BASIC_EXTENDED: 13, + BASIC_SYS_COMP: 14, + BASIC_SEQ: 15, + BASIC_MULTI_SYSTEM_STREAM: 16, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM: 17, UBX_FRAME: 18, MAVLINK_V1_FRAME: 19, MAVLINK_V2_FRAME: 20, diff --git a/src/struct_frame/boilerplate/js/index.js b/src/struct_frame/boilerplate/js/index.js index e180ae9b..c3434fb8 100644 --- a/src/struct_frame/boilerplate/js/index.js +++ b/src/struct_frame/boilerplate/js/index.js @@ -1,28 +1,28 @@ // Automatically generated frame parser package -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. // Base utilities const frameBase = require('./frame_base'); // Individual frame format parsers -const minimal_frame = require('./MinimalFrame'); -const basic_frame = require('./BasicFrame'); -const basic_frame_no_crc = require('./BasicFrameNoCrc'); -const tiny_frame = require('./TinyFrame'); -const tiny_frame_no_crc = require('./TinyFrameNoCrc'); -const minimal_frame_with_len = require('./MinimalFrameWithLen'); -const minimal_frame_with_len_no_crc = require('./MinimalFrameWithLenNoCrc'); -const basic_frame_with_len = require('./BasicFrameWithLen'); -const basic_frame_with_len_no_crc = require('./BasicFrameWithLenNoCrc'); -const tiny_frame_with_len = require('./TinyFrameWithLen'); -const tiny_frame_with_len_no_crc = require('./TinyFrameWithLenNoCrc'); -const minimal_frame_with_len16 = require('./MinimalFrameWithLen16'); -const minimal_frame_with_len16_no_crc = require('./MinimalFrameWithLen16NoCrc'); -const basic_frame_with_len16 = require('./BasicFrameWithLen16'); -const basic_frame_with_len16_no_crc = require('./BasicFrameWithLen16NoCrc'); -const tiny_frame_with_len16 = require('./TinyFrameWithLen16'); -const tiny_frame_with_len16_no_crc = require('./TinyFrameWithLen16NoCrc'); -const basic_frame_with_sys_comp = require('./BasicFrameWithSysComp'); +const tiny_minimal = require('./TinyMinimal'); +const tiny_default = require('./TinyDefault'); +const tiny_extended_msg_ids = require('./TinyExtendedMsgIds'); +const tiny_extended_length = require('./TinyExtendedLength'); +const tiny_extended = require('./TinyExtended'); +const tiny_sys_comp = require('./TinySysComp'); +const tiny_seq = require('./TinySeq'); +const tiny_multi_system_stream = require('./TinyMultiSystemStream'); +const tiny_extended_multi_system_stream = require('./TinyExtendedMultiSystemStream'); +const basic_minimal = require('./BasicMinimal'); +const basic_default = require('./BasicDefault'); +const basic_extended_msg_ids = require('./BasicExtendedMsgIds'); +const basic_extended_length = require('./BasicExtendedLength'); +const basic_extended = require('./BasicExtended'); +const basic_sys_comp = require('./BasicSysComp'); +const basic_seq = require('./BasicSeq'); +const basic_multi_system_stream = require('./BasicMultiSystemStream'); +const basic_extended_multi_system_stream = require('./BasicExtendedMultiSystemStream'); const ubx_frame = require('./UbxFrame'); const mavlink_v1_frame = require('./MavlinkV1Frame'); const mavlink_v2_frame = require('./MavlinkV2Frame'); @@ -32,24 +32,24 @@ module.exports = { // Base utilities ...frameBase, // Frame formats - ...minimal_frame, - ...basic_frame, - ...basic_frame_no_crc, - ...tiny_frame, - ...tiny_frame_no_crc, - ...minimal_frame_with_len, - ...minimal_frame_with_len_no_crc, - ...basic_frame_with_len, - ...basic_frame_with_len_no_crc, - ...tiny_frame_with_len, - ...tiny_frame_with_len_no_crc, - ...minimal_frame_with_len16, - ...minimal_frame_with_len16_no_crc, - ...basic_frame_with_len16, - ...basic_frame_with_len16_no_crc, - ...tiny_frame_with_len16, - ...tiny_frame_with_len16_no_crc, - ...basic_frame_with_sys_comp, + ...tiny_minimal, + ...tiny_default, + ...tiny_extended_msg_ids, + ...tiny_extended_length, + ...tiny_extended, + ...tiny_sys_comp, + ...tiny_seq, + ...tiny_multi_system_stream, + ...tiny_extended_multi_system_stream, + ...basic_minimal, + ...basic_default, + ...basic_extended_msg_ids, + ...basic_extended_length, + ...basic_extended, + ...basic_sys_comp, + ...basic_seq, + ...basic_multi_system_stream, + ...basic_extended_multi_system_stream, ...ubx_frame, ...mavlink_v1_frame, ...mavlink_v2_frame, diff --git a/src/struct_frame/boilerplate/py/__init__.py b/src/struct_frame/boilerplate/py/__init__.py index 772366e3..2aebcb59 100644 --- a/src/struct_frame/boilerplate/py/__init__.py +++ b/src/struct_frame/boilerplate/py/__init__.py @@ -1,5 +1,5 @@ # Automatically generated frame parser package -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. # Base utilities from .frame_base import ( @@ -9,24 +9,24 @@ ) # Individual frame format parsers -from .minimal_frame import MinimalFrame, MinimalFrameParserState -from .basic_frame import BasicFrame, BasicFrameParserState -from .basic_frame_no_crc import BasicFrameNoCrc, BasicFrameNoCrcParserState -from .tiny_frame import TinyFrame, TinyFrameParserState -from .tiny_frame_no_crc import TinyFrameNoCrc, TinyFrameNoCrcParserState -from .minimal_frame_with_len import MinimalFrameWithLen, MinimalFrameWithLenParserState -from .minimal_frame_with_len_no_crc import MinimalFrameWithLenNoCrc, MinimalFrameWithLenNoCrcParserState -from .basic_frame_with_len import BasicFrameWithLen, BasicFrameWithLenParserState -from .basic_frame_with_len_no_crc import BasicFrameWithLenNoCrc, BasicFrameWithLenNoCrcParserState -from .tiny_frame_with_len import TinyFrameWithLen, TinyFrameWithLenParserState -from .tiny_frame_with_len_no_crc import TinyFrameWithLenNoCrc, TinyFrameWithLenNoCrcParserState -from .minimal_frame_with_len16 import MinimalFrameWithLen16, MinimalFrameWithLen16ParserState -from .minimal_frame_with_len16_no_crc import MinimalFrameWithLen16NoCrc, MinimalFrameWithLen16NoCrcParserState -from .basic_frame_with_len16 import BasicFrameWithLen16, BasicFrameWithLen16ParserState -from .basic_frame_with_len16_no_crc import BasicFrameWithLen16NoCrc, BasicFrameWithLen16NoCrcParserState -from .tiny_frame_with_len16 import TinyFrameWithLen16, TinyFrameWithLen16ParserState -from .tiny_frame_with_len16_no_crc import TinyFrameWithLen16NoCrc, TinyFrameWithLen16NoCrcParserState -from .basic_frame_with_sys_comp import BasicFrameWithSysComp, BasicFrameWithSysCompParserState +from .tiny_minimal import TinyMinimal, TinyMinimalParserState +from .tiny_default import TinyDefault, TinyDefaultParserState +from .tiny_extended_msg_ids import TinyExtendedMsgIds, TinyExtendedMsgIdsParserState +from .tiny_extended_length import TinyExtendedLength, TinyExtendedLengthParserState +from .tiny_extended import TinyExtended, TinyExtendedParserState +from .tiny_sys_comp import TinySysComp, TinySysCompParserState +from .tiny_seq import TinySeq, TinySeqParserState +from .tiny_multi_system_stream import TinyMultiSystemStream, TinyMultiSystemStreamParserState +from .tiny_extended_multi_system_stream import TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamParserState +from .basic_minimal import BasicMinimal, BasicMinimalParserState +from .basic_default import BasicDefault, BasicDefaultParserState +from .basic_extended_msg_ids import BasicExtendedMsgIds, BasicExtendedMsgIdsParserState +from .basic_extended_length import BasicExtendedLength, BasicExtendedLengthParserState +from .basic_extended import BasicExtended, BasicExtendedParserState +from .basic_sys_comp import BasicSysComp, BasicSysCompParserState +from .basic_seq import BasicSeq, BasicSeqParserState +from .basic_multi_system_stream import BasicMultiSystemStream, BasicMultiSystemStreamParserState +from .basic_extended_multi_system_stream import BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamParserState from .ubx_frame import UbxFrame, UbxFrameParserState from .mavlink_v1_frame import MavlinkV1Frame, MavlinkV1FrameParserState from .mavlink_v2_frame import MavlinkV2Frame, MavlinkV2FrameParserState @@ -39,42 +39,42 @@ "FrameMsgInfo", "fletcher_checksum", # Frame formats - "MinimalFrame", - "MinimalFrameParserState", - "BasicFrame", - "BasicFrameParserState", - "BasicFrameNoCrc", - "BasicFrameNoCrcParserState", - "TinyFrame", - "TinyFrameParserState", - "TinyFrameNoCrc", - "TinyFrameNoCrcParserState", - "MinimalFrameWithLen", - "MinimalFrameWithLenParserState", - "MinimalFrameWithLenNoCrc", - "MinimalFrameWithLenNoCrcParserState", - "BasicFrameWithLen", - "BasicFrameWithLenParserState", - "BasicFrameWithLenNoCrc", - "BasicFrameWithLenNoCrcParserState", - "TinyFrameWithLen", - "TinyFrameWithLenParserState", - "TinyFrameWithLenNoCrc", - "TinyFrameWithLenNoCrcParserState", - "MinimalFrameWithLen16", - "MinimalFrameWithLen16ParserState", - "MinimalFrameWithLen16NoCrc", - "MinimalFrameWithLen16NoCrcParserState", - "BasicFrameWithLen16", - "BasicFrameWithLen16ParserState", - "BasicFrameWithLen16NoCrc", - "BasicFrameWithLen16NoCrcParserState", - "TinyFrameWithLen16", - "TinyFrameWithLen16ParserState", - "TinyFrameWithLen16NoCrc", - "TinyFrameWithLen16NoCrcParserState", - "BasicFrameWithSysComp", - "BasicFrameWithSysCompParserState", + "TinyMinimal", + "TinyMinimalParserState", + "TinyDefault", + "TinyDefaultParserState", + "TinyExtendedMsgIds", + "TinyExtendedMsgIdsParserState", + "TinyExtendedLength", + "TinyExtendedLengthParserState", + "TinyExtended", + "TinyExtendedParserState", + "TinySysComp", + "TinySysCompParserState", + "TinySeq", + "TinySeqParserState", + "TinyMultiSystemStream", + "TinyMultiSystemStreamParserState", + "TinyExtendedMultiSystemStream", + "TinyExtendedMultiSystemStreamParserState", + "BasicMinimal", + "BasicMinimalParserState", + "BasicDefault", + "BasicDefaultParserState", + "BasicExtendedMsgIds", + "BasicExtendedMsgIdsParserState", + "BasicExtendedLength", + "BasicExtendedLengthParserState", + "BasicExtended", + "BasicExtendedParserState", + "BasicSysComp", + "BasicSysCompParserState", + "BasicSeq", + "BasicSeqParserState", + "BasicMultiSystemStream", + "BasicMultiSystemStreamParserState", + "BasicExtendedMultiSystemStream", + "BasicExtendedMultiSystemStreamParserState", "UbxFrame", "UbxFrameParserState", "MavlinkV1Frame", diff --git a/src/struct_frame/boilerplate/py/basic_frame_with_len.py b/src/struct_frame/boilerplate/py/basic_default.py similarity index 68% rename from src/struct_frame/boilerplate/py/basic_frame_with_len.py rename to src/struct_frame/boilerplate/py/basic_default.py index 99467a2a..93fea600 100644 --- a/src/struct_frame/boilerplate/py/basic_frame_with_len.py +++ b/src/struct_frame/boilerplate/py/basic_default.py @@ -1,15 +1,15 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# BasicFrameWithLen Frame Format +# BasicDefault Frame Format # ============================================================================= -class BasicFrameWithLenParserState(Enum): +class BasicDefaultParserState(Enum): LOOKING_FOR_START1 = 0 LOOKING_FOR_START2 = 1 GETTING_MSG_ID = 2 @@ -17,15 +17,15 @@ class BasicFrameWithLenParserState(Enum): GETTING_PAYLOAD = 4 -class BasicFrameWithLen: +class BasicDefault: """ - BasicFrameWithLen - Frame format parser and encoder + BasicDefault - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x92] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x92 + START_BYTE2 = 0x71 HEADER_SIZE = 4 FOOTER_SIZE = 2 OVERHEAD = 6 @@ -33,7 +33,7 @@ class BasicFrameWithLen: def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the BasicFrameWithLen parser + Initialize the BasicDefault parser Args: get_msg_length: Callback function to get message length from msg_id @@ -44,7 +44,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = BasicFrameWithLenParserState.LOOKING_FOR_START1 + self.state = BasicDefaultParserState.LOOKING_FOR_START1 self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -59,33 +59,33 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == BasicFrameWithLenParserState.LOOKING_FOR_START1: + if self.state == BasicDefaultParserState.LOOKING_FOR_START1: if byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithLenParserState.LOOKING_FOR_START2 + self.state = BasicDefaultParserState.LOOKING_FOR_START2 - elif self.state == BasicFrameWithLenParserState.LOOKING_FOR_START2: + elif self.state == BasicDefaultParserState.LOOKING_FOR_START2: if byte == self.START_BYTE2: self.buffer.append(byte) - self.state = BasicFrameWithLenParserState.GETTING_MSG_ID + self.state = BasicDefaultParserState.GETTING_MSG_ID elif byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithLenParserState.LOOKING_FOR_START2 + self.state = BasicDefaultParserState.LOOKING_FOR_START2 else: - self.state = BasicFrameWithLenParserState.LOOKING_FOR_START1 + self.state = BasicDefaultParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameWithLenParserState.GETTING_MSG_ID: + elif self.state == BasicDefaultParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = BasicFrameWithLenParserState.GETTING_LENGTH + self.state = BasicDefaultParserState.GETTING_LENGTH - elif self.state == BasicFrameWithLenParserState.GETTING_LENGTH: + elif self.state == BasicDefaultParserState.GETTING_LENGTH: self.buffer.append(byte) self.msg_length = byte self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicFrameWithLenParserState.GETTING_PAYLOAD + self.state = BasicDefaultParserState.GETTING_PAYLOAD - elif self.state == BasicFrameWithLenParserState.GETTING_PAYLOAD: + elif self.state == BasicDefaultParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -97,13 +97,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = BasicFrameWithLenParserState.LOOKING_FOR_START1 + self.state = BasicDefaultParserState.LOOKING_FOR_START1 return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with BasicFrameWithLen format + Encode a message with BasicDefault format Args: msg_id: Message ID @@ -130,7 +130,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete BasicFrameWithLen packet in a buffer + Validate a complete BasicDefault packet in a buffer Args: buffer: Buffer containing the complete packet @@ -140,15 +140,15 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < BasicFrameWithLen.OVERHEAD: + if len(buffer) < BasicDefault.OVERHEAD: return result - if buffer[0] != BasicFrameWithLen.START_BYTE1: + if buffer[0] != BasicDefault.START_BYTE1: return result - if buffer[1] != BasicFrameWithLen.START_BYTE2: + if buffer[1] != BasicDefault.START_BYTE2: return result - msg_length = len(buffer) - BasicFrameWithLen.OVERHEAD + msg_length = len(buffer) - BasicDefault.OVERHEAD # Validate checksum ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1) @@ -156,6 +156,6 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: result.valid = True result.msg_id = buffer[2] result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameWithLen.HEADER_SIZE:len(buffer) - BasicFrameWithLen.FOOTER_SIZE]) + result.msg_data = bytes(buffer[BasicDefault.HEADER_SIZE:len(buffer) - BasicDefault.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/basic_frame_with_sys_comp.py b/src/struct_frame/boilerplate/py/basic_extended.py similarity index 59% rename from src/struct_frame/boilerplate/py/basic_frame_with_sys_comp.py rename to src/struct_frame/boilerplate/py/basic_extended.py index c7f2e78e..cef13417 100644 --- a/src/struct_frame/boilerplate/py/basic_frame_with_sys_comp.py +++ b/src/struct_frame/boilerplate/py/basic_extended.py @@ -1,37 +1,39 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# BasicFrameWithSysComp Frame Format +# BasicExtended Frame Format # ============================================================================= -class BasicFrameWithSysCompParserState(Enum): +class BasicExtendedParserState(Enum): LOOKING_FOR_START1 = 0 LOOKING_FOR_START2 = 1 GETTING_MSG_ID = 2 - GETTING_PAYLOAD = 3 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 -class BasicFrameWithSysComp: +class BasicExtended: """ - BasicFrameWithSysComp - Frame format parser and encoder + BasicExtended - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x94] [MSG_ID] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x94 - HEADER_SIZE = 3 + START_BYTE2 = 0x74 + HEADER_SIZE = 6 FOOTER_SIZE = 2 - OVERHEAD = 5 + OVERHEAD = 8 + LENGTH_BYTES = 2 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the BasicFrameWithSysComp parser + Initialize the BasicExtended parser Args: get_msg_length: Callback function to get message length from msg_id @@ -42,10 +44,12 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START1 + self.state = BasicExtendedParserState.LOOKING_FOR_START1 self.buffer = [] self.packet_size = 0 self.msg_id = 0 + self.msg_length = 0 + self.length_lo = 0 def parse_byte(self, byte: int) -> FrameMsgInfo: """ @@ -56,53 +60,54 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == BasicFrameWithSysCompParserState.LOOKING_FOR_START1: + if self.state == BasicExtendedParserState.LOOKING_FOR_START1: if byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START2 + self.state = BasicExtendedParserState.LOOKING_FOR_START2 - elif self.state == BasicFrameWithSysCompParserState.LOOKING_FOR_START2: + elif self.state == BasicExtendedParserState.LOOKING_FOR_START2: if byte == self.START_BYTE2: self.buffer.append(byte) - self.state = BasicFrameWithSysCompParserState.GETTING_MSG_ID + self.state = BasicExtendedParserState.GETTING_MSG_ID elif byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START2 + self.state = BasicExtendedParserState.LOOKING_FOR_START2 else: - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START1 + self.state = BasicExtendedParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameWithSysCompParserState.GETTING_MSG_ID: + elif self.state == BasicExtendedParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = BasicFrameWithSysCompParserState.GETTING_PAYLOAD - else: - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START1 + self.state = BasicExtendedParserState.GETTING_LENGTH + + elif self.state == BasicExtendedParserState.GETTING_LENGTH: + self.buffer.append(byte) + if len(self.buffer) == 4: + self.length_lo = byte else: - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START1 + self.msg_length = self.length_lo | (byte << 8) + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicExtendedParserState.GETTING_PAYLOAD - elif self.state == BasicFrameWithSysCompParserState.GETTING_PAYLOAD: + elif self.state == BasicExtendedParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: # Validate checksum msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1) + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 2) if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: result.valid = True result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = BasicFrameWithSysCompParserState.LOOKING_FOR_START1 + self.state = BasicExtendedParserState.LOOKING_FOR_START1 return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with BasicFrameWithSysComp format + Encode a message with BasicExtended format Args: msg_id: Message ID @@ -115,8 +120,10 @@ def encode(self, msg_id: int, msg: bytes) -> bytes: output.append(self.START_BYTE1) output.append(self.START_BYTE2) output.append(msg_id) + output.append(len(msg) & 0xFF) + output.append((len(msg) >> 8) & 0xFF) output.extend(msg) - ck = fletcher_checksum(output, 2, 2 + len(msg) + 1) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 2) output.append(ck[0]) output.append(ck[1]) return bytes(output) @@ -128,7 +135,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete BasicFrameWithSysComp packet in a buffer + Validate a complete BasicExtended packet in a buffer Args: buffer: Buffer containing the complete packet @@ -138,22 +145,22 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < BasicFrameWithSysComp.OVERHEAD: + if len(buffer) < BasicExtended.OVERHEAD: return result - if buffer[0] != BasicFrameWithSysComp.START_BYTE1: + if buffer[0] != BasicExtended.START_BYTE1: return result - if buffer[1] != BasicFrameWithSysComp.START_BYTE2: + if buffer[1] != BasicExtended.START_BYTE2: return result - msg_length = len(buffer) - BasicFrameWithSysComp.OVERHEAD + msg_length = len(buffer) - BasicExtended.OVERHEAD # Validate checksum - ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1) + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2) if ck[0] == buffer[-2] and ck[1] == buffer[-1]: result.valid = True result.msg_id = buffer[2] result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameWithSysComp.HEADER_SIZE:len(buffer) - BasicFrameWithSysComp.FOOTER_SIZE]) + result.msg_data = bytes(buffer[BasicExtended.HEADER_SIZE:len(buffer) - BasicExtended.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/basic_frame_with_len16.py b/src/struct_frame/boilerplate/py/basic_extended_length.py similarity index 71% rename from src/struct_frame/boilerplate/py/basic_frame_with_len16.py rename to src/struct_frame/boilerplate/py/basic_extended_length.py index 17c527e2..1d490351 100644 --- a/src/struct_frame/boilerplate/py/basic_frame_with_len16.py +++ b/src/struct_frame/boilerplate/py/basic_extended_length.py @@ -1,15 +1,15 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# BasicFrameWithLen16 Frame Format +# BasicExtendedLength Frame Format # ============================================================================= -class BasicFrameWithLen16ParserState(Enum): +class BasicExtendedLengthParserState(Enum): LOOKING_FOR_START1 = 0 LOOKING_FOR_START2 = 1 GETTING_MSG_ID = 2 @@ -17,15 +17,15 @@ class BasicFrameWithLen16ParserState(Enum): GETTING_PAYLOAD = 4 -class BasicFrameWithLen16: +class BasicExtendedLength: """ - BasicFrameWithLen16 - Frame format parser and encoder + BasicExtendedLength - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x93] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x93 + START_BYTE2 = 0x73 HEADER_SIZE = 5 FOOTER_SIZE = 2 OVERHEAD = 7 @@ -33,7 +33,7 @@ class BasicFrameWithLen16: def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the BasicFrameWithLen16 parser + Initialize the BasicExtendedLength parser Args: get_msg_length: Callback function to get message length from msg_id @@ -44,7 +44,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = BasicFrameWithLen16ParserState.LOOKING_FOR_START1 + self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -60,36 +60,36 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == BasicFrameWithLen16ParserState.LOOKING_FOR_START1: + if self.state == BasicExtendedLengthParserState.LOOKING_FOR_START1: if byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithLen16ParserState.LOOKING_FOR_START2 + self.state = BasicExtendedLengthParserState.LOOKING_FOR_START2 - elif self.state == BasicFrameWithLen16ParserState.LOOKING_FOR_START2: + elif self.state == BasicExtendedLengthParserState.LOOKING_FOR_START2: if byte == self.START_BYTE2: self.buffer.append(byte) - self.state = BasicFrameWithLen16ParserState.GETTING_MSG_ID + self.state = BasicExtendedLengthParserState.GETTING_MSG_ID elif byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameWithLen16ParserState.LOOKING_FOR_START2 + self.state = BasicExtendedLengthParserState.LOOKING_FOR_START2 else: - self.state = BasicFrameWithLen16ParserState.LOOKING_FOR_START1 + self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameWithLen16ParserState.GETTING_MSG_ID: + elif self.state == BasicExtendedLengthParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = BasicFrameWithLen16ParserState.GETTING_LENGTH + self.state = BasicExtendedLengthParserState.GETTING_LENGTH - elif self.state == BasicFrameWithLen16ParserState.GETTING_LENGTH: + elif self.state == BasicExtendedLengthParserState.GETTING_LENGTH: self.buffer.append(byte) if len(self.buffer) == 4: self.length_lo = byte else: self.msg_length = self.length_lo | (byte << 8) self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicFrameWithLen16ParserState.GETTING_PAYLOAD + self.state = BasicExtendedLengthParserState.GETTING_PAYLOAD - elif self.state == BasicFrameWithLen16ParserState.GETTING_PAYLOAD: + elif self.state == BasicExtendedLengthParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -101,13 +101,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = BasicFrameWithLen16ParserState.LOOKING_FOR_START1 + self.state = BasicExtendedLengthParserState.LOOKING_FOR_START1 return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with BasicFrameWithLen16 format + Encode a message with BasicExtendedLength format Args: msg_id: Message ID @@ -135,7 +135,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete BasicFrameWithLen16 packet in a buffer + Validate a complete BasicExtendedLength packet in a buffer Args: buffer: Buffer containing the complete packet @@ -145,15 +145,15 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < BasicFrameWithLen16.OVERHEAD: + if len(buffer) < BasicExtendedLength.OVERHEAD: return result - if buffer[0] != BasicFrameWithLen16.START_BYTE1: + if buffer[0] != BasicExtendedLength.START_BYTE1: return result - if buffer[1] != BasicFrameWithLen16.START_BYTE2: + if buffer[1] != BasicExtendedLength.START_BYTE2: return result - msg_length = len(buffer) - BasicFrameWithLen16.OVERHEAD + msg_length = len(buffer) - BasicExtendedLength.OVERHEAD # Validate checksum ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2) @@ -161,6 +161,6 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: result.valid = True result.msg_id = buffer[2] result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameWithLen16.HEADER_SIZE:len(buffer) - BasicFrameWithLen16.FOOTER_SIZE]) + result.msg_data = bytes(buffer[BasicExtendedLength.HEADER_SIZE:len(buffer) - BasicExtendedLength.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py b/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py new file mode 100644 index 00000000..cf18c8eb --- /dev/null +++ b/src/struct_frame/boilerplate/py/basic_extended_msg_ids.py @@ -0,0 +1,161 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# BasicExtendedMsgIds Frame Format +# ============================================================================= + +class BasicExtendedMsgIdsParserState(Enum): + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class BasicExtendedMsgIds: + """ + BasicExtendedMsgIds - Frame format parser and encoder + + Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE1 = 0x90 + START_BYTE2 = 0x72 + HEADER_SIZE = 5 + FOOTER_SIZE = 2 + OVERHEAD = 7 + LENGTH_BYTES = 1 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the BasicExtendedMsgIds parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: + if byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2 + + elif self.state == BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: + if byte == self.START_BYTE2: + self.buffer.append(byte) + self.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID + elif byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2 + else: + self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 + + elif self.state == BasicExtendedMsgIdsParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH + + elif self.state == BasicExtendedMsgIdsParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD + + elif self.state == BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1 + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with BasicExtendedMsgIds format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE1) + output.append(self.START_BYTE2) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 1) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete BasicExtendedMsgIds packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < BasicExtendedMsgIds.OVERHEAD: + return result + + if buffer[0] != BasicExtendedMsgIds.START_BYTE1: + return result + if buffer[1] != BasicExtendedMsgIds.START_BYTE2: + return result + + msg_length = len(buffer) - BasicExtendedMsgIds.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[2] + result.msg_len = msg_length + result.msg_data = bytes(buffer[BasicExtendedMsgIds.HEADER_SIZE:len(buffer) - BasicExtendedMsgIds.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py b/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py new file mode 100644 index 00000000..b0b8a065 --- /dev/null +++ b/src/struct_frame/boilerplate/py/basic_extended_multi_system_stream.py @@ -0,0 +1,166 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# BasicExtendedMultiSystemStream Frame Format +# ============================================================================= + +class BasicExtendedMultiSystemStreamParserState(Enum): + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class BasicExtendedMultiSystemStream: + """ + BasicExtendedMultiSystemStream - Frame format parser and encoder + + Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE1 = 0x90 + START_BYTE2 = 0x78 + HEADER_SIZE = 9 + FOOTER_SIZE = 2 + OVERHEAD = 11 + LENGTH_BYTES = 2 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the BasicExtendedMultiSystemStream parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + self.length_lo = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: + if byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2 + + elif self.state == BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: + if byte == self.START_BYTE2: + self.buffer.append(byte) + self.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID + elif byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2 + else: + self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 + + elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH + + elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: + self.buffer.append(byte) + if len(self.buffer) == 4: + self.length_lo = byte + else: + self.msg_length = self.length_lo | (byte << 8) + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD + + elif self.state == BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 2) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1 + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with BasicExtendedMultiSystemStream format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE1) + output.append(self.START_BYTE2) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.append((len(msg) >> 8) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 2) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete BasicExtendedMultiSystemStream packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < BasicExtendedMultiSystemStream.OVERHEAD: + return result + + if buffer[0] != BasicExtendedMultiSystemStream.START_BYTE1: + return result + if buffer[1] != BasicExtendedMultiSystemStream.START_BYTE2: + return result + + msg_length = len(buffer) - BasicExtendedMultiSystemStream.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[2] + result.msg_len = msg_length + result.msg_data = bytes(buffer[BasicExtendedMultiSystemStream.HEADER_SIZE:len(buffer) - BasicExtendedMultiSystemStream.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/basic_frame_with_len16_no_crc.py b/src/struct_frame/boilerplate/py/basic_frame_with_len16_no_crc.py deleted file mode 100644 index 44d31343..00000000 --- a/src/struct_frame/boilerplate/py/basic_frame_with_len16_no_crc.py +++ /dev/null @@ -1,156 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# BasicFrameWithLen16NoCrc Frame Format -# ============================================================================= - -class BasicFrameWithLen16NoCrcParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicFrameWithLen16NoCrc: - """ - BasicFrameWithLen16NoCrc - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x97] [MSG_ID] [LEN16] [MSG...] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x97 - HEADER_SIZE = 5 - FOOTER_SIZE = 0 - OVERHEAD = 5 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicFrameWithLen16NoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START2 - - elif self.state == BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicFrameWithLen16NoCrcParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START2 - else: - self.state = BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START1 - - elif self.state == BasicFrameWithLen16NoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicFrameWithLen16NoCrcParserState.GETTING_LENGTH - - elif self.state == BasicFrameWithLen16NoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 4: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicFrameWithLen16NoCrcParserState.GETTING_PAYLOAD - - elif self.state == BasicFrameWithLen16NoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = BasicFrameWithLen16NoCrcParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicFrameWithLen16NoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.append((len(msg) >> 8) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicFrameWithLen16NoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < BasicFrameWithLen16NoCrc.OVERHEAD: - return result - - if buffer[0] != BasicFrameWithLen16NoCrc.START_BYTE1: - return result - if buffer[1] != BasicFrameWithLen16NoCrc.START_BYTE2: - return result - - msg_length = len(buffer) - BasicFrameWithLen16NoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[2] - result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameWithLen16NoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/basic_frame_with_len_no_crc.py b/src/struct_frame/boilerplate/py/basic_frame_with_len_no_crc.py deleted file mode 100644 index 1580ed56..00000000 --- a/src/struct_frame/boilerplate/py/basic_frame_with_len_no_crc.py +++ /dev/null @@ -1,151 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# BasicFrameWithLenNoCrc Frame Format -# ============================================================================= - -class BasicFrameWithLenNoCrcParserState(Enum): - LOOKING_FOR_START1 = 0 - LOOKING_FOR_START2 = 1 - GETTING_MSG_ID = 2 - GETTING_LENGTH = 3 - GETTING_PAYLOAD = 4 - - -class BasicFrameWithLenNoCrc: - """ - BasicFrameWithLenNoCrc - Frame format parser and encoder - - Format: [START_BYTE1=0x90] [START_BYTE2=0x96] [MSG_ID] [LEN] [MSG...] - """ - - START_BYTE1 = 0x90 - START_BYTE2 = 0x96 - HEADER_SIZE = 4 - FOOTER_SIZE = 0 - OVERHEAD = 4 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the BasicFrameWithLenNoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START1 - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START1: - if byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START2 - - elif self.state == BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START2: - if byte == self.START_BYTE2: - self.buffer.append(byte) - self.state = BasicFrameWithLenNoCrcParserState.GETTING_MSG_ID - elif byte == self.START_BYTE1: - self.buffer = [byte] - self.state = BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START2 - else: - self.state = BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START1 - - elif self.state == BasicFrameWithLenNoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = BasicFrameWithLenNoCrcParserState.GETTING_LENGTH - - elif self.state == BasicFrameWithLenNoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = BasicFrameWithLenNoCrcParserState.GETTING_PAYLOAD - - elif self.state == BasicFrameWithLenNoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = BasicFrameWithLenNoCrcParserState.LOOKING_FOR_START1 - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with BasicFrameWithLenNoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE1) - output.append(self.START_BYTE2) - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete BasicFrameWithLenNoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < BasicFrameWithLenNoCrc.OVERHEAD: - return result - - if buffer[0] != BasicFrameWithLenNoCrc.START_BYTE1: - return result - if buffer[1] != BasicFrameWithLenNoCrc.START_BYTE2: - return result - - msg_length = len(buffer) - BasicFrameWithLenNoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[2] - result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameWithLenNoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/basic_frame_no_crc.py b/src/struct_frame/boilerplate/py/basic_minimal.py similarity index 65% rename from src/struct_frame/boilerplate/py/basic_frame_no_crc.py rename to src/struct_frame/boilerplate/py/basic_minimal.py index dadec44c..7d73f069 100644 --- a/src/struct_frame/boilerplate/py/basic_frame_no_crc.py +++ b/src/struct_frame/boilerplate/py/basic_minimal.py @@ -1,37 +1,37 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# BasicFrameNoCrc Frame Format +# BasicMinimal Frame Format # ============================================================================= -class BasicFrameNoCrcParserState(Enum): +class BasicMinimalParserState(Enum): LOOKING_FOR_START1 = 0 LOOKING_FOR_START2 = 1 GETTING_MSG_ID = 2 GETTING_PAYLOAD = 3 -class BasicFrameNoCrc: +class BasicMinimal: """ - BasicFrameNoCrc - Frame format parser and encoder + BasicMinimal - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x95] [MSG_ID] [MSG...] + Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x95 + START_BYTE2 = 0x70 HEADER_SIZE = 3 FOOTER_SIZE = 0 OVERHEAD = 3 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the BasicFrameNoCrc parser + Initialize the BasicMinimal parser Args: get_msg_length: Callback function to get message length from msg_id @@ -42,7 +42,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START1 + self.state = BasicMinimalParserState.LOOKING_FOR_START1 self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -56,35 +56,35 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == BasicFrameNoCrcParserState.LOOKING_FOR_START1: + if self.state == BasicMinimalParserState.LOOKING_FOR_START1: if byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START2 + self.state = BasicMinimalParserState.LOOKING_FOR_START2 - elif self.state == BasicFrameNoCrcParserState.LOOKING_FOR_START2: + elif self.state == BasicMinimalParserState.LOOKING_FOR_START2: if byte == self.START_BYTE2: self.buffer.append(byte) - self.state = BasicFrameNoCrcParserState.GETTING_MSG_ID + self.state = BasicMinimalParserState.GETTING_MSG_ID elif byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START2 + self.state = BasicMinimalParserState.LOOKING_FOR_START2 else: - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START1 + self.state = BasicMinimalParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameNoCrcParserState.GETTING_MSG_ID: + elif self.state == BasicMinimalParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte if self.get_msg_length: msg_length = self.get_msg_length(byte) if msg_length is not None: self.packet_size = self.OVERHEAD + msg_length - self.state = BasicFrameNoCrcParserState.GETTING_PAYLOAD + self.state = BasicMinimalParserState.GETTING_PAYLOAD else: - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START1 + self.state = BasicMinimalParserState.LOOKING_FOR_START1 else: - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START1 + self.state = BasicMinimalParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameNoCrcParserState.GETTING_PAYLOAD: + elif self.state == BasicMinimalParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -92,13 +92,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = self.packet_size - self.OVERHEAD result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = BasicFrameNoCrcParserState.LOOKING_FOR_START1 + self.state = BasicMinimalParserState.LOOKING_FOR_START1 return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with BasicFrameNoCrc format + Encode a message with BasicMinimal format Args: msg_id: Message ID @@ -121,7 +121,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete BasicFrameNoCrc packet in a buffer + Validate a complete BasicMinimal packet in a buffer Args: buffer: Buffer containing the complete packet @@ -131,19 +131,19 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < BasicFrameNoCrc.OVERHEAD: + if len(buffer) < BasicMinimal.OVERHEAD: return result - if buffer[0] != BasicFrameNoCrc.START_BYTE1: + if buffer[0] != BasicMinimal.START_BYTE1: return result - if buffer[1] != BasicFrameNoCrc.START_BYTE2: + if buffer[1] != BasicMinimal.START_BYTE2: return result - msg_length = len(buffer) - BasicFrameNoCrc.OVERHEAD + msg_length = len(buffer) - BasicMinimal.OVERHEAD result.valid = True result.msg_id = buffer[2] result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrameNoCrc.HEADER_SIZE:]) + result.msg_data = bytes(buffer[BasicMinimal.HEADER_SIZE:]) return result diff --git a/src/struct_frame/boilerplate/py/basic_multi_system_stream.py b/src/struct_frame/boilerplate/py/basic_multi_system_stream.py new file mode 100644 index 00000000..fda0a261 --- /dev/null +++ b/src/struct_frame/boilerplate/py/basic_multi_system_stream.py @@ -0,0 +1,161 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# BasicMultiSystemStream Frame Format +# ============================================================================= + +class BasicMultiSystemStreamParserState(Enum): + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class BasicMultiSystemStream: + """ + BasicMultiSystemStream - Frame format parser and encoder + + Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE1 = 0x90 + START_BYTE2 = 0x77 + HEADER_SIZE = 7 + FOOTER_SIZE = 2 + OVERHEAD = 9 + LENGTH_BYTES = 1 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the BasicMultiSystemStream parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == BasicMultiSystemStreamParserState.LOOKING_FOR_START1: + if byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2 + + elif self.state == BasicMultiSystemStreamParserState.LOOKING_FOR_START2: + if byte == self.START_BYTE2: + self.buffer.append(byte) + self.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID + elif byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2 + else: + self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 + + elif self.state == BasicMultiSystemStreamParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = BasicMultiSystemStreamParserState.GETTING_LENGTH + + elif self.state == BasicMultiSystemStreamParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD + + elif self.state == BasicMultiSystemStreamParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1 + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with BasicMultiSystemStream format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE1) + output.append(self.START_BYTE2) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 1) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete BasicMultiSystemStream packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < BasicMultiSystemStream.OVERHEAD: + return result + + if buffer[0] != BasicMultiSystemStream.START_BYTE1: + return result + if buffer[1] != BasicMultiSystemStream.START_BYTE2: + return result + + msg_length = len(buffer) - BasicMultiSystemStream.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[2] + result.msg_len = msg_length + result.msg_data = bytes(buffer[BasicMultiSystemStream.HEADER_SIZE:len(buffer) - BasicMultiSystemStream.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/basic_frame.py b/src/struct_frame/boilerplate/py/basic_seq.py similarity index 62% rename from src/struct_frame/boilerplate/py/basic_frame.py rename to src/struct_frame/boilerplate/py/basic_seq.py index acc04862..623d2aa9 100644 --- a/src/struct_frame/boilerplate/py/basic_frame.py +++ b/src/struct_frame/boilerplate/py/basic_seq.py @@ -1,37 +1,39 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# BasicFrame Frame Format +# BasicSeq Frame Format # ============================================================================= -class BasicFrameParserState(Enum): +class BasicSeqParserState(Enum): LOOKING_FOR_START1 = 0 LOOKING_FOR_START2 = 1 GETTING_MSG_ID = 2 - GETTING_PAYLOAD = 3 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 -class BasicFrame: +class BasicSeq: """ - BasicFrame - Frame format parser and encoder + BasicSeq - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x91] [MSG_ID] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x91 - HEADER_SIZE = 3 + START_BYTE2 = 0x76 + HEADER_SIZE = 5 FOOTER_SIZE = 2 - OVERHEAD = 5 + OVERHEAD = 7 + LENGTH_BYTES = 1 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the BasicFrame parser + Initialize the BasicSeq parser Args: get_msg_length: Callback function to get message length from msg_id @@ -42,10 +44,11 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = BasicFrameParserState.LOOKING_FOR_START1 + self.state = BasicSeqParserState.LOOKING_FOR_START1 self.buffer = [] self.packet_size = 0 self.msg_id = 0 + self.msg_length = 0 def parse_byte(self, byte: int) -> FrameMsgInfo: """ @@ -56,53 +59,51 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == BasicFrameParserState.LOOKING_FOR_START1: + if self.state == BasicSeqParserState.LOOKING_FOR_START1: if byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameParserState.LOOKING_FOR_START2 + self.state = BasicSeqParserState.LOOKING_FOR_START2 - elif self.state == BasicFrameParserState.LOOKING_FOR_START2: + elif self.state == BasicSeqParserState.LOOKING_FOR_START2: if byte == self.START_BYTE2: self.buffer.append(byte) - self.state = BasicFrameParserState.GETTING_MSG_ID + self.state = BasicSeqParserState.GETTING_MSG_ID elif byte == self.START_BYTE1: self.buffer = [byte] - self.state = BasicFrameParserState.LOOKING_FOR_START2 + self.state = BasicSeqParserState.LOOKING_FOR_START2 else: - self.state = BasicFrameParserState.LOOKING_FOR_START1 + self.state = BasicSeqParserState.LOOKING_FOR_START1 - elif self.state == BasicFrameParserState.GETTING_MSG_ID: + elif self.state == BasicSeqParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = BasicFrameParserState.GETTING_PAYLOAD - else: - self.state = BasicFrameParserState.LOOKING_FOR_START1 - else: - self.state = BasicFrameParserState.LOOKING_FOR_START1 + self.state = BasicSeqParserState.GETTING_LENGTH + + elif self.state == BasicSeqParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicSeqParserState.GETTING_PAYLOAD - elif self.state == BasicFrameParserState.GETTING_PAYLOAD: + elif self.state == BasicSeqParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: # Validate checksum msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1) + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 1) if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: result.valid = True result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = BasicFrameParserState.LOOKING_FOR_START1 + self.state = BasicSeqParserState.LOOKING_FOR_START1 return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with BasicFrame format + Encode a message with BasicSeq format Args: msg_id: Message ID @@ -115,8 +116,9 @@ def encode(self, msg_id: int, msg: bytes) -> bytes: output.append(self.START_BYTE1) output.append(self.START_BYTE2) output.append(msg_id) + output.append(len(msg) & 0xFF) output.extend(msg) - ck = fletcher_checksum(output, 2, 2 + len(msg) + 1) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 1) output.append(ck[0]) output.append(ck[1]) return bytes(output) @@ -128,7 +130,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete BasicFrame packet in a buffer + Validate a complete BasicSeq packet in a buffer Args: buffer: Buffer containing the complete packet @@ -138,22 +140,22 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < BasicFrame.OVERHEAD: + if len(buffer) < BasicSeq.OVERHEAD: return result - if buffer[0] != BasicFrame.START_BYTE1: + if buffer[0] != BasicSeq.START_BYTE1: return result - if buffer[1] != BasicFrame.START_BYTE2: + if buffer[1] != BasicSeq.START_BYTE2: return result - msg_length = len(buffer) - BasicFrame.OVERHEAD + msg_length = len(buffer) - BasicSeq.OVERHEAD # Validate checksum - ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1) + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1) if ck[0] == buffer[-2] and ck[1] == buffer[-1]: result.valid = True result.msg_id = buffer[2] result.msg_len = msg_length - result.msg_data = bytes(buffer[BasicFrame.HEADER_SIZE:len(buffer) - BasicFrame.FOOTER_SIZE]) + result.msg_data = bytes(buffer[BasicSeq.HEADER_SIZE:len(buffer) - BasicSeq.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/basic_sys_comp.py b/src/struct_frame/boilerplate/py/basic_sys_comp.py new file mode 100644 index 00000000..49a44f35 --- /dev/null +++ b/src/struct_frame/boilerplate/py/basic_sys_comp.py @@ -0,0 +1,161 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# BasicSysComp Frame Format +# ============================================================================= + +class BasicSysCompParserState(Enum): + LOOKING_FOR_START1 = 0 + LOOKING_FOR_START2 = 1 + GETTING_MSG_ID = 2 + GETTING_LENGTH = 3 + GETTING_PAYLOAD = 4 + + +class BasicSysComp: + """ + BasicSysComp - Frame format parser and encoder + + Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE1 = 0x90 + START_BYTE2 = 0x75 + HEADER_SIZE = 6 + FOOTER_SIZE = 2 + OVERHEAD = 8 + LENGTH_BYTES = 1 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the BasicSysComp parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = BasicSysCompParserState.LOOKING_FOR_START1 + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == BasicSysCompParserState.LOOKING_FOR_START1: + if byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicSysCompParserState.LOOKING_FOR_START2 + + elif self.state == BasicSysCompParserState.LOOKING_FOR_START2: + if byte == self.START_BYTE2: + self.buffer.append(byte) + self.state = BasicSysCompParserState.GETTING_MSG_ID + elif byte == self.START_BYTE1: + self.buffer = [byte] + self.state = BasicSysCompParserState.LOOKING_FOR_START2 + else: + self.state = BasicSysCompParserState.LOOKING_FOR_START1 + + elif self.state == BasicSysCompParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = BasicSysCompParserState.GETTING_LENGTH + + elif self.state == BasicSysCompParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = BasicSysCompParserState.GETTING_PAYLOAD + + elif self.state == BasicSysCompParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = BasicSysCompParserState.LOOKING_FOR_START1 + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with BasicSysComp format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE1) + output.append(self.START_BYTE2) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 2, 2 + len(msg) + 1 + 1) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete BasicSysComp packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < BasicSysComp.OVERHEAD: + return result + + if buffer[0] != BasicSysComp.START_BYTE1: + return result + if buffer[1] != BasicSysComp.START_BYTE2: + return result + + msg_length = len(buffer) - BasicSysComp.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[2] + result.msg_len = msg_length + result.msg_data = bytes(buffer[BasicSysComp.HEADER_SIZE:len(buffer) - BasicSysComp.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/frame_base.py b/src/struct_frame/boilerplate/py/frame_base.py index 82c3000f..558e5acb 100644 --- a/src/struct_frame/boilerplate/py/frame_base.py +++ b/src/struct_frame/boilerplate/py/frame_base.py @@ -1,5 +1,5 @@ # Automatically generated frame parser base utilities -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import List, Tuple, Union @@ -7,24 +7,24 @@ # Frame format type enumeration class FrameFormatType(Enum): - MINIMAL_FRAME = 0 - BASIC_FRAME = 1 - BASIC_FRAME_NO_CRC = 2 - TINY_FRAME = 3 - TINY_FRAME_NO_CRC = 4 - MINIMAL_FRAME_WITH_LEN = 5 - MINIMAL_FRAME_WITH_LEN_NO_CRC = 6 - BASIC_FRAME_WITH_LEN = 7 - BASIC_FRAME_WITH_LEN_NO_CRC = 8 - TINY_FRAME_WITH_LEN = 9 - TINY_FRAME_WITH_LEN_NO_CRC = 10 - MINIMAL_FRAME_WITH_LEN16 = 11 - MINIMAL_FRAME_WITH_LEN16_NO_CRC = 12 - BASIC_FRAME_WITH_LEN16 = 13 - BASIC_FRAME_WITH_LEN16_NO_CRC = 14 - TINY_FRAME_WITH_LEN16 = 15 - TINY_FRAME_WITH_LEN16_NO_CRC = 16 - BASIC_FRAME_WITH_SYS_COMP = 17 + TINY_MINIMAL = 0 + TINY_DEFAULT = 1 + TINY_EXTENDED_MSG_IDS = 2 + TINY_EXTENDED_LENGTH = 3 + TINY_EXTENDED = 4 + TINY_SYS_COMP = 5 + TINY_SEQ = 6 + TINY_MULTI_SYSTEM_STREAM = 7 + TINY_EXTENDED_MULTI_SYSTEM_STREAM = 8 + BASIC_MINIMAL = 9 + BASIC_DEFAULT = 10 + BASIC_EXTENDED_MSG_IDS = 11 + BASIC_EXTENDED_LENGTH = 12 + BASIC_EXTENDED = 13 + BASIC_SYS_COMP = 14 + BASIC_SEQ = 15 + BASIC_MULTI_SYSTEM_STREAM = 16 + BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 17 UBX_FRAME = 18 MAVLINK_V1_FRAME = 19 MAVLINK_V2_FRAME = 20 diff --git a/src/struct_frame/boilerplate/py/frame_format_config.py b/src/struct_frame/boilerplate/py/frame_format_config.py index 893b3cf6..b0ccf4c2 100644 --- a/src/struct_frame/boilerplate/py/frame_format_config.py +++ b/src/struct_frame/boilerplate/py/frame_format_config.py @@ -1,5 +1,5 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union @@ -20,11 +20,11 @@ class FrameFormatConfig: """ FrameFormatConfig - Frame format parser and encoder - Format: [START_BYTE1=0x90] [START_BYTE2=0x91] [MSG_ID] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] """ START_BYTE1 = 0x90 - START_BYTE2 = 0x91 + START_BYTE2 = 0x71 HEADER_SIZE = 2 FOOTER_SIZE = 1 OVERHEAD = 3 diff --git a/src/struct_frame/boilerplate/py/mavlink_v1_frame.py b/src/struct_frame/boilerplate/py/mavlink_v1_frame.py index f15713dd..96333fbe 100644 --- a/src/struct_frame/boilerplate/py/mavlink_v1_frame.py +++ b/src/struct_frame/boilerplate/py/mavlink_v1_frame.py @@ -1,5 +1,5 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union @@ -24,9 +24,9 @@ class MavlinkV1Frame: """ START_BYTE = 0xFE - HEADER_SIZE = 3 + HEADER_SIZE = 6 FOOTER_SIZE = 2 - OVERHEAD = 5 + OVERHEAD = 8 LENGTH_BYTES = 1 def __init__(self, get_msg_length: Callable[[int], int] = None): diff --git a/src/struct_frame/boilerplate/py/mavlink_v2_frame.py b/src/struct_frame/boilerplate/py/mavlink_v2_frame.py index 039323f3..d653cbe1 100644 --- a/src/struct_frame/boilerplate/py/mavlink_v2_frame.py +++ b/src/struct_frame/boilerplate/py/mavlink_v2_frame.py @@ -1,5 +1,5 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union @@ -24,9 +24,9 @@ class MavlinkV2Frame: """ START_BYTE = 0xFD - HEADER_SIZE = 5 + HEADER_SIZE = 8 FOOTER_SIZE = 2 - OVERHEAD = 7 + OVERHEAD = 10 LENGTH_BYTES = 1 def __init__(self, get_msg_length: Callable[[int], int] = None): diff --git a/src/struct_frame/boilerplate/py/minimal_frame.py b/src/struct_frame/boilerplate/py/minimal_frame.py deleted file mode 100644 index 48b39d8e..00000000 --- a/src/struct_frame/boilerplate/py/minimal_frame.py +++ /dev/null @@ -1,134 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# MinimalFrame Frame Format -# ============================================================================= - -class MinimalFrameParserState(Enum): - GETTING_MSG_ID = 0 - GETTING_PAYLOAD = 1 - - -class MinimalFrame: - """ - MinimalFrame - Frame format parser and encoder - - Format: [MSG_ID] [MSG...] [CRC1] [CRC2] - """ - - HEADER_SIZE = 1 - FOOTER_SIZE = 2 - OVERHEAD = 3 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the MinimalFrame parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = MinimalFrameParserState.GETTING_MSG_ID - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == MinimalFrameParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = MinimalFrameParserState.GETTING_PAYLOAD - else: - self.state = MinimalFrameParserState.GETTING_MSG_ID - else: - self.state = MinimalFrameParserState.GETTING_MSG_ID - - elif self.state == MinimalFrameParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - # Validate checksum - msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 0, 0 + msg_length + 1) - if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = msg_length - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = MinimalFrameParserState.GETTING_MSG_ID - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with MinimalFrame format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(msg_id) - output.extend(msg) - ck = fletcher_checksum(output, 0, 0 + len(msg) + 1) - output.append(ck[0]) - output.append(ck[1]) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete MinimalFrame packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < MinimalFrame.OVERHEAD: - return result - - - msg_length = len(buffer) - MinimalFrame.OVERHEAD - - # Validate checksum - ck = fletcher_checksum(buffer, 0, 0 + msg_length + 1) - if ck[0] == buffer[-2] and ck[1] == buffer[-1]: - result.valid = True - result.msg_id = buffer[0] - result.msg_len = msg_length - result.msg_data = bytes(buffer[MinimalFrame.HEADER_SIZE:len(buffer) - MinimalFrame.FOOTER_SIZE]) - - return result diff --git a/src/struct_frame/boilerplate/py/minimal_frame_with_len16_no_crc.py b/src/struct_frame/boilerplate/py/minimal_frame_with_len16_no_crc.py deleted file mode 100644 index 84067b28..00000000 --- a/src/struct_frame/boilerplate/py/minimal_frame_with_len16_no_crc.py +++ /dev/null @@ -1,131 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# MinimalFrameWithLen16NoCrc Frame Format -# ============================================================================= - -class MinimalFrameWithLen16NoCrcParserState(Enum): - GETTING_MSG_ID = 0 - GETTING_LENGTH = 1 - GETTING_PAYLOAD = 2 - - -class MinimalFrameWithLen16NoCrc: - """ - MinimalFrameWithLen16NoCrc - Frame format parser and encoder - - Format: [MSG_ID] [LEN16] [MSG...] - """ - - HEADER_SIZE = 3 - FOOTER_SIZE = 0 - OVERHEAD = 3 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the MinimalFrameWithLen16NoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = MinimalFrameWithLen16NoCrcParserState.GETTING_MSG_ID - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == MinimalFrameWithLen16NoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = MinimalFrameWithLen16NoCrcParserState.GETTING_LENGTH - - elif self.state == MinimalFrameWithLen16NoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 2: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = MinimalFrameWithLen16NoCrcParserState.GETTING_PAYLOAD - - elif self.state == MinimalFrameWithLen16NoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = MinimalFrameWithLen16NoCrcParserState.GETTING_MSG_ID - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with MinimalFrameWithLen16NoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.append((len(msg) >> 8) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete MinimalFrameWithLen16NoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < MinimalFrameWithLen16NoCrc.OVERHEAD: - return result - - - msg_length = len(buffer) - MinimalFrameWithLen16NoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[0] - result.msg_len = msg_length - result.msg_data = bytes(buffer[MinimalFrameWithLen16NoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/minimal_frame_with_len_no_crc.py b/src/struct_frame/boilerplate/py/minimal_frame_with_len_no_crc.py deleted file mode 100644 index 546ede0f..00000000 --- a/src/struct_frame/boilerplate/py/minimal_frame_with_len_no_crc.py +++ /dev/null @@ -1,126 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# MinimalFrameWithLenNoCrc Frame Format -# ============================================================================= - -class MinimalFrameWithLenNoCrcParserState(Enum): - GETTING_MSG_ID = 0 - GETTING_LENGTH = 1 - GETTING_PAYLOAD = 2 - - -class MinimalFrameWithLenNoCrc: - """ - MinimalFrameWithLenNoCrc - Frame format parser and encoder - - Format: [MSG_ID] [LEN] [MSG...] - """ - - HEADER_SIZE = 2 - FOOTER_SIZE = 0 - OVERHEAD = 2 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the MinimalFrameWithLenNoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = MinimalFrameWithLenNoCrcParserState.GETTING_MSG_ID - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == MinimalFrameWithLenNoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = MinimalFrameWithLenNoCrcParserState.GETTING_LENGTH - - elif self.state == MinimalFrameWithLenNoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = MinimalFrameWithLenNoCrcParserState.GETTING_PAYLOAD - - elif self.state == MinimalFrameWithLenNoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = MinimalFrameWithLenNoCrcParserState.GETTING_MSG_ID - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with MinimalFrameWithLenNoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete MinimalFrameWithLenNoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < MinimalFrameWithLenNoCrc.OVERHEAD: - return result - - - msg_length = len(buffer) - MinimalFrameWithLenNoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[0] - result.msg_len = msg_length - result.msg_data = bytes(buffer[MinimalFrameWithLenNoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame_with_len.py b/src/struct_frame/boilerplate/py/tiny_default.py similarity index 73% rename from src/struct_frame/boilerplate/py/tiny_frame_with_len.py rename to src/struct_frame/boilerplate/py/tiny_default.py index 16ef3eeb..25efcd78 100644 --- a/src/struct_frame/boilerplate/py/tiny_frame_with_len.py +++ b/src/struct_frame/boilerplate/py/tiny_default.py @@ -1,24 +1,24 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# TinyFrameWithLen Frame Format +# TinyDefault Frame Format # ============================================================================= -class TinyFrameWithLenParserState(Enum): +class TinyDefaultParserState(Enum): LOOKING_FOR_START = 0 GETTING_MSG_ID = 1 GETTING_LENGTH = 2 GETTING_PAYLOAD = 3 -class TinyFrameWithLen: +class TinyDefault: """ - TinyFrameWithLen - Frame format parser and encoder + TinyDefault - Frame format parser and encoder Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] """ @@ -31,7 +31,7 @@ class TinyFrameWithLen: def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the TinyFrameWithLen parser + Initialize the TinyDefault parser Args: get_msg_length: Callback function to get message length from msg_id @@ -42,7 +42,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = TinyFrameWithLenParserState.LOOKING_FOR_START + self.state = TinyDefaultParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -57,23 +57,23 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == TinyFrameWithLenParserState.LOOKING_FOR_START: + if self.state == TinyDefaultParserState.LOOKING_FOR_START: if byte == self.START_BYTE: self.buffer = [byte] - self.state = TinyFrameWithLenParserState.GETTING_MSG_ID + self.state = TinyDefaultParserState.GETTING_MSG_ID - elif self.state == TinyFrameWithLenParserState.GETTING_MSG_ID: + elif self.state == TinyDefaultParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = TinyFrameWithLenParserState.GETTING_LENGTH + self.state = TinyDefaultParserState.GETTING_LENGTH - elif self.state == TinyFrameWithLenParserState.GETTING_LENGTH: + elif self.state == TinyDefaultParserState.GETTING_LENGTH: self.buffer.append(byte) self.msg_length = byte self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyFrameWithLenParserState.GETTING_PAYLOAD + self.state = TinyDefaultParserState.GETTING_PAYLOAD - elif self.state == TinyFrameWithLenParserState.GETTING_PAYLOAD: + elif self.state == TinyDefaultParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -85,13 +85,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = TinyFrameWithLenParserState.LOOKING_FOR_START + self.state = TinyDefaultParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with TinyFrameWithLen format + Encode a message with TinyDefault format Args: msg_id: Message ID @@ -117,7 +117,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete TinyFrameWithLen packet in a buffer + Validate a complete TinyDefault packet in a buffer Args: buffer: Buffer containing the complete packet @@ -127,13 +127,13 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < TinyFrameWithLen.OVERHEAD: + if len(buffer) < TinyDefault.OVERHEAD: return result - if buffer[0] != TinyFrameWithLen.START_BYTE: + if buffer[0] != TinyDefault.START_BYTE: return result - msg_length = len(buffer) - TinyFrameWithLen.OVERHEAD + msg_length = len(buffer) - TinyDefault.OVERHEAD # Validate checksum ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1) @@ -141,6 +141,6 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: result.valid = True result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrameWithLen.HEADER_SIZE:len(buffer) - TinyFrameWithLen.FOOTER_SIZE]) + result.msg_data = bytes(buffer[TinyDefault.HEADER_SIZE:len(buffer) - TinyDefault.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/minimal_frame_with_len16.py b/src/struct_frame/boilerplate/py/tiny_extended.py similarity index 63% rename from src/struct_frame/boilerplate/py/minimal_frame_with_len16.py rename to src/struct_frame/boilerplate/py/tiny_extended.py index 0c620d5e..c6bf322d 100644 --- a/src/struct_frame/boilerplate/py/minimal_frame_with_len16.py +++ b/src/struct_frame/boilerplate/py/tiny_extended.py @@ -1,35 +1,37 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# MinimalFrameWithLen16 Frame Format +# TinyExtended Frame Format # ============================================================================= -class MinimalFrameWithLen16ParserState(Enum): - GETTING_MSG_ID = 0 - GETTING_LENGTH = 1 - GETTING_PAYLOAD = 2 +class TinyExtendedParserState(Enum): + LOOKING_FOR_START = 0 + GETTING_MSG_ID = 1 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 -class MinimalFrameWithLen16: +class TinyExtended: """ - MinimalFrameWithLen16 - Frame format parser and encoder + TinyExtended - Frame format parser and encoder - Format: [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] """ - HEADER_SIZE = 3 + START_BYTE = 0x74 + HEADER_SIZE = 5 FOOTER_SIZE = 2 - OVERHEAD = 5 + OVERHEAD = 7 LENGTH_BYTES = 2 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the MinimalFrameWithLen16 parser + Initialize the TinyExtended parser Args: get_msg_length: Callback function to get message length from msg_id @@ -40,7 +42,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = MinimalFrameWithLen16ParserState.GETTING_MSG_ID + self.state = TinyExtendedParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -56,39 +58,44 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == MinimalFrameWithLen16ParserState.GETTING_MSG_ID: + if self.state == TinyExtendedParserState.LOOKING_FOR_START: + if byte == self.START_BYTE: + self.buffer = [byte] + self.state = TinyExtendedParserState.GETTING_MSG_ID + + elif self.state == TinyExtendedParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = MinimalFrameWithLen16ParserState.GETTING_LENGTH + self.state = TinyExtendedParserState.GETTING_LENGTH - elif self.state == MinimalFrameWithLen16ParserState.GETTING_LENGTH: + elif self.state == TinyExtendedParserState.GETTING_LENGTH: self.buffer.append(byte) - if len(self.buffer) == 2: + if len(self.buffer) == 3: self.length_lo = byte else: self.msg_length = self.length_lo | (byte << 8) self.packet_size = self.OVERHEAD + self.msg_length - self.state = MinimalFrameWithLen16ParserState.GETTING_PAYLOAD + self.state = TinyExtendedParserState.GETTING_PAYLOAD - elif self.state == MinimalFrameWithLen16ParserState.GETTING_PAYLOAD: + elif self.state == TinyExtendedParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: # Validate checksum msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 0, 0 + msg_length + 1 + 2) + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 2) if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: result.valid = True result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = MinimalFrameWithLen16ParserState.GETTING_MSG_ID + self.state = TinyExtendedParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with MinimalFrameWithLen16 format + Encode a message with TinyExtended format Args: msg_id: Message ID @@ -98,11 +105,12 @@ def encode(self, msg_id: int, msg: bytes) -> bytes: Encoded frame as bytes """ output = [] + output.append(self.START_BYTE) output.append(msg_id) output.append(len(msg) & 0xFF) output.append((len(msg) >> 8) & 0xFF) output.extend(msg) - ck = fletcher_checksum(output, 0, 0 + len(msg) + 1 + 2) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 2) output.append(ck[0]) output.append(ck[1]) return bytes(output) @@ -114,7 +122,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete MinimalFrameWithLen16 packet in a buffer + Validate a complete TinyExtended packet in a buffer Args: buffer: Buffer containing the complete packet @@ -124,18 +132,20 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < MinimalFrameWithLen16.OVERHEAD: + if len(buffer) < TinyExtended.OVERHEAD: return result + if buffer[0] != TinyExtended.START_BYTE: + return result - msg_length = len(buffer) - MinimalFrameWithLen16.OVERHEAD + msg_length = len(buffer) - TinyExtended.OVERHEAD # Validate checksum - ck = fletcher_checksum(buffer, 0, 0 + msg_length + 1 + 2) + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2) if ck[0] == buffer[-2] and ck[1] == buffer[-1]: result.valid = True - result.msg_id = buffer[0] + result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[MinimalFrameWithLen16.HEADER_SIZE:len(buffer) - MinimalFrameWithLen16.FOOTER_SIZE]) + result.msg_data = bytes(buffer[TinyExtended.HEADER_SIZE:len(buffer) - TinyExtended.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame_with_len16.py b/src/struct_frame/boilerplate/py/tiny_extended_length.py similarity index 74% rename from src/struct_frame/boilerplate/py/tiny_frame_with_len16.py rename to src/struct_frame/boilerplate/py/tiny_extended_length.py index 86e861f5..87214843 100644 --- a/src/struct_frame/boilerplate/py/tiny_frame_with_len16.py +++ b/src/struct_frame/boilerplate/py/tiny_extended_length.py @@ -1,29 +1,29 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# TinyFrameWithLen16 Frame Format +# TinyExtendedLength Frame Format # ============================================================================= -class TinyFrameWithLen16ParserState(Enum): +class TinyExtendedLengthParserState(Enum): LOOKING_FOR_START = 0 GETTING_MSG_ID = 1 GETTING_LENGTH = 2 GETTING_PAYLOAD = 3 -class TinyFrameWithLen16: +class TinyExtendedLength: """ - TinyFrameWithLen16 - Frame format parser and encoder + TinyExtendedLength - Frame format parser and encoder - Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] """ - START_BYTE = 0x74 + START_BYTE = 0x73 HEADER_SIZE = 4 FOOTER_SIZE = 2 OVERHEAD = 6 @@ -31,7 +31,7 @@ class TinyFrameWithLen16: def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the TinyFrameWithLen16 parser + Initialize the TinyExtendedLength parser Args: get_msg_length: Callback function to get message length from msg_id @@ -42,7 +42,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = TinyFrameWithLen16ParserState.LOOKING_FOR_START + self.state = TinyExtendedLengthParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -58,26 +58,26 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == TinyFrameWithLen16ParserState.LOOKING_FOR_START: + if self.state == TinyExtendedLengthParserState.LOOKING_FOR_START: if byte == self.START_BYTE: self.buffer = [byte] - self.state = TinyFrameWithLen16ParserState.GETTING_MSG_ID + self.state = TinyExtendedLengthParserState.GETTING_MSG_ID - elif self.state == TinyFrameWithLen16ParserState.GETTING_MSG_ID: + elif self.state == TinyExtendedLengthParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = TinyFrameWithLen16ParserState.GETTING_LENGTH + self.state = TinyExtendedLengthParserState.GETTING_LENGTH - elif self.state == TinyFrameWithLen16ParserState.GETTING_LENGTH: + elif self.state == TinyExtendedLengthParserState.GETTING_LENGTH: self.buffer.append(byte) if len(self.buffer) == 3: self.length_lo = byte else: self.msg_length = self.length_lo | (byte << 8) self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyFrameWithLen16ParserState.GETTING_PAYLOAD + self.state = TinyExtendedLengthParserState.GETTING_PAYLOAD - elif self.state == TinyFrameWithLen16ParserState.GETTING_PAYLOAD: + elif self.state == TinyExtendedLengthParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -89,13 +89,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = TinyFrameWithLen16ParserState.LOOKING_FOR_START + self.state = TinyExtendedLengthParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with TinyFrameWithLen16 format + Encode a message with TinyExtendedLength format Args: msg_id: Message ID @@ -122,7 +122,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete TinyFrameWithLen16 packet in a buffer + Validate a complete TinyExtendedLength packet in a buffer Args: buffer: Buffer containing the complete packet @@ -132,13 +132,13 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < TinyFrameWithLen16.OVERHEAD: + if len(buffer) < TinyExtendedLength.OVERHEAD: return result - if buffer[0] != TinyFrameWithLen16.START_BYTE: + if buffer[0] != TinyExtendedLength.START_BYTE: return result - msg_length = len(buffer) - TinyFrameWithLen16.OVERHEAD + msg_length = len(buffer) - TinyExtendedLength.OVERHEAD # Validate checksum ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2) @@ -146,6 +146,6 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: result.valid = True result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrameWithLen16.HEADER_SIZE:len(buffer) - TinyFrameWithLen16.FOOTER_SIZE]) + result.msg_data = bytes(buffer[TinyExtendedLength.HEADER_SIZE:len(buffer) - TinyExtendedLength.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py b/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py new file mode 100644 index 00000000..a8d4d6db --- /dev/null +++ b/src/struct_frame/boilerplate/py/tiny_extended_msg_ids.py @@ -0,0 +1,146 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# TinyExtendedMsgIds Frame Format +# ============================================================================= + +class TinyExtendedMsgIdsParserState(Enum): + LOOKING_FOR_START = 0 + GETTING_MSG_ID = 1 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 + + +class TinyExtendedMsgIds: + """ + TinyExtendedMsgIds - Frame format parser and encoder + + Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE = 0x72 + HEADER_SIZE = 4 + FOOTER_SIZE = 2 + OVERHEAD = 6 + LENGTH_BYTES = 1 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the TinyExtendedMsgIds parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == TinyExtendedMsgIdsParserState.LOOKING_FOR_START: + if byte == self.START_BYTE: + self.buffer = [byte] + self.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID + + elif self.state == TinyExtendedMsgIdsParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH + + elif self.state == TinyExtendedMsgIdsParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD + + elif self.state == TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 1) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with TinyExtendedMsgIds format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 1) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete TinyExtendedMsgIds packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < TinyExtendedMsgIds.OVERHEAD: + return result + + if buffer[0] != TinyExtendedMsgIds.START_BYTE: + return result + + msg_length = len(buffer) - TinyExtendedMsgIds.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[1] + result.msg_len = msg_length + result.msg_data = bytes(buffer[TinyExtendedMsgIds.HEADER_SIZE:len(buffer) - TinyExtendedMsgIds.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py b/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py new file mode 100644 index 00000000..70adf9d9 --- /dev/null +++ b/src/struct_frame/boilerplate/py/tiny_extended_multi_system_stream.py @@ -0,0 +1,151 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# TinyExtendedMultiSystemStream Frame Format +# ============================================================================= + +class TinyExtendedMultiSystemStreamParserState(Enum): + LOOKING_FOR_START = 0 + GETTING_MSG_ID = 1 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 + + +class TinyExtendedMultiSystemStream: + """ + TinyExtendedMultiSystemStream - Frame format parser and encoder + + Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE = 0x78 + HEADER_SIZE = 8 + FOOTER_SIZE = 2 + OVERHEAD = 10 + LENGTH_BYTES = 2 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the TinyExtendedMultiSystemStream parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + self.length_lo = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: + if byte == self.START_BYTE: + self.buffer = [byte] + self.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID + + elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH + + elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: + self.buffer.append(byte) + if len(self.buffer) == 3: + self.length_lo = byte + else: + self.msg_length = self.length_lo | (byte << 8) + self.packet_size = self.OVERHEAD + self.msg_length + self.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD + + elif self.state == TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 2) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with TinyExtendedMultiSystemStream format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.append((len(msg) >> 8) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 2) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete TinyExtendedMultiSystemStream packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < TinyExtendedMultiSystemStream.OVERHEAD: + return result + + if buffer[0] != TinyExtendedMultiSystemStream.START_BYTE: + return result + + msg_length = len(buffer) - TinyExtendedMultiSystemStream.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[1] + result.msg_len = msg_length + result.msg_data = bytes(buffer[TinyExtendedMultiSystemStream.HEADER_SIZE:len(buffer) - TinyExtendedMultiSystemStream.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame_with_len16_no_crc.py b/src/struct_frame/boilerplate/py/tiny_frame_with_len16_no_crc.py deleted file mode 100644 index b00e879d..00000000 --- a/src/struct_frame/boilerplate/py/tiny_frame_with_len16_no_crc.py +++ /dev/null @@ -1,141 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# TinyFrameWithLen16NoCrc Frame Format -# ============================================================================= - -class TinyFrameWithLen16NoCrcParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyFrameWithLen16NoCrc: - """ - TinyFrameWithLen16NoCrc - Frame format parser and encoder - - Format: [START_BYTE=0x75] [MSG_ID] [LEN16] [MSG...] - """ - - START_BYTE = 0x75 - HEADER_SIZE = 4 - FOOTER_SIZE = 0 - OVERHEAD = 4 - LENGTH_BYTES = 2 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyFrameWithLen16NoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyFrameWithLen16NoCrcParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - self.length_lo = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyFrameWithLen16NoCrcParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyFrameWithLen16NoCrcParserState.GETTING_MSG_ID - - elif self.state == TinyFrameWithLen16NoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyFrameWithLen16NoCrcParserState.GETTING_LENGTH - - elif self.state == TinyFrameWithLen16NoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - if len(self.buffer) == 3: - self.length_lo = byte - else: - self.msg_length = self.length_lo | (byte << 8) - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyFrameWithLen16NoCrcParserState.GETTING_PAYLOAD - - elif self.state == TinyFrameWithLen16NoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = TinyFrameWithLen16NoCrcParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyFrameWithLen16NoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.append((len(msg) >> 8) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyFrameWithLen16NoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < TinyFrameWithLen16NoCrc.OVERHEAD: - return result - - if buffer[0] != TinyFrameWithLen16NoCrc.START_BYTE: - return result - - msg_length = len(buffer) - TinyFrameWithLen16NoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[1] - result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrameWithLen16NoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame_with_len_no_crc.py b/src/struct_frame/boilerplate/py/tiny_frame_with_len_no_crc.py deleted file mode 100644 index 6db4a26b..00000000 --- a/src/struct_frame/boilerplate/py/tiny_frame_with_len_no_crc.py +++ /dev/null @@ -1,136 +0,0 @@ -# Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. - -from enum import Enum -from typing import Callable, List, Union -from .frame_base import FrameMsgInfo, fletcher_checksum - -# ============================================================================= -# TinyFrameWithLenNoCrc Frame Format -# ============================================================================= - -class TinyFrameWithLenNoCrcParserState(Enum): - LOOKING_FOR_START = 0 - GETTING_MSG_ID = 1 - GETTING_LENGTH = 2 - GETTING_PAYLOAD = 3 - - -class TinyFrameWithLenNoCrc: - """ - TinyFrameWithLenNoCrc - Frame format parser and encoder - - Format: [START_BYTE=0x73] [MSG_ID] [LEN] [MSG...] - """ - - START_BYTE = 0x73 - HEADER_SIZE = 3 - FOOTER_SIZE = 0 - OVERHEAD = 3 - LENGTH_BYTES = 1 - - def __init__(self, get_msg_length: Callable[[int], int] = None): - """ - Initialize the TinyFrameWithLenNoCrc parser - - Args: - get_msg_length: Callback function to get message length from msg_id - Required for formats without a length field - """ - self.get_msg_length = get_msg_length - self.reset() - - def reset(self): - """Reset parser state""" - self.state = TinyFrameWithLenNoCrcParserState.LOOKING_FOR_START - self.buffer = [] - self.packet_size = 0 - self.msg_id = 0 - self.msg_length = 0 - - def parse_byte(self, byte: int) -> FrameMsgInfo: - """ - Parse a single byte - - Returns: - FrameMsgInfo with valid=True when a complete valid message is received - """ - result = FrameMsgInfo() - - if self.state == TinyFrameWithLenNoCrcParserState.LOOKING_FOR_START: - if byte == self.START_BYTE: - self.buffer = [byte] - self.state = TinyFrameWithLenNoCrcParserState.GETTING_MSG_ID - - elif self.state == TinyFrameWithLenNoCrcParserState.GETTING_MSG_ID: - self.buffer.append(byte) - self.msg_id = byte - self.state = TinyFrameWithLenNoCrcParserState.GETTING_LENGTH - - elif self.state == TinyFrameWithLenNoCrcParserState.GETTING_LENGTH: - self.buffer.append(byte) - self.msg_length = byte - self.packet_size = self.OVERHEAD + self.msg_length - self.state = TinyFrameWithLenNoCrcParserState.GETTING_PAYLOAD - - elif self.state == TinyFrameWithLenNoCrcParserState.GETTING_PAYLOAD: - self.buffer.append(byte) - - if len(self.buffer) >= self.packet_size: - result.valid = True - result.msg_id = self.msg_id - result.msg_len = self.packet_size - self.OVERHEAD - result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = TinyFrameWithLenNoCrcParserState.LOOKING_FOR_START - - return result - - def encode(self, msg_id: int, msg: bytes) -> bytes: - """ - Encode a message with TinyFrameWithLenNoCrc format - - Args: - msg_id: Message ID - msg: Message data bytes - - Returns: - Encoded frame as bytes - """ - output = [] - output.append(self.START_BYTE) - output.append(msg_id) - output.append(len(msg) & 0xFF) - output.extend(msg) - return bytes(output) - - def encode_msg(self, msg) -> bytes: - """Encode a message object (must have msg_id and pack() method)""" - return self.encode(msg.msg_id, msg.pack()) - - @staticmethod - def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: - """ - Validate a complete TinyFrameWithLenNoCrc packet in a buffer - - Args: - buffer: Buffer containing the complete packet - - Returns: - FrameMsgInfo with valid=True if packet is valid - """ - result = FrameMsgInfo() - - if len(buffer) < TinyFrameWithLenNoCrc.OVERHEAD: - return result - - if buffer[0] != TinyFrameWithLenNoCrc.START_BYTE: - return result - - msg_length = len(buffer) - TinyFrameWithLenNoCrc.OVERHEAD - - result.valid = True - result.msg_id = buffer[1] - result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrameWithLenNoCrc.HEADER_SIZE:]) - - return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame_no_crc.py b/src/struct_frame/boilerplate/py/tiny_minimal.py similarity index 69% rename from src/struct_frame/boilerplate/py/tiny_frame_no_crc.py rename to src/struct_frame/boilerplate/py/tiny_minimal.py index cbf4d0c3..3ef9e57d 100644 --- a/src/struct_frame/boilerplate/py/tiny_frame_no_crc.py +++ b/src/struct_frame/boilerplate/py/tiny_minimal.py @@ -1,35 +1,35 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# TinyFrameNoCrc Frame Format +# TinyMinimal Frame Format # ============================================================================= -class TinyFrameNoCrcParserState(Enum): +class TinyMinimalParserState(Enum): LOOKING_FOR_START = 0 GETTING_MSG_ID = 1 GETTING_PAYLOAD = 2 -class TinyFrameNoCrc: +class TinyMinimal: """ - TinyFrameNoCrc - Frame format parser and encoder + TinyMinimal - Frame format parser and encoder - Format: [START_BYTE=0x72] [MSG_ID] [MSG...] + Format: [START_BYTE=0x70] [MSG_ID] [MSG...] """ - START_BYTE = 0x72 + START_BYTE = 0x70 HEADER_SIZE = 2 FOOTER_SIZE = 0 OVERHEAD = 2 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the TinyFrameNoCrc parser + Initialize the TinyMinimal parser Args: get_msg_length: Callback function to get message length from msg_id @@ -40,7 +40,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = TinyFrameNoCrcParserState.LOOKING_FOR_START + self.state = TinyMinimalParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -54,25 +54,25 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == TinyFrameNoCrcParserState.LOOKING_FOR_START: + if self.state == TinyMinimalParserState.LOOKING_FOR_START: if byte == self.START_BYTE: self.buffer = [byte] - self.state = TinyFrameNoCrcParserState.GETTING_MSG_ID + self.state = TinyMinimalParserState.GETTING_MSG_ID - elif self.state == TinyFrameNoCrcParserState.GETTING_MSG_ID: + elif self.state == TinyMinimalParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte if self.get_msg_length: msg_length = self.get_msg_length(byte) if msg_length is not None: self.packet_size = self.OVERHEAD + msg_length - self.state = TinyFrameNoCrcParserState.GETTING_PAYLOAD + self.state = TinyMinimalParserState.GETTING_PAYLOAD else: - self.state = TinyFrameNoCrcParserState.LOOKING_FOR_START + self.state = TinyMinimalParserState.LOOKING_FOR_START else: - self.state = TinyFrameNoCrcParserState.LOOKING_FOR_START + self.state = TinyMinimalParserState.LOOKING_FOR_START - elif self.state == TinyFrameNoCrcParserState.GETTING_PAYLOAD: + elif self.state == TinyMinimalParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: @@ -80,13 +80,13 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: result.msg_id = self.msg_id result.msg_len = self.packet_size - self.OVERHEAD result.msg_data = bytes(self.buffer[self.HEADER_SIZE:]) - self.state = TinyFrameNoCrcParserState.LOOKING_FOR_START + self.state = TinyMinimalParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with TinyFrameNoCrc format + Encode a message with TinyMinimal format Args: msg_id: Message ID @@ -108,7 +108,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete TinyFrameNoCrc packet in a buffer + Validate a complete TinyMinimal packet in a buffer Args: buffer: Buffer containing the complete packet @@ -118,17 +118,17 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < TinyFrameNoCrc.OVERHEAD: + if len(buffer) < TinyMinimal.OVERHEAD: return result - if buffer[0] != TinyFrameNoCrc.START_BYTE: + if buffer[0] != TinyMinimal.START_BYTE: return result - msg_length = len(buffer) - TinyFrameNoCrc.OVERHEAD + msg_length = len(buffer) - TinyMinimal.OVERHEAD result.valid = True result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrameNoCrc.HEADER_SIZE:]) + result.msg_data = bytes(buffer[TinyMinimal.HEADER_SIZE:]) return result diff --git a/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py b/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py new file mode 100644 index 00000000..721d6889 --- /dev/null +++ b/src/struct_frame/boilerplate/py/tiny_multi_system_stream.py @@ -0,0 +1,146 @@ +# Automatically generated frame parser +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +from enum import Enum +from typing import Callable, List, Union +from .frame_base import FrameMsgInfo, fletcher_checksum + +# ============================================================================= +# TinyMultiSystemStream Frame Format +# ============================================================================= + +class TinyMultiSystemStreamParserState(Enum): + LOOKING_FOR_START = 0 + GETTING_MSG_ID = 1 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 + + +class TinyMultiSystemStream: + """ + TinyMultiSystemStream - Frame format parser and encoder + + Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + """ + + START_BYTE = 0x77 + HEADER_SIZE = 6 + FOOTER_SIZE = 2 + OVERHEAD = 8 + LENGTH_BYTES = 1 + + def __init__(self, get_msg_length: Callable[[int], int] = None): + """ + Initialize the TinyMultiSystemStream parser + + Args: + get_msg_length: Callback function to get message length from msg_id + Required for formats without a length field + """ + self.get_msg_length = get_msg_length + self.reset() + + def reset(self): + """Reset parser state""" + self.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START + self.buffer = [] + self.packet_size = 0 + self.msg_id = 0 + self.msg_length = 0 + + def parse_byte(self, byte: int) -> FrameMsgInfo: + """ + Parse a single byte + + Returns: + FrameMsgInfo with valid=True when a complete valid message is received + """ + result = FrameMsgInfo() + + if self.state == TinyMultiSystemStreamParserState.LOOKING_FOR_START: + if byte == self.START_BYTE: + self.buffer = [byte] + self.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID + + elif self.state == TinyMultiSystemStreamParserState.GETTING_MSG_ID: + self.buffer.append(byte) + self.msg_id = byte + self.state = TinyMultiSystemStreamParserState.GETTING_LENGTH + + elif self.state == TinyMultiSystemStreamParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD + + elif self.state == TinyMultiSystemStreamParserState.GETTING_PAYLOAD: + self.buffer.append(byte) + + if len(self.buffer) >= self.packet_size: + # Validate checksum + msg_length = self.packet_size - self.OVERHEAD + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 1) + if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: + result.valid = True + result.msg_id = self.msg_id + result.msg_len = msg_length + result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) + self.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START + + return result + + def encode(self, msg_id: int, msg: bytes) -> bytes: + """ + Encode a message with TinyMultiSystemStream format + + Args: + msg_id: Message ID + msg: Message data bytes + + Returns: + Encoded frame as bytes + """ + output = [] + output.append(self.START_BYTE) + output.append(msg_id) + output.append(len(msg) & 0xFF) + output.extend(msg) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 1) + output.append(ck[0]) + output.append(ck[1]) + return bytes(output) + + def encode_msg(self, msg) -> bytes: + """Encode a message object (must have msg_id and pack() method)""" + return self.encode(msg.msg_id, msg.pack()) + + @staticmethod + def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: + """ + Validate a complete TinyMultiSystemStream packet in a buffer + + Args: + buffer: Buffer containing the complete packet + + Returns: + FrameMsgInfo with valid=True if packet is valid + """ + result = FrameMsgInfo() + + if len(buffer) < TinyMultiSystemStream.OVERHEAD: + return result + + if buffer[0] != TinyMultiSystemStream.START_BYTE: + return result + + msg_length = len(buffer) - TinyMultiSystemStream.OVERHEAD + + # Validate checksum + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1) + if ck[0] == buffer[-2] and ck[1] == buffer[-1]: + result.valid = True + result.msg_id = buffer[1] + result.msg_len = msg_length + result.msg_data = bytes(buffer[TinyMultiSystemStream.HEADER_SIZE:len(buffer) - TinyMultiSystemStream.FOOTER_SIZE]) + + return result diff --git a/src/struct_frame/boilerplate/py/tiny_frame.py b/src/struct_frame/boilerplate/py/tiny_seq.py similarity index 64% rename from src/struct_frame/boilerplate/py/tiny_frame.py rename to src/struct_frame/boilerplate/py/tiny_seq.py index 05284669..39797efe 100644 --- a/src/struct_frame/boilerplate/py/tiny_frame.py +++ b/src/struct_frame/boilerplate/py/tiny_seq.py @@ -1,35 +1,37 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# TinyFrame Frame Format +# TinySeq Frame Format # ============================================================================= -class TinyFrameParserState(Enum): +class TinySeqParserState(Enum): LOOKING_FOR_START = 0 GETTING_MSG_ID = 1 - GETTING_PAYLOAD = 2 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 -class TinyFrame: +class TinySeq: """ - TinyFrame - Frame format parser and encoder + TinySeq - Frame format parser and encoder - Format: [START_BYTE=0x70] [MSG_ID] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] """ - START_BYTE = 0x70 - HEADER_SIZE = 2 + START_BYTE = 0x76 + HEADER_SIZE = 4 FOOTER_SIZE = 2 - OVERHEAD = 4 + OVERHEAD = 6 + LENGTH_BYTES = 1 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the TinyFrame parser + Initialize the TinySeq parser Args: get_msg_length: Callback function to get message length from msg_id @@ -40,10 +42,11 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = TinyFrameParserState.LOOKING_FOR_START + self.state = TinySeqParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 + self.msg_length = 0 def parse_byte(self, byte: int) -> FrameMsgInfo: """ @@ -54,43 +57,41 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == TinyFrameParserState.LOOKING_FOR_START: + if self.state == TinySeqParserState.LOOKING_FOR_START: if byte == self.START_BYTE: self.buffer = [byte] - self.state = TinyFrameParserState.GETTING_MSG_ID + self.state = TinySeqParserState.GETTING_MSG_ID - elif self.state == TinyFrameParserState.GETTING_MSG_ID: + elif self.state == TinySeqParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - if self.get_msg_length: - msg_length = self.get_msg_length(byte) - if msg_length is not None: - self.packet_size = self.OVERHEAD + msg_length - self.state = TinyFrameParserState.GETTING_PAYLOAD - else: - self.state = TinyFrameParserState.LOOKING_FOR_START - else: - self.state = TinyFrameParserState.LOOKING_FOR_START - - elif self.state == TinyFrameParserState.GETTING_PAYLOAD: + self.state = TinySeqParserState.GETTING_LENGTH + + elif self.state == TinySeqParserState.GETTING_LENGTH: + self.buffer.append(byte) + self.msg_length = byte + self.packet_size = self.OVERHEAD + self.msg_length + self.state = TinySeqParserState.GETTING_PAYLOAD + + elif self.state == TinySeqParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: # Validate checksum msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1) + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 1) if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: result.valid = True result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = TinyFrameParserState.LOOKING_FOR_START + self.state = TinySeqParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with TinyFrame format + Encode a message with TinySeq format Args: msg_id: Message ID @@ -102,8 +103,9 @@ def encode(self, msg_id: int, msg: bytes) -> bytes: output = [] output.append(self.START_BYTE) output.append(msg_id) + output.append(len(msg) & 0xFF) output.extend(msg) - ck = fletcher_checksum(output, 1, 1 + len(msg) + 1) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 1) output.append(ck[0]) output.append(ck[1]) return bytes(output) @@ -115,7 +117,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete TinyFrame packet in a buffer + Validate a complete TinySeq packet in a buffer Args: buffer: Buffer containing the complete packet @@ -125,20 +127,20 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < TinyFrame.OVERHEAD: + if len(buffer) < TinySeq.OVERHEAD: return result - if buffer[0] != TinyFrame.START_BYTE: + if buffer[0] != TinySeq.START_BYTE: return result - msg_length = len(buffer) - TinyFrame.OVERHEAD + msg_length = len(buffer) - TinySeq.OVERHEAD # Validate checksum - ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1) + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1) if ck[0] == buffer[-2] and ck[1] == buffer[-1]: result.valid = True result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[TinyFrame.HEADER_SIZE:len(buffer) - TinyFrame.FOOTER_SIZE]) + result.msg_data = bytes(buffer[TinySeq.HEADER_SIZE:len(buffer) - TinySeq.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/minimal_frame_with_len.py b/src/struct_frame/boilerplate/py/tiny_sys_comp.py similarity index 62% rename from src/struct_frame/boilerplate/py/minimal_frame_with_len.py rename to src/struct_frame/boilerplate/py/tiny_sys_comp.py index e6a8346a..f2310ecb 100644 --- a/src/struct_frame/boilerplate/py/minimal_frame_with_len.py +++ b/src/struct_frame/boilerplate/py/tiny_sys_comp.py @@ -1,35 +1,37 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union from .frame_base import FrameMsgInfo, fletcher_checksum # ============================================================================= -# MinimalFrameWithLen Frame Format +# TinySysComp Frame Format # ============================================================================= -class MinimalFrameWithLenParserState(Enum): - GETTING_MSG_ID = 0 - GETTING_LENGTH = 1 - GETTING_PAYLOAD = 2 +class TinySysCompParserState(Enum): + LOOKING_FOR_START = 0 + GETTING_MSG_ID = 1 + GETTING_LENGTH = 2 + GETTING_PAYLOAD = 3 -class MinimalFrameWithLen: +class TinySysComp: """ - MinimalFrameWithLen - Frame format parser and encoder + TinySysComp - Frame format parser and encoder - Format: [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] """ - HEADER_SIZE = 2 + START_BYTE = 0x75 + HEADER_SIZE = 5 FOOTER_SIZE = 2 - OVERHEAD = 4 + OVERHEAD = 7 LENGTH_BYTES = 1 def __init__(self, get_msg_length: Callable[[int], int] = None): """ - Initialize the MinimalFrameWithLen parser + Initialize the TinySysComp parser Args: get_msg_length: Callback function to get message length from msg_id @@ -40,7 +42,7 @@ def __init__(self, get_msg_length: Callable[[int], int] = None): def reset(self): """Reset parser state""" - self.state = MinimalFrameWithLenParserState.GETTING_MSG_ID + self.state = TinySysCompParserState.LOOKING_FOR_START self.buffer = [] self.packet_size = 0 self.msg_id = 0 @@ -55,36 +57,41 @@ def parse_byte(self, byte: int) -> FrameMsgInfo: """ result = FrameMsgInfo() - if self.state == MinimalFrameWithLenParserState.GETTING_MSG_ID: + if self.state == TinySysCompParserState.LOOKING_FOR_START: + if byte == self.START_BYTE: + self.buffer = [byte] + self.state = TinySysCompParserState.GETTING_MSG_ID + + elif self.state == TinySysCompParserState.GETTING_MSG_ID: self.buffer.append(byte) self.msg_id = byte - self.state = MinimalFrameWithLenParserState.GETTING_LENGTH + self.state = TinySysCompParserState.GETTING_LENGTH - elif self.state == MinimalFrameWithLenParserState.GETTING_LENGTH: + elif self.state == TinySysCompParserState.GETTING_LENGTH: self.buffer.append(byte) self.msg_length = byte self.packet_size = self.OVERHEAD + self.msg_length - self.state = MinimalFrameWithLenParserState.GETTING_PAYLOAD + self.state = TinySysCompParserState.GETTING_PAYLOAD - elif self.state == MinimalFrameWithLenParserState.GETTING_PAYLOAD: + elif self.state == TinySysCompParserState.GETTING_PAYLOAD: self.buffer.append(byte) if len(self.buffer) >= self.packet_size: # Validate checksum msg_length = self.packet_size - self.OVERHEAD - ck = fletcher_checksum(self.buffer, 0, 0 + msg_length + 1 + 1) + ck = fletcher_checksum(self.buffer, 1, 1 + msg_length + 1 + 1) if ck[0] == self.buffer[-2] and ck[1] == self.buffer[-1]: result.valid = True result.msg_id = self.msg_id result.msg_len = msg_length result.msg_data = bytes(self.buffer[self.HEADER_SIZE:self.packet_size - self.FOOTER_SIZE]) - self.state = MinimalFrameWithLenParserState.GETTING_MSG_ID + self.state = TinySysCompParserState.LOOKING_FOR_START return result def encode(self, msg_id: int, msg: bytes) -> bytes: """ - Encode a message with MinimalFrameWithLen format + Encode a message with TinySysComp format Args: msg_id: Message ID @@ -94,10 +101,11 @@ def encode(self, msg_id: int, msg: bytes) -> bytes: Encoded frame as bytes """ output = [] + output.append(self.START_BYTE) output.append(msg_id) output.append(len(msg) & 0xFF) output.extend(msg) - ck = fletcher_checksum(output, 0, 0 + len(msg) + 1 + 1) + ck = fletcher_checksum(output, 1, 1 + len(msg) + 1 + 1) output.append(ck[0]) output.append(ck[1]) return bytes(output) @@ -109,7 +117,7 @@ def encode_msg(self, msg) -> bytes: @staticmethod def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ - Validate a complete MinimalFrameWithLen packet in a buffer + Validate a complete TinySysComp packet in a buffer Args: buffer: Buffer containing the complete packet @@ -119,18 +127,20 @@ def validate_packet(buffer: Union[bytes, List[int]]) -> FrameMsgInfo: """ result = FrameMsgInfo() - if len(buffer) < MinimalFrameWithLen.OVERHEAD: + if len(buffer) < TinySysComp.OVERHEAD: return result + if buffer[0] != TinySysComp.START_BYTE: + return result - msg_length = len(buffer) - MinimalFrameWithLen.OVERHEAD + msg_length = len(buffer) - TinySysComp.OVERHEAD # Validate checksum - ck = fletcher_checksum(buffer, 0, 0 + msg_length + 1 + 1) + ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1) if ck[0] == buffer[-2] and ck[1] == buffer[-1]: result.valid = True - result.msg_id = buffer[0] + result.msg_id = buffer[1] result.msg_len = msg_length - result.msg_data = bytes(buffer[MinimalFrameWithLen.HEADER_SIZE:len(buffer) - MinimalFrameWithLen.FOOTER_SIZE]) + result.msg_data = bytes(buffer[TinySysComp.HEADER_SIZE:len(buffer) - TinySysComp.FOOTER_SIZE]) return result diff --git a/src/struct_frame/boilerplate/py/ubx_frame.py b/src/struct_frame/boilerplate/py/ubx_frame.py index 3c09bc7a..cf048fe5 100644 --- a/src/struct_frame/boilerplate/py/ubx_frame.py +++ b/src/struct_frame/boilerplate/py/ubx_frame.py @@ -1,5 +1,5 @@ # Automatically generated frame parser -# Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +# Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. from enum import Enum from typing import Callable, List, Union diff --git a/src/struct_frame/boilerplate/ts/BasicDefault.ts b/src/struct_frame/boilerplate/ts/BasicDefault.ts new file mode 100644 index 00000000..64b08bb3 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicDefault.ts @@ -0,0 +1,175 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicDefault Frame Format +// ============================================================================= + +export enum BasicDefaultParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicDefault - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class BasicDefault { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x71; + static readonly HEADER_SIZE = 4; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 6; + static readonly LENGTH_BYTES = 1; + + private state: BasicDefaultParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicDefault parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicDefaultParserState.LOOKING_FOR_START1: + if (byte === BasicDefault.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicDefaultParserState.LOOKING_FOR_START2; + } + break; + + case BasicDefaultParserState.LOOKING_FOR_START2: + if (byte === BasicDefault.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicDefaultParserState.GETTING_MSG_ID; + } else if (byte === BasicDefault.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicDefaultParserState.LOOKING_FOR_START2; + } else { + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + } + break; + + case BasicDefaultParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicDefaultParserState.GETTING_LENGTH; + break; + + case BasicDefaultParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicDefault.OVERHEAD + this.msg_length; + this.state = BasicDefaultParserState.GETTING_PAYLOAD; + break; + + case BasicDefaultParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicDefault.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicDefault.HEADER_SIZE, this.packet_size - BasicDefault.FOOTER_SIZE)); + } + this.state = BasicDefaultParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicDefault format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicDefault.START_BYTE1); + output.push(BasicDefault.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicDefault packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicDefault.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicDefault.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicDefault.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicDefault.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicDefault.HEADER_SIZE, buffer.length - BasicDefault.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicExtended.ts b/src/struct_frame/boilerplate/ts/BasicExtended.ts new file mode 100644 index 00000000..3771dcad --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicExtended.ts @@ -0,0 +1,182 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicExtended Frame Format +// ============================================================================= + +export enum BasicExtendedParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicExtended - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class BasicExtended { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x74; + static readonly HEADER_SIZE = 6; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 8; + static readonly LENGTH_BYTES = 2; + + private state: BasicExtendedParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicExtended parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedParserState.LOOKING_FOR_START1: + if (byte === BasicExtended.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedParserState.LOOKING_FOR_START2: + if (byte === BasicExtended.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedParserState.GETTING_MSG_ID; + } else if (byte === BasicExtended.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedParserState.GETTING_LENGTH; + break; + + case BasicExtendedParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtended.OVERHEAD + this.msg_length; + this.state = BasicExtendedParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicExtended.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtended.HEADER_SIZE, this.packet_size - BasicExtended.FOOTER_SIZE)); + } + this.state = BasicExtendedParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicExtended format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicExtended.START_BYTE1); + output.push(BasicExtended.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicExtended packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtended.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtended.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtended.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtended.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtended.HEADER_SIZE, buffer.length - BasicExtended.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts b/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts new file mode 100644 index 00000000..2605cbe0 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicExtendedLength.ts @@ -0,0 +1,182 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicExtendedLength Frame Format +// ============================================================================= + +export enum BasicExtendedLengthParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicExtendedLength - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class BasicExtendedLength { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x73; + static readonly HEADER_SIZE = 5; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 7; + static readonly LENGTH_BYTES = 2; + + private state: BasicExtendedLengthParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicExtendedLength parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedLengthParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedLength.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedLengthParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedLength.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedLengthParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedLength.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedLengthParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedLengthParserState.GETTING_LENGTH; + break; + + case BasicExtendedLengthParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtendedLength.OVERHEAD + this.msg_length; + this.state = BasicExtendedLengthParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedLengthParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicExtendedLength.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedLength.HEADER_SIZE, this.packet_size - BasicExtendedLength.FOOTER_SIZE)); + } + this.state = BasicExtendedLengthParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicExtendedLength format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicExtendedLength.START_BYTE1); + output.push(BasicExtendedLength.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicExtendedLength packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedLength.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedLength.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedLength.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedLength.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedLength.HEADER_SIZE, buffer.length - BasicExtendedLength.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts b/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts new file mode 100644 index 00000000..18df02be --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicExtendedMsgIds.ts @@ -0,0 +1,175 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicExtendedMsgIds Frame Format +// ============================================================================= + +export enum BasicExtendedMsgIdsParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicExtendedMsgIds - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class BasicExtendedMsgIds { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x72; + static readonly HEADER_SIZE = 5; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 7; + static readonly LENGTH_BYTES = 1; + + private state: BasicExtendedMsgIdsParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicExtendedMsgIds parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedMsgIdsParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedMsgIds.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedMsgIdsParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedMsgIds.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedMsgIdsParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedMsgIds.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedMsgIdsParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedMsgIdsParserState.GETTING_LENGTH; + break; + + case BasicExtendedMsgIdsParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicExtendedMsgIds.OVERHEAD + this.msg_length; + this.state = BasicExtendedMsgIdsParserState.GETTING_PAYLOAD; + break; + + case BasicExtendedMsgIdsParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicExtendedMsgIds.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedMsgIds.HEADER_SIZE, this.packet_size - BasicExtendedMsgIds.FOOTER_SIZE)); + } + this.state = BasicExtendedMsgIdsParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicExtendedMsgIds format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicExtendedMsgIds.START_BYTE1); + output.push(BasicExtendedMsgIds.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicExtendedMsgIds packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedMsgIds.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedMsgIds.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedMsgIds.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedMsgIds.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedMsgIds.HEADER_SIZE, buffer.length - BasicExtendedMsgIds.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts new file mode 100644 index 00000000..f8a6800a --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicExtendedMultiSystemStream.ts @@ -0,0 +1,182 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicExtendedMultiSystemStream Frame Format +// ============================================================================= + +export enum BasicExtendedMultiSystemStreamParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicExtendedMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class BasicExtendedMultiSystemStream { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x78; + static readonly HEADER_SIZE = 9; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 11; + static readonly LENGTH_BYTES = 2; + + private state: BasicExtendedMultiSystemStreamParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicExtendedMultiSystemStream parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1: + if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; + } + break; + + case BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2: + if (byte === BasicExtendedMultiSystemStream.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID; + } else if (byte === BasicExtendedMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START2; + } else { + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 4) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = BasicExtendedMultiSystemStream.OVERHEAD + this.msg_length; + this.state = BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; + } + break; + + case BasicExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicExtendedMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicExtendedMultiSystemStream.HEADER_SIZE, this.packet_size - BasicExtendedMultiSystemStream.FOOTER_SIZE)); + } + this.state = BasicExtendedMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicExtendedMultiSystemStream format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicExtendedMultiSystemStream.START_BYTE1); + output.push(BasicExtendedMultiSystemStream.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicExtendedMultiSystemStream packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicExtendedMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicExtendedMultiSystemStream.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicExtendedMultiSystemStream.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicExtendedMultiSystemStream.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicExtendedMultiSystemStream.HEADER_SIZE, buffer.length - BasicExtendedMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicMinimal.ts b/src/struct_frame/boilerplate/ts/BasicMinimal.ts new file mode 100644 index 00000000..b08ba744 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicMinimal.ts @@ -0,0 +1,160 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicMinimal Frame Format +// ============================================================================= + +export enum BasicMinimalParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_PAYLOAD = 3 +} + +/** + * BasicMinimal - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x70] [MSG_ID] [MSG...] + */ +export class BasicMinimal { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x70; + static readonly HEADER_SIZE = 3; + static readonly FOOTER_SIZE = 0; + static readonly OVERHEAD = 3; + + private state: BasicMinimalParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicMinimal parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicMinimalParserState.LOOKING_FOR_START1: + if (byte === BasicMinimal.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMinimalParserState.LOOKING_FOR_START2; + } + break; + + case BasicMinimalParserState.LOOKING_FOR_START2: + if (byte === BasicMinimal.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicMinimalParserState.GETTING_MSG_ID; + } else if (byte === BasicMinimal.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMinimalParserState.LOOKING_FOR_START2; + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + + case BasicMinimalParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.get_msg_length) { + const msg_length = this.get_msg_length(byte); + if (msg_length !== undefined) { + this.packet_size = BasicMinimal.OVERHEAD + msg_length; + this.state = BasicMinimalParserState.GETTING_PAYLOAD; + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + } else { + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + + case BasicMinimalParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = this.packet_size - BasicMinimal.OVERHEAD; + result.msg_data = new Uint8Array(this.buffer.slice(BasicMinimal.HEADER_SIZE)); + this.state = BasicMinimalParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicMinimal format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicMinimal.START_BYTE1); + output.push(BasicMinimal.START_BYTE2); + output.push(msg_id); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + return new Uint8Array(output); + } + + /** + * Validate a complete BasicMinimal packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicMinimal.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicMinimal.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicMinimal.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicMinimal.OVERHEAD; + + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicMinimal.HEADER_SIZE)); + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts new file mode 100644 index 00000000..6cd2cef2 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicMultiSystemStream.ts @@ -0,0 +1,175 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicMultiSystemStream Frame Format +// ============================================================================= + +export enum BasicMultiSystemStreamParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class BasicMultiSystemStream { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x77; + static readonly HEADER_SIZE = 7; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 9; + static readonly LENGTH_BYTES = 1; + + private state: BasicMultiSystemStreamParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicMultiSystemStream parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicMultiSystemStreamParserState.LOOKING_FOR_START1: + if (byte === BasicMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; + } + break; + + case BasicMultiSystemStreamParserState.LOOKING_FOR_START2: + if (byte === BasicMultiSystemStream.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicMultiSystemStreamParserState.GETTING_MSG_ID; + } else if (byte === BasicMultiSystemStream.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START2; + } else { + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + + case BasicMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case BasicMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicMultiSystemStream.OVERHEAD + this.msg_length; + this.state = BasicMultiSystemStreamParserState.GETTING_PAYLOAD; + break; + + case BasicMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicMultiSystemStream.HEADER_SIZE, this.packet_size - BasicMultiSystemStream.FOOTER_SIZE)); + } + this.state = BasicMultiSystemStreamParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicMultiSystemStream format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicMultiSystemStream.START_BYTE1); + output.push(BasicMultiSystemStream.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicMultiSystemStream packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicMultiSystemStream.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicMultiSystemStream.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicMultiSystemStream.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicMultiSystemStream.HEADER_SIZE, buffer.length - BasicMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicSeq.ts b/src/struct_frame/boilerplate/ts/BasicSeq.ts new file mode 100644 index 00000000..4a684e36 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicSeq.ts @@ -0,0 +1,175 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicSeq Frame Format +// ============================================================================= + +export enum BasicSeqParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicSeq - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class BasicSeq { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x76; + static readonly HEADER_SIZE = 5; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 7; + static readonly LENGTH_BYTES = 1; + + private state: BasicSeqParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicSeq parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicSeqParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicSeqParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicSeqParserState.LOOKING_FOR_START1: + if (byte === BasicSeq.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSeqParserState.LOOKING_FOR_START2; + } + break; + + case BasicSeqParserState.LOOKING_FOR_START2: + if (byte === BasicSeq.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicSeqParserState.GETTING_MSG_ID; + } else if (byte === BasicSeq.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSeqParserState.LOOKING_FOR_START2; + } else { + this.state = BasicSeqParserState.LOOKING_FOR_START1; + } + break; + + case BasicSeqParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicSeqParserState.GETTING_LENGTH; + break; + + case BasicSeqParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicSeq.OVERHEAD + this.msg_length; + this.state = BasicSeqParserState.GETTING_PAYLOAD; + break; + + case BasicSeqParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicSeq.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicSeq.HEADER_SIZE, this.packet_size - BasicSeq.FOOTER_SIZE)); + } + this.state = BasicSeqParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicSeq format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicSeq.START_BYTE1); + output.push(BasicSeq.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicSeq packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicSeq.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicSeq.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicSeq.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicSeq.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicSeq.HEADER_SIZE, buffer.length - BasicSeq.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/BasicSysComp.ts b/src/struct_frame/boilerplate/ts/BasicSysComp.ts new file mode 100644 index 00000000..6af82076 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/BasicSysComp.ts @@ -0,0 +1,175 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// BasicSysComp Frame Format +// ============================================================================= + +export enum BasicSysCompParserState { + LOOKING_FOR_START1 = 0, + LOOKING_FOR_START2 = 1, + GETTING_MSG_ID = 2, + GETTING_LENGTH = 3, + GETTING_PAYLOAD = 4 +} + +/** + * BasicSysComp - Frame format parser and encoder + * + * Format: [START_BYTE1=0x90] [START_BYTE2=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class BasicSysComp { + static readonly START_BYTE1 = 0x90; + static readonly START_BYTE2 = 0x75; + static readonly HEADER_SIZE = 6; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 8; + static readonly LENGTH_BYTES = 1; + + private state: BasicSysCompParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new BasicSysComp parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case BasicSysCompParserState.LOOKING_FOR_START1: + if (byte === BasicSysComp.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSysCompParserState.LOOKING_FOR_START2; + } + break; + + case BasicSysCompParserState.LOOKING_FOR_START2: + if (byte === BasicSysComp.START_BYTE2) { + this.buffer.push(byte); + this.state = BasicSysCompParserState.GETTING_MSG_ID; + } else if (byte === BasicSysComp.START_BYTE1) { + this.buffer = [byte]; + this.state = BasicSysCompParserState.LOOKING_FOR_START2; + } else { + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + } + break; + + case BasicSysCompParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = BasicSysCompParserState.GETTING_LENGTH; + break; + + case BasicSysCompParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = BasicSysComp.OVERHEAD + this.msg_length; + this.state = BasicSysCompParserState.GETTING_PAYLOAD; + break; + + case BasicSysCompParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - BasicSysComp.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(BasicSysComp.HEADER_SIZE, this.packet_size - BasicSysComp.FOOTER_SIZE)); + } + this.state = BasicSysCompParserState.LOOKING_FOR_START1; + } + break; + } + + return result; + } + + /** + * Encode a message with BasicSysComp format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(BasicSysComp.START_BYTE1); + output.push(BasicSysComp.START_BYTE2); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 2, 2 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete BasicSysComp packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < BasicSysComp.OVERHEAD) { + return result; + } + + if (buffer[0] !== BasicSysComp.START_BYTE1) { + return result; + } + if (buffer[1] !== BasicSysComp.START_BYTE2) { + return result; + } + + const msg_length = buffer.length - BasicSysComp.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 2, 2 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[2]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, BasicSysComp.HEADER_SIZE, buffer.length - BasicSysComp.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts b/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts index 76e80b2d..60774f83 100644 --- a/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts +++ b/src/struct_frame/boilerplate/ts/FrameFormatConfig.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; @@ -17,11 +17,11 @@ export enum FrameFormatConfigParserState { /** * FrameFormatConfig - Frame format parser and encoder * - * Format: [START_BYTE1=0x90] [START_BYTE2=0x91] [MSG_ID] [MSG...] [CRC1] [CRC2] + * Format: [START_BYTE1=0x90] [START_BYTE2=0x71] [MSG_ID] [MSG...] [CRC1] [CRC2] */ export class FrameFormatConfig { static readonly START_BYTE1 = 0x90; - static readonly START_BYTE2 = 0x91; + static readonly START_BYTE2 = 0x71; static readonly HEADER_SIZE = 2; static readonly FOOTER_SIZE = 1; static readonly OVERHEAD = 3; diff --git a/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts b/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts index e143ce51..77349218 100644 --- a/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts +++ b/src/struct_frame/boilerplate/ts/MavlinkV1Frame.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; @@ -21,9 +21,9 @@ export enum MavlinkV1FrameParserState { */ export class MavlinkV1Frame { static readonly START_BYTE = 0xFE; - static readonly HEADER_SIZE = 3; + static readonly HEADER_SIZE = 6; static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 5; + static readonly OVERHEAD = 8; static readonly LENGTH_BYTES = 1; private state: MavlinkV1FrameParserState; diff --git a/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts b/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts index f80bb848..47df48c2 100644 --- a/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts +++ b/src/struct_frame/boilerplate/ts/MavlinkV2Frame.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; @@ -21,9 +21,9 @@ export enum MavlinkV2FrameParserState { */ export class MavlinkV2Frame { static readonly START_BYTE = 0xFD; - static readonly HEADER_SIZE = 5; + static readonly HEADER_SIZE = 8; static readonly FOOTER_SIZE = 2; - static readonly OVERHEAD = 7; + static readonly OVERHEAD = 10; static readonly LENGTH_BYTES = 1; private state: MavlinkV2FrameParserState; diff --git a/src/struct_frame/boilerplate/ts/TinyDefault.ts b/src/struct_frame/boilerplate/ts/TinyDefault.ts new file mode 100644 index 00000000..8a14d075 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyDefault.ts @@ -0,0 +1,157 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyDefault Frame Format +// ============================================================================= + +export enum TinyDefaultParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyDefault - Frame format parser and encoder + * + * Format: [START_BYTE=0x71] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class TinyDefault { + static readonly START_BYTE = 0x71; + static readonly HEADER_SIZE = 3; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 5; + static readonly LENGTH_BYTES = 1; + + private state: TinyDefaultParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyDefault parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyDefaultParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyDefaultParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyDefaultParserState.LOOKING_FOR_START: + if (byte === TinyDefault.START_BYTE) { + this.buffer = [byte]; + this.state = TinyDefaultParserState.GETTING_MSG_ID; + } + break; + + case TinyDefaultParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyDefaultParserState.GETTING_LENGTH; + break; + + case TinyDefaultParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyDefault.OVERHEAD + this.msg_length; + this.state = TinyDefaultParserState.GETTING_PAYLOAD; + break; + + case TinyDefaultParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyDefault.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyDefault.HEADER_SIZE, this.packet_size - TinyDefault.FOOTER_SIZE)); + } + this.state = TinyDefaultParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyDefault format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyDefault.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyDefault packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyDefault.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyDefault.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyDefault.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyDefault.HEADER_SIZE, buffer.length - TinyDefault.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyExtended.ts b/src/struct_frame/boilerplate/ts/TinyExtended.ts new file mode 100644 index 00000000..35292c40 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyExtended.ts @@ -0,0 +1,164 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyExtended Frame Format +// ============================================================================= + +export enum TinyExtendedParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyExtended - Frame format parser and encoder + * + * Format: [START_BYTE=0x74] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class TinyExtended { + static readonly START_BYTE = 0x74; + static readonly HEADER_SIZE = 5; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 7; + static readonly LENGTH_BYTES = 2; + + private state: TinyExtendedParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyExtended parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyExtendedParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedParserState.LOOKING_FOR_START: + if (byte === TinyExtended.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedParserState.GETTING_LENGTH; + break; + + case TinyExtendedParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtended.OVERHEAD + this.msg_length; + this.state = TinyExtendedParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyExtended.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtended.HEADER_SIZE, this.packet_size - TinyExtended.FOOTER_SIZE)); + } + this.state = TinyExtendedParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyExtended format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyExtended.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyExtended packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtended.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtended.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtended.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtended.HEADER_SIZE, buffer.length - TinyExtended.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts b/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts new file mode 100644 index 00000000..6026a279 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyExtendedLength.ts @@ -0,0 +1,164 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyExtendedLength Frame Format +// ============================================================================= + +export enum TinyExtendedLengthParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyExtendedLength - Frame format parser and encoder + * + * Format: [START_BYTE=0x73] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class TinyExtendedLength { + static readonly START_BYTE = 0x73; + static readonly HEADER_SIZE = 4; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 6; + static readonly LENGTH_BYTES = 2; + + private state: TinyExtendedLengthParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyExtendedLength parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedLengthParserState.LOOKING_FOR_START: + if (byte === TinyExtendedLength.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedLengthParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedLengthParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedLengthParserState.GETTING_LENGTH; + break; + + case TinyExtendedLengthParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtendedLength.OVERHEAD + this.msg_length; + this.state = TinyExtendedLengthParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedLengthParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyExtendedLength.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedLength.HEADER_SIZE, this.packet_size - TinyExtendedLength.FOOTER_SIZE)); + } + this.state = TinyExtendedLengthParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyExtendedLength format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyExtendedLength.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyExtendedLength packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedLength.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedLength.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedLength.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedLength.HEADER_SIZE, buffer.length - TinyExtendedLength.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts b/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts new file mode 100644 index 00000000..23902cc3 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyExtendedMsgIds.ts @@ -0,0 +1,157 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyExtendedMsgIds Frame Format +// ============================================================================= + +export enum TinyExtendedMsgIdsParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyExtendedMsgIds - Frame format parser and encoder + * + * Format: [START_BYTE=0x72] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class TinyExtendedMsgIds { + static readonly START_BYTE = 0x72; + static readonly HEADER_SIZE = 4; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 6; + static readonly LENGTH_BYTES = 1; + + private state: TinyExtendedMsgIdsParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyExtendedMsgIds parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedMsgIdsParserState.LOOKING_FOR_START: + if (byte === TinyExtendedMsgIds.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedMsgIdsParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedMsgIdsParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedMsgIdsParserState.GETTING_LENGTH; + break; + + case TinyExtendedMsgIdsParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyExtendedMsgIds.OVERHEAD + this.msg_length; + this.state = TinyExtendedMsgIdsParserState.GETTING_PAYLOAD; + break; + + case TinyExtendedMsgIdsParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyExtendedMsgIds.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedMsgIds.HEADER_SIZE, this.packet_size - TinyExtendedMsgIds.FOOTER_SIZE)); + } + this.state = TinyExtendedMsgIdsParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyExtendedMsgIds format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyExtendedMsgIds.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyExtendedMsgIds packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedMsgIds.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedMsgIds.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedMsgIds.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedMsgIds.HEADER_SIZE, buffer.length - TinyExtendedMsgIds.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts new file mode 100644 index 00000000..d51b18b9 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyExtendedMultiSystemStream.ts @@ -0,0 +1,164 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyExtendedMultiSystemStream Frame Format +// ============================================================================= + +export enum TinyExtendedMultiSystemStreamParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyExtendedMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE=0x78] [MSG_ID] [LEN16] [MSG...] [CRC1] [CRC2] + */ +export class TinyExtendedMultiSystemStream { + static readonly START_BYTE = 0x78; + static readonly HEADER_SIZE = 8; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 10; + static readonly LENGTH_BYTES = 2; + + private state: TinyExtendedMultiSystemStreamParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private length_lo: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyExtendedMultiSystemStream parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + this.length_lo = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START: + if (byte === TinyExtendedMultiSystemStream.START_BYTE) { + this.buffer = [byte]; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID; + } + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + if (this.buffer.length === 3) { + this.length_lo = byte; + } else { + this.msg_length = this.length_lo | (byte << 8); + this.packet_size = TinyExtendedMultiSystemStream.OVERHEAD + this.msg_length; + this.state = TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD; + } + break; + + case TinyExtendedMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyExtendedMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyExtendedMultiSystemStream.HEADER_SIZE, this.packet_size - TinyExtendedMultiSystemStream.FOOTER_SIZE)); + } + this.state = TinyExtendedMultiSystemStreamParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyExtendedMultiSystemStream format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyExtendedMultiSystemStream.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + output.push((msg.length >> 8) & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 2); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyExtendedMultiSystemStream packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyExtendedMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyExtendedMultiSystemStream.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyExtendedMultiSystemStream.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 2); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyExtendedMultiSystemStream.HEADER_SIZE, buffer.length - TinyExtendedMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyMinimal.ts b/src/struct_frame/boilerplate/ts/TinyMinimal.ts new file mode 100644 index 00000000..bedeef30 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyMinimal.ts @@ -0,0 +1,142 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyMinimal Frame Format +// ============================================================================= + +export enum TinyMinimalParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_PAYLOAD = 2 +} + +/** + * TinyMinimal - Frame format parser and encoder + * + * Format: [START_BYTE=0x70] [MSG_ID] [MSG...] + */ +export class TinyMinimal { + static readonly START_BYTE = 0x70; + static readonly HEADER_SIZE = 2; + static readonly FOOTER_SIZE = 0; + static readonly OVERHEAD = 2; + + private state: TinyMinimalParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyMinimal parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyMinimalParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyMinimalParserState.LOOKING_FOR_START: + if (byte === TinyMinimal.START_BYTE) { + this.buffer = [byte]; + this.state = TinyMinimalParserState.GETTING_MSG_ID; + } + break; + + case TinyMinimalParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + if (this.get_msg_length) { + const msg_length = this.get_msg_length(byte); + if (msg_length !== undefined) { + this.packet_size = TinyMinimal.OVERHEAD + msg_length; + this.state = TinyMinimalParserState.GETTING_PAYLOAD; + } else { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + } else { + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + break; + + case TinyMinimalParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = this.packet_size - TinyMinimal.OVERHEAD; + result.msg_data = new Uint8Array(this.buffer.slice(TinyMinimal.HEADER_SIZE)); + this.state = TinyMinimalParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyMinimal format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyMinimal.START_BYTE); + output.push(msg_id); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + return new Uint8Array(output); + } + + /** + * Validate a complete TinyMinimal packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyMinimal.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyMinimal.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyMinimal.OVERHEAD; + + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyMinimal.HEADER_SIZE)); + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts b/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts new file mode 100644 index 00000000..da5bcf97 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinyMultiSystemStream.ts @@ -0,0 +1,157 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinyMultiSystemStream Frame Format +// ============================================================================= + +export enum TinyMultiSystemStreamParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinyMultiSystemStream - Frame format parser and encoder + * + * Format: [START_BYTE=0x77] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class TinyMultiSystemStream { + static readonly START_BYTE = 0x77; + static readonly HEADER_SIZE = 6; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 8; + static readonly LENGTH_BYTES = 1; + + private state: TinyMultiSystemStreamParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinyMultiSystemStream parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinyMultiSystemStreamParserState.LOOKING_FOR_START: + if (byte === TinyMultiSystemStream.START_BYTE) { + this.buffer = [byte]; + this.state = TinyMultiSystemStreamParserState.GETTING_MSG_ID; + } + break; + + case TinyMultiSystemStreamParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinyMultiSystemStreamParserState.GETTING_LENGTH; + break; + + case TinyMultiSystemStreamParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinyMultiSystemStream.OVERHEAD + this.msg_length; + this.state = TinyMultiSystemStreamParserState.GETTING_PAYLOAD; + break; + + case TinyMultiSystemStreamParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinyMultiSystemStream.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinyMultiSystemStream.HEADER_SIZE, this.packet_size - TinyMultiSystemStream.FOOTER_SIZE)); + } + this.state = TinyMultiSystemStreamParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinyMultiSystemStream format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinyMultiSystemStream.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinyMultiSystemStream packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinyMultiSystemStream.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinyMultiSystemStream.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinyMultiSystemStream.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinyMultiSystemStream.HEADER_SIZE, buffer.length - TinyMultiSystemStream.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinySeq.ts b/src/struct_frame/boilerplate/ts/TinySeq.ts new file mode 100644 index 00000000..1b9cd4d5 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinySeq.ts @@ -0,0 +1,157 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinySeq Frame Format +// ============================================================================= + +export enum TinySeqParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinySeq - Frame format parser and encoder + * + * Format: [START_BYTE=0x76] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class TinySeq { + static readonly START_BYTE = 0x76; + static readonly HEADER_SIZE = 4; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 6; + static readonly LENGTH_BYTES = 1; + + private state: TinySeqParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinySeq parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinySeqParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinySeqParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinySeqParserState.LOOKING_FOR_START: + if (byte === TinySeq.START_BYTE) { + this.buffer = [byte]; + this.state = TinySeqParserState.GETTING_MSG_ID; + } + break; + + case TinySeqParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinySeqParserState.GETTING_LENGTH; + break; + + case TinySeqParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinySeq.OVERHEAD + this.msg_length; + this.state = TinySeqParserState.GETTING_PAYLOAD; + break; + + case TinySeqParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinySeq.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinySeq.HEADER_SIZE, this.packet_size - TinySeq.FOOTER_SIZE)); + } + this.state = TinySeqParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinySeq format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinySeq.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinySeq packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinySeq.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinySeq.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinySeq.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinySeq.HEADER_SIZE, buffer.length - TinySeq.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/TinySysComp.ts b/src/struct_frame/boilerplate/ts/TinySysComp.ts new file mode 100644 index 00000000..43f73d42 --- /dev/null +++ b/src/struct_frame/boilerplate/ts/TinySysComp.ts @@ -0,0 +1,157 @@ +// Automatically generated frame parser +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. + +import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; + +// ============================================================================= +// TinySysComp Frame Format +// ============================================================================= + +export enum TinySysCompParserState { + LOOKING_FOR_START = 0, + GETTING_MSG_ID = 1, + GETTING_LENGTH = 2, + GETTING_PAYLOAD = 3 +} + +/** + * TinySysComp - Frame format parser and encoder + * + * Format: [START_BYTE=0x75] [MSG_ID] [LEN] [MSG...] [CRC1] [CRC2] + */ +export class TinySysComp { + static readonly START_BYTE = 0x75; + static readonly HEADER_SIZE = 5; + static readonly FOOTER_SIZE = 2; + static readonly OVERHEAD = 7; + static readonly LENGTH_BYTES = 1; + + private state: TinySysCompParserState; + private buffer: number[]; + private packet_size: number; + private msg_id: number; + private msg_length: number; + private get_msg_length?: (msg_id: number) => number | undefined; + + /** + * Create a new TinySysComp parser + * @param get_msg_length Callback to get message length from msg_id (required for non-length frames) + */ + constructor(get_msg_length?: (msg_id: number) => number | undefined) { + this.get_msg_length = get_msg_length; + this.state = TinySysCompParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** Reset parser state */ + reset(): void { + this.state = TinySysCompParserState.LOOKING_FOR_START; + this.buffer = []; + this.packet_size = 0; + this.msg_id = 0; + this.msg_length = 0; + } + + /** + * Parse a single byte + * @param byte The byte to parse + * @returns FrameMsgInfo with valid=true when a complete valid message is received + */ + parse_byte(byte: number): FrameMsgInfo { + const result = createFrameMsgInfo(); + + switch (this.state) { + case TinySysCompParserState.LOOKING_FOR_START: + if (byte === TinySysComp.START_BYTE) { + this.buffer = [byte]; + this.state = TinySysCompParserState.GETTING_MSG_ID; + } + break; + + case TinySysCompParserState.GETTING_MSG_ID: + this.buffer.push(byte); + this.msg_id = byte; + this.state = TinySysCompParserState.GETTING_LENGTH; + break; + + case TinySysCompParserState.GETTING_LENGTH: + this.buffer.push(byte); + this.msg_length = byte; + this.packet_size = TinySysComp.OVERHEAD + this.msg_length; + this.state = TinySysCompParserState.GETTING_PAYLOAD; + break; + + case TinySysCompParserState.GETTING_PAYLOAD: + this.buffer.push(byte); + + if (this.buffer.length >= this.packet_size) { + // Validate checksum + const msg_length = this.packet_size - TinySysComp.OVERHEAD; + const ck = fletcher_checksum(this.buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === this.buffer[this.buffer.length - 2] && ck[1] === this.buffer[this.buffer.length - 1]) { + result.valid = true; + result.msg_id = this.msg_id; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(this.buffer.slice(TinySysComp.HEADER_SIZE, this.packet_size - TinySysComp.FOOTER_SIZE)); + } + this.state = TinySysCompParserState.LOOKING_FOR_START; + } + break; + } + + return result; + } + + /** + * Encode a message with TinySysComp format + * @param msg_id Message ID + * @param msg Message data + * @returns Encoded frame as Uint8Array + */ + static encode(msg_id: number, msg: Uint8Array | number[]): Uint8Array { + const output: number[] = []; + output.push(TinySysComp.START_BYTE); + output.push(msg_id); + output.push(msg.length & 0xFF); + for (let i = 0; i < msg.length; i++) { + output.push(msg[i]); + } + const ck = fletcher_checksum(output, 1, 1 + msg.length + 1 + 1); + output.push(ck[0]); + output.push(ck[1]); + return new Uint8Array(output); + } + + /** + * Validate a complete TinySysComp packet in a buffer + * @param buffer Buffer containing the complete packet + * @returns FrameMsgInfo with valid=true if packet is valid + */ + static validate_packet(buffer: Uint8Array | number[]): FrameMsgInfo { + const result = createFrameMsgInfo(); + + if (buffer.length < TinySysComp.OVERHEAD) { + return result; + } + + if (buffer[0] !== TinySysComp.START_BYTE) { + return result; + } + + const msg_length = buffer.length - TinySysComp.OVERHEAD; + + // Validate checksum + const ck = fletcher_checksum(buffer, 1, 1 + msg_length + 1 + 1); + if (ck[0] === buffer[buffer.length - 2] && ck[1] === buffer[buffer.length - 1]) { + result.valid = true; + result.msg_id = buffer[1]; + result.msg_len = msg_length; + result.msg_data = new Uint8Array(Array.prototype.slice.call(buffer, TinySysComp.HEADER_SIZE, buffer.length - TinySysComp.FOOTER_SIZE)); + } + + return result; + } +} diff --git a/src/struct_frame/boilerplate/ts/UbxFrame.ts b/src/struct_frame/boilerplate/ts/UbxFrame.ts index 684d0fd7..e848316c 100644 --- a/src/struct_frame/boilerplate/ts/UbxFrame.ts +++ b/src/struct_frame/boilerplate/ts/UbxFrame.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. import { FrameMsgInfo, createFrameMsgInfo, fletcher_checksum } from './frame_base'; diff --git a/src/struct_frame/boilerplate/ts/frame_base.ts b/src/struct_frame/boilerplate/ts/frame_base.ts index 5b3c6745..ed282df6 100644 --- a/src/struct_frame/boilerplate/ts/frame_base.ts +++ b/src/struct_frame/boilerplate/ts/frame_base.ts @@ -1,26 +1,26 @@ // Automatically generated frame parser base utilities -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. // Frame format type enumeration export enum FrameFormatType { - MINIMAL_FRAME = 0, - BASIC_FRAME = 1, - BASIC_FRAME_NO_CRC = 2, - TINY_FRAME = 3, - TINY_FRAME_NO_CRC = 4, - MINIMAL_FRAME_WITH_LEN = 5, - MINIMAL_FRAME_WITH_LEN_NO_CRC = 6, - BASIC_FRAME_WITH_LEN = 7, - BASIC_FRAME_WITH_LEN_NO_CRC = 8, - TINY_FRAME_WITH_LEN = 9, - TINY_FRAME_WITH_LEN_NO_CRC = 10, - MINIMAL_FRAME_WITH_LEN16 = 11, - MINIMAL_FRAME_WITH_LEN16_NO_CRC = 12, - BASIC_FRAME_WITH_LEN16 = 13, - BASIC_FRAME_WITH_LEN16_NO_CRC = 14, - TINY_FRAME_WITH_LEN16 = 15, - TINY_FRAME_WITH_LEN16_NO_CRC = 16, - BASIC_FRAME_WITH_SYS_COMP = 17, + TINY_MINIMAL = 0, + TINY_DEFAULT = 1, + TINY_EXTENDED_MSG_IDS = 2, + TINY_EXTENDED_LENGTH = 3, + TINY_EXTENDED = 4, + TINY_SYS_COMP = 5, + TINY_SEQ = 6, + TINY_MULTI_SYSTEM_STREAM = 7, + TINY_EXTENDED_MULTI_SYSTEM_STREAM = 8, + BASIC_MINIMAL = 9, + BASIC_DEFAULT = 10, + BASIC_EXTENDED_MSG_IDS = 11, + BASIC_EXTENDED_LENGTH = 12, + BASIC_EXTENDED = 13, + BASIC_SYS_COMP = 14, + BASIC_SEQ = 15, + BASIC_MULTI_SYSTEM_STREAM = 16, + BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 17, UBX_FRAME = 18, MAVLINK_V1_FRAME = 19, MAVLINK_V2_FRAME = 20, diff --git a/src/struct_frame/boilerplate/ts/index.ts b/src/struct_frame/boilerplate/ts/index.ts index 1f3b8394..5490e38d 100644 --- a/src/struct_frame/boilerplate/ts/index.ts +++ b/src/struct_frame/boilerplate/ts/index.ts @@ -1,5 +1,5 @@ // Automatically generated frame parser package -// Generated by 0.0.1 at Wed Dec 3 17:57:16 2025. +// Generated by 0.0.1 at Thu Dec 4 19:40:48 2025. // Base utilities export { @@ -10,24 +10,24 @@ export { } from './frame_base'; // Individual frame format parsers -export { MinimalFrame, MinimalFrameParserState } from './MinimalFrame'; -export { BasicFrame, BasicFrameParserState } from './BasicFrame'; -export { BasicFrameNoCrc, BasicFrameNoCrcParserState } from './BasicFrameNoCrc'; -export { TinyFrame, TinyFrameParserState } from './TinyFrame'; -export { TinyFrameNoCrc, TinyFrameNoCrcParserState } from './TinyFrameNoCrc'; -export { MinimalFrameWithLen, MinimalFrameWithLenParserState } from './MinimalFrameWithLen'; -export { MinimalFrameWithLenNoCrc, MinimalFrameWithLenNoCrcParserState } from './MinimalFrameWithLenNoCrc'; -export { BasicFrameWithLen, BasicFrameWithLenParserState } from './BasicFrameWithLen'; -export { BasicFrameWithLenNoCrc, BasicFrameWithLenNoCrcParserState } from './BasicFrameWithLenNoCrc'; -export { TinyFrameWithLen, TinyFrameWithLenParserState } from './TinyFrameWithLen'; -export { TinyFrameWithLenNoCrc, TinyFrameWithLenNoCrcParserState } from './TinyFrameWithLenNoCrc'; -export { MinimalFrameWithLen16, MinimalFrameWithLen16ParserState } from './MinimalFrameWithLen16'; -export { MinimalFrameWithLen16NoCrc, MinimalFrameWithLen16NoCrcParserState } from './MinimalFrameWithLen16NoCrc'; -export { BasicFrameWithLen16, BasicFrameWithLen16ParserState } from './BasicFrameWithLen16'; -export { BasicFrameWithLen16NoCrc, BasicFrameWithLen16NoCrcParserState } from './BasicFrameWithLen16NoCrc'; -export { TinyFrameWithLen16, TinyFrameWithLen16ParserState } from './TinyFrameWithLen16'; -export { TinyFrameWithLen16NoCrc, TinyFrameWithLen16NoCrcParserState } from './TinyFrameWithLen16NoCrc'; -export { BasicFrameWithSysComp, BasicFrameWithSysCompParserState } from './BasicFrameWithSysComp'; +export { TinyMinimal, TinyMinimalParserState } from './TinyMinimal'; +export { TinyDefault, TinyDefaultParserState } from './TinyDefault'; +export { TinyExtendedMsgIds, TinyExtendedMsgIdsParserState } from './TinyExtendedMsgIds'; +export { TinyExtendedLength, TinyExtendedLengthParserState } from './TinyExtendedLength'; +export { TinyExtended, TinyExtendedParserState } from './TinyExtended'; +export { TinySysComp, TinySysCompParserState } from './TinySysComp'; +export { TinySeq, TinySeqParserState } from './TinySeq'; +export { TinyMultiSystemStream, TinyMultiSystemStreamParserState } from './TinyMultiSystemStream'; +export { TinyExtendedMultiSystemStream, TinyExtendedMultiSystemStreamParserState } from './TinyExtendedMultiSystemStream'; +export { BasicMinimal, BasicMinimalParserState } from './BasicMinimal'; +export { BasicDefault, BasicDefaultParserState } from './BasicDefault'; +export { BasicExtendedMsgIds, BasicExtendedMsgIdsParserState } from './BasicExtendedMsgIds'; +export { BasicExtendedLength, BasicExtendedLengthParserState } from './BasicExtendedLength'; +export { BasicExtended, BasicExtendedParserState } from './BasicExtended'; +export { BasicSysComp, BasicSysCompParserState } from './BasicSysComp'; +export { BasicSeq, BasicSeqParserState } from './BasicSeq'; +export { BasicMultiSystemStream, BasicMultiSystemStreamParserState } from './BasicMultiSystemStream'; +export { BasicExtendedMultiSystemStream, BasicExtendedMultiSystemStreamParserState } from './BasicExtendedMultiSystemStream'; export { UbxFrame, UbxFrameParserState } from './UbxFrame'; export { MavlinkV1Frame, MavlinkV1FrameParserState } from './MavlinkV1Frame'; export { MavlinkV2Frame, MavlinkV2FrameParserState } from './MavlinkV2Frame'; diff --git a/src/struct_frame/frame_format.py b/src/struct_frame/frame_format.py index 22944472..fdf14a80 100644 --- a/src/struct_frame/frame_format.py +++ b/src/struct_frame/frame_format.py @@ -29,6 +29,14 @@ def __init__(self, name, field_type, hex_value=None): self.is_length = 'length' in name.lower() or 'len' in name.lower() self.is_msg_id = 'msg_id' in name.lower() or name == 'msg_id' self.is_payload = name == 'payload' + # New header fields for extended frame formats + self.is_sequence = name in ['sequence', 'seq'] + self.is_system_id = name == 'system_id' + self.is_component_id = name == 'component_id' + self.is_package_id = name == 'package_id' + # Check if this is a header field (not start byte, payload, or CRC) + self.is_header_field = (self.is_sequence or self.is_system_id or + self.is_component_id or self.is_package_id) def __repr__(self): return f"FrameFormatField({self.name}, {self.field_type}, hex={self.hex_value})" @@ -103,6 +111,10 @@ def parse(self, message): # Track payload/msg_id (1 byte for msg_id) if field.is_payload or field.is_msg_id: self.header_size += 1 + + # Track additional header fields (sequence, system_id, component_id, package_id) + if field.is_header_field: + self.header_size += 1 return True diff --git a/src/struct_frame/frame_formats.proto b/src/struct_frame/frame_formats.proto index 89ffe90b..0e1c848e 100644 --- a/src/struct_frame/frame_formats.proto +++ b/src/struct_frame/frame_formats.proto @@ -1,250 +1,466 @@ // Frame Format Definitions for struct-frame // Defines message framing formats for communication over serial, network, or byte streams. +// +// FRAMING ARCHITECTURE: +// The framing system has two levels: +// 1. FRAMER (Basic/Tiny/None): Determines start bytes for synchronization +// - Basic: 2 start bytes [0x90] [0x70+payload_type] +// - Tiny: 1 start byte [0x70+payload_type] +// - None: 0 start bytes (relies on external sync) +// +// 2. PAYLOAD TYPE: Defines the header/footer structure of the payload +// The second start byte of Basic (or the single start byte of Tiny) encodes the payload type. +// +// Start byte 1 (Basic only): 0x90 +// Start byte 2 (Basic) or Start byte (Tiny): 0x70 + PayloadType offset package frame_formats; -// Frame format type enumeration -enum FrameFormatType { - NO_FORMAT = 0; - MINIMAL_FRAME = 1; - MINIMAL_FRAME_NO_CRC = 2; - BASIC_FRAME = 3; - BASIC_FRAME_NO_CRC = 4; - TINY_FRAME = 5; - TINY_FRAME_NO_CRC = 6; - MINIMAL_FRAME_WITH_LEN = 7; - MINIMAL_FRAME_WITH_LEN_NO_CRC = 8; - MINIMAL_FRAME_WITH_LEN16 = 9; - MINIMAL_FRAME_WITH_LEN16_NO_CRC = 10; - BASIC_FRAME_WITH_LEN = 11; - BASIC_FRAME_WITH_LEN_NO_CRC = 12; - BASIC_FRAME_WITH_LEN16 = 13; - BASIC_FRAME_WITH_LEN16_NO_CRC = 14; - TINY_FRAME_WITH_LEN = 15; - TINY_FRAME_WITH_LEN_NO_CRC = 16; - TINY_FRAME_WITH_LEN16 = 17; - TINY_FRAME_WITH_LEN16_NO_CRC = 18; - BASIC_FRAME_WITH_SYS_COMP = 19; - UBX = 20; - MAVLINK_V1 = 21; - MAVLINK_V2 = 22; -} +// ============================================================================ +// PAYLOAD TYPE ENUMERATION +// ============================================================================ +// PayloadType defines how the payload is structured (header fields + CRC) +// The start byte encodes this: 0x70 + PayloadType value -// Basic message payload included in all frame formats -message BasicMessage { - uint8 msg_id = 1; +enum PayloadType { + // Minimal: [MSG_ID] [PACKET] + // No length field, no CRC. Requires known message sizes. + PAYLOAD_MINIMAL = 0; + + // Default: [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // 1-byte length, 2-byte CRC. Standard format. + PAYLOAD_DEFAULT = 1; + + // ExtendedMsgIds: [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds package ID for message namespace separation. + PAYLOAD_EXTENDED_MSG_IDS = 2; + + // ExtendedLength: [LEN16] [MSG_ID] [PACKET] [CRC1] [CRC2] + // 2-byte length for payloads up to 65535 bytes. + PAYLOAD_EXTENDED_LENGTH = 3; + + // Extended: [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Extended message IDs + 2-byte length. + PAYLOAD_EXTENDED = 4; + + // SysComp: [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds system and component IDs for multi-system networks. + PAYLOAD_SYS_COMP = 5; + + // Seq: [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Adds sequence number for packet loss detection. + PAYLOAD_SEQ = 6; + + // MultiSystemStream: [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Combines Seq + SysComp for multi-system streaming. + PAYLOAD_MULTI_SYSTEM_STREAM = 7; + + // ExtendedMultiSystemStream: [SEQ] [SYS_ID] [COMP_ID] [LEN16] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] + // Full featured format with all extensions. + PAYLOAD_EXTENDED_MULTI_SYSTEM_STREAM = 8; } // ============================================================================ -// NO FORMAT - Raw message, no framing -// Format: [MSG] -// Overhead: 0 bytes -message NoFormat { - BasicMessage payload = 1; +// FRAME TYPE ENUMERATION +// ============================================================================ +// FrameType defines the framing level (number of start bytes) + +enum FrameType { + // None: No start bytes, relies on external synchronization + FRAME_NONE = 0; + + // Tiny: 1 start byte [0x70+PayloadType] + FRAME_TINY = 1; + + // Basic: 2 start bytes [0x90] [0x70+PayloadType] + FRAME_BASIC = 2; } -// ============================================================================ -// MINIMAL FRAME - No start bytes, just MSG_ID with CRC -// Format: [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 3 bytes -message MinimalFrame { - BasicMessage payload = 1; - uint8 crc_byte1 = 2; - uint8 crc_byte2 = 3; +// Legacy frame format type enumeration (for backward compatibility) +enum FrameFormatType { + // None frames (0 start bytes) + NONE_MINIMAL = 0; + NONE_DEFAULT = 1; + NONE_EXTENDED_MSG_IDS = 2; + NONE_EXTENDED_LENGTH = 3; + NONE_EXTENDED = 4; + NONE_SYS_COMP = 5; + NONE_SEQ = 6; + NONE_MULTI_SYSTEM_STREAM = 7; + NONE_EXTENDED_MULTI_SYSTEM_STREAM = 8; + + // Tiny frames (1 start byte at 0x70+PayloadType) + TINY_MINIMAL = 10; + TINY_DEFAULT = 11; + TINY_EXTENDED_MSG_IDS = 12; + TINY_EXTENDED_LENGTH = 13; + TINY_EXTENDED = 14; + TINY_SYS_COMP = 15; + TINY_SEQ = 16; + TINY_MULTI_SYSTEM_STREAM = 17; + TINY_EXTENDED_MULTI_SYSTEM_STREAM = 18; + + // Basic frames (2 start bytes: 0x90, 0x70+PayloadType) + BASIC_MINIMAL = 20; + BASIC_DEFAULT = 21; + BASIC_EXTENDED_MSG_IDS = 22; + BASIC_EXTENDED_LENGTH = 23; + BASIC_EXTENDED = 24; + BASIC_SYS_COMP = 25; + BASIC_SEQ = 26; + BASIC_MULTI_SYSTEM_STREAM = 27; + BASIC_EXTENDED_MULTI_SYSTEM_STREAM = 28; + + // Third party protocols + UBX = 100; + MAVLINK_V1 = 101; + MAVLINK_V2 = 102; } -// MINIMAL FRAME NO CRC -// Format: [MSG_ID] [MSG] +// ============================================================================ +// FRAME FORMAT CONSTANTS +// ============================================================================ + +// Start byte values +// Basic frame start byte 1 is always 0x90 +// Basic frame start byte 2 and Tiny frame start byte are 0x70 + PayloadType + +// ============================================================================ +// NONE FRAME FORMATS (0 start bytes) +// ============================================================================ + +// NONE_MINIMAL - Minimal payload with no framing +// Format: [MSG_ID] [PACKET] // Overhead: 1 byte -message MinimalFrameNoCrc { +message NoneMinimal { BasicMessage payload = 1; } -// ============================================================================ -// BASIC FRAME - 2 start bytes with CRC (Recommended) -// Format: [START1=0x90] [START2=0x91] [MSG_ID] [MSG] [CRC1] [CRC2] +// NONE_DEFAULT - Default payload with no framing +// Format: [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 4 bytes +message NoneDefault { + uint8 length = 1; + BasicMessage payload = 2; + uint8 crc_byte1 = 3; + uint8 crc_byte2 = 4; +} + +// NONE_EXTENDED_MSG_IDS - Extended message IDs payload with no framing +// Format: [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] // Overhead: 5 bytes -message BasicFrame { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x91]; +message NoneExtendedMsgIds { + uint8 length = 1; + uint8 package_id = 2; BasicMessage payload = 3; uint8 crc_byte1 = 4; uint8 crc_byte2 = 5; } -// BASIC FRAME NO CRC -// Format: [START1=0x90] [START2=0x95] [MSG_ID] [MSG] -// Overhead: 3 bytes -message BasicFrameNoCrc { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x95]; - BasicMessage payload = 3; -} - -// ============================================================================ -// TINY FRAME - 1 start byte with CRC (Recommended) -// Format: [START=0x70] [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 4 bytes -message TinyFrame { - uint8 start_byte = 1 [(hex) = 0x70]; +// NONE_EXTENDED_LENGTH - Extended length payload with no framing +// Format: [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message NoneExtendedLength { + uint16 length = 1; BasicMessage payload = 2; uint8 crc_byte1 = 3; uint8 crc_byte2 = 4; } -// TINY FRAME NO CRC -// Format: [START=0x72] [MSG_ID] [MSG] -// Overhead: 2 bytes -message TinyFrameNoCrc { - uint8 start_byte = 1 [(hex) = 0x72]; - BasicMessage payload = 2; +// NONE_EXTENDED - Extended payload with no framing +// Format: [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message NoneExtended { + uint16 length = 1; + uint8 package_id = 2; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// NONE_SYS_COMP - System/Component ID payload with no framing +// Format: [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message NoneSysComp { + uint8 system_id = 1; + uint8 component_id = 2; + uint8 length = 3; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; +} + +// NONE_SEQ - Sequence number payload with no framing +// Format: [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message NoneSeq { + uint8 sequence = 1; + uint8 length = 2; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// NONE_MULTI_SYSTEM_STREAM - Multi-system stream payload with no framing +// Format: [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message NoneMultiSystemStream { + uint8 sequence = 1; + uint8 system_id = 2; + uint8 component_id = 3; + uint8 length = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; +} + +// NONE_EXTENDED_MULTI_SYSTEM_STREAM - Extended multi-system stream payload with no framing +// Format: [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 9 bytes +message NoneExtendedMultiSystemStream { + uint8 sequence = 1; + uint8 system_id = 2; + uint8 component_id = 3; + uint16 length = 4; + uint8 package_id = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; } // ============================================================================ -// LENGTH-PREFIXED VARIANTS (1-byte length, up to 255 bytes) +// TINY FRAME FORMATS (1 start byte at 0x70+PayloadType) // ============================================================================ -// MINIMAL FRAME WITH LEN -// Format: [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] -// Overhead: 4 bytes -message MinimalFrameWithLen { - BasicMessage payload = 1; +// TINY_MINIMAL - Tiny frame with minimal payload +// Format: [START=0x70] [MSG_ID] [PACKET] +// Overhead: 2 bytes +message TinyMinimal { + uint8 start_byte = 1 [(hex) = 0x70]; + BasicMessage payload = 2; +} + +// TINY_DEFAULT - Tiny frame with default payload (Recommended) +// Format: [START=0x71] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 5 bytes +message TinyDefault { + uint8 start_byte = 1 [(hex) = 0x71]; uint8 length = 2; - uint8 crc_byte1 = 3; - uint8 crc_byte2 = 4; + BasicMessage payload = 3; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; } -// MINIMAL FRAME WITH LEN NO CRC -// Format: [MSG_ID] [LEN] [MSG] -// Overhead: 2 bytes -message MinimalFrameWithLenNoCrc { - BasicMessage payload = 1; +// TINY_EXTENDED_MSG_IDS - Tiny frame with extended message IDs +// Format: [START=0x72] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message TinyExtendedMsgIds { + uint8 start_byte = 1 [(hex) = 0x72]; uint8 length = 2; + uint8 package_id = 3; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN (Recommended for variable length) -// Format: [START1=0x90] [START2=0x92] [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] +// TINY_EXTENDED_LENGTH - Tiny frame with extended length +// Format: [START=0x73] [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] // Overhead: 6 bytes -message BasicFrameWithLen { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x92]; +message TinyExtendedLength { + uint8 start_byte = 1 [(hex) = 0x73]; + uint16 length = 2; BasicMessage payload = 3; - uint8 length = 4; + uint8 crc_byte1 = 4; + uint8 crc_byte2 = 5; +} + +// TINY_EXTENDED - Tiny frame with extended payload +// Format: [START=0x74] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message TinyExtended { + uint8 start_byte = 1 [(hex) = 0x74]; + uint16 length = 2; + uint8 package_id = 3; + BasicMessage payload = 4; uint8 crc_byte1 = 5; uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN NO CRC -// Format: [START1=0x90] [START2=0x96] [MSG_ID] [LEN] [MSG] -// Overhead: 4 bytes -message BasicFrameWithLenNoCrc { - uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x96]; - BasicMessage payload = 3; +// TINY_SYS_COMP - Tiny frame with system/component IDs +// Format: [START=0x75] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message TinySysComp { + uint8 start_byte = 1 [(hex) = 0x75]; + uint8 system_id = 2; + uint8 component_id = 3; uint8 length = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// TINY FRAME WITH LEN (Recommended) -// Format: [START=0x71] [MSG_ID] [LEN] [MSG] [CRC1] [CRC2] -// Overhead: 5 bytes -message TinyFrameWithLen { - uint8 start_byte = 1 [(hex) = 0x71]; - BasicMessage payload = 2; +// TINY_SEQ - Tiny frame with sequence number +// Format: [START=0x76] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message TinySeq { + uint8 start_byte = 1 [(hex) = 0x76]; + uint8 sequence = 2; uint8 length = 3; - uint8 crc_byte1 = 4; - uint8 crc_byte2 = 5; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// TINY FRAME WITH LEN NO CRC -// Format: [START=0x73] [MSG_ID] [LEN] [MSG] -// Overhead: 3 bytes -message TinyFrameWithLenNoCrc { - uint8 start_byte = 1 [(hex) = 0x73]; - BasicMessage payload = 2; - uint8 length = 3; +// TINY_MULTI_SYSTEM_STREAM - Tiny frame with multi-system stream +// Format: [START=0x77] [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message TinyMultiSystemStream { + uint8 start_byte = 1 [(hex) = 0x77]; + uint8 sequence = 2; + uint8 system_id = 3; + uint8 component_id = 4; + uint8 length = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; +} + +// TINY_EXTENDED_MULTI_SYSTEM_STREAM - Tiny frame with extended multi-system stream +// Format: [START=0x78] [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 10 bytes +message TinyExtendedMultiSystemStream { + uint8 start_byte = 1 [(hex) = 0x78]; + uint8 sequence = 2; + uint8 system_id = 3; + uint8 component_id = 4; + uint16 length = 5; + uint8 package_id = 6; + BasicMessage payload = 7; + uint8 crc_byte1 = 8; + uint8 crc_byte2 = 9; } // ============================================================================ -// LENGTH-PREFIXED VARIANTS (2-byte length, up to 65535 bytes) +// BASIC FRAME FORMATS (2 start bytes: 0x90, 0x70+PayloadType) // ============================================================================ -// MINIMAL FRAME WITH LEN16 -// Format: [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 5 bytes -message MinimalFrameWithLen16 { - BasicMessage payload = 1; - uint16 length = 2; - uint8 crc_byte1 = 3; - uint8 crc_byte2 = 4; -} - -// MINIMAL FRAME WITH LEN16 NO CRC -// Format: [MSG_ID] [LEN_LO] [LEN_HI] [MSG] +// BASIC_MINIMAL - Basic frame with minimal payload +// Format: [START1=0x90] [START2=0x70] [MSG_ID] [PACKET] // Overhead: 3 bytes -message MinimalFrameWithLen16NoCrc { - BasicMessage payload = 1; - uint16 length = 2; +message BasicMinimal { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x70]; + BasicMessage payload = 3; } -// BASIC FRAME WITH LEN16 (Recommended for large payloads) -// Format: [START1=0x90] [START2=0x93] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 7 bytes -message BasicFrameWithLen16 { +// BASIC_DEFAULT - Basic frame with default payload (Recommended) +// Format: [START1=0x90] [START2=0x71] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 6 bytes +message BasicDefault { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x93]; - BasicMessage payload = 3; - uint16 length = 4; + uint8 start_byte2 = 2 [(hex) = 0x71]; + uint8 length = 3; + BasicMessage payload = 4; uint8 crc_byte1 = 5; uint8 crc_byte2 = 6; } -// BASIC FRAME WITH LEN16 NO CRC -// Format: [START1=0x90] [START2=0x97] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] -// Overhead: 5 bytes -message BasicFrameWithLen16NoCrc { +// BASIC_EXTENDED_MSG_IDS - Basic frame with extended message IDs +// Format: [START1=0x90] [START2=0x72] [LEN] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicExtendedMsgIds { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x97]; - BasicMessage payload = 3; - uint16 length = 4; + uint8 start_byte2 = 2 [(hex) = 0x72]; + uint8 length = 3; + uint8 package_id = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// TINY FRAME WITH LEN16 -// Format: [START=0x74] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] [CRC1] [CRC2] -// Overhead: 6 bytes -message TinyFrameWithLen16 { - uint8 start_byte = 1 [(hex) = 0x74]; - BasicMessage payload = 2; +// BASIC_EXTENDED_LENGTH - Basic frame with extended length +// Format: [START1=0x90] [START2=0x73] [LEN_LO] [LEN_HI] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicExtendedLength { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x73]; uint16 length = 3; - uint8 crc_byte1 = 4; - uint8 crc_byte2 = 5; + BasicMessage payload = 4; + uint8 crc_byte1 = 5; + uint8 crc_byte2 = 6; } -// TINY FRAME WITH LEN16 NO CRC -// Format: [START=0x75] [MSG_ID] [LEN_LO] [LEN_HI] [MSG] -// Overhead: 4 bytes -message TinyFrameWithLen16NoCrc { - uint8 start_byte = 1 [(hex) = 0x75]; - BasicMessage payload = 2; +// BASIC_EXTENDED - Basic frame with extended payload +// Format: [START1=0x90] [START2=0x74] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message BasicExtended { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x74]; uint16 length = 3; + uint8 package_id = 4; + BasicMessage payload = 5; + uint8 crc_byte1 = 6; + uint8 crc_byte2 = 7; } -// ============================================================================ -// SYSTEM/COMPONENT ID VARIANT (Recommended for multi-system networks) -// ============================================================================ - -// BASIC FRAME WITH SYS COMP -// Format: [START1=0x90] [START2=0x94] [SYS_ID] [COMP_ID] [MSG_ID] [MSG] [CRC1] [CRC2] -// Overhead: 7 bytes -message BasicFrameWithSysComp { +// BASIC_SYS_COMP - Basic frame with system/component IDs +// Format: [START1=0x90] [START2=0x75] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 8 bytes +message BasicSysComp { uint8 start_byte1 = 1 [(hex) = 0x90]; - uint8 start_byte2 = 2 [(hex) = 0x94]; + uint8 start_byte2 = 2 [(hex) = 0x75]; uint8 system_id = 3; uint8 component_id = 4; + uint8 length = 5; + BasicMessage payload = 6; + uint8 crc_byte1 = 7; + uint8 crc_byte2 = 8; +} + +// BASIC_SEQ - Basic frame with sequence number +// Format: [START1=0x90] [START2=0x76] [SEQ] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 7 bytes +message BasicSeq { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x76]; + uint8 sequence = 3; + uint8 length = 4; BasicMessage payload = 5; uint8 crc_byte1 = 6; uint8 crc_byte2 = 7; } +// BASIC_MULTI_SYSTEM_STREAM - Basic frame with multi-system stream +// Format: [START1=0x90] [START2=0x77] [SEQ] [SYS_ID] [COMP_ID] [LEN] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 9 bytes +message BasicMultiSystemStream { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x77]; + uint8 sequence = 3; + uint8 system_id = 4; + uint8 component_id = 5; + uint8 length = 6; + BasicMessage payload = 7; + uint8 crc_byte1 = 8; + uint8 crc_byte2 = 9; +} + +// BASIC_EXTENDED_MULTI_SYSTEM_STREAM - Basic frame with extended multi-system stream +// Format: [START1=0x90] [START2=0x78] [SEQ] [SYS_ID] [COMP_ID] [LEN_LO] [LEN_HI] [PKG_ID] [MSG_ID] [PACKET] [CRC1] [CRC2] +// Overhead: 11 bytes +message BasicExtendedMultiSystemStream { + uint8 start_byte1 = 1 [(hex) = 0x90]; + uint8 start_byte2 = 2 [(hex) = 0x78]; + uint8 sequence = 3; + uint8 system_id = 4; + uint8 component_id = 5; + uint16 length = 6; + uint8 package_id = 7; + BasicMessage payload = 8; + uint8 crc_byte1 = 9; + uint8 crc_byte2 = 10; +} + // ============================================================================ // THIRD PARTY PROTOCOLS // ============================================================================ @@ -312,15 +528,24 @@ message MavlinkV2Signature { uint8 signature_5 = 13; } +// ============================================================================ +// HELPER MESSAGES +// ============================================================================ + +// Basic message payload included in all frame formats +message BasicMessage { + uint8 msg_id = 1; +} + // ============================================================================ // CONFIGURATION // ============================================================================ // Runtime frame format configuration message FrameFormatConfig { - FrameFormatType format_type = 1; - uint8 start_byte1 = 2 [(hex) = 0x90]; - uint8 start_byte2 = 3 [(hex) = 0x91]; - bool crc_enabled = 4; - bool signing_enabled = 5; + FrameType frame_type = 1; + PayloadType payload_type = 2; + uint8 start_byte1 = 3 [(hex) = 0x90]; + uint8 start_byte2 = 4 [(hex) = 0x71]; + bool crc_enabled = 5; } diff --git a/src/struct_frame/frame_parser_c_gen.py b/src/struct_frame/frame_parser_c_gen.py index b72f101d..e0bc4b70 100644 --- a/src/struct_frame/frame_parser_c_gen.py +++ b/src/struct_frame/frame_parser_c_gen.py @@ -448,9 +448,8 @@ def generate_format(fmt): for i, (sb_name, sb_value) in enumerate(fmt.start_bytes): yield f' buffer[{idx}] = {PREFIX}_START_BYTE{i + 1 if len(fmt.start_bytes) > 1 else ""};\n' idx += 1 - yield f' buffer[{idx}] = msg_id;\n' - idx += 1 + # Write length BEFORE msg_id (per frame_formats.proto definition) if fmt.has_length: if fmt.length_bytes == 1: yield f' buffer[{idx}] = (uint8_t)msg_size;\n' @@ -459,6 +458,9 @@ def generate_format(fmt): yield f' buffer[{idx + 1}] = (uint8_t)((msg_size >> 8) & 0xFF);\n' idx += fmt.length_bytes + yield f' buffer[{idx}] = msg_id;\n' + idx += 1 + yield f'\n /* Write message data */\n' yield f' if (msg_size > 0 && msg != NULL) {{\n' yield f' memcpy(buffer + {PREFIX}_HEADER_SIZE, msg, msg_size);\n' @@ -495,6 +497,9 @@ def generate_format(fmt): yield f'\n size_t msg_length = length - {PREFIX}_OVERHEAD;\n\n' + # Calculate msg_id offset: start_bytes + length_bytes (if has_length) + msg_id_offset = len(fmt.start_bytes) + (fmt.length_bytes if fmt.has_length else 0) + if fmt.has_crc: yield f' /* Validate checksum */\n' yield f' frame_checksum_t ck = frame_fletcher_checksum(buffer + {len(fmt.start_bytes)}, msg_length + 1' @@ -503,13 +508,13 @@ def generate_format(fmt): yield f');\n' yield f' if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) {{\n' yield f' result.valid = true;\n' - yield f' result.msg_id = buffer[{len(fmt.start_bytes)}];\n' + yield f' result.msg_id = buffer[{msg_id_offset}];\n' yield f' result.msg_len = msg_length;\n' yield f' result.msg_data = (uint8_t*)(buffer + {PREFIX}_HEADER_SIZE);\n' yield f' }}\n' else: yield f' result.valid = true;\n' - yield f' result.msg_id = buffer[{len(fmt.start_bytes)}];\n' + yield f' result.msg_id = buffer[{msg_id_offset}];\n' yield f' result.msg_len = msg_length;\n' yield f' result.msg_data = (uint8_t*)(buffer + {PREFIX}_HEADER_SIZE);\n' diff --git a/src/struct_frame/frame_parser_cpp_gen.py b/src/struct_frame/frame_parser_cpp_gen.py index 0ccf6a4c..85524764 100644 --- a/src/struct_frame/frame_parser_cpp_gen.py +++ b/src/struct_frame/frame_parser_cpp_gen.py @@ -471,9 +471,8 @@ def generate_format(fmt): const_name = f'{PREFIX}_START_BYTE{i + 1}' if len(fmt.start_bytes) > 1 else f'{PREFIX}_START_BYTE' yield f' buffer[{idx}] = {const_name};\n' idx += 1 - yield f' buffer[{idx}] = msg_id;\n' - idx += 1 + # Write length BEFORE msg_id (per frame_formats.proto definition) if fmt.has_length: if fmt.length_bytes == 1: yield f' buffer[{idx}] = static_cast(msg_size);\n' @@ -482,6 +481,9 @@ def generate_format(fmt): yield f' buffer[{idx + 1}] = static_cast((msg_size >> 8) & 0xFF);\n' idx += fmt.length_bytes + yield f' buffer[{idx}] = msg_id;\n' + idx += 1 + yield f'\n if (msg_size > 0 && msg != nullptr) {{\n' yield f' std::memcpy(buffer + {PREFIX}_HEADER_SIZE, msg, msg_size);\n' yield f' }}\n\n' @@ -512,6 +514,9 @@ def generate_format(fmt): yield f'\n size_t msg_length = length - {PREFIX}_OVERHEAD;\n\n' + # Calculate msg_id offset: start_bytes + length_bytes (if has_length) + msg_id_offset = len(fmt.start_bytes) + (fmt.length_bytes if fmt.has_length else 0) + if fmt.has_crc: crc_data_start = len(fmt.start_bytes) crc_data_len = f'msg_length + 1' @@ -520,13 +525,13 @@ def generate_format(fmt): yield f' FrameChecksum ck = fletcher_checksum(buffer + {crc_data_start}, {crc_data_len});\n' yield f' if (ck.byte1 == buffer[length - 2] && ck.byte2 == buffer[length - 1]) {{\n' yield f' result.valid = true;\n' - yield f' result.msg_id = buffer[{len(fmt.start_bytes)}];\n' + yield f' result.msg_id = buffer[{msg_id_offset}];\n' yield f' result.msg_len = msg_length;\n' yield f' result.msg_data = const_cast(buffer + {PREFIX}_HEADER_SIZE);\n' yield f' }}\n' else: yield f' result.valid = true;\n' - yield f' result.msg_id = buffer[{len(fmt.start_bytes)}];\n' + yield f' result.msg_id = buffer[{msg_id_offset}];\n' yield f' result.msg_len = msg_length;\n' yield f' result.msg_data = const_cast(buffer + {PREFIX}_HEADER_SIZE);\n' diff --git a/tests/c/test_arrays.c b/tests/c/test_arrays.c index 68293c96..38cb95a2 100644 --- a/tests/c/test_arrays.c +++ b/tests/c/test_arrays.c @@ -72,19 +72,19 @@ int test_array_operations() { msg.bounded_sensors.data[0].status = 2; strncpy(msg.bounded_sensors.data[0].name, "Pressure", 16); - // Encode message into BasicFrame format + // Encode message into BasicDefault format uint8_t encode_buffer[1024]; - size_t encoded_size = basic_frame_encode(encode_buffer, sizeof(encode_buffer), - COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MSG_ID, - (const uint8_t*)&msg, COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MAX_SIZE); + size_t encoded_size = basic_default_encode(encode_buffer, sizeof(encode_buffer), + COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MSG_ID, + (const uint8_t*)&msg, COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MAX_SIZE); if (encoded_size == 0) { print_failure_details("Encoding failed", NULL, 0); return 0; } - // Validate and decode the BasicFrame - frame_msg_info_t decode_result = basic_frame_validate_packet(encode_buffer, encoded_size); + // Validate and decode the BasicDefault frame + frame_msg_info_t decode_result = basic_default_validate_packet(encode_buffer, encoded_size); if (!decode_result.valid) { print_failure_details("Validation failed", encode_buffer, encoded_size); return 0; diff --git a/tests/c/test_basic_types.c b/tests/c/test_basic_types.c index 620845f2..f77f629b 100644 --- a/tests/c/test_basic_types.c +++ b/tests/c/test_basic_types.c @@ -59,19 +59,19 @@ int test_basic_types() { msg.description.length = strlen("Test description for basic types"); strncpy(msg.description.data, "Test description for basic types", msg.description.length); - // Encode message into BasicFrame format + // Encode message into BasicDefault format uint8_t encode_buffer[1024]; - size_t encoded_size = basic_frame_encode(encode_buffer, sizeof(encode_buffer), - BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, - (const uint8_t*)&msg, BASIC_TYPES_BASIC_TYPES_MESSAGE_MAX_SIZE); + size_t encoded_size = basic_default_encode(encode_buffer, sizeof(encode_buffer), + BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, + (const uint8_t*)&msg, BASIC_TYPES_BASIC_TYPES_MESSAGE_MAX_SIZE); if (encoded_size == 0) { print_failure_details("Encoding failed", &msg, NULL, NULL, 0); return 0; } - // Validate and decode the BasicFrame - frame_msg_info_t decode_result = basic_frame_validate_packet(encode_buffer, encoded_size); + // Validate and decode the BasicDefault frame + frame_msg_info_t decode_result = basic_default_validate_packet(encode_buffer, encoded_size); if (!decode_result.valid) { print_failure_details("Validation failed", &msg, NULL, encode_buffer, encoded_size); return 0; diff --git a/tests/c/test_cross_platform_deserialization.c b/tests/c/test_cross_platform_deserialization.c index dbc30d3f..3e5eee93 100644 --- a/tests/c/test_cross_platform_deserialization.c +++ b/tests/c/test_cross_platform_deserialization.c @@ -83,7 +83,7 @@ int read_and_validate_test_data(const char* filename) { return 0; } - frame_msg_info_t decode_result = basic_frame_validate_packet(buffer, size); + frame_msg_info_t decode_result = basic_default_validate_packet(buffer, size); if (!decode_result.valid) { print_failure_details("Failed to decode data", buffer, size); diff --git a/tests/c/test_cross_platform_serialization.c b/tests/c/test_cross_platform_serialization.c index dcdf2ffd..e9e25f43 100644 --- a/tests/c/test_cross_platform_serialization.c +++ b/tests/c/test_cross_platform_serialization.c @@ -38,9 +38,9 @@ int create_test_data() { msg.test_array.data[2] = 300; uint8_t encode_buffer[512]; - size_t encoded_size = basic_frame_encode(encode_buffer, sizeof(encode_buffer), - SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, - (const uint8_t*)&msg, SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MAX_SIZE); + size_t encoded_size = basic_default_encode(encode_buffer, sizeof(encode_buffer), + SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, + (const uint8_t*)&msg, SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MAX_SIZE); if (encoded_size == 0) { print_failure_details("Encoding failed", NULL, 0); @@ -57,7 +57,7 @@ int create_test_data() { fclose(file); // Self-validate - frame_msg_info_t decode_result = basic_frame_validate_packet(encode_buffer, encoded_size); + frame_msg_info_t decode_result = basic_default_validate_packet(encode_buffer, encoded_size); if (!decode_result.valid) { print_failure_details("Self-validation failed", encode_buffer, encoded_size); return 0; diff --git a/tests/cpp/test_arrays.cpp b/tests/cpp/test_arrays.cpp index e6e1cbf9..edf0590b 100644 --- a/tests/cpp/test_arrays.cpp +++ b/tests/cpp/test_arrays.cpp @@ -25,9 +25,9 @@ int main() { msg.bounded_uints.data[1] = 200; msg.bounded_uints.data[2] = 300; - // Encode message into BasicFrame format + // Encode message into BasicDefault format uint8_t buffer[1024]; - FrameParsers::BasicFrameEncodeBuffer encoder(buffer, sizeof(buffer)); + FrameParsers::BasicDefaultEncodeBuffer encoder(buffer, sizeof(buffer)); if (!encoder.encode(COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MSG_ID, &msg, COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MAX_SIZE)) { diff --git a/tests/cpp/test_basic_types.cpp b/tests/cpp/test_basic_types.cpp index 252ff2d7..5194f65c 100644 --- a/tests/cpp/test_basic_types.cpp +++ b/tests/cpp/test_basic_types.cpp @@ -42,9 +42,9 @@ int main() { msg.description.length = 12; std::strncpy(msg.description.data, "Test message", sizeof(msg.description.data)); - // Encode message into BasicFrame format + // Encode message into BasicDefault format uint8_t buffer[512]; - FrameParsers::BasicFrameEncodeBuffer encoder(buffer, sizeof(buffer)); + FrameParsers::BasicDefaultEncodeBuffer encoder(buffer, sizeof(buffer)); if (!encoder.encode(BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, &msg, BASIC_TYPES_BASIC_TYPES_MESSAGE_MAX_SIZE)) { diff --git a/tests/cpp/test_cross_platform_deserialization.cpp b/tests/cpp/test_cross_platform_deserialization.cpp index 160c43a2..71b497ee 100644 --- a/tests/cpp/test_cross_platform_deserialization.cpp +++ b/tests/cpp/test_cross_platform_deserialization.cpp @@ -77,7 +77,7 @@ bool read_and_validate_test_data(const char* filename) { return false; } - FrameParsers::FrameMsgInfo decode_result = FrameParsers::basic_frame_validate_packet(buffer, size); + FrameParsers::FrameMsgInfo decode_result = FrameParsers::basic_default_validate_packet(buffer, size); if (!decode_result.valid) { print_failure_details("Failed to decode data"); diff --git a/tests/cpp/test_cross_platform_serialization.cpp b/tests/cpp/test_cross_platform_serialization.cpp index 9d142b72..fa0518ba 100644 --- a/tests/cpp/test_cross_platform_serialization.cpp +++ b/tests/cpp/test_cross_platform_serialization.cpp @@ -27,7 +27,7 @@ int main() { msg.test_array.data[2] = 300; uint8_t buffer[512]; - FrameParsers::BasicFrameEncodeBuffer encoder(buffer, sizeof(buffer)); + FrameParsers::BasicDefaultEncodeBuffer encoder(buffer, sizeof(buffer)); if (!encoder.encode(SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, &msg, SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MAX_SIZE)) { diff --git a/tests/js/test_cross_platform_deserialization.js b/tests/js/test_cross_platform_deserialization.js index 7f62fe0a..67318ed5 100644 --- a/tests/js/test_cross_platform_deserialization.js +++ b/tests/js/test_cross_platform_deserialization.js @@ -7,11 +7,11 @@ const fs = require('fs'); const path = require('path'); -// BasicFrame constants -const BASIC_FRAME_START_BYTE1 = 0x90; -const BASIC_FRAME_START_BYTE2 = 0x91; -const BASIC_FRAME_HEADER_SIZE = 3; // start1 + start2 + msg_id -const BASIC_FRAME_FOOTER_SIZE = 2; // crc1 + crc2 +// BasicDefault constants +const BASIC_DEFAULT_START_BYTE1 = 0x90; +const BASIC_DEFAULT_START_BYTE2 = 0x71; +const BASIC_DEFAULT_HEADER_SIZE = 4; // start1 + start2 + length + msg_id +const BASIC_DEFAULT_FOOTER_SIZE = 2; // crc1 + crc2 function printFailureDetails(label) { console.log('\n============================================================'); @@ -30,31 +30,33 @@ function loadExpectedValues() { } } -function validateBasicFrame(buffer, expected) { - // BasicFrame validation with 2 start bytes - if (buffer.length < BASIC_FRAME_HEADER_SIZE + BASIC_FRAME_FOOTER_SIZE) { +function validateBasicDefault(buffer, expected) { + // BasicDefault validation with 2 start bytes + length + msg_id + if (buffer.length < BASIC_DEFAULT_HEADER_SIZE + BASIC_DEFAULT_FOOTER_SIZE) { console.log(' Data too short'); return false; } // Check start bytes - if (buffer[0] !== BASIC_FRAME_START_BYTE1 || buffer[1] !== BASIC_FRAME_START_BYTE2) { - console.log(' Invalid start bytes (expected 0x90 0x91, got 0x' + buffer[0].toString(16) + ' 0x' + buffer[1].toString(16) + ')'); + if (buffer[0] !== BASIC_DEFAULT_START_BYTE1 || buffer[1] !== BASIC_DEFAULT_START_BYTE2) { + console.log(' Invalid start bytes (expected 0x90 0x71, got 0x' + buffer[0].toString(16) + ' 0x' + buffer[1].toString(16) + ')'); return false; } - // Check message ID (at offset 2 in BasicFrame) - if (buffer[2] !== 204) { - console.log(' Invalid message ID (expected 204, got ' + buffer[2] + ')'); + // Check message ID (at offset 3 in BasicDefault - after length) + if (buffer[3] !== 204) { + console.log(' Invalid message ID (expected 204, got ' + buffer[3] + ')'); return false; } // Validate checksum - const msgLen = buffer.length - BASIC_FRAME_HEADER_SIZE - BASIC_FRAME_FOOTER_SIZE; - let byte1 = buffer[2]; // Start with msg_id + const msgLen = buffer.length - BASIC_DEFAULT_HEADER_SIZE - BASIC_DEFAULT_FOOTER_SIZE; + let byte1 = buffer[2]; // Start with length byte let byte2 = buffer[2]; + byte1 = (byte1 + buffer[3]) % 256; // Add msg_id + byte2 = (byte2 + byte1) % 256; for (let i = 0; i < msgLen; i++) { - byte1 = (byte1 + buffer[BASIC_FRAME_HEADER_SIZE + i]) & 0xFF; + byte1 = (byte1 + buffer[BASIC_DEFAULT_HEADER_SIZE + i]) & 0xFF; byte2 = (byte2 + byte1) & 0xFF; } @@ -63,8 +65,8 @@ function validateBasicFrame(buffer, expected) { return false; } - // Extract magic number from payload (starts at offset 3 in BasicFrame) - const magicNumber = buffer.readUInt32LE(BASIC_FRAME_HEADER_SIZE); + // Extract magic number from payload (starts at offset 4 in BasicDefault) + const magicNumber = buffer.readUInt32LE(BASIC_DEFAULT_HEADER_SIZE); if (magicNumber !== expected.magic_number) { console.log(' Magic number mismatch (expected ' + expected.magic_number + ', got ' + magicNumber + ')'); return false; @@ -93,7 +95,7 @@ function readAndValidateTestData(filename) { return false; } - if (!validateBasicFrame(binaryData, expected)) { + if (!validateBasicDefault(binaryData, expected)) { console.log(' Validation failed'); return false; } diff --git a/tests/js/test_cross_platform_serialization.js b/tests/js/test_cross_platform_serialization.js index cc8b9e33..b1009c2e 100644 --- a/tests/js/test_cross_platform_serialization.js +++ b/tests/js/test_cross_platform_serialization.js @@ -7,11 +7,11 @@ const fs = require('fs'); const path = require('path'); -// BasicFrame constants -const BASIC_FRAME_START_BYTE1 = 0x90; -const BASIC_FRAME_START_BYTE2 = 0x91; -const BASIC_FRAME_HEADER_SIZE = 3; // start1 + start2 + msg_id -const BASIC_FRAME_FOOTER_SIZE = 2; // crc1 + crc2 +// BasicDefault constants +const BASIC_DEFAULT_START_BYTE1 = 0x90; +const BASIC_DEFAULT_START_BYTE2 = 0x71; +const BASIC_DEFAULT_HEADER_SIZE = 4; // start1 + start2 + length + msg_id +const BASIC_DEFAULT_FOOTER_SIZE = 2; // crc1 + crc2 function printFailureDetails(label, expectedValues, actualValues, rawData) { console.log('\n============================================================'); @@ -59,8 +59,8 @@ function createTestData() { return false; } - // Create a full BasicFrame message that matches C/Python format - // Frame format: [START1=0x90] [START2=0x91] [MSG_ID] [payload] [checksum1] [checksum2] + // Create a full BasicDefault message that matches C/Python format + // Frame format: [START1=0x90] [START2=0x71] [LEN] [MSG_ID] [payload] [checksum1] [checksum2] const msg_id = 204; // Create full payload matching the message structure: @@ -107,20 +107,23 @@ function createTestData() { offset += 4; } - // Calculate Fletcher checksum on msg_id + payload (consistent with C and Python BasicFrame) - let byte1 = msg_id; // Start with msg_id - let byte2 = msg_id; + // Calculate Fletcher checksum on length + msg_id + payload (consistent with BasicDefault) + let byte1 = payloadSize & 0xFF; // Start with length byte + let byte2 = payloadSize & 0xFF; + byte1 = (byte1 + msg_id) & 0xFF; // Add msg_id + byte2 = (byte2 + byte1) & 0xFF; for (let i = 0; i < payload.length; i++) { byte1 = (byte1 + payload[i]) & 0xFF; byte2 = (byte2 + byte1) & 0xFF; } - // Build complete frame with BasicFrame format - const frame = Buffer.alloc(BASIC_FRAME_HEADER_SIZE + payloadSize + BASIC_FRAME_FOOTER_SIZE); - frame[0] = BASIC_FRAME_START_BYTE1; - frame[1] = BASIC_FRAME_START_BYTE2; - frame[2] = msg_id; - payload.copy(frame, BASIC_FRAME_HEADER_SIZE); + // Build complete frame with BasicDefault format + const frame = Buffer.alloc(BASIC_DEFAULT_HEADER_SIZE + payloadSize + BASIC_DEFAULT_FOOTER_SIZE); + frame[0] = BASIC_DEFAULT_START_BYTE1; + frame[1] = BASIC_DEFAULT_START_BYTE2; + frame[2] = payloadSize & 0xFF; // Length byte + frame[3] = msg_id; + payload.copy(frame, BASIC_DEFAULT_HEADER_SIZE); frame[frame.length - 2] = byte1; frame[frame.length - 1] = byte2; diff --git a/tests/py/test_cross_platform_deserialization.py b/tests/py/test_cross_platform_deserialization.py index daf20847..1ef9fb37 100644 --- a/tests/py/test_cross_platform_deserialization.py +++ b/tests/py/test_cross_platform_deserialization.py @@ -116,10 +116,10 @@ def read_and_validate_test_data(filename): sys.path.insert(0, '../generated/py') from serialization_test_sf import SerializationTestSerializationTestMessage - from frame_parsers_gen import BasicFrame + from basic_default import BasicDefault - # Validate and decode using BasicFrame - result = BasicFrame.validate_packet(list(binary_data)) + # Validate and decode using BasicDefault + result = BasicDefault.validate_packet(list(binary_data)) if not result.valid: print_failure_details( diff --git a/tests/ts/test_cross_platform_deserialization.ts b/tests/ts/test_cross_platform_deserialization.ts index 34a522a2..11415e99 100644 --- a/tests/ts/test_cross_platform_deserialization.ts +++ b/tests/ts/test_cross_platform_deserialization.ts @@ -1,11 +1,11 @@ import * as fs from 'fs'; import * as path from 'path'; -// BasicFrame constants -const BASIC_FRAME_START_BYTE1 = 0x90; -const BASIC_FRAME_START_BYTE2 = 0x91; -const BASIC_FRAME_HEADER_SIZE = 3; // start1 + start2 + msg_id -const BASIC_FRAME_FOOTER_SIZE = 2; // crc1 + crc2 +// BasicDefault constants +const BASIC_DEFAULT_START_BYTE1 = 0x90; +const BASIC_DEFAULT_START_BYTE2 = 0x71; +const BASIC_DEFAULT_HEADER_SIZE = 4; // start1 + start2 + length + msg_id +const BASIC_DEFAULT_FOOTER_SIZE = 2; // crc1 + crc2 function printFailureDetails(label: string): void { console.log('\n============================================================'); @@ -24,31 +24,33 @@ function loadExpectedValues(): any { } } -function validateBasicFrame(buffer: Buffer, expected: any): boolean { - // BasicFrame validation with 2 start bytes - if (buffer.length < BASIC_FRAME_HEADER_SIZE + BASIC_FRAME_FOOTER_SIZE) { +function validateBasicDefault(buffer: Buffer, expected: any): boolean { + // BasicDefault validation with 2 start bytes + length + msg_id + if (buffer.length < BASIC_DEFAULT_HEADER_SIZE + BASIC_DEFAULT_FOOTER_SIZE) { console.log(' Data too short'); return false; } // Check start bytes - if (buffer[0] !== BASIC_FRAME_START_BYTE1 || buffer[1] !== BASIC_FRAME_START_BYTE2) { - console.log(` Invalid start bytes (expected 0x90 0x91, got 0x${buffer[0].toString(16)} 0x${buffer[1].toString(16)})`); + if (buffer[0] !== BASIC_DEFAULT_START_BYTE1 || buffer[1] !== BASIC_DEFAULT_START_BYTE2) { + console.log(` Invalid start bytes (expected 0x90 0x71, got 0x${buffer[0].toString(16)} 0x${buffer[1].toString(16)})`); return false; } - // Check message ID (at offset 2 in BasicFrame) - if (buffer[2] !== 204) { - console.log(` Invalid message ID (expected 204, got ${buffer[2]})`); + // Check message ID (at offset 3 in BasicDefault - after length) + if (buffer[3] !== 204) { + console.log(` Invalid message ID (expected 204, got ${buffer[3]})`); return false; } // Validate checksum - const msgLen = buffer.length - BASIC_FRAME_HEADER_SIZE - BASIC_FRAME_FOOTER_SIZE; - let byte1 = buffer[2]; // Start with msg_id + const msgLen = buffer.length - BASIC_DEFAULT_HEADER_SIZE - BASIC_DEFAULT_FOOTER_SIZE; + let byte1 = buffer[2]; // Start with length byte let byte2 = buffer[2]; + byte1 = (byte1 + buffer[3]) % 256; // Add msg_id + byte2 = (byte2 + byte1) % 256; for (let i = 0; i < msgLen; i++) { - byte1 = (byte1 + buffer[BASIC_FRAME_HEADER_SIZE + i]) & 0xFF; + byte1 = (byte1 + buffer[BASIC_DEFAULT_HEADER_SIZE + i]) & 0xFF; byte2 = (byte2 + byte1) & 0xFF; } @@ -57,8 +59,8 @@ function validateBasicFrame(buffer: Buffer, expected: any): boolean { return false; } - // Extract magic number from payload (starts at offset 3 in BasicFrame) - const magicNumber = buffer.readUInt32LE(BASIC_FRAME_HEADER_SIZE); + // Extract magic number from payload (starts at offset 4 in BasicDefault) + const magicNumber = buffer.readUInt32LE(BASIC_DEFAULT_HEADER_SIZE); if (magicNumber !== expected.magic_number) { console.log(` Magic number mismatch (expected ${expected.magic_number}, got ${magicNumber})`); return false; @@ -87,7 +89,7 @@ function readAndValidateTestData(filename: string): boolean { return false; } - if (!validateBasicFrame(binaryData, expected)) { + if (!validateBasicDefault(binaryData, expected)) { console.log(' Validation failed'); return false; } diff --git a/tests/ts/test_cross_platform_serialization.ts b/tests/ts/test_cross_platform_serialization.ts index 790510be..de77c06f 100644 --- a/tests/ts/test_cross_platform_serialization.ts +++ b/tests/ts/test_cross_platform_serialization.ts @@ -28,11 +28,11 @@ function printFailureDetails(label: string, expectedValues?: any, actualValues?: console.log('============================================================\n'); } -// BasicFrame constants -const BASIC_FRAME_START_BYTE1 = 0x90; -const BASIC_FRAME_START_BYTE2 = 0x91; -const BASIC_FRAME_HEADER_SIZE = 3; // start1 + start2 + msg_id -const BASIC_FRAME_FOOTER_SIZE = 2; // crc1 + crc2 +// BasicDefault constants +const BASIC_DEFAULT_START_BYTE1 = 0x90; +const BASIC_DEFAULT_START_BYTE2 = 0x71; +const BASIC_DEFAULT_HEADER_SIZE = 4; // start1 + start2 + length + msg_id +const BASIC_DEFAULT_FOOTER_SIZE = 2; // crc1 + crc2 function loadExpectedValues(): any { try { @@ -53,8 +53,8 @@ function createTestData(): boolean { return false; } - // Create a full BasicFrame message that matches C/Python format - // Frame format: [START1=0x90] [START2=0x91] [MSG_ID] [payload] [checksum1] [checksum2] + // Create a full BasicDefault message that matches C/Python format + // Frame format: [START1=0x90] [START2=0x71] [LEN] [MSG_ID] [payload] [checksum1] [checksum2] const msg_id = 204; // Create full payload matching the message structure: @@ -101,20 +101,23 @@ function createTestData(): boolean { offset += 4; } - // Calculate Fletcher checksum on msg_id + payload (consistent with C and Python BasicFrame) - let byte1 = msg_id; // Start with msg_id - let byte2 = msg_id; + // Calculate Fletcher checksum on length + msg_id + payload (consistent with BasicDefault) + let byte1 = payloadSize & 0xFF; // Start with length byte + let byte2 = payloadSize & 0xFF; + byte1 = (byte1 + msg_id) & 0xFF; // Add msg_id + byte2 = (byte2 + byte1) & 0xFF; for (let i = 0; i < payload.length; i++) { byte1 = (byte1 + payload[i]) & 0xFF; byte2 = (byte2 + byte1) & 0xFF; } - // Build complete frame with BasicFrame format - const frame = Buffer.alloc(BASIC_FRAME_HEADER_SIZE + payloadSize + BASIC_FRAME_FOOTER_SIZE); - frame[0] = BASIC_FRAME_START_BYTE1; - frame[1] = BASIC_FRAME_START_BYTE2; - frame[2] = msg_id; - payload.copy(frame, BASIC_FRAME_HEADER_SIZE); + // Build complete frame with BasicDefault format + const frame = Buffer.alloc(BASIC_DEFAULT_HEADER_SIZE + payloadSize + BASIC_DEFAULT_FOOTER_SIZE); + frame[0] = BASIC_DEFAULT_START_BYTE1; + frame[1] = BASIC_DEFAULT_START_BYTE2; + frame[2] = payloadSize & 0xFF; // Length byte + frame[3] = msg_id; + payload.copy(frame, BASIC_DEFAULT_HEADER_SIZE); frame[frame.length - 2] = byte1; frame[frame.length - 1] = byte2;