실행되는 기본 함수
Freeswitch 에서 Python 스크립트를 호출할 때, 호출하는 주체가 어디냐에 따라 자동으로 실행되는 Default 함수가 달라진다.
– Dialplan 내에서 <action application=”python” data=”mod_fstest.python_example”/> 와 같은 형식으로 호출되는 경우.
호출되는 스크립트 내, handler() 함수가 호출된다.
handler() 함수의 모습은
# APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n')
처럼 되어야 한다.
– fs_cli 등에서 python 명령으로 호출되는 스크립트의 경우.
호출되는 스크립트 내의 fsapi() 함수가 호출된다.
fsapi() 함수의 모습은
# FSAPI CALL FROM CLI, DP HTTP etc # # default name for python FSAPI is "fsapi" it can be overridden with <modname>::<function> # stream is a switch_stream, anything written with stream.write() is returned to the caller # env is a switch_event # args is all the args passed after the module name # session is a session object when called from the dial plan or the string "na" when not. def fsapi(session, stream, env, args): stream.write("w00t!n" + env.serialize())
처럼 되어야 한다.
– fs_cli 등에서 pyrun 명령으로 호출되는 스크립트의 경우,
호출되는 스크립트 내의 runtime() 함수가 호출된다.
runtime() 함수의 모습은
# RUN A FUNCTION IN A THREAD # # default name for pyrun is "runtime" it can be overridden with <modname>::<function> # args is all the args passed after the module name def runtime(args): print args + "n"
처럼 되어야 한다.
지원 API
mod_python 모듈을 이용하여 스크립트 작성시, freeswitch 에서 제공하는 여러가지 API 들을 이용하여 편리하게 프로그래밍을 할 수 있다.
지원하는 API 내용은 mod_lua 와 똑같은 내용의 API 를 지원하며 자세한 기능 및 API 일람은 아래의 링크에서 확인할 수 있다.
mod_lua API 목록: https://wiki.freeswitch.org/wiki/Mod_lua
예제 python Script
예제로 사용한 python script 이다. 원본은 https://wiki.freeswitch.org/wiki/Mod_python#Sample_Python_Scripts 에서 구할 수 있다.
import os from freeswitch import * # HANGUP HOOK # # session is a session object # what is "hangup" or "transfer" # if you pass an extra arg to setInputCallback then append 'arg' to get that value # def hangup_hook(session, what, arg): def hangup_hook(session, what): consoleLog("info","hangup hook for %s!!nn" % what) return # INPUT CALLBACK # # session is a session object # what is "dtmf" or "event" # obj is a dtmf object or an event object depending on the 'what' var. # if you pass an extra arg to setInputCallback then append 'arg' to get that value # def input_callback(session, what, obj, arg): def input_callback(session, what, obj): if (what == "dtmf"): consoleLog("info", what + " " + obj.digit + "n") else: consoleLog("info", what + " " + obj.serialize() + "n") return "pause" # APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n') consoleLog('info', 'Arguments: %sn' % args) session.answer() session.setHangupHook(hangup_hook) session.setInputCallback(input_callback) session.execute("playback", session.getVariable("hold_music")) # FSAPI CALL FROM CLI, DP HTTP etc # # default name for python FSAPI is "fsapi" it can be overridden with <modname>::<function> # stream is a switch_stream, anything written with stream.write() is returned to the caller # env is a switch_event # args is all the args passed after the module name # session is a session object when called from the dial plan or the string "na" when not. def fsapi(session, stream, env, args): stream.write("w00t!n" + env.serialize()) # RUN A FUNCTION IN A THREAD # # default name for pyrun is "runtime" it can be overridden with <modname>::<function> # args is all the args passed after the module name def runtime(args): print args + "n" # BIND TO AN XML LOOKUP # # default name for binding to an XML lookup is "xml_fetch" it can be overridden with <modname>::<function> # params a switch_event with all the relevant data about what is being searched for in the XML registry. # def xml_fetch(params): xml = ''' <?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="freeswitch/xml"> <section name="dialplan" description="RE Dial Plan For FreeSWITCH"> <context name="default"> <extension name="generated"> <condition> <action application="answer"/> <action application="playback" data="${hold_music}"/> </condition> </extension> </context> </section> </document> ''' return xml
예제로 사용한 dialplan 이다. “5555555”로 전화를 걸면 스크립트가 사용된다.
<include> <extension name="python_test"> <condition field="destination_number" expression="^(5555555)$"> <!-- If you're hosting multiple domains you will want to set the target_domain on these calls so they hit the proper domain after you transfer the caller into the default context. $${domain} is the default domain set from vars.xml but you can set it to any domain you have setup in your user directory. --> <action application="info"/> <action application="python" data="mod_fstest.python_example"/> <!--<action application="set" data="domain_name=$${domain}"/>--> <!-- This example maps the DID 5551212 to ring 1000 in the default context --> <!--<action application="transfer" data="1000 XML default"/>--> </condition> </extension> </include>
작성한 Python 스크립트를 dialplan 에서 호출하기 위해서는, 당연하겠지만 Dialplan 내에서 어떤 스크립트를 호출할지를 지정해 주어야 한다.
<action application=”python” data=”foo.bar”/>
위에 입력한 foo.bar 는 foo package 에 있는 bar 모듈을 호출한다는 설정이다. 뒤에 확장자 .py 를 붙이지 않도록 주의하자.
이 경우, 사용하게 되는 함수는 ‘handler’ 함수이다.
2014-05-06 17:55:40.838121 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example 2014-05-06 17:55:40.838121 [DEBUG] mod_python.c:281 Call python script 2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Answering call from Python. 2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Arguments:
handler 함수.
# APPLICATION # # default name for apps is "handler" it can be overridden with <modname>::<function> # session is a session object # args is all the args passed after the module name def handler(session, args): consoleLog('info', 'Answering call from Python.n') consoleLog('info', 'Arguments: %sn' % args) session.answer() session.setHangupHook(hangup_hook) session.setInputCallback(input_callback) session.execute("playback", session.getVariable("hold_music"))
인자 값으로 session 과 args 를 입력받는다.
session 은 python 스크립트 내에서 사용되는 freeswitch interface 객체이며, args 는 모듈 호출시 넘겨지는 인자값들이다.
또한, fs_cli 에서 바로 작성한 python 스크립트를 호출할 수 있다. 이 경우, 사용한 명령어에 따라 호출되는 함수가 달라지는데, python 명령으로 호출할 경우, 스크립트 내, ‘fsapi’ 함수가 바로 호출이 된다.
freeswitch@192.168.200.10@internal> python mod_fstest.python_example w00t! 'Event-Name: API Core-UUID: 86d48a48-6f22-475c-89ac-146e6d0217d9 FreeSWITCH-Hostname: MyDebian FreeSWITCH-Switchname: MyDebian FreeSWITCH-IPv4: 10.0.2.10 FreeSWITCH-IPv6: %3A%3A1 Event-Date-Local: 2014-05-06%2017%3A43%3A01 Event-Date-GMT: Tue,%2006%20May%202014%2015%3A43%3A01%20GMT Event-Date-Timestamp: 1399390981818146 Event-Calling-File: switch_loadable_module.c Event-Calling-Function: switch_api_execute Event-Calling-Line-Number: 2406 Event-Sequence: 4158 API-Command: python API-Command-Argument: mod_fstest.python_example ' 2014-05-06 17:43:01.818146 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example 2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:281 Call python script 2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:284 Finished calling python script
참조 : https://wiki.freeswitch.org/wiki/Mod_python#Sample_Python_Scripts
Tags: freeswitch, python