# `Sidereon.Format.OMM`
[🔗](https://github.com/neilberkman/sidereon-ex/blob/main/lib/sidereon/format/omm.ex#L1)

Parse and encode CCSDS Orbit Mean-Elements Messages (OMM).

OMM is the modern standard format for orbital data, carrying the same
elements as TLE plus metadata such as originator, reference frame, time
system, and mean-element theory. CelesTrak and Space-Track distribute OMM
messages as KVN, XML, and JSON.

`parse_kvn/1`, `parse_xml/1`, `parse_json/1`, and string `parse/1` return a
typed `%Sidereon.Format.OMM{}` that preserves the OMM metadata and
microsecond epoch fields. The legacy decoded-map `parse/1` clause is kept for
CelesTrak JSON maps and returns `%Sidereon.Elements{}`.

# `encode_error`

```elixir
@type encode_error() ::
  {:missing_field, atom()} | {:invalid_field, atom(), term()} | String.t()
```

# `parse_error`

```elixir
@type parse_error() ::
  {:missing_field, String.t()} | {:invalid_field, String.t(), term()}
```

# `t`

```elixir
@type t() :: %Sidereon.Format.OMM{
  arg_of_pericenter_deg: float(),
  bstar: float(),
  ccsds_omm_vers: String.t(),
  center_name: String.t() | nil,
  classification_type: String.t(),
  creation_date: String.t() | nil,
  eccentricity: float(),
  element_set_no: integer(),
  ephemeris_type: integer(),
  epoch: Sidereon.Format.OMM.Epoch.t(),
  inclination_deg: float(),
  mean_anomaly_deg: float(),
  mean_element_theory: String.t() | nil,
  mean_motion: float(),
  mean_motion_ddot: float(),
  mean_motion_dot: float(),
  norad_cat_id: integer(),
  object_id: String.t() | nil,
  object_name: String.t() | nil,
  originator: String.t() | nil,
  ra_of_asc_node_deg: float(),
  ref_frame: String.t() | nil,
  rev_at_epoch: integer(),
  time_system: String.t() | nil
}
```

# `encode`

```elixir
@spec encode(
  t(),
  keyword()
) :: {:ok, String.t()} | {:error, encode_error()}
```

Encode an OMM value.

A typed `%Sidereon.Format.OMM{}` is serialized as text. The `:format` option
may be `:kvn`, `:xml`, or `:json` and defaults to `:kvn`.

The legacy `%Sidereon.Elements{}` clause returns a JSON-compatible map with
standard OMM field names.

# `encode_json`

```elixir
@spec encode_json(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Encode a typed OMM struct as CCSDS/CelesTrak OMM JSON text.

Returns `{:ok, text}` or `{:error, reason}`.

# `encode_kvn`

```elixir
@spec encode_kvn(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Encode a typed OMM struct as CCSDS OMM KVN text.

Returns `{:ok, text}` or `{:error, reason}`.

# `encode_xml`

```elixir
@spec encode_xml(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Encode a typed OMM struct as CCSDS OMM XML text.

Returns `{:ok, text}` or `{:error, reason}`.

# `parse`

```elixir
@spec parse(String.t()) :: {:ok, t()} | {:error, String.t()}
@spec parse(map()) :: {:ok, Sidereon.Elements.t()} | {:error, parse_error()}
```

Parse an OMM from text or from a decoded JSON map.

For binary input, the text format is auto-detected: a leading `<` selects XML,
a leading `{` or `[` selects JSON, and all other input is parsed as KVN. Text
parsing returns `{:ok, %Sidereon.Format.OMM{}}` or `{:error, reason}`.

For map input, accepts decoded CelesTrak/Space-Track OMM JSON maps with field
names such as `"NORAD_CAT_ID"`, `"INCLINATION"`, and `"MEAN_MOTION"`. This
legacy path returns `{:ok, %Sidereon.Elements{}}` and handles both numeric and
string values for numeric fields.

## Examples

    iex> {:ok, el} = Sidereon.Format.OMM.parse(%{
    ...>   "NORAD_CAT_ID" => 25544,
    ...>   "OBJECT_NAME" => "ISS (ZARYA)",
    ...>   "EPOCH" => "2024-01-01T00:00:00",
    ...>   "INCLINATION" => 51.6,
    ...>   "RA_OF_ASC_NODE" => 300.0,
    ...>   "ECCENTRICITY" => 0.0007,
    ...>   "ARG_OF_PERICENTER" => 90.0,
    ...>   "MEAN_ANOMALY" => 270.0,
    ...>   "MEAN_MOTION" => 15.5
    ...> })
    iex> el.catalog_number
    "25544"
    iex> el.object_name
    "ISS (ZARYA)"

# `parse_json`

```elixir
@spec parse_json(String.t()) :: {:ok, t()} | {:error, String.t()}
```

Parse CCSDS/CelesTrak OMM JSON text into a typed OMM struct.

JSON input may be a single OMM object or an array of OMM objects; the core
parser follows CelesTrak convention and selects the first array item.

Returns `{:ok, %Sidereon.Format.OMM{}}` or `{:error, reason}`.

# `parse_kvn`

```elixir
@spec parse_kvn(String.t()) :: {:ok, t()} | {:error, String.t()}
```

Parse CCSDS OMM KVN text into a typed OMM struct.

Returns `{:ok, %Sidereon.Format.OMM{}}` or `{:error, reason}`.

# `parse_xml`

```elixir
@spec parse_xml(String.t()) :: {:ok, t()} | {:error, String.t()}
```

Parse CCSDS OMM XML text into a typed OMM struct.

Returns `{:ok, %Sidereon.Format.OMM{}}` or `{:error, reason}`.

# `to_elements`

```elixir
@spec to_elements(t()) :: {:ok, Sidereon.Elements.t()} | {:error, encode_error()}
```

Convert a typed OMM struct to `%Sidereon.Elements{}` for SGP4 propagation.

OMM-specific metadata remains available on the original OMM struct; the
returned `%Sidereon.Elements{}` carries the TLE-compatible mean elements.

Returns `{:ok, elements}` or `{:error, reason}`.

# `to_json_string`

```elixir
@spec to_json_string(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Alias for `encode_json/1`, matching the core and Python binding terminology.

# `to_kvn_string`

```elixir
@spec to_kvn_string(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Alias for `encode_kvn/1`, matching the core and Python binding terminology.

# `to_xml_string`

```elixir
@spec to_xml_string(t()) :: {:ok, String.t()} | {:error, encode_error()}
```

Alias for `encode_xml/1`, matching the core and Python binding terminology.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
