Overview(综述)
Asterisk 12引入了Asterisk REST接口:用于构建基于asterisk的应用的RESTful API。本文将引导你启动并运行ARI。
构建ARI应用有三个主要的组件。
显然,第一个是RESTful API接口。API使用Swagger记录,Swagger用于记录RESTful API的轻量级规范。Swagger API文 docs用于生成asterisk本身的验证和样本,以及静态wiki文档和使用Swagger-UI的交互式文档。
然后,asterisk需要向应用发送异步事件(new channel, channel left abridge, channel hang up etc)。这通过ari/event上的Websocket实现。事件使用json发送消息,并记录在REST Data Models page。Message Data model的列表查看 Message data model。
最后,连接dialplan到你的应用的是Stasis() dialplan应用。在dialplan中,你可以发送channel到Stasis(),指定外呼应用的名字,并且传递可选的参数给应用。
Example: ARI Hello World!
在这个示例中,我们将做如下操作
- 配置astersik以启用ARI。
- 发送一个channel到Stasis
- 在channel播放"Hello World"
该示例并不包含如下: - 安装asterisk.我们假设你已经安装并运行了asterisk或更高版本。
- 在asterisk中配置一个sip设备。为了示例,我们假设你使用chan_sip或者chan_pjsip注册sip软电话或者ip话机到asterisk。
Getting wscat
ARI需要websocket连接来接收事件。为了这个例子,我们将使用wscat,一个类似于netcat的非常方便的命令行程序,但是基于node.js websocket库。如果没有wscat:
如果没有部署,需要安装npm
apt-get install npm
#linux
yum -y install npm
安装ws node 包
npm install -g wscat
注意 : 一些发行版repos(例如ubuntu)可能装了老版本的nodejs和npm:这样在安装ws包时,可能会遇到一些麻烦。你必须从另一个repo或者via source安装新版本。
installing nodejs via packages
installing npm in a variety of ways
Getting curl
为了通过ARI控制Stasis dialplan应用的channel,我们还需要一个HTTP客户端。这里我们使用curl:
apt-get install curl
#linux
yum -y install curl
Configuring Asterisk
在http.conf中开启asteirsk HTTP服务。
http.conf
############
[general]
enabled = yes
bindaddr = 0.0.0.0
在ari.conf中配置一个ARI
ari.conf
###############
[general]
enabled = yes
pretty = yes
[asterisk]
type = user
read_only = no
password = asterisk
这仅仅是一个demo
请为生产应用使用更安全的账户用户和密码。除了示例和演示之外,asterisk/asterisk都是一个糟糕,可怕,不好的选择。
为Stasis应用创建一个dialplan extension。
在这里,我们在context default中创建extension 1000-如果SIP phone配置了不同的context,进行相应的调整。
extensions.conf
[default]
exten => 1000,1,NoOp()
same => n,Answer()
same => n,Stasis(hello-world)
same => n,Hangup()
Hello World
使用wscat连接到asterisk
$ wscat -c "ws://localhost:8088/ari/events?api_key=asterisk:asterisk&app=hello-world"
connected (press CTRL+C to quit)
>
在asterisk中,我们可以看到一个新的websocket连接,从输出信息可以看到我们的Stasis应用已经创建。
== WebSocket connection from '127.0.0.1:37872' for protocol '' accepted using version '13'
Creating Stasis app 'hello-world'
从你的sip设备,呼叫extension 1000:
-- Executing [1000@default:1] NoOp("PJSIP/1000-00000001", "") in new stack
-- Executing [1000@default:2] Answer("PJSIP/1000-00000001", "") in new stack
-- PJSIP/1000-00000001 answered
-- Executing [1000@default:3] Stasis("PJSIP/1000-00000001", "hello-world") in new stack
在wscat中,我们可以看到StasisStart事件,表明某个channel已经进入我们的Stasis应用。
< {
"application":"hello-world",
"type":"StasisStart",
"timestamp":"2014-05-20T13:15:27.131-0500",
"args":[],
"channel":{
"id":"1400609726.3",
"state":"Up",
"name":"PJSIP/1000-00000001",
"caller":{
"name":"",
"number":""},
"connected":{
"name":"",
"number":""},
"accountcode":"",
"dialplan":{
"context":"default",
"exten":"1000",
"priority":3},
"creationtime":"2014-05-20T13:15:26.628-0500"}
}
>
使用curl,告送asteirsk播放 hello-world。
请注意channel的标识符必须与StasisStart事件的channel id匹配:
curl -v -u asterisk:asterisk -X POST "http://localhost:8088/ari/channels/1400609726.3/play?media=sound:hello-world"
从http请求的返回值我们可以看出请求成功与否(在我们的例子中,成功将会在channel上播放语音)以及在json中返回为操作创建的playback资源。
* About to connect() to localhost port 8088 (#0)
* Trying 127.0.0.1... connected
* Server auth using Basic with user 'asterisk'
> POST /ari/channels/1400609726.3/play?media=sound:hello-world HTTP/1.1
> Authorization: Basic YXN0ZXJpc2s6c2VjcmV0
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8088
> Accept: */*
>
< HTTP/1.1 201 Created
< Server: Asterisk/SVN-branch-12-r414137M
< Date: Tue, 20 May 2014 18:25:15 GMT
< Connection: close
< Cache-Control: no-cache, no-store
< Content-Length: 146
< Location: /playback/9567ea46-440f-41be-a044-6ecc8100730a
< Content-type: application/json
<
* Closing connection #0
{"id":"9567ea46-440f-41be-a044-6ecc8100730a",
"media_uri":"sound:hello-world",
"target_uri":"channel:1400609726.3",
"language":"en",
"state":"queued"}
$
在asterisk,在channl中播放对应的语音文件。
-- <PJSIP/1000-00000001> Playing 'hello-world.gsm' (language 'en')
并且在我们的wscat websocket连接中,将告知我们播放的开始以及结束。
< {"application":"hello-world",
"type":"PlaybackStarted",
"playback":{
"id":"9567ea46-440f-41be-a044-6ecc8100730a",
"media_uri":"sound:hello-world",
"target_uri":"channel:1400609726.3",
"language":"en",
"state":"playing"}
}
< {"application":"hello-world",
"type":"PlaybackFinished",
"playback":{
"id":"9567ea46-440f-41be-a044-6ecc8100730a",
"media_uri":"sound:hello-world",
"target_uri":"channel:1400609726.3",
"language":"en",
"state":"done"}
}
挂断电话
挂断电话,这将导致asterisk对应的channel挂断,并且channel将离开Stasis应用,通过StasisEnd事件通知客户端:
< {"application":"hello-world",
"type":"StasisEnd",
"timestamp":"2014-05-20T13:30:01.852-0500",
"channel":{
"id":"1400609726.3",
"state":"Up",
"name":"PJSIP/1000-00000001",
"caller":{
"name":"",
"number":""},
"connected":{
"name":"",
"number":""},
"accountcode":"",
"dialplan":{
"context":"default",
"exten":"1000",
"priority":3},
"creationtime":"2014-05-20T13:15:26.628-0500"}
}
使用Swagger驱动ARI
使用Swagger-UI
构成ARI的REST API使用Swagger进行记录,Swagger是用来记录RESTful API的轻量级规范。Swagger API文档用于生成asterisk本身的验证和样板,以及静态的wiki文档和使用Swagger-UI的交互文档。
Swagger-UI是一个纯粹的HTML+JavaScript应用:可以下载Swagger api-docs;生成交互式界面:可以查看资源,操作和提交API请求。Swagger-ui的fork在ari.asterisk.org:允许删除操作(在Swagger-UI默认不开启),并设置默认URL为运行本地操作系统的asterisk。
为了访问ARI,需要必须使用在ari.conf配置的username:password填充api_key字段。并且在ari.conf中设置allowed_origins以允许托管Swagger-UI的站点访问ARI。
[general]
enabled=yes
;pretty=yes ; we don't need pretty-printing of the JSON responses in this
; example, but you might if you use curl a lot.
;
; In this example, we are going to use the version of Swagger-UI that is hosted
; at ari.asterisk.org. In order to get past CORS restrictions in the browser,
; That origin needs to be added to the allowed_origins list.
;
allowed_origins=http://ari.asterisk.org
[hey]
type=user
password=peekaboo
;read_only=no ; Set to yes for read-only applications