Skip to content

Command Protocol

SmartPot uses a bidirectional LoRa command protocol between the base station and individual smart buoys. All packets are AES-128 encrypted. Every critical command requires an acknowledgment handshake confirming receipt and execution.

flowchart LR
    P["Preamble\n2 bytes"]
    ID["Pot ID\n2 bytes"]
    CMD["Cmd\n1 byte"]
    PL["Payload\n0–24 bytes"]
    SEQ["Seq\n2 bytes"]
    MAC["CMAC\n4 bytes"]

    P --> ID --> CMD --> PL --> SEQ --> MAC

    style P fill:#e6f3f0,stroke:#2d7d6f
    style ID fill:#e6f3f0,stroke:#2d7d6f
    style CMD fill:#e8f0f5,stroke:#3a6d8c
    style PL fill:#f0f4f8,stroke:#4a6785
    style SEQ fill:#e8f0f5,stroke:#3a6d8c
    style MAC fill:#e6f3f0,stroke:#2d7d6f
FieldSizeDescription
Preamble2 bytes0x5350 (“SP” for SmartPot)
Pot ID2 bytesUnique trap identifier (0x0001–0xFFFE)
Command1 byteCommand opcode
Payload0–24 bytesCommand-specific data
Sequence2 bytesMonotonic counter for replay protection
CMAC4 bytesAES-CMAC truncated authentication tag
OpcodeNamePayloadDescription
0x01LOCK_DOORLock the servo-driven door latch to retain catch
0x02UNLOCK_DOORUnlock door to release contents
0x03SURFACETrigger ballast release for ropeless recovery
0x04CAPTURERequest on-demand image from trap camera
0x05STATUSForce immediate telemetry report
0x06SLEEPduration_hours (2B)Enter deep hibernation
0x07SET_MODEmode (1B)Set classification mode (0=auto, 1=manual, 2=log-only)
0x08REBOOTSoft restart both submerged unit and buoy
OpcodeNamePayloadDescription
0x80ACKcmd_acked (1B) + status (1B)Command acknowledgment
0x81TELEMETRYSee Telemetry FormatPeriodic status report
0x82CATCH_EVENTspecies (1B) + size_mm (2B) + action (1B)Classification result
0x83ALERTalert_type (1B) + data (4B)Drift, low battery, or fault alert
0x84IMAGE_READYchunk_count (1B) + total_bytes (2B)Image available for download

Critical commands (LOCK_DOOR, UNLOCK_DOOR, SURFACE) use a three-phase handshake:

sequenceDiagram
    participant Base as Base Station
    participant Buoy as Smart Buoy
    participant Trap as Submerged Unit

    Base->>Buoy: Command (seq=N)
    Buoy-->>Base: ACK (status=0x01, received)
    Buoy->>Trap: Forward over tether
    Trap-->>Buoy: Execution result
    Buoy-->>Base: ACK (status=0x02, confirmed)

    Note over Base: 10s timeout per attempt
    Note over Base: 3 retries max

If no ACK is received within 10 seconds, the base retransmits up to 3 times using the same sequence number. After 3 failures, the command is marked as failed and the operator is alerted.

The CAPTURE command triggers an on-demand image from the trap camera. The resulting image is delivered using a progressive JPEG transfer protocol — the same protocol used by the ESP32-CAM project.

Standard JPEG files must be received in full before rendering. Progressive JPEGs encode the image in successive scans — a blurry full-frame preview arrives in the first few fragments, with each subsequent scan adding detail. Over a slow LoRa link (~686 bytes/sec), this means the operator sees a usable preview in seconds rather than waiting minutes for the full image.

sequenceDiagram
    participant Base as Base Station
    participant Buoy as Smart Buoy
    participant Trap as Submerged Unit

    Base->>Buoy: CAPTURE (0x04)
    Buoy-->>Base: ACK (received)
    Buoy->>Trap: Forward over tether
    Trap-->>Buoy: IMAGE_READY (0x84)<br/>chunk_count + total_bytes
    Buoy-->>Base: IMAGE_READY relay

    loop Scan-by-scan delivery
        Trap->>Buoy: Image fragments (8-fragment windows)
        Buoy->>Base: LoRa relay (168 raw bytes/fragment)
        Base-->>Buoy: Window ACK bitmap
        Buoy-->>Trap: ACK relay
    end

    Note over Base: Each scan = renderable preview
ParameterValue
Fragment payload168 bytes raw JPEG data
Window size8 fragments
ACK timeout5 seconds per window
Max retries3 per window
Inter-packet delay50ms
IntegrityCRC8-CCITT per fragment, CRC16-CCITT full image

For the complete protocol specification — including binary header format, segment indexing, NACK handling, and scan-level flags — see the Transfer Protocol reference.

  • AES-128-CMAC authentication on every packet
  • Sequence counter prevents replay attacks
  • Per-pot keys — compromise of one pot doesn’t affect the fleet
  • Key provisioning happens during initial flash (see Encryption)