Astarte.Flow.Message (astarte_flow v0.1.0)

Link to this section Summary

Functions

Converts a message map to a Message struct, this function is useful for handling JSON decoded messages.

Converts a Message struct to a serialization friendly map, so it can be used with a JSON serializer.

Converts a "wrapped" value to a value that can be used as a Message data.

Converts a value to a "wrapped" value that can be easily serialized.

Link to this section Types

Link to this type

basic_data()

@type basic_data() ::
  integer() | float() | boolean() | DateTime.t() | binary() | String.t()
Link to this type

basic_data_type()

@type basic_data_type() :: :integer | :real | :boolean | :datetime | :binary | :string
@type data() :: data_with_array() | %{optional(String.t()) => data_with_array()}
@type data_type() ::
  %{required(String.t()) => data_type_with_array()} | data_type_with_array()
Link to this type

data_type_with_array()

@type data_type_with_array() :: basic_data_type() | {:array, basic_data_type()}
Link to this type

data_with_array()

@type data_with_array() :: basic_data() | [basic_data()]
Link to this type

message_metadata()

@type message_metadata() :: %{optional(String.t()) => String.t()}
Link to this type

message_timestamp()

@type message_timestamp() :: integer()
@type subtype() :: nil | String.t() | %{required(String.t()) => String.t()}
@type t() :: %Astarte.Flow.Message{
  data: data(),
  key: String.t(),
  metadata: message_metadata(),
  subtype: subtype(),
  timestamp: message_timestamp(),
  type: data_type()
}

An Astarte Flow message.

  • :key: a unicode string that identifies the stream the message belongs to.
  • :metadata: additional message metadata.
  • :type': message data type (e.g. integer, real, boolean, etc...). *:subtype: a string that represents the subtype, that is a mimetype for binaries. *:timestamp: timestamp in microseconds. *:data`: the message payload.

Link to this section Functions

Link to this function

deserialize_type(message_type)

@spec deserialize_type(String.t() | %{required(String.t()) => String.t()}) ::
  {:ok, data_type()} | {:error, :invalid_message_type}
@spec from_map(%{required(String.t()) => term()}) ::
  {:ok, t()} | {:error, :invalid_message}

Converts a message map to a Message struct, this function is useful for handling JSON decoded messages.

examples

Examples

iex> %{
...>   "schema" => "astarte_flow/message/v0.1",
...>   "data" => 42,
...>   "key" => "meaning-of-life",
...>   "metadata" => %{},
...>   "timestamp" => 1551884045074,
...>   "timestamp_us" => 181,
...>   "type" => "integer"
...> }
...> |> Message.from_map()
{:ok,
  %Message{
  data: 42,
  key: "meaning-of-life",
  metadata: %{},
  timestamp: 1551884045074181,
  type: :integer
}}

iex> %{
...>   "schema" => "astarte_flow/message/v0.1",
...> }
...> |> Message.from_map()
{:error, :invalid_message}

iex> Message.from_map(%{})
{:error, :invalid_message}
Link to this function

serialize_type(data_type)

@spec serialize_type(basic_data_type()) :: String.t()
Link to this function

to_map(message)

@spec to_map(t()) :: %{required(String.t()) => term()}

Converts a Message struct to a serialization friendly map, so it can be used with a JSON serializer.

examples

Examples

iex> %Message{
...>   data: 42,
...>   key: "meaning-of-life",
...>   metadata: %{},
...>   timestamp: 1551884045074181,
...>   type: :integer
...> }
...> |> Message.to_map()
%{
  "schema" => "astarte_flow/message/v0.1",
  "data" => 42,
  "key" => "meaning-of-life",
  "metadata" => %{},
  "timestamp" => 1551884045074,
  "timestamp_us" => 181,
  "type" => "integer"
}

iex> %Message{
...>   data: <<0, 1, 2, 0>>,
...>   key: "binaries_stream",
...>   metadata: %{},
...>   timestamp: 1551884045074181,
...>   type: :binary,
...>   subtype: "application/octet-stream"
...> }
...> |> Message.to_map()
%{
  "schema" => "astarte_flow/message/v0.1",
  "data" => "AAECAA==",
  "key" => "binaries_stream",
  "metadata" => %{},
  "timestamp" => 1551884045074,
  "timestamp_us" => 181,
  "type" => "binary",
  "subtype" => "application/octet-stream"
}

iex> %Message{
...>   data: %{
...>     "a" => -1,
...>     "b" => "Ciao\n"
...>   },
...>   key: "binaries_stream",
...>   metadata: %{},
...>   timestamp: 1551884045074181,
...>   type: %{
...>     "a" => :real,
...>     "b" => :binary
...>   },
...>   subtype: %{
...>     "b" => "text/plain"
...>   }
...> }
...> |> Message.to_map()
%{
  "schema" => "astarte_flow/message/v0.1",
  "data" => %{
    "a" => -1,
    "b" => "Q2lhbwo="
  },
  "key" => "binaries_stream",
  "metadata" => %{},
  "timestamp" => 1551884045074,
  "timestamp_us" => 181,
  "type" => %{
    "a" => "real",
    "b" => "binary"
  },
  "subtype" => %{
    "b" => "text/plain"
  }
}
Link to this function

unwrap_data(wrapped_data, type_map)

@spec unwrap_data(integer(), :integer) :: {:ok, integer()} | {:error, :invalid_data}
@spec unwrap_data(float(), :real) :: {:ok, float()} | {:error, :invalid_data}
@spec unwrap_data(boolean(), :boolean) :: {:ok, boolean()} | {:error, :invalid_data}
@spec unwrap_data(String.t(), :datetime) ::
  {:ok, DateTime.t()} | {:error, :invalid_data}
@spec unwrap_data(binary(), :binary) :: {:ok, binary()} | {:error, :invalid_data}
@spec unwrap_data(String.t(), :string) :: {:ok, String.t()} | {:error, :invalid_data}
@spec unwrap_data(list(), {:array, basic_data_type()}) ::
  {:ok, [basic_data_type()]} | {:error, :invalid_data}
@spec unwrap_data(%{optional(String.t()) => term()}, :map) ::
  {:ok, data()} | {:error, :invalid_data}

Converts a "wrapped" value to a value that can be used as a Message data.

examples

Examples

iex> Message.unwrap_data(42, :integer)
{:ok, 42}

iex> Message.unwrap_data(0.5, :real)
{:ok, 0.5}

iex> Message.unwrap_data(true, :boolean)
{:ok, true}

iex> Message.unwrap_data("dGVzdA==", :binary)
{:ok, "test"}

iex> Message.unwrap_data("Hello World", :string)
{:ok, "Hello World"}

iex> Message.unwrap_data([1, 2, 3], {:array, :integer})
{:ok, [1, 2, 3]}

iex> Message.unwrap_data([1, 2.5, 3], {:array, :integer})
{:error, :invalid_data}

iex> %{
...>   "key1" => "AAECAQA=",
...>   "key2" => [-1, 0, 0.5, 1]
...> }
...> |> Message.unwrap_data(%{"key1" => :binary, "key2" => {:array, :real}})
{:ok,
  %{
    "key1" => <<0, 1, 2, 1, 0>>,
    "key2" => [-1, 0, 0.5, 1]
  }
}
Link to this function

wrap_data(data, types_map)

@spec wrap_data(integer(), :integer) :: integer()
@spec wrap_data(number(), :real) :: number()
@spec wrap_data(boolean(), :boolean) :: boolean()
@spec wrap_data(DateTime.t(), :datetime) :: String.t()
@spec wrap_data(binary(), :binary) :: String.t()
@spec wrap_data(String.t(), :string) :: String.t()
@spec wrap_data([basic_data()], {:array, basic_data_type()}) :: list()
@spec wrap_data(
  %{optional(String.t()) => {atom(), String.t(), data_with_array()}},
  :map
) :: %{optional(String.t()) => %{optional(String.t()) => term()}}

Converts a value to a "wrapped" value that can be easily serialized.

examples

Examples

iex> Message.wrap_data(42, :integer)
42

iex> Message.wrap_data(0.5, :real)
0.5

iex> Message.wrap_data(false, :boolean)
false

iex> Message.wrap_data(<<0, 1, 2, 3>>, :binary)
"AAECAw=="

iex> Message.wrap_data("Hello World", :string)
"Hello World"

iex> Message.wrap_data([0, 1, 2], {:array, :integer})
[0, 1, 2]

iex> %{"my_key" => <<0, 1>>}
...> |> Message.wrap_data(%{"my_key" => :binary})
%{"my_key" => "AAE="}