# `Espex.ClientInfo`
[🔗](https://github.com/bbangert/espex/blob/main/lib/espex/client_info.ex#L1)

A snapshot of one currently-connected ESPHome native-API client.

Returned by `Espex.connected_clients/1`. Each struct describes a live
TCP connection to the server:

  * `:id` — the connection handler pid; unique and stable for the
    lifetime of the connection, suitable as a UI row key.
  * `:peer` — the remote `"ip:port"` string.
  * `:client_info` — the `client_info` the client sent in its
    `HelloRequest` (e.g. `"Home Assistant 2026.1.0"`), or `nil` before
    the client has completed its hello.
  * `:api_version` — `{major, minor}` from the client's hello, or `nil`
    before hello.
  * `:encrypted?` — whether the connection negotiated the Noise
    encrypted transport.
  * `:connected_at` — epoch seconds when the TCP connection was
    accepted.
  * `:last_activity_at` — epoch seconds of the most recent inbound
    data (any bytes, mirroring the keepalive liveness signal — not only
    fully-decoded frames); advances as the client sends and is the
    basis for an idle-time display.

# `t`

```elixir
@type t() :: %Espex.ClientInfo{
  api_version: {non_neg_integer(), non_neg_integer()} | nil,
  client_info: String.t() | nil,
  connected_at: integer() | nil,
  encrypted?: boolean(),
  id: pid(),
  last_activity_at: integer() | nil,
  peer: String.t()
}
```

# `new`

```elixir
@spec new(pid(), Espex.ConnectionState.t()) :: t()
```

Build a `ClientInfo` snapshot for `pid` from its `ConnectionState`.

Stored as the connection's Registry value so `Espex.connected_clients/1`
is a plain Registry read.

---

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