ว่ากันว่า "Dialplan" ถือเป็นหัวใจสำคัญของการใช้งาน Asterisk เลยก็ว่าได้ ผมพูดแบบนี้ก็เพราะว่าสาเหตุที่เราเอา Asterisk มาใช้งานก็เพื่อให้โทรไปที่นู่น ที่นี่ได้ ให้รับสายได้ ถ้าไม่มี "Dialplan" แล้วก็จะทำอย่างนี้ไม่ได้ Asterisk ก็จะไม่ต่างอะไรกับโปรแกรมอื่นๆที่เราลงในเครื่องแต่ไม่ได้ใช้งาน ดังนั้นถ้าจะใช้งาน Asterisk ให้ได้อย่างใจแล้วหล่ะก็ ต้องเขียน Dialplan เป็นครับ เขียนแบบเบสิคก็พอแล้วครับ เอาให้มันโทรออกรับสายเข้าได้ ไม่ต้องเขียนให้หรู ไม่ต้องเขียนได้อย่างมืออาชีพก็ได้ ผมเองก็เขียนได้แต่แบบเบสิคครับ ค่อยๆเป็นค่อยๆไป หาข้อมูลแล้วก็ลองผิดลองถูกไปเรื่อยๆ เดี๋ยวก็เก่งเอง ผมก็กำลังทำแบบที่ว่านี้อยู่ครับ "ทำให้มันง่ายที่สุด"
บทความที่เกี่ยวข้อง
- ไฟล์ extensions.conf
- Asterisk Context ในไฟล์ extensions.conf
เอาหล่ะครับ มาเริ่มศึกษา Dialplan กันเลยดีกว่า
1. ความสำคัญของ Dial Plan
Dial Plan ถือเป็นหัวใจของ Asterisk นะครับ เพราะมันจะคอยสั่งงาน Asterisk ให้จัดการกับการโทรออก (Outbound calls) และรับสายเข้า (Inbound calls) ยังไง ภายใน Dialplan ประกอบไปด้วยคำสั่ง (Instructions) ซึ่งเป็นขั้นตอนที่การทำงานที่ Asterisk จะต้องทำ เป็นหน้าที่เราที่จะเขียน Dialplan ครับ ซึ่งก็เป็นหน้าที่ของผมที่จะแนะนำอย่างเป็นขั้นตอนและในขณะเดียวกันก็จะแทรกเทคนิคการเขียนนิดๆหน่อยๆให้ด้วย
2. ไฟล์ที่เก็บ Dialplan
เวลาเราเขียน Dialplan ให้เขียนในไฟล์ extensions.conf นะครับ (ต้องเป็นไฟล์ชื่อนี้เท่านั้นนะครับ หรือไฟล์ที่ถูก Include เข้าไปก็ได้ เป็นชื่ออื่นไม่ได้) คงจะพอจำได้นะครับว่าตอนที่เราคอมไพล์ Asterisk เราใช้คำสั่ง make samples ด้วย ก็จะมีไฟล์ extensions.conf ถูกก๊อปไปไว้ที่ไดเร็คตอรี่ /etc/asterisk (หรือไดเร็คตอรี่อื่น) ซึ่งมีตัวอย่าง Dialplan อยู่เยอะแยะมากมาย ดูลำบากครับ ดูแล้วเวียนหัว แต่ก็เป็นดูเป็นตัวอย่างได้ ผมแนะนำว่าให้เปลี่ยนชื่อไฟล์นี้เป็นชื่อใหม่ไปเลย เช่น extensions.conf.bak แล้วสร้างไฟล์ extension.conf ขึ้นมาใหม่เป็นเวอร์ชั่นของเราเอง แล้วเริ่มลงมือเขียน Dialplan จะดีกว่า
- โค้ด: เลือกทั้งหมด
mv extensions.conf extensions.conf.bak
touch extensions.conf
3. รูปแบบการเขียน Dialplan
Dialplan ในไฟล์ extensions.conf ประกอบไปด้วย 4 ส่วนหลัก ได้แก่ Context, Extension, Priority และ Application มาดูรายละเอียดของแต่ละส่วนกันครับ
3.1 Context
เราแบ่ง Dialplan ออกเป็นส่วนๆซึ่งเรียกว่า Context ครับ ซึ่ง Context เป็นชื่อของกลุ่มเบอร์ Extension ที่เราเอามารวมไว้ที่เดียวกัน (เอาเบอร์ Extension ตั้งแต่ 1 เบอร์ขึ้นไปมารวมอยู่ในที่ๆเดียวกัน แล้วก็ตั้งชื่อไว้อ้างอิงหรือเพื่อไว้เรียกใช้งาน เวลาเราจะเรียกใช้งานเบอร์ Extensions เหล่านั้น เราก็ใช้ชื่อกลุ่มแทน ก็สะดวกดีครับ) ถ้าเรามีหลายๆ Context เราสามารถเชื่อมโยงเข้าหากันได้ แต่ผมว่าเราควรจะเริ่มต้นจากแบบง่ายๆที่สุดก่อนคือยังไม่ต้องเชื่อมโยง Context เข้าหากัน ให้มันยังไม่ต้องรู้จักกันก่อน เบอร์ Extension ที่อยู่ใน Context หนึ่งจะแยกเป็นอิสระจากเบอร์ Extension ใน Context อื่น ซึ่งหมายความว่า เบอร์ Extension ซ้ำกันได้ตราบใดที่มันอยู่คนละ Context กันและมันโทรหากันไม่ได้ด้วยนะครับ จะโทรได้ก็ต่อเมื่อมีการเชื่อมโยง Context เข้าหากันแล้วเท่านั้น
ลองนึกเล่นๆนะครับ สมมติว่าเรามี 2 บริษัทที่ใช้ Asterisk เครื่องเดียวกันอยู่ เราสร้างระบบตอบรับหรือ IVR หรือเมนูวอยส์ (Voice Menu) ให้อยู่แยกคนละ Context ก็จะทำให้ Voice ของ 2 บริษัทนี้แยกกันโดยสิ้นเชิง สองบริษัทนี้สามารถมีเบอร์ Extension เหมือนกันได้ เช่น Extension 0 ของโอเปอเรเตอร์ ถ้าคนโทรเข้ามาที่บริษัท A เขาสามารถกด 0 หาโอเปอเรเตอร์ได้ และขณะเดียวกันมีอีกคนโทรหาบริษัท B เขาก็กด 0 หาโอเปอเรเตอร์ของบริษัท B ได้เช่นเดียวกัน
วิธีการสร้าง Context นั้นนะครับ อันดับแรกให้เรานึกก่อนว่าเราจะเอา Context นี้ไปทำอะไร ให้มันรองรับงานแบบไหน จากนั้นก็ตั้งชื่อ Context โดยเขียนชื่อไว้ในเครื่องหมาย [ ] ชื่ออาจจะประกอบไปด้วยตัวอักษร A-Z (ทั้งตัวเล็กและตัวใหญ่) ตัวเลข 0-9 เครื่องหมาย _ และ - แต่ห้ามเว้นวรรคนะรับ ควรตั้งชื่อที่สื่อความหมายบอกจุดประสงค์ของการใช้ ยกตัวอย่างเช่น Context สำหรับรับสายเข้า (Incoming call) อาจจะตั้งชื่อว่า
[incoming]
พอเราได้ชื่อ Context แล้วขั้นตอนต่อมาเป็นการเขียนคำสั่ง (คำสั่งจะประกอบไปด้วย Extensions + Priority + Application) พอเขียนเสร็จแล้วก็เริ่มสร้าง Context อื่นๆเพิ่มอีก (ถ้าต้องการ)
Context พิเศษใน Dialplan
Context พิเศษทีว่านี้จะอยู่ตอนต้นของไฟล์ extensions.conf ครับ ชื่อว่า [general] และ [globals] จุดประสงค์หลักของการใช้ Context พิเศษนี้ก็คือเพื่อความปลอดภัยและการประกาศค่าตัวแปร โดยเมื่อใช้อย่างเหมาะสมเราสามารถกำหนดได้ว่าใคร เบอร์ Extension เบอร์ไหนสามารถใช้ฟีเจอร์อะไรได้บ้าง เช่น โทรทางไกล ในขณะที่บางเบอร์ทำไม่ได้ ถ้าเราไม่ได้ออกแบบ Dialplan ไว้อย่างระมัดระวังแล้วหล่ะก็ อาจมีใครบางคนมาลักลอบให้ระบบของเราก็เป็นได้ เดี๋ยวค่อยดูรายละเอียดเกี่ยวกับเรื่องนี้อีกทีครับ
3.2 Extension
ภายในแต่ละ Context ให้เรากำหนดเบอร์ Extension ขึ้นมา อาจมีแค่เบอร์เดียวหรือหลายเบอร์ก็ได้นะครับเพราะว่าแต่ละ Context มีเบอร์ Extension ได้ไม่จำกัดอยู่แล้ว จริงๆแล้ว Extension ไม่ใช่เป็นเพียงแค่เบอร์ แต่จริงๆแล้วมันเป็นคำสั่งๆหนึ่งที่ Asterisk จะทำตาม เราเขียนเสร็จแล้วปล่อยทิ้งไว้มันก็จะไม่มีการทำงานเกิดขึ้นนะครับ จนกว่าจะมีตัวกระตุ้นให้ Asterisk ทำงานซึ่งอาจจะเป็นสายที่โทรเข้ามา (Incoming Calls) หรือเมื่อยูสเซอร์ภายในกด (Dialed number) ไปหา Extension นั้นพอดี
Extension จะบอกเราว่าจะเกิดอะไรขึ้นกับคอลบ้างในระหว่างที่มันกำลังเดินทางท่องเที่ยวใน Dialplan ถึงแม้ว่า Extension จะถูกใช้เพื่อสร้างเบอร์ Extension เหมือนกับในระบบตู้สาขาโทรศัพท์ก็ตามแต่สำหรับ Asterisk มันมีความหมายมากกว่านั้นนะครับ
รูปแบบการเขียน extension ก็คือ เขียนคำว่า exten ตามด้วยเครื่องหมายลูกศร => (เครื่องหมาย = และ >) ดังตัวอย่าง
exten =>
แล้วก็จะตามด้วยชื่อของ Extension
จากที่ผมพูดถึงในตอนต้นว่า Asterisk มันไม่ได้มองว่า Extension เป็นเพียงแค่เบอร์โทรศัพท์ที่เป็นตัวเลขเท่านั้น เราเคยชินกับ Extension ที่เป็นตัวเลข แต่สำหรับใน Asterisk มันไม่ใช่แค่ตัวเลข จริงๆเราต้องพูดว่า "ชื่อ Extension" นะครับไม่ใช่ "เบอร์ Extension" ยกตัวอย่างเช่น ชื่อ Extension เป็นตัวเลขก็ได้ ตัวอักษรก็ได้ หรือทั้งตัวเลขและตัวอักษรผสมกัน
การ Asterisk ยอมให้เราตั้งชื่อ Extension ได้ทั้งตัวเลขและตัวอักษร ก็นับว่าสอดคล้องกับระบบ VoIP ในปัจจุบันนี้นะครับ ซึ่งโทรไปหาปลายทางได้ทั้งที่เป็นตัวเลข ตัวอักษร หรือแม้แต่อีเมล์แอดเดรส จึงทำให้ Asterisk มีความยืดหยุ่นในการใช้งานมาก
Extension ที่สมบูรณ์ จะประกอบด้วย 3 ส่วนได้แก่
Name (หรือ Number) ของ Extension
Priority (แต่ละ Extension อาจมีขั้นตอนการทำงานหลายขั้นตอนจนกว่าจะเสร็จ ลำดับหรือหมายเลขของขั้นตอนเหล่านั้นเราเรียกว่า Priority ครับ ซึ่ง Asterisk จะทำงานตามลำดับขั้นตอนที่เราได้วางไว้)
Application (หรือคำสั่ง) ซึ่งก่อให้เกิดการกระทำบางอย่างในระหว่างคอล
ทั้ง 3 ส่วนคั่นด้วยเครื่องหมายคอมม่า , (สำหรับ Asterisk เวอร์ชั่น 1.2 และ 1.6) หรือเครื่องหมายไปป์ | (สำหรับ Asterisk เวอร์ชั่น 1.4) เช่น
exten => name,priority,application()
ตัวอย่าง Extension ง่ายๆแต่ใช้งานได้จริง
exten => 123,1,Answer()
ในตัวอย่างนี้ชื่อ Extension คือ 123, Priority คือ 1 และ Application คือ Answer()
3.3 Priority
แต่ละ Extension อาจจะมีการทำงานแค่ขั้นตอนเดียวหรือว่าหลายขั้นตอนก็ได้นะครับ แต่ละขั้นตอนซึ่งเราเรียกว่า Priority หรือลำดับของการทำงาน แต่ละ Priority เป็นตัวเลขซึ่งเริ่มต้นที่ 1 (แต่มี Priority อีกแบบหนึ่งเรียกว่า Unnumbered Priority ไม่ต้องมีตัวเลข แต่ยังไงก็ต้องเริ่มต้นด้วย 1 แต่ Priority ต่อมาไม่ต้องระบุเป็นตัวเลข ผมมีอธิบายไว้ด้านล่างด้วย) แต่ละ Priority จะมี Application 1 อย่างคู่กัน ดูตัวอย่าง Extension ต่อไปนี้นะครับซึ่งควรจะตอบรับโทรศัพท์ (ใน Priority หมายเลข 1) จากนั้นวางสาย (ใน Priority หมายเลข 2)
exten => 123,1,Answer()
exten => 123,2,Hangup()
ต้องแน่ใจนะครับว่า Priority เริ่มต้นด้วยหมายเลข 1 และเรียงลำดับกันไปเรื่อยๆ เพราะถ้าหากเราเรียงไม่ถูกหรือลำดับไม่ต่อเนื่องกัน Asterisk ก็จะทำงานไม่ต่อเนื่อง ไม่เป็นไปตามที่เราคิด ถ้าพบว่า Asterisk ทำงานไม่เป็นไปตามลำดับ Priority ที่เราเขียนไว้ใน Extension ลองเช็ค Priority ดูครับ ให้แน่ใจว่าเราไม่ได้เขียนข้ามหรือว่าลืมใส่
ทั้ง Answer() และ Hangup() เป็นชื่อ Application นะครับ แต่ตอนนี้ยังไม่ต้องห่วงว่ามันคืออะไร เดี๋ยวผมจะอธิบายอีกที ขอให้เข้าใจว่า Asterisk จะทำงานตามลำดับของ Priority
Unnumbered Priority
ตั้งแต่ Asterisk 1.2 เป็นต้นมามีการเพิ่ม n Priority ซึ่ง n ย่อมาจาก next โดยแต่ละครั้งที่ Asterisk เจอ Priority ที่มีชื่อว่า n มันจะแปลงเป็นหมายเลขให้เราเองโยเอาค่า Priority ก่อนหน้าบวกด้วย 1 นี้ ผมว่าวิธีการกำหนด Priority แบบนี้สะดวกมากมาย เราสร้างหรือแก้ไข Dialplan ได้ง่ายขึ้นโดยไม่ต้องห่วงเรื่องลำดับของ Priority เช่น มี Dial Plan แบบนี้
exten => 123,1,Answer()
exten => 123,n,do something
exten => 123,n,do something else
exten => 123,n,do one last thing
exten => 123,n,Hangup()
ผมเองก็ใช้แบบ Unnunbered Priority อยู่ครับ สะดวกจริงๆนะครับ โดยเฉพาะตอนจะแทรกเพิ่มบรรทัดเข้าไป ถ้าใช้แบบที่เป็นตัวเลข ก็คงต้องมาแก้ตัวเลขกันใหม่ทั้งหมด
นอกจากนั้น Asterisk ยังยอมให้เราตั้ง Priority แบบใช้ Label ได้ด้วย โดยเพิ่มไว้ภายในเครื่องหมาย () แบบนี้
exten => 123,n(label),do something
3.4 Application
ถือได้ว่า Application เป็นสิ่งที่ขาดไม่ได้ใน Dialplan นะครับ เพราะมันคือคำสั่งที่สั่งงาน Asterisk ว่าจะต้องทำอะไร แต่ละ Application จะทำงานเฉพาะอย่างบนแชนแนลที่กำลังรับคอลอยู่ในขณะนั้น เช่นเล่นไฟล์เสียงให้ยูสเซอร์ฟัง หรือรับตัวเลขที่ยูสเซอร์กดจากแป้นโทรศัพท์ หรือวางสายโทรศัพท์ เป็นต้น Asterisk รองรับ Application ได้มากมายทั้ง Application ที่ผู้พัฒนาได้สร้างเอาไว้แล้วและ Application ที่เราสร้างเพิ่มเองได้ (สร้างด้วยโปรแกรมภาษาต่างๆ เช่น Perl, PHP, Python, C/C++ เป็นต้น แล้วเชื่อมต่อกับ Asterisk ด้วย Asterisk Gateway Interface หรือ AGI ไว้ผมจะเขียนบทความเกี่ยวกับ AGI นะครับ) ในตัวอย่างที่ผ่านมาเราได้รู้จักกับ 2 Applicaitons ง่ายๆคือ Answer() และ Hangup()
บาง Application เช่น Answer() และ Hangup() ไม่ต้องการข้อมูลใดๆในการทำงาน ในขณะที่ Application อื่นส่วนมากต้องการข้อมูลเพิ่มเติม ข้อมูลเพิ่มเติมเหล่านี้เราเรียกว่า "Arguments" ซึ่งจะถูกส่งไปพร้อมๆกับการเรียกใช้ Applicaton และ Application ก็จะเอาข้อมูลนี้มาช่วยในการทำงาน ในการส่ง Argument ไปยัง Application ให้ใส่ Argument อยู่ภายในเครื่องหมายวงเล็บต่อท้ายชื่อ Application แล้วคั่นแต่ละ Argument ด้วยเครื่องหมายคอมม่า , สำหรับ Asterisk 1.4 ใช้เครื่องหมายไปป์ | แทนเครื่องหมายคอมม่านะครับ ส่วน Asterisk 1.6 ใช้เครื่องหมายคอมม่าได้เลย
Asterisk Dialplan ตอนที่ 2