一、項目應用解決方案
1、內呼方案流程:
客戶撥號 <——> 運營商/網關 <——> FreeSWITCH(MRCP +ASR/TTS/NLP) <——>Lua(嵌入FS)
Ps: 根據特定號碼,FS路由配置好的撥號計劃(dialplan),進而調用lua APP,Lua腳本的運行,實現業務邏輯控制,每一通電話都可以調用該lua腳本;
2、外呼方案流程:
Web(http) <——> Python(ESL) <——> FreeSWITCH(MRCP +ASR/TTS/NLP) <——> 運營商/網關 <——> 目標客戶
Ps: Python腳本通過http協議對接Web,實現批量的自動撥號與電話通道的管理與控制;當客戶接通電話後,調用Lua腳本實現外呼的業務邏輯;
二、Event Socket
與Lua嵌入式腳本不同,通過Event Socket方式,可以在遠程機器的外部獨立程序控制FreeSWITCH。大多數語言都支持Socket,所以幾乎可以和任何語言開發的程序通信,便於跟任何系統進行集成。
Event Socket的連接分兩種模式: InBound/OutBound
1、內連模式InBound
InBound模式:FS作爲服務端,監聽所配置的端口,FS啓動時自動加載,當外部客戶端程序主動向FS發起socket連接來實現通信。
該模式由於是可以主動連接並可長期穩定保持,且此通道有且只有一個,心跳、外呼和註冊等動作必須通過此種連接完成。
2、外連模式OutBound
OutBound模式:FS作爲客戶端,需要在dialplan的配置文件中設置,當有電話進來時,FS路由dialplan, 觸發一個app(socket)動作,向外部服務端程序建立一個socket連接來實現通信。
該模式一般用於外線電話呼入的時候會觸發socket連接事件,支持同一時間呼入數量不唯一,每個來電建立一個socket連接,所以此連接的數目也是動態變化的。
3、FS mod_event_socket模塊配置
a.進入安裝FS的根目錄:
cd /usr/local/freeswitch(默認)
b.編輯FS模塊加載配置文件:vim ./conf/autoload_configs/modules.conf.xml
c.編輯event_socket配置文件:vim ./conf/autoload_configs/event_socket.conf.xml
d. 重啓freeswitch,使相應配置生效。
三、Event Socket Library
FreeSWITCH用C語言將Event Socket協議寫了一些庫函數,並用SWIG封裝成各種高級語言的接口,目前支持的語言有Perl、PHP、Python、Ruby、Java、C#等,這些高級語言的庫函數開發接口即爲ESL(Event Socket Library),通過這些開發接口來使用FS內部提供的APP和API,可以很方便地與FreeSWITCH交互,進而控制FS的所有通道和各種媒體功能。
本文介紹Python 利用 Event Socket Library 與FreeSWITCH通信,並控制其進行相應操作;
1、Python ESL的兩種安裝方式
a.FS源碼的Pymod編譯、安裝:
cd /usr/src/freeswitch/libs/esl
make pymod
make pymod-install
(默認安裝路徑:/usr/lib/pythonX.X/site-packages/)
b.在線pip安裝:pip install python-ESL
(默認安裝路徑:/usr/lib64/pythonX.X/site-packages/)
2、Python ESL使用
ESLconnection對象
ESLconnection對象維護與freeswitch之間的連接,以發送命令並進行事件處理。 成員函數列表如下:
- socketDescriptor()
該函數返回連接的UNIX文件句柄 - connected()
判斷是否已連接,連接返回1,否則返回0 - getInfo()
- 當freeswitch使用outbound模式連接時,它將首先發一個CHANNEL_DATA事件,getInfo會返回該事件;
在inbound模式中返回None - send(command)
向freeswitch發送一個command,但不會等待返回結果,需要顯式調用recvEvent或recvEventTimed以接收返回的事件。 - sendRecv(command)
向freeswitch發送一個command,並等待返回結果(一個ESLevent對象)。 - api(command[,arguments])
向freeswitch發送api命令,阻塞執行 - bgapi(command[, arguments][,custom_job_uuid])
向freeswitch發送bgapi命令,後臺執行,非阻塞執行 - sendEvent(event)
向freeswitch發送一個事件 - sendMSG(event,uuid)
參考sendmsg命令 - recvEvent()
從freeswitch接收事件,阻塞模式 - recvEventTimed(milliseconds)
與recvEvent類似,但不會無限等待,而是在參數指定的毫秒數會返回。
recvEventTimed(0)會立即返回。 - filter (header,value)
事件過濾,類似filter命令。 - events (event_type,value)
事件訂閱,類似event命令。 - execute (app[,arg][,uuid])
執行dialplan的app,並阻塞等待返回. 返回結果爲一個ESLevent對象,通過getHeader(“Reply-Text”)可以獲取返回值,”+OK”表示成功,”-ERR”表示失敗。 - executeAsync (app[,arg][,uuid])
與execute()相同,但非阻塞執行。 - setAsyncExecute(value)
強制將socket設置爲異步模式,value爲1是異步,0是同步。 - setEventLock(value)
使用該選項後,後續所有的execute()調用都將帶有”event-lock:true”頭域。 - disconnect()
主動中斷與freeswitch的連接。
ESLevent對象
當接收一個事件時,用戶將獲得一個ESLevent對象,這個對象包含各種幫助函數變量 來幫助解析和處理收到的事件。
- ESLevent對象成員函數列表如下:
- serialize([format])
- 將event數據轉換成”name:value”型數據,format參數可以爲:
- "xml"
"json"
"plain" (default) - 示例如下:
- eventData.serialize('json') 獲取json格式數據
- setPriority([number])
設置事件的級別 - getHeader(headerName)
獲取header對應的value,示例如下: - eventData .getHeader('Event-Name') #獲取事件名稱
- getBody()
獲取事件的正文 - getType()
獲取event object的事件類型 - addBody(value)
向事件中加入正文,可以調用多次 - addHeader(key,value)
向事件中加入一個頭域(ESL_STACK_BOTTOM) - pushHeader(key,value)
向事件中加入一個頭域(ESL_STACK_PUSH) - unshiftHeader(key,value)
向事件中加入一個頭域(ESL_STACK_UNSHIFT) - delHeader(key)
從Event中刪除頭域 - firstHeader()
將指針指向Event的第一個頭域,並返回它的key值。它必須在nextHeader之前調用 - nextHeader()
移動指針指向下一個header,在函數調用前必須先調用firstHeader()
應用示例:
Python InBound
模式示例代碼:
import ESL
import time
hostIp,port,user = "127.0.0.1","8021","ClueCon"
con = ESL.ESLconnection(hostIp,port,user)
con.events("CHANNEL_CREATE")
eventData = con.api("originate {ignore_early_media=true}user/1005 &park")
print eventData.getHeader("Job-UUID")
while True:
eventData = con.recvEvent()
print eventData.getHeader("Event-Name")
con.disconnect()
originate返回的事件信息:
//tcp header
Content-Length: 625
Content-Type: text/event-plain
//event header
Job-UUID: 7f4db78a-17d7-11dd-b7a0-db4edd065621
Job-Command: originate
Job-Command-Arg: sofia/default/1005%20'%26park'
Event-Name: BACKGROUND_JOB
Core-UUID: 42bdf272-16e6-11dd-b7a0-db4edd065621
FreeSWITCH-Hostname: ser
FreeSWITCH-IPv4: 192.168.1.104
FreeSWITCH-IPv6: 127.0.0.1
Event-Date-Local: 2008-05-02%2007%3A37%3A03
Event-Date-GMT: Thu,%2020%20Jun%202008%2023%3A37%3A03%20GMT
Event-Date-timestamp: 1209685023894968
Event-Calling-File: mod_event_socket.c
Event-Calling-Function: api_exec
Event-Calling-Line-Number: 609
Content-Length: 41
//event body
+OK 7f4de4bc-17d7-11dd-b7a0-db4edd065621