# `DSMR.Telegram`
[🔗](https://github.com/mijnverbruik/dsmr/blob/v1.1.0/lib/dsmr/telegram.ex#L1)

A parsed DSMR telegram.

A telegram contains the values broadcast by a smart meter at a point in time.
Different DSMR versions expose different fields, so most fields are optional
and remain `nil` when the input does not contain the corresponding OBIS code.

Unknown OBIS codes are preserved in `unknown_fields` instead of being rejected.
This keeps parsing tolerant of regional extensions and meter-specific fields.

# `maybe`

```elixir
@type maybe(type) :: type | nil
```

# `obis_t`

```elixir
@type obis_t() ::
  {non_neg_integer(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
   non_neg_integer()}
```

# `obj_t`

```elixir
@type obj_t() :: {obis_t(), value_t() | [value_t()]}
```

# `power_failure_event_t`

```elixir
@type power_failure_event_t() :: [DSMR.Timestamp.t() | DSMR.Measurement.t()]
```

# `t`

```elixir
@type t() :: %DSMR.Telegram{
  actual_switch_position: maybe(String.t()),
  actual_threshold_electricity: maybe(DSMR.Measurement.t()),
  checksum: String.t(),
  currently_delivered_l1: maybe(DSMR.Measurement.t()),
  currently_delivered_l2: maybe(DSMR.Measurement.t()),
  currently_delivered_l3: maybe(DSMR.Measurement.t()),
  currently_returned_l1: maybe(DSMR.Measurement.t()),
  currently_returned_l2: maybe(DSMR.Measurement.t()),
  currently_returned_l3: maybe(DSMR.Measurement.t()),
  electricity_currently_delivered: maybe(DSMR.Measurement.t()),
  electricity_currently_returned: maybe(DSMR.Measurement.t()),
  electricity_delivered_1: maybe(DSMR.Measurement.t()),
  electricity_delivered_2: maybe(DSMR.Measurement.t()),
  electricity_returned_1: maybe(DSMR.Measurement.t()),
  electricity_returned_2: maybe(DSMR.Measurement.t()),
  electricity_tariff_indicator: maybe(String.t()),
  equipment_id: maybe(String.t()),
  header: String.t(),
  mbus_devices: [DSMR.MBusDevice.t()],
  measured_at: maybe(DSMR.Timestamp.t()),
  phase_power_current_l1: maybe(DSMR.Measurement.t()),
  phase_power_current_l2: maybe(DSMR.Measurement.t()),
  phase_power_current_l3: maybe(DSMR.Measurement.t()),
  power_failures_count: maybe(String.t()),
  power_failures_log: maybe([power_failure_event_t()]),
  power_failures_long_count: maybe(String.t()),
  text_message: maybe(String.t()),
  text_message_code: maybe(String.t()),
  unknown_fields: [unknown_field_t()],
  version: maybe(String.t()),
  voltage_l1: maybe(DSMR.Measurement.t()),
  voltage_l2: maybe(DSMR.Measurement.t()),
  voltage_l3: maybe(DSMR.Measurement.t()),
  voltage_sags_l1_count: maybe(String.t()),
  voltage_sags_l2_count: maybe(String.t()),
  voltage_sags_l3_count: maybe(String.t()),
  voltage_swells_l1_count: maybe(String.t()),
  voltage_swells_l2_count: maybe(String.t()),
  voltage_swells_l3_count: maybe(String.t())
}
```

# `unknown_field_t`

```elixir
@type unknown_field_t() :: {obis_t(), value_t() | [value_t()]}
```

# `value_t`

```elixir
@type value_t() ::
  String.t()
  | integer()
  | float()
  | Decimal.t()
  | obis_t()
  | DSMR.Timestamp.t()
  | DSMR.Measurement.t()
  | nil
```

# `decode_octet_string`

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

Decodes a hex-encoded octet-string value to its ASCII representation.

The DSMR standard encodes octet-string values as hexadecimal ASCII: this
applies to `equipment_id`, `text_message`, and `DSMR.MBusDevice`
equipment ids. Parsed telegrams keep the raw hex value so that
serialization stays lossless; use this function to read the decoded text.

Returns `:error` when the value is not valid hex.

## Examples

    iex> DSMR.Telegram.decode_octet_string("4B384547303034303436333935353037")
    {:ok, "K8EG004046395507"}

    iex> DSMR.Telegram.decode_octet_string("XYZ")
    :error

# `to_string`

```elixir
@spec to_string(t()) :: String.t()
```

Converts a Telegram struct back to its string representation.

Fields with `nil` or empty string values are omitted.

## Examples

    iex> telegram = %DSMR.Telegram{
    ...>   header: "ISk5\\2MT382-1000",
    ...>   checksum: "5106",
    ...>   version: "50"
    ...> }
    iex> DSMR.Telegram.to_string(telegram)
    "/ISk5\\2MT382-1000\r\n\r\n1-3:0.2.8(50)\r\n!5106\r\n"

---

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