Skip to content

Commands Domain

The Commands domain generates code from command protocol definitions, typically used for embedded communication protocols.

YAML Schema

name: string              # Required: Name for the command set
file: string              # Optional: Output filename (defaults to lowercase name)
endianness: "<" | ">"     # Optional: Little or big endian (default: "<")
commands:                 # Required: List of commands
  - name: string          # Command name
    id: integer           # Unique command ID
    description: string   # Optional: Human-readable description
    args:                 # Optional: List of arguments
      - name: string
        type: string      # Argument type (see below)
        description: string
        default: value    # Optional: Default value
        enums:            # Optional: Enumeration values
          - name: string
            value: integer
            description: string
    returns:              # Optional: Return values (same format as args)
      - name: string
        type: string
        description: string

Argument Types

Type Description Python Type
B Unsigned 8-bit integer int
H Unsigned 16-bit integer int
I Unsigned 32-bit integer int
Q Unsigned 64-bit integer int
b Signed 8-bit integer int
h Signed 16-bit integer int
i Signed 32-bit integer int
q Signed 64-bit integer int
e 16-bit float float
f 32-bit float float
d 64-bit float float
? Boolean bool
s Byte string bytes

These type codes follow Python's struct module conventions.

Example Configuration

name: Simple
file: commands
endianness: "<"

commands:
  - name: ping
    id: 0
    description: "Ping the device"
    args:
      - name: probe_id
        type: B
        default: 1
        description: "ID of the probe to ping"

  - name: set_mode
    id: 1
    description: "Set the operating mode"
    args:
      - name: mode
        type: B
        description: "Operating mode"
        enums:
          - { name: IDLE, value: 0, description: "Idle mode" }
          - { name: ACTIVE, value: 1, description: "Active mode" }
          - { name: SLEEP, value: 2, description: "Sleep mode" }

  - name: read_sensor
    id: 2
    description: "Read sensor value"
    args:
      - name: sensor_id
        type: B
        description: "Sensor ID to read"
    returns:
      - name: value
        type: f
        description: "Sensor reading"

  - name: write_data
    id: 3
    description: "Write raw data"
    args:
      - name: data
        type: s
        description: "Data bytes to write"

Generated Outputs

C Header (--h)

embgen commands config.yml -o output/ --h

Generates:

  • commands.h — Main header with:
  • Command ID enum
  • Argument type enums
  • Struct definitions for command arguments
// commands.h - Generated by embgen
#ifndef COMMANDS_H
#define COMMANDS_H

#include <stdint.h>
#include <stdbool.h>

// Command IDs
typedef enum {
    CMD_PING = 0,
    CMD_SET_MODE = 1,
    CMD_READ_SENSOR = 2,
    CMD_WRITE_DATA = 3,
} CommandId;

// Mode enumeration
typedef enum {
    MODE_IDLE = 0,
    MODE_ACTIVE = 1,
    MODE_SLEEP = 2,
} SetModeMode;

// Command argument structures
typedef struct {
    uint8_t probe_id;
} PingArgs;

typedef struct {
    SetModeMode mode;
} SetModeArgs;

// ... etc

#endif // COMMANDS_H

Python Module (--py)

embgen commands config.yml -o output/ --py

Generates:

  • commands.py — Command dataclasses with serialization
  • commands_base.py — Base classes for command handling
# commands.py - Generated by embgen
from dataclasses import dataclass
from enum import IntEnum
from commands_base import Command

class SetModeMode(IntEnum):
    IDLE = 0
    ACTIVE = 1
    SLEEP = 2

@dataclass
class Ping(Command):
    probe_id: int = 1

    ID = 0
    FORMAT = "<B"

@dataclass  
class SetMode(Command):
    mode: SetModeMode = SetModeMode.IDLE

    ID = 1
    FORMAT = "<B"

# ... etc

Markdown Documentation (--md)

embgen commands config.yml -o output/ --md

Generates human-readable documentation with:

  • Command table with IDs and descriptions
  • Detailed argument documentation
  • Enumeration value tables

CLI Usage

# Generate C header only
embgen commands config.yml -o output/ --h

# Generate all formats
embgen commands config.yml -o output/ --h --py --md

# With debug output
embgen -d commands config.yml -o output/ --h

Python API Usage

from pathlib import Path
from embgen.discovery import discover_domains
from embgen.generator import CodeGenerator

domains = discover_domains()
code_gen = CodeGenerator(domains["commands"], Path("output"))

templates = {"h": "template.h.j2", "py": "template.py.j2"}
code_gen.generate_from_file(Path("commands.yml"), templates)

Post-Generation Files

When generating Python output (--py), the Commands domain automatically copies commands_base.py to the output directory. This file contains base classes for command serialization and deserialization.