Erlang client library for the Spot Protocol, providing secure real-time messaging between clients and servers.
- WebSocket connection to Spot servers with TLS
- ECDSA key generation and signature
- ID card creation and management
- CBOR message encoding/decoding
- Query support for server endpoints
- g-dns.net resolver for host lookup
Add to your rebar.config dependencies:
{deps, [
{spoterl, "0.1.0"}
]}.% Start the application
application:ensure_all_started(spoterl).
% Create a new client (generates ephemeral key)
{ok, Client} = spoterl:new().
% Wait for connection to come online
ok = spoterl:wait_online(Client, 10000).
% Query server time
{ok, Time} = spoterl:get_time(Client).
% Get client's target ID (for receiving messages)
TargetId = spoterl:target_id(Client).
% Clean up
spoterl:close(Client).% Create client with custom options
{ok, Client} = spoterl:new([
{keychain, Keychain}, % Use existing keychain
{meta, #{<<"name">> => <<"MyClient">>}}, % ID card metadata
{handlers, #{<<"custom">> => fun handle_custom/1}} % Message handlers
]).spoterl:new() -> {ok, pid()}- Create new client with ephemeral keyspoterl:new(Opts) -> {ok, pid()}- Create client with optionsspoterl:close(Client) -> ok- Close client and connectionsspoterl:wait_online(Client, Timeout) -> ok | {error, timeout}- Wait for connectionspoterl:connection_count(Client) -> {Total, Online}- Get connection stats
spoterl:target_id(Client) -> binary()- Get client's target ID (k.<hash>)spoterl:id_card(Client) -> idcard()- Get client's ID card
spoterl:query(Client, Target, Body) -> {ok, Response} | {error, Reason}- Send query and wait for responsespoterl:query(Client, Target, Body, Timeout) -> {ok, Response} | {error, Reason}- Query with custom timeoutspoterl:send_to(Client, Target, Payload) -> ok | {error, Reason}- Send message without waiting for responsespoterl:get_time(Client) -> {ok, Timestamp} | {error, Reason}- Get server time
spoterl:store_blob(Client, Key, Value) -> ok | {error, Reason}- Store encrypted blobspoterl:fetch_blob(Client, Key) -> {ok, Value} | {error, Reason}- Fetch encrypted blob
% Set a message handler for an endpoint
spoterl:set_handler(Client, <<"myendpoint">>, fun(Msg) ->
Body = spoterl_proto:get_body(Msg),
% Process message...
{ok, <<"response">>} % or {error, <<"error msg">>} or ok
end).
% Remove handler
spoterl:set_handler(Client, <<"myendpoint">>, undefined).- bottlerl - Bottle protocol implementation
- gun - HTTP/WebSocket client
- jiffy - JSON encoding
- uuid - UUID generation
$ rebar3 compile$ rebar3 ctMIT License - see LICENSE.md