Asterisk & FastAGI with Node.js #3 AGI Commands - 1

Pustinia·2020년 6월 29일
1
post-thumbnail

1. 사전 준비물..

  • sngrep 이라는 프로그램이 필요하다.
    - centos 기준으로 설명한다.
    - yum install sngrep
    - 왜 필요하지? SIP에 대한 flow가 한눈에 잘 나타난다.
    • sngrep 명령어로 실행한다.
  • 이전 글에서의 vscode, node.js, npm 설치 (이전 글 바로가기)

2. 그래서 어떤걸 한다는 이야기 ?

  • Asterisk는 AGI Command를 지원하며, 이 AGI Command를 tcp 로 원격에서 지원 가능한 모듈이 FastAGI 이다.( Asterisk AGI Commands )
  • 그래서 npm ding-dong 모듈을 이용해 FastAGI를 Node.js로 여러 AGICommand를 Asterisk와 함께 만들어 보면서 확인해 보겠다는 이야기 이다.

3. 그럼, Let's Roll !!

  • 먼저, npm 을 따라가면 ding-dong에서 API.md 문서를 열어보자
  • ding-dong에서 지원 가능한 함수 및 event목록 확인이 가능하다.
1. context.onEvent(event) //=> event 설정
events
'variables' - on start call 
'close' - on end session 
'hangup' - on hangup channel
2. context.answer() //=> sip answer 수행
3. context.end()    //=> FastAGI 종료, 다시 dialplan 으로..

아직 javascript에 익숙하지 않다면, 위 소스에서 event가 어떤 의미 인지 모를 수 있다. 간단히 한글로 설명 하자면,

만약 당신이 내 이름을 부른다면, 난 춤을 출 거에요.

내 이름을 부른다면, 에서의 이름은 => event명
춤을 춘다. => event발생시 내가 하려고 하는 일을 미리 설정한다.

이제 이벤트 들을 확인하기 위해 Node.js소스로 코딩을 해보자.

const AGIServer = require('ding-dong');
const handler = (context) => {
    context
        .onEvent('close')
        .then((data) => {
            console.log('close event=>', data);
        })
        .catch((error) => {
            context.end();
        });
        
    context
        .onEvent('hangup')
        .then(() => {
            console.log('hangup event 발생');
        })
        .catch((error) => {
            context.end();
        });

    context
        .onEvent('variables')
        .then((vars) => {
            return context.answer();
        })
        .then((result) => {
            return context.end(); // context.end() 결과는 없다. undefined
        })
        .catch((error) => {
            context.end();
        });
};
const agi = new AGIServer(handler, { debug: true });
agi.start(5000);

[dialplan]
exten => s,1,NoOp(dialplan start====>)  ; log
 same => n,AGI(agi://127.0.0.1:5000) ; call FastAGI module
 same => n,wait(10)               ; wait 10 sec
 same => n,Hangup()               ; call hangup

위 AGI를 설명하자면 그냥 answer하고 해당 AGI를 end한다.

사실, 보통은 ding-dong모듈에서 variables event만 사용하지만, 문서에 close, hangup event가 보여 함께 확인해 보았다.

  • variables: dialplan에서 node.js AGI모듈 진입시 발생하는 event. vars에 채널정보가 담겨져 있다.
  • hangup: hangup event는 node.js AGI모듈로 제어가 옮겨진 상태에서 전화가 끊어지거나, context.end()가 수행되어 AGI모듈에서 다시 dialplan으로 제어가 돌아가면 발생했다.
  • close: context.end() 수행시점에 false로 값을 주며 이벤트가 발생한다. 어디다 쓰는걸까? ..

위 소스를 sngrep의 도움으로 흐름도를 뽑아 제어를 확인해 보면 아래와 같다.

자, 아무일도 하지 않으니 심심하다. 소스를 수정해서 소리가 들리게 만들어 보자. !!

const AGIServer = require('ding-dong');
const handler = (context) => {
    context
        .onEvent('variables')
        .then((vars) => {
            return context.channelStatus(vars.agi_channel); // get channel status
        })
        .then((results) => {
            return context.answer(); // answer to caller
        })
        .then((results) => {
            return context.streamFile('tt-monkeys', '1');
        })
        .then((results) => {
            return context.end(); // return to the dialplan
        })
        .catch((error) => {
            context.end();
        });
};
const agi = new AGIServer(handler, { debug: true });
agi.start(5000);

이제 전화를 걸면, 시끄러운 원숭이소리가 들린다.

  • streamFile: wav파일을 play한다. 해당 파일은 Asterisk서버 내부에 파일로 이미 존재하며, Asterisk CLI명령어로 'core show sounds'라고 명령어를 날리면 나오는 멘트 중 하나이다.(실제파일위치 => /var/lib/asterisk/sounds/en)
  • Asterisk에서 지원하는 STREAM FILE => 설명바로가기
  • Arguments들이 여러개 보인다. 현재의 ding-dong에서는 2개의 Arguments만 지원한다. 즉, filename값과 escape_digits값만 설정이 가능하다.
  • channelStatus: 채널명을 파라미터로 주면 해당 채널의 상태 값을 알려준다. 채널 상태 값 설명은 다음과 같다.

streamFile에서 절대경로는 가능할까 ? 해보자 !!!

return context.streamFile('/var/lib/asterisk/sounds/en/tt-monkeys', '1');

시끄러운 원숭이 소리가 들린다. 성공적이다. wav확장자가 없음을 유의하자.

streamFile 이라는 명령어가 왠지 stream으로 play 해줄 것 같은 기분이 든다. try 해보자 !!
웹상에서 wav파일을 다운로드 해주면 좋겠다. 구글링으로 Asterisk에서 play가능한 음원을 찾아보자. 16bit/mono/8000Hz PCM파일을 찾았다. 위대한 구글! 다른 규격의 음원도 있으니 스크랩 해두자!! (sample PCM)
그리고, streamFile부분을 아래처럼 변경한다.

return context.streamFile('http://mauvecloud.net/sounds/pcm1608m.wav', '1');

변경하고, 다시 node 실행. 전화를 걸면 기분 나쁜 웃음소리가 들릴 것이다.

4. 정리하자면,,,

  • sngrep을 설치해라. 꼭 설치해라.
  • ding-dong 모듈에서는 variables event만 잘 알아두자.
  • ding-dong 에서 streamFile은 2개의 Arguments만 지원한다.(file_name, escape_digits)
  • streamFile은, Asterisk에서 sounds에 정의된 음원파일, 확장자가 없는 절대경로의 음원파일, http로 바로 download가 가능한 음원파일을 play할 수 있다.
  • streamFile에서 기본적으로 지원하는 음원은 16bit/mono/8000Hz PCM파일이다.
  • AGI도 Dialplan과 동일하게 한번에 한가지 명령어를 수행한다.

5. 다음 시간에는?

  • controlStreamFile, recordFile, databaseGet/Put 등을 알아보자.
  • 아무래도.. AGI를 ding-dong으로 개발하는 사람은 없는 듯? => 있는 것도 같다.
profile
취미로 개발 하고 싶은 개발자

2개의 댓글

comment-user-thumbnail
2021년 3월 2일

어우,, 저도 글을 쓰려고 노력중이라 더더욱 글의 수고를 이해합니다.
ReactNative 앱에서 보이스통화를 하려고 하고, 보이스통화는 voip밖에 안들어봤던 저로써
어디서부터 찾아봐야하나 깝깝햇는데..감사합니다.

1개의 답글