The Asterisk External Application Protocol (AEAP) framework helps to facilitate development of Asterisk modules that need to communicate with external applications. Before getting started, I suggest reading an introduction to AEAP. As well, you can check out a specific speech to text use case that’s already in Asterisk.
So you’ve now read up on AEAP, and thought “hey I might be able to use this for my Asterisk module”. If so, hopefully this article will help. Since the framework is used to connect and communicate with remote applications start by asking yourself the following questions:
- Does my Asterisk module need to initiate a connection to a remote application?
- Will it then need to communicate, and exchange information with said application?
- Does my module need to send and/or receive audio over the connection?
If you answered “yes” to all of these questions then the AEAP framework should indeed be of help. Let’s get into some of the details of how it can do just that.
The AEAP public API is located in res_aeap.h and res_aeap_message.h. Those files should contain all the methods you’ll need to connect to, receive /send messages, and read/write audio from/to a remote application. Implementation details and “private” headers can be found in res_aeap.c and res/res_aeap/. Associated configuration is located in aeap.conf. Also, you can take a look at res_speech_aeap.c as an example of a working use case.
Always be sure to check the wiki for the most up to date information.
All connections take place “through” an “aeap” object. To connect to a remote application simply call the relevant API method, passing in the appropriate parameters. If you connect by “id” connection information is pulled from the matching “client” found in aeap.conf. The connection type is dependent on the supplied URL scheme. Currently, only the websocket type is supported, i.e “ws” or “wss”.
Does your module needs to connect using an unsupported connection type? In that case you’ll need to extend the transport component, and create a new transport type. The new transport type will need to implement each of the aeap_transport_vtable callbacks found in transport.h. A working example can be seen in transport_websocket.c. Lastly, a new transport object instantiation call will need to be added to the create method in transport.c.
All communications take place “through” a connected “aeap” object. After connecting you can send messages using one of the send_msg API calls. In most cases you’ll want to use the ast_aeap_send_msg_tsx method. This method allows you to configure a message timeout, or specify whether you want the call to block until a response is received.
When a message request or response is received, the connected “aeap” object attempts to match it to a registered handler. Handlers are configured as an aeap_params field passed to the “aeap” object at creation. If a handler can be matched then it’s triggered, otherwise an un-handled error response is automatically sent to the remote.
Message are exchanged according to the AEAP definition. However, a particular implementation will have it’s own set of required parameters. So both the client module and remote application need to be able to parse the message definition, and if needed be able to also key off module specific parameters. Currently, the only supported message format is JSON.
Does your module need to communicate in another message format? If so, you’ll need to extend the messaging component, and create a new message type. You’ll need to implement most, if not all, of the virtual methods found in ast_aeap_message_type located in res_aeap_message.h. A working example can be seen in message_json.c.
The AEAP framework also has the ability to send binary data, audio or otherwise, once connected. Binary data can be sent using the ast_aeap_send_binary API call. If set on the “aeap” object, received binary data is “bubbled up” via an on_binary callback.
Hopefully now you have enough information to get started on your own Asterisk module using the AEAP framework. I recommend reading through the source API documentation before you begin as it contains more details than mentioned here. As well, new stuff may have been added since this posting. Lastly, be sure to check us out on IRC or the asterisk-dev mailing list if you have any questions.