open Wire let frame_size = 256 let header_size = 8 let max_payload = frame_size - header_size type kind = | TM | TC | EVR | PRM_GET | PRM_SET | PRM_RSP | DP | HEALTH | LOG | ERROR let kind_to_int = function | TM -> 0x00 | TC -> 0x01 | EVR -> 0x02 | PRM_GET -> 0x03 | PRM_SET -> 0x04 | PRM_RSP -> 0x05 | DP -> 0x06 | HEALTH -> 0x07 | LOG -> 0x08 | ERROR -> 0x09 let kind_of_int = function | 0x00 -> Some TM | 0x01 -> Some TC | 0x02 -> Some EVR | 0x03 -> Some PRM_GET | 0x04 -> Some PRM_SET | 0x05 -> Some PRM_RSP | 0x06 -> Some DP | 0x07 -> Some HEALTH | 0x08 -> Some LOG | 0x09 -> Some ERROR | _ -> None let pp_kind ppf = function | TM -> Fmt.string ppf "TM" | TC -> Fmt.string ppf "TC" | EVR -> Fmt.string ppf "EVR" | PRM_GET -> Fmt.string ppf "PRM_GET" | PRM_SET -> Fmt.string ppf "PRM_SET" | PRM_RSP -> Fmt.string ppf "PRM_RSP" | DP -> Fmt.string ppf "DP" | HEALTH -> Fmt.string ppf "HEALTH" | LOG -> Fmt.string ppf "LOG" | ERROR -> Fmt.string ppf "ERROR" type t = { version : int; msg_type : int; apid : int; payload_length : int; reserved : int; payload : string; } let codec = let open Codec in record "SpaceOSFrame" (fun version msg_type apid payload_length reserved payload -> { version; msg_type; apid; payload_length; reserved; payload }) |+ field "version" uint8 (fun t -> t.version) |+ field "msg_type" uint8 (fun t -> t.msg_type) |+ field "apid" uint16be (fun t -> t.apid) |+ field "payload_length" uint16be (fun t -> t.payload_length) |+ field "reserved" uint16be (fun t -> t.reserved) |+ field "payload" (byte_array ~size:(int max_payload)) (fun t -> t.payload) |> seal let v typ ~apid payload = let payload_length = min max_payload (String.length payload) in (* Pad payload to full 248 bytes for exact roundtrip *) let padded = Bytes.make max_payload '\x00' in Bytes.blit_string payload 0 padded 0 payload_length; { version = 0x01; msg_type = kind_to_int typ; apid; payload_length; reserved = 0; payload = Bytes.unsafe_to_string padded; } let payload_bytes t = let n = max 0 (min max_payload t.payload_length) in String.sub t.payload 0 n let pp ppf t = let typ_s = match kind_of_int t.msg_type with | Some mt -> Fmt.str "%a" pp_kind mt | None -> Fmt.str "0x%02x" t.msg_type in Fmt.pf ppf "@[frame(ver=%d type=%s apid=%d payload=%d)@]" t.version typ_s t.apid t.payload_length let equal a b = a.version = b.version && a.msg_type = b.msg_type && a.apid = b.apid && a.payload_length = b.payload_length && a.reserved = b.reserved && String.equal a.payload b.payload