http://blog.naver.com/hsunryou/60115858643

 

RealTime으로 Moh(Music on Hold) 기능 구현하기… Asterisk[IP-PBX]

2010/10/01 16:58

작성자 : 류현선(hsunryou@naver.com) / Twitter에서 제 이름으로 검색하시면.. 다양한 Asterisk 자료를 확인할 수 있습니다
목적 : 사용자 별로 Music On Hold 설정 기능 소개

http://www.voip-info.org/wiki/view/Asterisk+config+musiconhold.conf

이번 글에서는 RealTime(?) 으로 Music On Hold(Coloring기능) 기능을 설정하는 방법에 대해 글을 작성 할려고 합니다.

참고적으로 이 글은 Cent OS 5.4 + MySQL + Asterisk 1.4 최신 버전으로 구성된 시스템에서 검증된 자료임을 알려드립니다.

자 그럼 이제 시작 하겠습니다.

Music On Hold 구성을 위한 Schema 정보

CREATE TABLE `MusicOnHold`
(

`name` varchar(80) NOT NULL,

`directory` varchar(255) NOT NULL default '',

`application` varchar(255) NOT NULL default '',

`mode` varchar(80) NOT NULL default '',

`digit` char(1) NOT NULL default '',

`sort` varchar(16) NOT NULL default '',

`format` varchar(16) NOT NULL default '',

PRIMARY KEY (`name`)

);

 

CREATE TABLE `MusicOnHold`
(

`name` varchar(80) NOT NULL,

`directory` varchar(255) NOT NULL default '',

`application` varchar(255) NOT NULL default '',

`mode` varchar(80) NOT NULL default '',

`digit` char(1) NOT NULL default '',

`sort` varchar(16) NOT NULL default '',

`format` varchar(16) NOT NULL default '',

`extension` varchar(4) default NULL,

`type` char(1) NOT NULL default 'A',

PRIMARY KEY (`name`)

);


* type
컬럼 용도 : A=All, P=Private

그리고 /etc/asterisk/extconfig.conf 파일은 다음과 같이 설정하시면 됩니다

/etc/asterisk/extconfig.conf

musiconhold => mysql,asterisk,[table name]


위 스키마를 적용하면..
musiconhold => mysql,asterisk,MusicOnHold
와 같을 것입니다.


자 이렇게 Music on Hold Schema 구성과 설정 방법을 알아보았습니다.

Music On Hold 기능을 점검하겠습니다. 테스트하기 위한 시나리오는 다음과 같습니다.

Music On Hold 테스트 시나리오

내선 7000사용자에게 전화가 올 경우, Music On Hold 기능을 살펴보도록 하겠습니다.

 Dial-Plan을 구성한다면 다음과 같을 것입니다.

[inbound]
exten => 7000,1,Answer

exten => 7000,2,MusicOnHold( ... )

Dial-Plan 처럼 내선 7002번에 전화가 온 경우, Caller에게 특별한 Coloring이 울리도록 설정을 하도록 하겠습니다.

 여기서는 Real-Time을 점검하고 있기 때문에 MusicOnHold 테이블에 Coloring 정보를 설정하여서 테스트하겠습니다.

 

.. 그럼 어떻게 설정하는지 확인해보겠습니다.

/etc/asterisk/musiconhold.conf

 

[default]

mode=files

directory=/var/lib/asterisk/moh

 

[native-random]

mode=files

directory=/var/lib/asterisk/moh

random=yes ; Play the files in a random order


[test]

mode=files

directory=/var/lib/asterisk/moh/test

 


그리고 위 Music On Hold 기능을 설정하기 위한 음원 파일의 Path 및 파일 목록입니다.

/var/lib/asterisk/moh Path & File List

[ippbx@localhost moh]$ pwd

/var/lib/asterisk/moh

[ippbx@localhost moh]$ tree

.

|-- CHANGES-asterisk-moh-opsound-wav

|-- CREDITS-asterisk-moh-opsound-wav

|-- LICENSE-asterisk-moh-opsound-wav

|-- macroform-cold_day.wav

|-- macroform-robot_dity.wav

|-- macroform-the_simplicity.wav

|-- manolo_camp-morning_coffee.wav

|-- reno_project-system.wav

`-- test

`-- manolo_camp-morning_coffee.wav

 

1 directory, 9 files

..

 

위와 같이 musiconhold.conf 내용과 Mapping되는 음원 파일 목록을 색으로 연결했습니다. 그렇다면..

extensions.conf (Dial-Plan)단에서는 어떻게 설정하면 될까요?

/etc/asterisk/musiconhold.conf

[inbound]



exten=>_070.,1,Ringing

exten=>_070.,n,Noop(EXTEN=${EXTEN})

exten=>_070.,n,Noop(CUSTNUM=${CUSTNUM})

exten=>_070.,n,Noop(CUSTIDX=${CUSTIDX})

exten=>_070.,n,Noop(GROUPIDX=${GROUPIDX})

exten=>_070.,n,Set(CALLTYPE=POLL)

;exten=>_070.,n,MusicOnHold(native-random)

;exten=>_070.,n,MusicOnHold(default)

exten=>_070.,n,MusicOnHold(test)

exten=>_070.,n,Dial(SIP/7002)

exten=>_070.,n,Hangup

위와 같이 MusicOnHold Command를 설정하여 테스트해보니… 정상적으로 잘~ 작동하는 것을 확인했습니다.

그렇다면.. 이제 Real-Time에 적용해보겠습니다.

우선 Asterisk에서 Moh(Music On Hold)기능을 Real-Time으로 설정한 내용을 반영하도록 하겠습니다.

Asterisk CLI Mode에서 "reload" 하기

localhost*CLI> reload

== Parsing '/etc/asterisk/cdr.conf': Found

[Oct 4 14:30:14] NOTICE[27967]: cdr.c:1449 do_reload: CDR simple logging enabled.

== Parsing '/etc/asterisk/dnsmgr.conf': Found

== Parsing '/etc/asterisk/extconfig.conf': Found

== Binding musiconhold to mysql/ippbx/MusicOnHold

== Parsing '/etc/asterisk/enum.conf': Found

== Parsing '/etc/asterisk/manager.conf': Found

== Parsing '/etc/asterisk/users.conf': Found

== Parsing '/etc/asterisk/rtp.conf': Found

== RTP Allocating from port range 10000 -> 20000

== Parsing '/etc/asterisk/http.conf': Found

== Parsing '/etc/asterisk/logger.conf': Found

Asterisk Event Logger restarted

Asterisk Queue Logger restarted

== Parsing '/etc/asterisk/codecs.conf': Found

-- Reloading module 'res_features.so' (Call Features Resource)

== Parsing '/etc/asterisk/features.conf': Found

-- Added extension '700' priority 1 to parkedcalls

-- Reloading module 'res_smdi.so' (Simplified Message Desk Interface (SMDI) Resource)

== Parsing '/etc/asterisk/smdi.conf': Found

[Oct 4 14:30:14] WARNING[27967]: res_smdi.c:1406 reload: No SMDI interfaces were specified to listen on,

not starting SDMI listener.

-- Reloading module 'res_adsi.so' (ADSI Resource)

== Parsing '/etc/asterisk/adsi.conf': Found

-- Reloading module 'res_musiconhold.so' (Music On Hold Resource)

== Parsing '/etc/asterisk/musiconhold.conf': Found

-- Reloading module 'cdr_custom.so' (Customizable Comma Separated Values CDR Backend)

== Parsing '/etc/asterisk/cdr_custom.conf': Found

-- Reloading module 'codec_alaw.so' (A-law Coder/Decoder)

-- Reloading module 'chan_sip.so' (Session Initiation Protocol (SIP))

-- Reloading module 'chan_iax2.so' (Inter Asterisk eXchange (Ver 2))

Reloading SIP

== Parsing '/etc/asterisk/iax.conf': Found

== Parsing '/etc/asterisk/sip.conf': Found

== Parsing '/etc/asterisk/users.conf': Found

> doing dnsmgr_lookup for '216.207.245.47'

== Parsing '/etc/asterisk/FHConf/test_sip.conf': == Parsing '/etc/asterisk/iaxprov.conf': Found

Found

-- Loaded provisioning template 'default'

-- Reloading module 'app_voicemail.so' (Comedian Mail (Voicemail System))

== Parsing '/etc/asterisk/voicemail.conf': Found

[Oct 4 14:30:14] WARNING[15991]: chan_sip.c:5033 sip_register:

Format for registration is user[:secret[:authuser]]@host[:port][/contact] at line 316

== Parsing '/etc/asterisk/users.conf': Found

== Parsing '/etc/asterisk/users.conf': Found

-- Reloading module 'pbx_dundi.so' (Distributed Universal Number Discovery (DUNDi))

== Parsing '/etc/asterisk/dundi.conf': == Parsing '/etc/asterisk/sip_notify.conf': Found

Found

-- Reloading module 'res_crypto.so' (Cryptographic Digital Signatures)

-- Reloading module 'cdr_csv.so' (Comma Separated Values CDR Backend)

== Parsing '/etc/asterisk/cdr.conf': Found

-- Reloading module 'codec_gsm.so' (GSM Coder/Decoder)

-- Reloading module 'res_indications.so' (Indications Resource)

-- Unregistered indication country 'at'

-- Unregistered indication country 'au'

위와 같이 Log 내용이 출력되면서 Real-Time으로 Binding된 테이블 정보가 출력되는 것을 확인할 수 있습니다.

~ 그럼, RealTime으로 Moh 기능을 적용해서 테스트해보겠습니다.

테스트 방법은 새로운 Moh class를 생성해서 점검해보겠습니다. , MusicOnHold 테이블에 새로운 Moh class 등록하도록 하겠습니다.

먼저 Real-Time으로 점검한 음원 파일을 다음과 같이 생성했습니다.

Music On Hold 정보

[ippbx@localhost moh]$ tree

.

|-- CHANGES-asterisk-moh-opsound-wav

|-- CREDITS-asterisk-moh-opsound-wav

|-- LICENSE-asterisk-moh-opsound-wav

|-- macroform-cold_day.wav

|-- macroform-robot_dity.wav

|-- macroform-the_simplicity.wav

|-- manolo_camp-morning_coffee.wav

|-- realtime

| `-- coffee.wav

|-- reno_project-system.wav

`-- test

`-- manolo_camp-morning_coffee.wav


그리고, extensions.conf 파일을 다음과 같이 수정 후 테스트해보겠습니다.

아래 로그 내용과 같이 등록된 musiconhold class가 없다는 로그 내용과 함께 DEFAULT Moh Class Loading되는 것을 확인할 수 있습니다.

[inbound]

exten=>_070.,1,Ringing

exten=>_070.,n,Noop(EXTEN=${EXTEN})

exten=>_070.,n,Noop(CUSTNUM=${CUSTNUM})

exten=>_070.,n,Noop(CUSTIDX=${CUSTIDX})

exten=>_070.,n,Noop(GROUPIDX=${GROUPIDX})

exten=>_070.,n,Set(CALLTYPE=POLL)

exten=>_070.,n,MusicOnHold(realtime)

exten=>_070.,n,Dial(SIP/7002)

exten=>_070.,n,Hangup

..
-- Registered extension context 'international'

-- Including context 'longdistance' in context 'international'

-- Including context 'trunkint' in context 'international'

-- Executing [0707545****@inbound:1] Ringing("SIP/gw.forhuman-00000036", "") in new stack

-- Executing [0707545****@inbound:2] NoOp("SIP/gw.forhuman-00000036", "EXTEN=0707545****") in new stack

-- Executing [0707545****@inbound:3] NoOp("SIP/gw.forhuman-00000036", "CUSTNUM=") in new stack

-- Executing [0707545****@inbound:4] NoOp("SIP/gw.forhuman-00000036", "CUSTIDX=") in new stack

-- Executing [0707545****@inbound:5] NoOp("SIP/gw.forhuman-00000036", "GROUPIDX=") in new stack

-- Executing [0707545****@inbound:6] Set("SIP/gw.forhuman-00000036", "CALLTYPE=POLL") in new stack

-- Executing [0707545****@inbound:7] MusicOnHold("SIP/gw.forhuman-00000036", "realtime") in new stack

[Oct 4 14:37:53] WARNING[28096]: res_musiconhold.c:682 get_mohbyname: Music on Hold class 'realtime' not found

-- Started music on hold, class 'default', on SIP/gw.forhuman-00000036

-- Stopped music on hold on SIP/gw.forhuman-00000036

== Spawn extension (inbound, 0707545****, 7) exited non-zero on 'SIP/gw.forhuman-00000036'

[Oct 4 14:38:59] NOTICE[15991]: chan_sip.c:16331 handle_request_subscribe: Received SIP subscribe for peer without mailbox: 7002

localhost*CLI>

..

 

, 그럼 이제 Real-Time으로 Moh class를 등록해보겠습니다. 우선 현재 등록된 MusicOnHold 테이블 구조는 다음과 같습니다.

 

mysql> use ippbx;

Database changed

mysql> show tables;

+-----------------+

| Tables_in_ippbx |

+-----------------+

| MusicOnHold |

+-----------------+

1 row in set (0.00 sec)

 

mysql> desc MusicOnHold;

+-------------+--------------+------+-----+---------+-------+

| Field | Type | Null | Key | Default | Extra |

+-------------+--------------+------+-----+---------+-------+

| name | varchar(80) | NO | PRI | NULL | |

| directory | varchar(255) | NO | | NULL | |

| application | varchar(255) | NO | | NULL | |

| mode | varchar(80) | NO | | NULL | |

| digit | char(1) | NO | | NULL | |

| sort | varchar(16) | NO | | NULL | |

| format | varchar(16) | NO | | NULL | |

+-------------+--------------+------+-----+---------+-------+

7 rows in set (0.02 sec)

mysql> show tables;

+-----------------+

| Tables_in_ippbx |

+-----------------+

| MusicOnHold |

+-----------------+

1 row in set (0.00 sec)

 

mysql> select * from MusicOnHold;

+----------+--------------------------------+-------------+-------+-------+------+--------+

| name | directory | application | mode | digit | sort | format |

+----------+--------------------------------+-------------+-------+-------+------+--------+

| realtime | /var/lib/asterisk/moh/realtime | | files | | | |

+----------+--------------------------------+-------------+-------+-------+------+--------+

1 row in set (0.00 sec)

 

mysql>


허걱.. MySQL에 접속할 때 에러가 발생하네요..

Asetrisk CLI 모드에서

..
localhost*CLI>

localhost*CLI> realtime mysql status

[Oct 4 15:21:47] ERROR[28258]: res_config_mysql.c:629 mysql_reconnect: MySQL RealTime:

Failed to connect database server asterisk on (err 1049). Check debug for more info.

localhost*CLI>

localhost*CLI>


좀더 구체적인 Log를 보기 위해서 /etc/logger.conf 파일을 수정했고…

로그 파일 점검

 

[ippbx@localhost asterisk]$ pwd

/var/log/asterisk

[ippbx@localhost asterisk]$ ll

합계 1444

drwxr-xr-x 2 ippbx ippbx 4096 10 1 15:50 cdr-csv

drwxr-xr-x 2 ippbx ippbx 4096 9 30 14:05 cdr-custom

-rw-rw-r-- 1 ippbx ippbx 0 9 30 14:50 event_log

-rw-rw-r-- 1 ippbx ippbx 1372 10 4 14:53 h323_log

-rw-rw-r-- 1 ippbx ippbx 1456954 10 4 15:21 messages

-rw-rw-r-- 1 ippbx ippbx 1582 10 4 15:20 queue_log

[ippbx@localhost asterisk]$ tail -f ./messages

[Oct 4 15:20:16] NOTICE[28258] pbx_ael.c: AEL load process: compiled config file name '/etc/asterisk/extensions.ael'.

[Oct 4 15:20:16] NOTICE[28258] pbx_ael.c: AEL load process: merged config file name '/etc/asterisk/extensions.ael'.

[Oct 4 15:20:16] NOTICE[28258] pbx_ael.c: AEL load process: verified config file name '/etc/asterisk/extensions.ael'.

[Oct 4 15:20:19] ERROR[28258] res_config_mysql.c: MySQL RealTime: Failed to connect database server asterisk on (err 1049). Check debug for more info.

[Oct 4 15:20:19] DEBUG[28258] res_config_mysql.c: MySQL RealTime: Cannot Connect (1049): Unknown database 'asterisk'

[Oct 4 15:20:25] ERROR[28258] res_config_mysql.c: MySQL RealTime: Failed to connect database server asterisk on (err 1049). Check debug for more info.

[Oct 4 15:20:25] DEBUG[28258] res_config_mysql.c: MySQL RealTime: Cannot Connect (1049): Unknown database 'asterisk'

[Oct 4 15:21:00] NOTICE[28185] chan_sip.c: Received SIP subscribe for peer without mailbox: 7002

[Oct 4 15:21:47] ERROR[28258] res_config_mysql.c: MySQL RealTime:

 Failed to connect database server asterisk on (err 1049). Check debug for more info.

[Oct 4 15:21:47] DEBUG[28258] res_config_mysql.c: MySQL RealTime: Cannot Connect (1049): Unknown database 'asterisk'

 

왜 이런 현상이 발생하는지는 정확한 원인은 파악하지 못했습니다. Asterisk CLI 모드에서

"stop now" Asterisk 서버 데몬을 종료 후 다시 시작했습니다. 그랬더니 아래와 같이 정상적으로 작동했습니다.(iptable을 죽인 상태에서 , Asterisk restart시켰습니다)

 

localhost*CLI>

localhost*CLI> realtime

load mysql update

localhost*CLI> realtime mysql status

Connected to ippbx@127.0.0.1, port 3306 with username asterisk for 6 minutes, 21 seconds.

localhost*CLI>

localhost*CLI>


이젠 정상적으로 MySQL에 접속된 것을 확인했습니다. 그럼, 본격적으로 Real-Time상에서 Moh 적용된 항목을 보도록 하겠습니다.

Moh Error

localhost*CLI>

localhost*CLI>

-- Executing [0707545****@inbound:1] Ringing("SIP/gw.forhuman-0000000b", "") in new stack

-- Executing [0707545****@inbound:2] NoOp("SIP/gw.forhuman-0000000b", "EXTEN=0707545****") in new stack

-- Executing [0707545****@inbound:3] NoOp("SIP/gw.forhuman-0000000b", "CUSTNUM=") in new stack

-- Executing [0707545****@inbound:4] NoOp("SIP/gw.forhuman-0000000b", "CUSTIDX=") in new stack

-- Executing [0707545****@inbound:5] NoOp("SIP/gw.forhuman-0000000b", "GROUPIDX=") in new stack

-- Executing [0707545****@inbound:6] Set("SIP/gw.forhuman-0000000b", "CALLTYPE=POLL") in new stack

-- Executing [0707545****@inbound:7] MusicOnHold("SIP/gw.forhuman-0000000b", "coffee") in new stack

[Oct 4 16:48:12] WARNING[30953]: res_musiconhold.c:682 get_mohbyname: Music on Hold class 'coffee' not found

-- Started music on hold, class 'default', on SIP/gw.forhuman-0000000b

localhost*CLI>

localhost*CLI>

localhost*CLI> realtime

load mysql update

localhost*CLI> realtime mysql status

Connected to ippbx@127.0.0.1, port 3306 with username asterisk for 15 minutes, 52 seconds.

localhost*CLI>

localhost*CLI>

-- Stopped music on hold on SIP/gw.forhuman-0000000b

== Spawn extension (inbound, 0707545****, 7) exited non-zero on 'SIP/gw.forhuman-0000000b'

localhost*CLI>

그래도.. Music On Hold에 문제가 발생하네요. 이 문제점을 파악해야 하는데.. 쉽게 잡히지가 않네요.

 

------------------ 새롭게 접급한 방법 ------------------

아직까지 위 문제점에 대한 해결 방법을 몰라서.. 다른 방법으로 접급해보았습니다.
1. Asterisk
환경설정

/etc/asterisk/extconf.conf


musiconhold.conf => mysql,ippbx,musicon

 


2. My-SQL
환경설정

My-SQL

 

mysql> desc musicon;

+------------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+------------+--------------+------+-----+---------+----------------+

| id | bigint(20) | NO | PRI | NULL | auto_increment |

| cat_metric | int(11) | NO | | 0 | |

| var_metric | int(11) | NO | | 0 | |

| commented | int(11) | NO | | 0 | |

| filename | varchar(128) | NO | | NULL | |

| category | varchar(128) | NO | | default | |

| var_name | varchar(128) | NO | | NULL | |

| var_val | varchar(128) | NO | | NULL | |

| domain | varchar(50) | YES | | NULL | |

+------------+--------------+------+-----+---------+----------------+

9 rows in set (0.00 sec)

 

mysql> select * from musicon;

+----+------------+------------+-----------+------------------+----------+-----------+--------------------------------+--------+

| id | cat_metric | var_metric | commented | filename | category | var_name | var_val | domain |

+----+------------+------------+-----------+------------------+----------+-----------+--------------------------------+--------+

| 1 | 0 | 0 | 0 | musiconhold.conf | coffee | mode | files | NULL |

| 2 | 0 | 0 | 0 | musiconhold.conf | coffee | directory | /var/lib/asterisk/moh/realtime | NULL |

| 3 | 0 | 0 | 0 | musiconhold.conf | general | mode | files | NULL |

| 4 | 0 | 0 | 0 | musiconhold.conf | general | directory | /var/lib/asterisk/moh | NULL |

+----+------------+------------+-----------+------------------+----------+-----------+--------------------------------+--------+

4 rows in set (0.00 sec)

 

위 방법이 정상적으로 동작하는 것은 확인했습니다. 그런데 이것은 My-SQL musicon 테이블에 2개의 Row를 설정을 해야 합니다.

 

------------------ 기존 문제점 해결 방법 ------------------

아직까지 정확한 원인을 파악하지 못한 상태입니다.

 

, 그럼 MusicOnHold 기능에 대해서 좀 더 알아보겠습니다.

MusicOnHold : Play Music On Hold indefinitely à MusicOnHold([class])

Plays hold music specified by class. If omitted, the default music source for the channel will be used. If you have configured MusicOnHold in musiconhold.conf it will get played automatically if the extension is put on hold. This command FORCES musiconhold music.

그리고 Dialing하는 시점에 Music On Hold를 설정 할 수도 있습니다.

exten => 7020,1,NoOp(Dial -> IAX2/outbound/${EXTEN})

exten => 7020,n,Dial(IAX2/outbound/${EXTEN},,M(nomusic))

exten => 7020,n,Hangup

 

태그저장 취소