(** SpaceOS fixed-size frame codec. Every read/write is exactly 256 bytes. The [payload_length] field tells how many of the 248 payload bytes are meaningful. {v +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version | Type | APID (uint16 BE) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Length (uint16) | Reserved (uint16) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload (248 bytes, zero-padded) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ v} *) val frame_size : int (** Fixed frame size: 256 bytes. *) val header_size : int (** Header size: 8 bytes. *) val max_payload : int (** Maximum payload: 248 bytes. *) (** {1 Message types} *) type kind = | TM | TC | EVR | PRM_GET | PRM_SET | PRM_RSP | DP | HEALTH | LOG | ERROR val kind_to_int : kind -> int (** Convert a message type to its wire representation. *) val kind_of_int : int -> kind option (** Parse a message type from its wire representation. *) val pp_kind : kind Fmt.t (** Pretty-print a message type. *) (** {1 Frame} *) type t = { version : int; msg_type : int; apid : int; payload_length : int; reserved : int; payload : string; } val codec : t Wire.Codec.t (** Wire codec for the full 256-byte frame. *) val v : kind -> apid:int -> string -> t (** [v typ ~apid payload] builds a frame. Payload is truncated to 248 bytes. *) val payload_bytes : t -> string (** [payload_bytes t] returns the meaningful payload bytes (first [payload_length] bytes). *) val pp : t Fmt.t (** Pretty-print a frame. *) val equal : t -> t -> bool (** Structural equality. *)