Fedecks Server

Provides a websocket for a Phoenix application, for establishing communications with a Fedecks Client, probably running on a Nerves Device.

Installation

Add to deps


{:fedecks_server, "~> 0.1"}

Using

Step 1 - Implement a handler

Implement a FedecksServer.FedecksHandler to handle connecting and upstream messages.

eg

defmodule MyAppWeb.MyFedecksHandler do
  @behaviour FedecksHandler

  @impl FedecksHandler
  def authenticate(%{"username" => username, 
                    "password" => password, 
                    "fedecks-device-id" => device_id}) do
    MyApp.MyAuth.device_auth(username, password, device_id)
  end

  def authenticate?(_), do: false

  @impl FedecksHandler
  def otp_app, do: :my_app
end

Other optional callbacks you can implement include

Step 2 - Add configuration

In your config you must add configuration for your handler. eg

import Config

config :my_app, MyAppWeb.MyFedecksHandler,
  salt: System.fetch_env!("FEDECKS_SALT"),
  secret: System.fetch_env!("FEDECKS_SECRET")

The salt and secret are used to encode the authentication token that is used for restablishing connections without logging in. You can generate them, for instance, with mix phx.gen.secret.

Additional optional configuration options are

Step 3 - Add to the endpoint

Add the endpoint with the macro FedecksServer.Socket.fedecks_socket/2. Eg

defmodule MyAppWeb.Endpoint
  use Phoenix.Endpoint, otp_app: :my_app

  import FedecksServer.Socket, only: [fedecks_socket: 1]

  fedecks_socket(MyApp.SocketHandler)
end

The socket path defaults to "fedecks" but can be optionally provided to the FedecksServer.Socket.fedecks_socket/2. Note that the actual path will have "/websocket" appended as Phoenix.Socket.Transport also supports long polling and needs to know which the client wants: the default path is actually "fedecks/websocket".

Step 4 - Implement the rest of the owl the client side

Use Fedecks Client on your Nerves device to communicate with the server.

Potential roadmap

Phoenix 1.7 now uses WebSock which is analagous to Plug for websockets, which allows for more flexible approach to adding a Phoenix.Socket.Transport to your endpoint. I want to find some time to explore that approach.