Packages

Elixir wrapper for the emqttc library. Some of the features: Reconnection, offline queueing, gen_* like callback APIs, QoS 0-2.

Current section

Files

Jump to
exmqttc lib exmqttc_callback.ex
Raw

lib/exmqttc_callback.ex

defmodule Exmqttc.Callback do
require Logger
@moduledoc """
Behaviour module for Exmqttc callbacks
"""
use GenServer
@doc """
Initializing the callback module, returned data is passed in as state on the next call.
"""
@callback init() :: {:ok, state :: any()}
@doc """
Called once a connection has been established.
"""
@callback handle_connected(state :: any()) :: {:ok, state :: any()}
@doc """
Called on disconnection from the broker.
"""
@callback handle_disconnected(state :: any()) :: {:ok, state :: any()}
@doc """
Called upon reception of a MQTT message, passes in topic and message.
"""
@callback handle_publish(topic :: String.t(), message :: String.t(), state :: any()) :: {:ok, state :: any()}
@doc """
Called if the connection process or the callback handler process receive unknown `handle_call/3` calls.
"""
@callback handle_call(message :: term(), from :: {pid(), atom()}, state :: term()) :: {:ok, state :: term()}
@doc """
Called if the connection process or the callback handler process receive unknown `handle_cast/2` calls.
"""
@callback handle_cast(message :: term(), state :: term()) :: {:ok, state :: term()} :: {:ok, state :: term()}
@doc """
Called if the connection process or the callback handler process receive unknown `handle_info/2` calls, and by extend also unknown Elixir messages.
"""
@callback handle_info(message :: term(), state :: term()) :: {:ok, state :: term()} :: {:ok, state :: term()}
@doc false
def start_link(module) do
GenServer.start_link(__MODULE__, {module, self()})
end
@doc false
def init({cb, connection_pid}) do
{:ok, state} = cb.init()
{:ok, %{cb: cb, state: state, connection_pid: connection_pid}}
end
@doc false
def handle_cast(:connect, %{cb: cb, state: state, connection_pid: connection_pid}) do
{:ok, new_state} = cb.handle_connect(state)
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
@doc false
def handle_cast(:disconnect, %{cb: cb, state: state, connection_pid: connection_pid}) do
{:ok, new_state} = cb.handle_disconnect(state)
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
@doc false
def handle_cast({:publish, topic, message}, %{cb: cb, state: state, connection_pid: connection_pid}) do
case cb.handle_publish(topic, message, state) do
{:ok, new_state} ->
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
{:reply, reply_topic, reply_message, new_state} ->
Exmqttc.publish(connection_pid, reply_topic, reply_message)
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
end
# Pass unknown casts through
def handle_cast(message, %{cb: cb, state: state, connection_pid: connection_pid}) do
{:ok, new_state} = cb.handle_cast(message, state)
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
# Pass unknown calls through
def handle_call(message, from, %{cb: cb, state: state, connection_pid: connection_pid}) do
{:ok, new_state} = cb.handle_call(message, from, state)
{:reply, :ok, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
# Pass unknown infos through
def handle_info(message, %{cb: cb, state: state, connection_pid: connection_pid}) do
{:ok, new_state} = cb.handle_info(message, state)
{:noreply, %{cb: cb, state: new_state, connection_pid: connection_pid}}
end
end