1. Asterisk Gateway Interface (AGI) là gì?
Tệp AGI là file tập lệnh được sử dụng bởi hệ thống điện thoại nguồn mở, Asterisk. Nó chứa thông tin có thể được sử dụng để tự động hóa các quy trình và sơ đồ quay số Asterisk. Sử dụng các file tập lệnh AGI, các kết nối có thể được thiết lập với cơ sở dữ liệu quan hệ như PostgreSQL hoặc MySQL. Ngoài ra, các tập lệnh AGI cũng có thể được sử dụng để truy cập các tài nguyên bên ngoài khác. Các tập lệnh AGI có thể chuyển quyền kiểm soát của dialplan sang một tập lệnh AGI bên ngoài, cho phép Asterisk thực hiện các tác vụ phức tạp.
2. Luồng thực thi AGI trong Asterisk.
- Cuộc gọi đến: Một cuộc gọi đến được tìm kiếm trong ngữ cảnh và kết nối với số máy chỉ định.
- Truyền tham số: Các tham số được truyền vào kịch bản AGI, bao gồm số điện thoại của người gọi, số máy và các tham số tùy chọn khác.
- Khởi chạy kịch bản AGI: Kịch bản AGI được khởi chạy và nó sẽ kết nối đến cơ sở dữ liệu hoặc các hệ thống bên ngoài để lấy dữ liệu cần thiết.
- Nhận dữ liệu: Kịch bản AGI sẽ nhận dữ liệu từ cơ sở dữ liệu hoặc các hệ thống bên ngoài và trả về dữ liệu cho Asterisk.
- Phát lại dữ liệu: Asterisk sẽ sử dụng dữ liệu được trả về để phát lại cho người gọi hoặc thực hiện các hành động khác.
- Kết thúc cuộc gọi: Cuộc gọi sẽ kết thúc sau khi dữ liệu được phát lại hoặc các hành động khác được thực hiện
3. Biến trong AGI.
Trong kịch bản AGI trong Asterisk, có nhiều biến có sẵn để sử dụng. Một số trong số chúng bao gồm:
- ${agi_request}: Tên của tập lệnh AGI đang được gọi.
- ${agi_channel}: Tên kênh cuộc gọi hiện tại.
- ${agi_language}: Ngôn ngữ mà người gọi chọn.
- ${agi_callerid}: Số điện thoại của người gọi.
- ${agi_uniqueid}: ID duy nhất của cuộc gọi hiện tại.
- ${agi_type}: Loại giao thức đang sử dụng (ví dụ: SIP, H323, etc.).
- ${agi_context}: Ngữ cảnh cuộc gọi hiện tại.
- ${agi_extension}: Số máy cuộc gọi đang truy cập.
- ${agi_priority}: Ưu tiên hiện tại của cuộc gọi.
- ${agi_arg_n}: Tham số n truyền vào kịch bản AGI.
Có rất nhiều biến khác có sẵn trong AGI, và bạn có thể tìm thấy danh sách đầy đủ của chúng trong tài liệu Asterisk.
4. Các yêu cầu để chạy script AGI
Có một số yêu cầu cần thiết để khởi chạy một kịch bản AGI trong Asterisk:
- Cài đặt và cấu hình Asterisk: Bạn cần cài đặt và cấu hình Asterisk để sử dụng các tính năng AGI.
- Tạo một kịch bản AGI: Bạn cần tạo một kịch bản AGI bằng ngôn ngữ lập trình như Python hoặc PHP.
- Cấu hình Dialplan: Bạn cần cấu hình Dialplan để gọi kịch bản AGI khi có cuộc gọi đến.
- Truyền tham số: Nếu cần, bạn cần truyền tham số cho kịch bản AGI khi gọi nó.
- Kiểm tra kết quả: Kết quả trả về từ kịch bản AGI cần được kiểm tra để xác định hành động tiếp theo.
Sau khi các bước trên được thực hiện, kịch bản AGI sẽ được chạy và có thể thực hiện các tác vụ như kết nối đến cơ sở dữ liệu, xử lý dữ liệu, v.v.
5. Một số ví dụ về AGI.
1. Ví dụ 1.
- Truy vấn cơ sở dữ liệu kết quả học sinh dựa trên ID/Số Roll
- Gọi đến số 09611000196 cung cấp thông tin số Roll của học sinh thông qua DTMF
- AGI sẽ gửi truy vấn đến CSDL dựa trên số Roll được cung cấp
- AGI sẽ trả về số đăng ký cụ thể của học sinh và CGPA hiện tại
- Asterisk sẽ phát lại giá trị số trả về trong kênh kết nối trực tiếp
Người dùng sẽ cung cấp số roll_no là 123456 và kết quả trà về sẽ là registration_no có dữ liệu 789123 và CGPA có dữ liệu 3.5
File script python của mình sẽ có nội dung dưới.
#!/usr/bin/python
import agi
import MySQLdb
import sys
agi = agi.AGI()
MYSQL_HOST='127.0.0.1'
MYSQL_USER='root'
MYSQL_PASS=‘morshedtest'
MYSQL_DB='admissions‘
rolno=sys.argv[1]
mysql = MySQLdb.connect(host=MYSQL_HOST , user=MYSQL_USER, passwd=MYSQL_PASS, db=MYSQL_DB)
db = mysql.cursor()
db.execute("""SELECT registration_no,sgpa FROM academics WHERE roll_no='%(rolno)s' """ %vars())
result = db.fetchall()
db.close()
regno = int(result[0][0])
cgpa = float(result[0][1])
agi.set_variable("REGNO", regno)
agi.set_variable("CGPA", cgpa)
Ứng dụng Asterisk:
- SayDigits (123) => đọc một số xác định một chữ số một lần (một hai ba và vân vân)
- SayAlpha () => được sử dụng để đọc lại chuỗi ký tự alphanumeric cho người gọi
- SayNumber (dữ liệu số) => đọc toàn bộ số (123, một trăm hai mươi ba)”
Viết Dialplan trong extension.conf để khởi chạy kịch bản AGI.
exten => 09611000196,1,Answer()
exten => 09611000196,n,read(rolno,enterrollnov) ; take the input of the roll no from DTMF
exten => 09611000196,n,AGI(result.py,${rolno}) ; launch the AGI script
exten => 09611000196,n,NoOp(${REGNO})
exten => 09611000196,n,NoOp(${CGPA})
exten => 09611000196,n,playback(regnois)
exten => 09611000196,n,sayalpha(${REGNO}) ;play back the AGI return variable (Registration no) from db
exten => 09611000196,n,playback(cgpais)
exten => 09611000196,n,sayalpha(${CGPA}) ;play back the AGI return variable (CGPA) from db
exten => 09611000196,n,Hangup()
Cách debug AGI trong Asterisk
Từ giao diện cli bạn gõ lệnh agi set debug on để bật tính năng debug.
localhost*CLI> agi set debug on
-- Executing [09611000196@default:1] Answer("SIP/sipksecu-0003134b", "") in new stack
-- Executing [09611000196@default:2] Read("SIP/sipksecu-0003134b", "rolno, enterrollnov") in new stack
-- <SIP/sipksecu-0003134b> Playing 'rolnov.slin' (language 'en')
-- User entered '123456'
-- Executing [09611000196@default:3] AGI("SIP/sipksecu-0003134b", "result.py,123456") in new stack
-- Launched AGI Script /var/lib/asterisk/agi-bin/result.py
<SIP/sipksecu-0003134b>AGI Tx >> agi_request: result.py
<SIP/sipksecu-0003134b>AGI Tx >> agi_channel: SIP/sipksecu-0003134b
<SIP/sipksecu-0003134b>AGI Tx >> agi_language: en
<SIP/sipksecu-0003134b>AGI Tx >> agi_type: SIP
<SIP/sipksecu-0003134b>AGI Tx >> agi_uniqueid: 1529916407.201547
<SIP/sipksecu-0003134b>AGI Tx >> agi_version: 1.8.32.1
<SIP/sipksecu-0003134b>AGI Tx >> agi_callerid: 09611000038
<SIP/sipksecu-0003134b>AGI Tx >> agi_calleridname: 09611000038
<SIP/sipksecu-0003134b>AGI Tx >> agi_callingpres: 0
<SIP/sipksecu-0003134b>AGI Tx >> agi_callingani2: 0
<SIP/sipksecu-0003134b>AGI Tx >> agi_callington: 0
<SIP/sipksecu-0003134b>AGI Tx >> agi_callingtns: 0
<SIP/sipksecu-0003134b>AGI Tx >> agi_dnid: 09611000196
<SIP/sipksecu-0003134b>AGI Tx >> agi_rdnis: unknown
<SIP/sipksecu-0003134b>AGI Tx >> agi_context: default
<SIP/sipksecu-0003134b>AGI Tx >> agi_extension: 09611000196
<SIP/sipksecu-0003134b>AGI Tx >> agi_priority: 3
<SIP/sipksecu-0003134b>AGI Tx >> agi_enhanced: 0.0
<SIP/sipksecu-0003134b>AGI Tx >> agi_accountcode:
<SIP/sipksecu-0003134b>AGI Tx >> agi_threadid: 140260657370880
<SIP/sipksecu-0003134b>AGI Tx >> agi_arg_1: 123456
<SIP/sipksecu-0003134b>AGI Tx >>
<SIP/sipksecu-0003134b>AGI Rx << SET VARIABLE "REGNO" "789123"
<SIP/sipksecu-0003134b>AGI Tx >> 200 result=1
<SIP/sipksecu-0003134b>AGI Rx << SET VARIABLE "CGPA" "3.5"
<SIP/sipksecu-0003134b>AGI Tx >> 200 result=1
-- <SIP/sipksecu-0003134b>AGI Script result.py completed, returning 0
-- Executing [09611000196@default:4] Playback("SIP/sipksecu-0003134b", "regnois") in new stack
-- <SIP/sipksecu-0003134b> Playing 'regv.slin' (language 'en')
-- Executing [09611000196@default:5] SayAlpha("SIP/sipksecu-0003134b", "789123") in new stack
-- <SIP/sipksecu-0003134b> Playing 'digits/7.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/8.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/9.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/1.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/2.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/3.gsm' (language 'en')
-- Executing [09611000196@default:6] Playback("SIP/sipksecu-0003134b", "cgpais") in new stack
-- <SIP/sipksecu-0003134b> Playing 'cgpav.slin' (language 'en')
-- Executing [09611000196@default:7] SayAlpha("SIP/sipksecu-0003134b", "3.5") in new stack
-- <SIP/sipksecu-0003134b> Playing 'digits/3.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'letters/dot.gsm' (language 'en')
-- <SIP/sipksecu-0003134b> Playing 'digits/5.gsm' (language 'en')
2. Ví dụ insert dữ liệu vào CSDL.
- Đặt hoặc thiết lập lại mã pin của người dùng thông qua phản hồi tương tác
- Tất nhiên được xác minh bởi nhân viên trung tâm liên lạc và sau đó chuyển sang một số máy đặc biệt để đặt/thiết lập mã pin
- Chúng ta cần số tài khoản người dùng hoặc ngay cả số thẻ ATM 16 chữ số
- Đặt một mã pin thông qua IVR sẽ được chèn vào CSDL”
File script python của mình sẽ có nội dung dưới.
#!/usr/bin/python
import agi
import MySQLdb
import sys
agi = agi.AGI()
MYSQL_HOST='127.0.0.1'
MYSQL_USER='root'
MYSQL_PASS=‘test123'
MYSQL_DB='bankacc'
atmcardno=sys.argv[1]
pinno=sys.argv[2]
mysql = MySQLdb.connect(host=MYSQL_HOST , user=MYSQL_USER, passwd=MYSQL_PASS, db=MYSQL_DB)
db = mysql.cursor()
db.execute("""UPDATE banktb SET Pinno='%(pinno)s' WHERE Atmcardno='%(atmcardno)s'""" %vars())
result = db.fetchall()
db.close()
Ghi chú:
- Số thẻ ATM có thể là một số 16 chữ số
- Mã Pin là khóa bí mật được cung cấp bởi người dùng
Viết Dialplan trong extension.conf để khởi chạy kịch bản AGI.
exten => 09611000196,1,Answer()
exten => 09611000196,n,Read(atmcardno,enteratmcardno,16) ;take the 16 digit atm card no through dtmf
exten => 09611000196,n,NoOp(${atmcardno})
exten => 09611000196,n,Read(pinno,enterpinno,4) ;take the 4 digit pin no through dtmf
exten => 09611000196,n,NoOp(${pinno})
exten => 09611000196,n,AGI(bankpin.py,${atmcardno}, ${pinno})) ;launch the AGI to insert new pin to db
against the given atm card no
exten => 09611000196,n,Hangup()