亚洲综合伊人,成人欧美一区二区三区视频不卡,欧美日韩在线高清,日韩国产午夜一区二区三区,大胆美女艺术,一级毛片毛片**毛片毛片,你瞅啥图片

您當(dāng)前的位置是:  首頁 > 新聞 > 國內(nèi) >
 首頁 > 新聞 > 國內(nèi) >

Aterisk接口-ARI對(duì)通道的狀態(tài)管理

2017-06-26 09:27:58   作者:james.zhu   來源:Aterisk   評(píng)論:0  點(diǎn)擊:


  以前我們討論了ARI接口對(duì)DTMF事件的處理,其實(shí)ARI也支持對(duì)通道方面的處理方式,否則ARI就不能成為一個(gè)未來Asterisk接口通信的主要方式。Asterisk通過ARI接口可以獲得各種通道的狀態(tài)信息,然后通過ARI對(duì)其進(jìn)行管理控制,按照用戶的業(yè)務(wù)需求做進(jìn)一步的處理。首先我們簡單說明一下什么是通道和其狀態(tài)的含義。通道狀態(tài)是反映當(dāng)前介于Asterisk和終端設(shè)備之間的通信介質(zhì)的狀態(tài)。通道的狀態(tài)會(huì)影響所支持的操作,什么樣的通道狀態(tài)支持什么樣的通道操作,同時(shí)也會(huì)最終影響終端設(shè)備的操作執(zhí)行。
  目前通道可以支持多種狀態(tài),基本常見的幾種狀態(tài)是:
  • Down - 通信路徑存在,但是Asterisk和終端之間沒有任何媒體。
  • Ringing - 設(shè)備正在振鈴,在Asterisk和設(shè)備之間可能存在媒體。
  • Up - 設(shè)備之間已經(jīng)互相應(yīng)答。當(dāng)在UP狀態(tài)時(shí),在Asterisk和設(shè)備之間的媒體可以雙向流動(dòng)。
  注意
  某些通道介紹,例如Dahdi通道,可能支持了更多的狀態(tài) (例如,"Pre-ring" 或者 "Dialing Offhook")。當(dāng)處理通道狀態(tài)市,需要訪問Channel data model 的各種變量信息。現(xiàn)在我們主要介紹幾種不同的狀態(tài)處理方式和腳本語言的處理流程。
  指示振鈴
  Asterisk 可以通知設(shè)備對(duì)呼叫方進(jìn)行振鈴,使用的方式是POST /channels/{channel_id}/ring 的操作模式,或者可以使用
  DELETE /channels/{channel_id}/ring 的操作停止振鈴。這里用戶要注意,指示振鈴并不是真正從Asterisk到設(shè)備之間傳輸媒體。Asterisk僅是通知設(shè)備振鈴,但是終端是否振鈴取決于設(shè)備自己本身。
\
  應(yīng)答通道
  當(dāng)通道沒有應(yīng)答之前,Asterisk仍然沒有通知設(shè)備如何進(jìn)行通信。應(yīng)答通道以后,Asterisk才完成了服務(wù)器端和設(shè)備端之間的通信路徑的創(chuàng)建,可以實(shí)現(xiàn)媒體的雙向流通。使用的方法是
  POST /channels/{channel_id}/answer 操作。
  對(duì)通道掛機(jī)
  用戶可以對(duì)通道掛機(jī),使用的是DELETE /channels/{channel_id} 操作方式。當(dāng)掛機(jī)以后,介于Asterisk和設(shè)備終端之間的通信會(huì)結(jié)束,通道離開Stasis的應(yīng)用程序。用戶的應(yīng)用程序通過一個(gè) StasisEnd 事件被提醒。
  設(shè)備掛機(jī)也是同樣的方式。在這種環(huán)境下,Asterisk和終端之間的通信結(jié)束以后,通道掛機(jī),用戶程序通過一個(gè)StasisEnd 事件被通知通道離開了應(yīng)用程序。
  一般情況下,一旦通道離開了用戶應(yīng)用程序,用戶就不能收到任何關(guān)于通道的事件信息。但是當(dāng)用戶程序訂閱了通道的所有事件時(shí),無論通道是否在應(yīng)用程序中,如果通道確實(shí)掛機(jī),用戶會(huì)收到一個(gè)ChannelDestroyed事件。
  舉例:控制通道的狀態(tài)
  這個(gè)實(shí)例ARI 程序會(huì)執(zhí)行以下步驟:
  • 等待通道進(jìn)入到一個(gè)Stasis 應(yīng)用程序。
  • 當(dāng)通道進(jìn)入到Stasis程序后,它會(huì)對(duì)通道指示振鈴,如果通道沒有準(zhǔn)備好振鈴,那么就讓通道現(xiàn)在開始振鈴。
  • 幾秒鐘以后,通道應(yīng)答呼叫。
  • 一旦通道應(yīng)答了呼叫,我們對(duì)通道啟動(dòng)一個(gè)靜音的時(shí)段。幾秒鐘以后,通道掛機(jī)。
  • 如果在這個(gè)過程中終端掛機(jī),系統(tǒng)會(huì)平滑處理掛機(jī)流程。
  • 撥號(hào)規(guī)則
  以下?lián)芴?hào)實(shí)例僅表示通道進(jìn)入到Stasis程序中:
  extensions.conf
\
  Python
  這個(gè)例子中我們使用了ari-py 支持包。這個(gè)基本的架構(gòu)類似于channel-dump Python- 用戶可以參考這個(gè)實(shí)例來學(xué)習(xí)如何使用這個(gè)支持包連接ARI。
  這里,我們首先需要?jiǎng)?chuàng)建我們的ARI客戶端,并且注冊(cè)三個(gè)不同的事件-StasisStart,ChannelStateChange,和StasisEnd。
  很多流程的處理是在StasisStart中進(jìn)行,當(dāng)通道進(jìn)入到我們的應(yīng)用程序時(shí),StasisStart就會(huì)被調(diào)用。大部分情況下,這里還要設(shè)置一個(gè)Python定時(shí)器來初始化通道中的一些指令。
  當(dāng)通道應(yīng)答呼叫后,ChannelStateChange 句柄會(huì)打印出通道改變狀態(tài)的輸出信息。
  最后,系統(tǒng)會(huì)把初始化的定時(shí)器權(quán)限,然后發(fā)出StasisEnd 的事件。當(dāng)通道離開應(yīng)用程序后,這個(gè)事件就會(huì)馬上被調(diào)用,通常情況下,可能是呼叫方掛機(jī),或者我們自己掛機(jī)。
  我們可以啟動(dòng)一個(gè)通道的定時(shí)器:
  \
  然后注冊(cè)三個(gè)事件:
\
  這里的StasisStart 事件需要用戶更多注意一下。
  • 首先,我們通知通道指令,2秒鐘以后,應(yīng)答這個(gè)通道:
 \
  這里,我們?cè)谕ǖ纁hannel_timers 中存儲(chǔ)了一個(gè)定時(shí)器,如果用戶掛機(jī)以后,我們可以發(fā)出StasisEnd 的事件。
  • 一旦程序執(zhí)行進(jìn)入到answer_channel中,系統(tǒng)應(yīng)答這個(gè)通道,在通道中啟動(dòng)一個(gè)靜音播放。注意,我們會(huì)繼續(xù)聲明一個(gè)answer_channel,這是一個(gè)在我們StasisStart 句柄內(nèi)嵌的函數(shù):
\
  • 我們應(yīng)答了通道以后,系統(tǒng)會(huì)在4秒鐘內(nèi)啟動(dòng)另外一個(gè)定時(shí)器對(duì)通道進(jìn)行掛機(jī)處理。當(dāng)定時(shí)器被觸發(fā)后,它會(huì)調(diào)用hangup_channel。這是通道中最后的掛機(jī)程序。另外,我們會(huì)在StasisStart句柄中再次聲明hangup_channel:
 \
  當(dāng)創(chuàng)建了定時(shí)器以后,我們?cè)谕ǖ乐姓疋彆r(shí),系統(tǒng)會(huì)把定時(shí)器信息存儲(chǔ)到程序中的channel_timers 中。在StasisEnd事件句柄中,我們可以取消掉定時(shí)器。如果通道離開了我們的應(yīng)用程序后,我們可以觸發(fā)這個(gè)定時(shí)器來執(zhí)行某些流程或告警信息,例如HTTP返回消息等。
  \
  最后,我們打印出在ChannelStateChanged 句柄中的通道狀態(tài)信息。這里打印出通道應(yīng)答的消息:
  \
  channel-state.py
  完整的channel-state.py 源代碼:
  channel-state.py
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

#!/usr/bin/env python
 
import ari
import logging
import threading
 
logging.basicConfig(level=logging.ERROR)
 
client = ari.connect('http://localhost:8088''asterisk''asterisk')
 
channel_timers = {}
 
def stasis_end_cb(channel, ev):
    """Handler for StasisEnd event"""
 
    print "Channel %s just left our application" % channel.json.get('name')
 
    # Cancel any pending timers
    timer = channel_timers.get(channel.id)
    if timer:
        timer.cancel()
        del channel_timers[channel.id]
 
def stasis_start_cb(channel_obj, ev):
    """Handler for StasisStart event"""
 
    def answer_channel(channel):
        """Callback that will actually answer the channel"""
        print "Answering channel %s" % channel.json.get('name')
        channel.answer()
        channel.startSilence()
 
        # Hang up the channel in 4 seconds
        timer = threading.Timer(4, hangup_channel, [channel])
        channel_timers[channel.id= timer
        timer.start()
 
     def hangup_channel(channel):
        """Callback that will actually hangup the channel"""
 
        print "Hanging up channel %s" % channel.json.get('name')
        channel.hangup()
 
    channel = channel_obj.get('channel')
    print "Channel %s has entered the application" % channel.json.get('name')
 
    channel.ring()
    # Answer the channel after 2 seconds
    timer = threading.Timer(2, answer_channel, [channel])
    channel_timers[channel.id= timer
    timer.start()
 
def channel_state_change_cb(channel, ev):
    """Handler for changes in a channel's state"""
    print "Channel %s is now: %s" % (channel.json.get('name'),
                                     channel.json.get('state'))
 
client.on_channel_event('StasisStart', stasis_start_cb)
client.on_channel_event('ChannelStateChange', channel_state_change_cb)
client.on_channel_event('StasisEnd', stasis_end_cb)
 
client.run(apps='channel-state')

  channel-state.py 實(shí)際輸出結(jié)果
  這是我們終端“alice” 使用PJSIP通道進(jìn)入到我們應(yīng)用程序時(shí)的輸出結(jié)果:
\
  JavaScript (Node.js)
  這個(gè)例子中我們使用了ari-client 支持包。這個(gè)基本的架構(gòu)類似于channel-dump JavaScript- 用戶可以參考這個(gè)實(shí)例來學(xué)習(xí)如何使用這個(gè)支持包連接ARI。
  這里,我們首先需要?jiǎng)?chuàng)建我們的ARI客戶端,并且注冊(cè)三個(gè)不同的事件-StasisStart,ChannelStateChange,和StasisEnd。
  很多流程的處理是在StasisStart中進(jìn)行,當(dāng)通道進(jìn)入到我們的應(yīng)用程序時(shí),StasisStart就會(huì)被調(diào)用。大部分情況下,這里還要設(shè)置一個(gè)Python定時(shí)器來初始化通道中的一些指令。
  當(dāng)通道應(yīng)答呼叫后,ChannelStateChange 句柄會(huì)打印出通道改變狀態(tài)的輸出信息。
  最后,系統(tǒng)會(huì)把初始化的定時(shí)器權(quán)限,然后發(fā)出StasisEnd 的事件。當(dāng)通道離開應(yīng)用程序后,這個(gè)事件就會(huì)馬上被調(diào)用,通常情況下,可能是呼叫方掛機(jī),或者我們自己掛機(jī)。
  我們可以啟動(dòng)一個(gè)通道的定時(shí)器:
  \
  然后注冊(cè)三個(gè)事件:
 \
  這里的StasisStart 事件需要用戶更多關(guān)注。
  首先我們通知通道指令,2秒鐘以后應(yīng)答通道:
  \
  這里,我們?cè)谕ǖ纁hannel_timers 中存儲(chǔ)了一個(gè)定時(shí)器,如果用戶掛機(jī)以后,我們可以發(fā)出StasisEnd 的事件。
  一旦程序執(zhí)行進(jìn)入到answer_channel中,系統(tǒng)應(yīng)答這個(gè)通道,在通道中啟動(dòng)一個(gè)靜音播放。注意,我們會(huì)繼續(xù)聲明一個(gè)answer_channel,這是一個(gè)在我們StasisStart 句柄內(nèi)嵌的函數(shù):
\
  我們應(yīng)答了通道以后,系統(tǒng)會(huì)在4秒鐘內(nèi)啟動(dòng)另外一個(gè)定時(shí)器對(duì)通道進(jìn)行掛機(jī)處理。當(dāng)定時(shí)器被觸發(fā)后,它會(huì)調(diào)用hangup_channel。這是通道中最后的掛機(jī)程序。另外,我們會(huì)在StasisStart句柄中再次聲明hangup_channel:
  \
  當(dāng)創(chuàng)建了定時(shí)器以后,我們?cè)谕ǖ乐姓疋彆r(shí),系統(tǒng)會(huì)把定時(shí)器信息存儲(chǔ)到程序中的channel_timers 中。在StasisEnd事件句柄中,我們可以取消掉定時(shí)器。如果通道離開了我們的應(yīng)用程序后,我們可以觸發(fā)這個(gè)定時(shí)器來執(zhí)行某些流程或告警信息,例如HTTP返回消息等。
  \
  最后,我們打印出在ChannelStateChanged 句柄中的通道狀態(tài)信息。這里打印出通道應(yīng)答的消息:
 \
  channel-state.js
  完整的channel-state.js 源代碼:
  channel-state.js
  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

/*jshint node: true*/
'use strict';
 
var ari = require('ari-client');
var util = require('util');
 
var timers = {};
ari.connect('http://localhost:8088''asterisk''asterisk', clientLoaded);
 
// handler for client being loaded
function clientLoaded (err, client) {
  if (err) {
    throw err;
  }
 
  // handler for StasisStart event
  function stasisStart(event, channel) {
    console.log(util.format(
          'Channel %s has entered the application', channel.name));
 
    channel.ring(function(err) {
      if (err) {
        throw err;
      }
    });
    // answer the channel after 2 seconds
    var timer = setTimeout(answer, 2000);
    timers[channel.id] = timer;
 
    // callback that will answer the channel
    function answer() {
      console.log(util.format('Answering channel %s', channel.name));
      channel.answer(function(err) {
        if (err) {
          throw err;
        }
      });
      channel.startSilence(function(err) {
        if (err) {
          throw err;
        }
      });
      // hang up the channel in 4 seconds
      var timer = setTimeout(hangup, 4000);
      timers[channel.id] = timer;
    }
 
    // callback that will hangup the channel
    function hangup() {
      console.log(util.format('Hanging up channel %s', channel.name));
      channel.hangup(function(err) {
        if (err) {
          throw err;
        }
      });
    }
  }
 
  // handler for StasisEnd event
  function stasisEnd(event, channel) {
    console.log(util.format(
          'Channel %s just left our application', channel.name));
    var timer = timers[channel.id];
    if (timer) {
      clearTimeout(timer);
      delete timers[channel.id];
    }
  }
 
  // handler for ChannelStateChange event
  function channelStateChange(event, channel) {
    console.log(util.format(
          'Channel %s is now: %s', channel.name, channel.state));
  }
 
  client.on('StasisStart', stasisStart);
  client.on('StasisEnd', stasisEnd);
  client.on('ChannelStateChange', channelStateChange);
 
  client.start('channel-state');
}

channel-state.js in action
  這是我們終端“alice” 使用PJSIP通道進(jìn)入到我們應(yīng)用程序時(shí)的輸出結(jié)果:
\

相關(guān)閱讀:

專題

外汇| 钟祥市| 惠东县| 鲁甸县| 合肥市| 泸水县| 淮南市| 沙洋县| 永安市| 桐城市| 二连浩特市| 集安市| 中卫市| 莱芜市| 板桥市| 城市| 云龙县| 信丰县| 武宣县| 孟津县| 沂南县| 靖江市| 额敏县| 扶余县| 忻城县| 梨树县| 康平县| 丽江市| 简阳市| 进贤县| 疏勒县| 洮南市| 石城县| 达孜县| 延吉市| 山阴县| 抚远县| 福清市| 万宁市| 濮阳市| 繁峙县|