アスタリスクRESTインターフェース(ARI)の概要

当初、アスタリスク機能の唯一の「プロバイダー」はモジュールでした。その多くは、アプリケーションとダイヤルプラン機能の兵器庫を拡張しました。







その後、当初、これらのコマンドと機能はすべて時代を先取りしており、それらのおかげで、アスタリスクは多くの商用製品を機能的に「作成」しました。







既存のアプリケーションと機能の制限を超える必要がある場合は、Cで独自のモジュールを作成できます。これは、機能が拡張され、どれだけ広くても既存の「セル」を終了する唯一の方法でした。







しかし、Cでのアスタリスクモジュールの開発は、些細な作業とはほとんど言えません。 これは非常に厄介なパスであり、非常に危険なパスでもあります。モジュールの重大なエラーが原因で、アスタリスクがコアに完全に落ち込んだためです。







必要なのは、機能を拡張し、他のシステムと統合するための、より「ソフト」でシンプルな方法でした。







そのため、AGIとAMIのインターフェースがありました。









アスタリスクゲートウェイインターフェイス(AGI)は、CGIとアーキテクチャ上「ラップ」された同期ダイヤルプラン実行インターフェイスです。 AGIダイヤルプランチームはプロセスを開始し、標準入出力を使用してコマンドを受信し、結果を送信しました。 AGIを使用すると、外部システムとの統合の問題を解決できます。たとえば、企業データベースにアクセスして、呼び出し元のクライアントの名前を番号で検索できます。







実際、AGIは、独自のビジネスロジックを構築するモジュールが提供するコマンドと機能を使用して、extensions.conf形式ではなく、独自のプログラミング言語でアスタリスクダイヤル計画を作成する方法を提供しました。







Asterisk Manager Interface(AMI)は、Asteriskのオブジェクトの内部状態を監視し、発生したイベントに関する情報を受け取ることができる非同期(イベント)インターフェイスです。 AGIがアーキテクチャ上CGIインターフェイスを連想させる場合、AMIセッションはtelnetセッションに似ており、サードパーティのアプリケーションがTCP / IPを介してAsterisk AMIポートに接続し、独自のコマンドを送信できます。 AMI接続でのコマンドへの応答に加えて、アスタリスクで発生するすべての種類のイベントは「フォール」し、クライアントに属するか、単に無視できるかを判断するのはクライアント次第です。







AGIについては、これは呼び出し実行メカニズムであり、AMIについては呼び出し制御メカニズムであると言えます。 ほとんどの場合、通信アプリケーションを構築するには、AGIとAMIを一緒に使用する必要があります。 さまざまなアプリケーションのビジネスロジックに「スミアリング」があり、その理解とさらなるメンテナンスと開発が複雑になっています。







さらに、さらにいくつかの制限があります。









その結果、コマンドと機能の既存の制限を超えるために、低レベルの電話プリミティブを実装し、AGI&AMIを使用して外部システムと統合する独自のCモジュールを作成する必要があります。







それは、 アスタリスクRESTインターフェイスの前でした。







ARIの主要な概念:









3頭のクジラARI:









制御をStaisに転送するダイヤルプランの例:







exten => _X.,1,Stasis(myapp,arg1,arg2) exten => _X.,n,NoOp(Left Stasis)
      
      





ARIにはいくつかの制限があります









ARIで利用可能な操作のカテゴリを検討してください。









さらに、各カテゴリについて詳しく説明します。







アスタリスク









チャンネル





チャンネル





装置





デバイスの状態





wikiアスタリスクで可能な操作の完全なリストを参照してください-https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+ARI







イベント



接続されたアプリケーションのWebソケットで利用可能なイベントの部分的なリストは次のとおりです。









アスタリスク14 ARIの新機能







結論として、Python ARIライブラリを使用した元の呼び出しの例を示します。







この例では、指定された宴会でオリジナル化が行われ、原因コードが返されます。







 #!/usr/bin/env python2.7 # Requirements: pip install ari gevent import argparse import ari import gevent from gevent.monkey import patch_all; patch_all() from gevent.event import Event import logging from requests.exceptions import HTTPError, ConnectionError import socket import time logging.basicConfig() # Important! # Otherwise you get No handlers could be found for # logger "ari.client" ARI_URL = 'http://192.168.56.101:8088/ari' ARI_USER = 'test' ARI_PASSWORD = 'test' client = ari.connect(ARI_URL, ARI_USER, ARI_PASSWORD) def run(): try: client.run('originator') except socket.error as e: if e.errno == 32: # Broken pipe as we close the client. pass except ValueError as e: if e.message == 'No JSON object could be decoded': # client.close() pass def originate(endpoint=None, callerid=None, context=None, extension=None, priority=None, timeout=None): # Go! evt = Event() # Wait flag for origination result = {} gevent.sleep(0.1) # Hack to let run() arrange all. start_time = time.time() try: channel = client.channels.originate( endpoint=endpoint, callerId=callerid, app='originator', timeout=timeout ) def state_change(channel, event): state = event['channel']['state'] if state == 'Up': channel = channel.continueInDialplan( context=context, extension=extension, priority=priority) def destroyed(channel, event): end_time = time.time() result['status'] = 'success' result['message'] = '%s (%s)' % ( event.get('cause_txt'), event.get('cause')) result['duration'] = '%0.2f' % (end_time - start_time) evt.set() channel.on_event('ChannelDestroyed', destroyed) channel.on_event('ChannelStateChange', state_change) # Wait until we get origination result evt.wait() client.close() return except HTTPError as e: result['status'] = 'error' try: error = e.response.json().get('error') result['message'] = e.response.json().get('error') except Exception: result['message'] = e.response.content finally: print result client.close() def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('endpoint', type=str, help='Endpoint, eg SIP/operator/123456789') parser.add_argument('callerid', type=str, help='CallerID, eg 111111') parser.add_argument('context', type=str, help='Asterisk context to connect call, eg default') parser.add_argument('extension', type=str, help='Context\'s extension, eg s') parser.add_argument('priority', type=str, help='Context\'s priority, eg 1') parser.add_argument('timeout', type=int, help='Originate timeout, eg 60') return parser.parse_args() if __name__ == '__main__': args = parse_args() runner = gevent.spawn(run) originator = gevent.spawn(originate, endpoint=args.endpoint, callerid=args.callerid, context=args.context, extension=args.extension, priority=args.priority, timeout=args.timeout ) gevent.joinall([originator, runner])
      
      





スクリプトのコメント





このスクリプトはコンソールから実行できますが、次のようなスクリプトが返されます。







 (env)MacBook-Pro-Max:barrier max$ ./ari_originate.py SIP/operator 11111 default s 1 4 {'status': 'success', 'duration': '2.54', 'message': u'Normal Clearing (16)'}
      
      





パラメーターの指定:







 (env)MacBook-Pro-Max:barrier max$ ./ari_originate.py -h usage: ari_originate.py [-h] endpoint callerid context extension priority timeout positional arguments: endpoint Endpoint, eg SIP/operator/123456789 callerid CallerID, eg 111111 context Asterisk context to connect call, eg default extension Context's extension, eg s priority Context's priority, eg 1 timeout Originate timeout, eg 60 optional arguments: -h, --help show this help message and exit
      
      





このスクリプトを実行するには、ariおよびgeventライブラリをインストールする必要があります。







 pip install ari gevent
      
      





PS Asterconf 2016での著者のスピーチに基づいて書かれています。







PPSスクリプトはここにあります-https://gist.github.com/litnimax/2b0f9d99e49e49a07e59c45496112133








All Articles