실행되는 기본 함수
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