# SPDX-License-Identifier: MIT # Copyright (c) 2025 Scott Thompson defmodule ArduinoRouter.Transport do @moduledoc """ Behaviour for a transport layer used to send and receive messages to an Arduino router. Implementations are responsible for establishing the underlying connection, sending outgoing RPC messages, delivering incoming RPC messages to the bridge process, and cleaning up resources when stopped. In most cases the `ArduinoRouter.Socket` will accomplish what is needed. By adopting this behaviour, a module can be plugged into the handle communication for the `ArduinoRouter.Bridge`. Writing a custom transport would be unusual. This abstraction of this behaviour was originally implemented in support of the library's unit tests. When implementing a transport, incoming RPC messages should be forwarded to the bridge's PID as a process message in the form `{:incoming_rpc, rpc_message}`. Implementations return an opaque `state()` value from `start/2` and pass it to subsequent callbacks. """ alias ArduinoRouter.MessagePackRPC @typedoc "state maintained on behalf of the transport layer" @type state() :: term() @typedoc "A result from a call to `start/2`" @type start_result() :: {:ok, state()} | {:error, term()} @typedoc "A result from a call to `send_message/2`" @type send_result() :: {:ok, state()} | {:error, term()} @doc """ Start the transport layer and return the state token. The receiver is the PID that will receive incoming RPC messages from the transport layer. RPC messages are sent to this PID as process messages in the format `{:incoming_rpc, rpc_message}`. """ @callback start(receiver :: pid(), options :: keyword()) :: start_result() @doc """ Send a message to the Arduino router. Returns `{:ok, state}` on success or `{:error, reason}` on failure. """ @callback send_message(state(), MessagePackRPC.rpc_message()) :: send_result() @doc """ Stop the transport layer and release any resources. """ @callback stop(state()) :: :ok end