An Asterisk client for the AMI protocol written in Elixir. For a quick introduction to AMI you can read this.
This is similar to PAMI for PHP, NAMI for NodeJS, and erlami for Erlang.
To use it in your Mix projects, first add it as a dependency:
def deps do
[{:elixir_ami, "~> 0.0.10"}]
end
Then run mix deps.get to install it.
Also add the app in your mix.exs file:
[
applications: [:logger, :elixir_ami],
...
]
To create a connection, you need to specify the connection information like this:
alias ElixirAmi.Connection, as: Conn
connection_data = %Conn{
name: :my_connection, # The gen_server connection will be registered with this name
host: "192.168.0.123",
port: 5038,
username: "frank",
password: "lean",
connection_timeout: 5000, # How many millseconds to wait when connecting
reconnect_timeout: 5000, # Wait this many milliseconds before attempting reconnection,
ssl_options: nil # Or [ssl:ssl_option()]. Will try a regular TCP connection if this value is nil
}
The recommended way to create a connection is to take advantage of the built in supervisor,
using ElixirAmi.Supervisor.Ami
(this connection will be automatically supervised and restarted
in case of a crash):
alias ElixirAmi.Supervisor.Ami, as AmiSup
{:ok, pid} = AmiSup.new connection_data
To start a connection under your own supervision tree or OTP application structure,
use ElixirAmi.Connection.start_link
or ElixirAmi.Connection.start
as follows:
{:ok, pid} = Conn.start_link connection_data
You can find actions inside the Action module (feel free to open pull requests to add more!).
alias ElixirAmi.Action, as: Action
Conn.send_action :my_connection, Action.ping
%ElixirAmi.Response{
source: :my_connection,
action_id: "-576460752303423460",
complete: true,
events: [],
keys: %{
"ping" => "Pong",
"timestamp" => "1445770404.871145"
},
success: true,
variables: %{}
}
The response will make its best to return all related events for the response (there might be cases where the Asterisk will violate the AMI protocol and this will not be possible). Sometimes the implementation of the events is not consistent, or it's just broken. Please report any issues you may have and I'll try to fix them.
All related events will be returned in the events
key of the response.
If you want to send an action that is not already supported in the Action
module, you have two choices:
Action.new/3
to create your custom action and send it. This is actually
the function used behind the scenes to send the supported actions.Conn.send_action :my_connection, Action.new(
"my_cool_action",
%{mykey: "myvalue"},
%{myvar: "myvarvalue"}
)
Where the arguments are:
To receive asynchronous events (i.e: not related to a response) you can register listeners with their filters, both are of type function and will receive 3 arguments:
listener_id = Conn.add_listener(
:my_connection,
fn(source, listener_id, event) -> event.event === "varset" end,
&MyModule.my_function/3
)
The filter must return true
or false
. If it returns true
, the second function
(in this case MyModule.my_function/2
will be called with the same arguments) to
process the event, the result is discarded.
Conn.del_listener :my_connection, listener_id
Async AGI is supported with the use of elixir_agi.
Conn.async_agi :my_connection, TestAgiApp, :run
This will start listening for AsyncAGIStart events
on the given connection and launch the AGI App by spawning a process and calling TestAgiApp.run/1
.
Note that this will listen for AsyncAGIStart events for all channels. You can specify a channel name with the optional ending argument:
Conn.async_agi :my_connection, TestAgiApp, :run, true, "SIP/trunk-234132423"
Feel free to take a look at the documentation served by hex.pm or the source itself to find more.
The source code is released under Apache 2 License.
Check LICENSE file for more information.