# `StemMqtt.Client`
[🔗](https://github.com/sorinirimies/stem-mqtt/blob/v0.6.1/lib/stem_mqtt/client.ex#L1)

An MQTT 3.1.1 / 5.0 client.

The process that creates a client owns it: received messages and connection
losses arrive in its mailbox, and when it exits the client disconnects.

    {:ok, client} = StemMqtt.Client.new(host: "localhost", client_id: "sensor-1")
    {:ok, %{session_present: false}} = StemMqtt.Client.connect(client)
    {:ok, _reason_code} = StemMqtt.Client.subscribe(client, "sensors/#", qos: 1)
    :ok = StemMqtt.Client.publish(client, "sensors/t", "21.5", qos: 1)

    receive do
      {:stem_mqtt, id, {:message, %StemMqtt.Message{topic: topic, payload: payload}}}
      when id == client.id ->
        {topic, payload}

      {:stem_mqtt, id, {:disconnected, reason}} when id == client.id ->
        reason
    end

## Options

  * `:host` (required), `:port` (1883), `:client_id` (`""`: the broker assigns one)
  * `:version` - `:v5` (default) or `:v311`
  * `:clean_start` (`true`), `:keep_alive_secs` (30)
  * `:username`, `:password` (binary)
  * `:will` - `%{topic: ..., payload: ..., qos: 0..2, retain: false}`
  * `:connect_timeout_secs` (10), `:operation_timeout_secs` (0: the default)
  * `:auto_reconnect` (`false`), `:reconnect_backoff_secs`, `:reconnect_max_backoff_secs`
  * `:tls` - `%{ca_cert_pem: ..., client_cert_pem: ..., client_key_pem: ...,
    insecure_skip_certificate_verification: false}`; `%{}` uses the system roots
  * `:max_packet_size` (0: the default)

Unknown options raise `ArgumentError`.

## Errors

Operations return `{:error, {kind, message}}` with `kind` one of
`:malformed_packet`, `:protocol`, `:io`, `:connection_refused`,
`:not_connected`, `:packet_too_large`, `:already_connected`, `:timeout`,
`:session`.

# `error`

```elixir
@type error() :: {:error, {atom(), String.t()}}
```

# `t`

```elixir
@type t() :: %StemMqtt.Client{id: pos_integer(), ref: reference()}
```

`id` tags every message this client sends to its owner.

# `connect`

```elixir
@spec connect(t()) ::
  {:ok, %{session_present: boolean(), reason_code: 0..255}} | error()
```

# `connected?`

```elixir
@spec connected?(t()) :: boolean()
```

# `disconnect`

```elixir
@spec disconnect(t()) :: :ok | error()
```

# `last_disconnect_reason`

```elixir
@spec last_disconnect_reason(t()) :: String.t() | nil
```

Why the last connection ended, or `nil`.

# `new`

```elixir
@spec new(keyword() | map(), pid()) :: {:ok, t()}
```

Creates a client owned by `owner` (default: the caller). Does not connect.

# `publish`

```elixir
@spec publish(t(), String.t(), iodata(), keyword()) :: :ok | error()
```

Options: `:qos` (0), `:retain` (`false`).

# `subscribe`

```elixir
@spec subscribe(t(), String.t(), keyword()) :: {:ok, 0..255} | error()
```

Options: `:qos` (0). Returns the broker's reason code (the granted QoS on success).

# `unsubscribe`

```elixir
@spec unsubscribe(t(), String.t()) :: :ok | error()
```

---

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