Meshcore.Client (Meshcore v0.1.0)

Copy Markdown View Source

The session process behind a MeshCore connection.

One Meshcore.Client owns

  • the transport process (and reconnects it when auto_reconnect is on),
  • the Meshcore.Reader that turns frames into events,
  • the list of event subscribers and of commands waiting for a response,
  • the contact list / self info / device time mirrored from the device,
  • a FIFO lock serialising "mesh requests" (login, status, telemetry…).

You normally use it through Meshcore and Meshcore.Commands; the functions here are the lower-level building blocks.

Fault tolerance

  • Commands are never answered by blocking the process: each one registers a waiter with a timer, so a silent device produces {:error, %Meshcore.Event{type: :error, payload: %{reason: :timeout}}} rather than a hang.
  • Waiters are failed immediately with reason: :disconnected when the link drops.
  • Subscribers are monitored; dead ones are dropped automatically.
  • The lock holder is monitored; a crashed holder releases the lock.
  • Decoding errors are contained in Meshcore.Reader.
  • A crashed transport is just another lost connection.

Summary

Functions

Returns a specification to start this module under a supervisor.

Sends data and waits for one of the expected event types.

Connects the transport and runs the app-start handshake.

Disconnects and stops the client process.

Reads a value of the mirrored session state. See Meshcore getters.

Sets a session setting (:auto_update_contacts, :default_timeout, :decrypt_channels).

Starts a client. See Meshcore.start_link/1 for the options.

Removes a subscription (idempotent).

Waits for an event of type (or any of a list of types) whose attributes match filters. Returns {:ok, event} or {:error, :timeout}.

Runs fun while holding the per-connection mesh request lock.

Types

result()

@type result() :: {:ok, Meshcore.Event.t()} | {:error, Meshcore.Event.t()}

t()

@type t() :: GenServer.server()

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

command(mc, data, expected, opts \\ [])

@spec command(t(), binary(), [Meshcore.Event.type()], keyword()) :: result()

Sends data and waits for one of the expected event types.

With an empty expected list the command is fire-and-forget and returns {:ok, %Event{type: :ok, payload: %{}}} immediately.

Options:

  • :timeout – milliseconds (default: the client's default timeout)
  • :touch_on – event types that restart the timeout (used for contact lists)
  • :register – registers a binary request as soon as :msg_sent arrives (race-free); a map with :prefix, :request_type, :timeout, :min_timeout, :context, :is_anon, :hops
  • :then – after :msg_sent, keep waiting for a follow-up event; a map with :types, :filters, :tag_filter (boolean), :timeout, :min_timeout

connect(mc)

@spec connect(t()) :: result() | {:error, term()}

Connects the transport and runs the app-start handshake.

disconnect(mc)

@spec disconnect(t()) :: :ok

Disconnects and stops the client process.

get(mc, key)

@spec get(t(), atom()) :: term()

Reads a value of the mirrored session state. See Meshcore getters.

put(mc, key, value)

@spec put(t(), atom(), term()) :: :ok

Sets a session setting (:auto_update_contacts, :default_timeout, :decrypt_channels).

start_link(opts)

@spec start_link(keyword()) :: GenServer.on_start()

Starts a client. See Meshcore.start_link/1 for the options.

subscribe(mc, types, filters, pid)

@spec subscribe(t(), atom() | [atom()] | nil, map(), pid()) ::
  {:ok, Meshcore.Subscription.t()}

Subscribes pid to events. See Meshcore.subscribe/3.

unsubscribe(mc, ref)

@spec unsubscribe(t(), Meshcore.Subscription.t() | reference()) :: :ok

Removes a subscription (idempotent).

wait_for_event(mc, type, filters \\ %{}, timeout \\ nil)

@spec wait_for_event(
  t(),
  Meshcore.Event.type() | [Meshcore.Event.type()],
  map(),
  timeout_ms :: non_neg_integer() | nil
) :: {:ok, Meshcore.Event.t()} | {:error, :timeout}

Waits for an event of type (or any of a list of types) whose attributes match filters. Returns {:ok, event} or {:error, :timeout}.

with_lock(mc, fun)

@spec with_lock(t(), (-> result)) :: result when result: term()

Runs fun while holding the per-connection mesh request lock.

The lock is FIFO, released automatically if the holder crashes and re-entrant for the process that holds it.