{"id":3182,"date":"2014-05-08T21:48:52","date_gmt":"2014-05-08T12:48:52","guid":{"rendered":"http:\/\/pchero21.com\/?p=3182"},"modified":"2014-05-08T21:48:52","modified_gmt":"2014-05-08T12:48:52","slug":"freeswitch-making-freeswitch-python-script","status":"publish","type":"post","link":"http:\/\/pchero21.com\/?p=3182","title":{"rendered":"[Freeswitch] Making freeswitch python script"},"content":{"rendered":"<p><strong>\uc2e4\ud589\ub418\ub294 \uae30\ubcf8 \ud568\uc218<\/strong><\/p>\n<p>Freeswitch \uc5d0\uc11c Python \uc2a4\ud06c\ub9bd\ud2b8\ub97c \ud638\ucd9c\ud560 \ub54c, \ud638\ucd9c\ud558\ub294 \uc8fc\uccb4\uac00 \uc5b4\ub514\ub0d0\uc5d0 \ub530\ub77c \uc790\ub3d9\uc73c\ub85c \uc2e4\ud589\ub418\ub294 Default \ud568\uc218\uac00 \ub2ec\ub77c\uc9c4\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>&#8211; Dialplan \ub0b4\uc5d0\uc11c <strong>&lt;action application=&#8221;python&#8221; data=&#8221;mod_fstest.python_example&#8221;\/&gt;<\/strong> \uc640 \uac19\uc740 \ud615\uc2dd\uc73c\ub85c \ud638\ucd9c\ub418\ub294 \uacbd\uc6b0.<\/p>\n<p>\ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4, handler() \ud568\uc218\uac00 \ud638\ucd9c\ub41c\ub2e4.<\/p>\n<p>handler() \ud568\uc218\uc758 \ubaa8\uc2b5\uc740<\/p>\n<pre class=\"brush:py\"># APPLICATION\n#\n# default name for apps is \"handler\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# session is a session object\n# args is all the args passed after the module name\ndef handler(session, args):\n\n\tconsoleLog('info', 'Answering call from Python.n')\n<\/pre>\n<p>\ucc98\ub7fc \ub418\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>&#8211; fs_cli \ub4f1\uc5d0\uc11c <strong>python<\/strong> \uba85\ub839\uc73c\ub85c \ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8\uc758 \uacbd\uc6b0.<br \/>\n\ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4\uc758 fsapi() \ud568\uc218\uac00 \ud638\ucd9c\ub41c\ub2e4.<\/p>\n<p>fsapi() \ud568\uc218\uc758 \ubaa8\uc2b5\uc740<\/p>\n<pre class=\"brush:py\"># FSAPI CALL FROM CLI, DP HTTP etc\n#\n# default name for python FSAPI is \"fsapi\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# stream is a switch_stream, anything written with stream.write() is returned to the caller\n# env is a switch_event\n# args is all the args passed after the module name\n# session is a session object when called from the dial plan or the string \"na\" when not.\ndef fsapi(session, stream, env, args):\n\n\tstream.write(\"w00t!n\" + env.serialize())<\/pre>\n<p>\ucc98\ub7fc \ub418\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>&#8211; fs_cli \ub4f1\uc5d0\uc11c <strong>pyrun<\/strong> \uba85\ub839\uc73c\ub85c \ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8\uc758 \uacbd\uc6b0,<\/p>\n<p>\ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4\uc758 runtime() \ud568\uc218\uac00 \ud638\ucd9c\ub41c\ub2e4.<\/p>\n<p>runtime() \ud568\uc218\uc758 \ubaa8\uc2b5\uc740<\/p>\n<pre class=\"brush:py\"># RUN A FUNCTION IN A THREAD\n#\n# default name for pyrun is \"runtime\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# args is all the args passed after the module name\ndef runtime(args):\n\n\tprint args + \"n\"<\/pre>\n<p>\ucc98\ub7fc \ub418\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>\uc9c0\uc6d0 API<\/strong><\/p>\n<p>mod_python \ubaa8\ub4c8\uc744 \uc774\uc6a9\ud558\uc5ec \uc2a4\ud06c\ub9bd\ud2b8 \uc791\uc131\uc2dc, freeswitch \uc5d0\uc11c \uc81c\uacf5\ud558\ub294 \uc5ec\ub7ec\uac00\uc9c0 API \ub4e4\uc744 \uc774\uc6a9\ud558\uc5ec \ud3b8\ub9ac\ud558\uac8c \ud504\ub85c\uadf8\ub798\ubc0d\uc744 \ud560 \uc218 \uc788\ub2e4.<br \/>\n\uc9c0\uc6d0\ud558\ub294 API \ub0b4\uc6a9\uc740 mod_lua \uc640 \ub611\uac19\uc740 \ub0b4\uc6a9\uc758 API \ub97c \uc9c0\uc6d0\ud558\uba70 \uc790\uc138\ud55c \uae30\ub2a5 \ubc0f API \uc77c\ub78c\uc740 \uc544\ub798\uc758 \ub9c1\ud06c\uc5d0\uc11c \ud655\uc778\ud560 \uc218 \uc788\ub2e4.<\/p>\n<p>mod_lua API \ubaa9\ub85d: <a title=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_lua\" href=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_lua\" target=\"_blank\">https:\/\/wiki.freeswitch.org\/wiki\/Mod_lua<\/a><\/p>\n<p>&nbsp;<\/p>\n<p><strong>\uc608\uc81c python Script<\/strong><\/p>\n<p>\uc608\uc81c\ub85c \uc0ac\uc6a9\ud55c python script \uc774\ub2e4. \uc6d0\ubcf8\uc740 <a title=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts\" href=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts\" target=\"_blank\">https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts<\/a> \uc5d0\uc11c \uad6c\ud560 \uc218 \uc788\ub2e4.<\/p>\n<pre class=\"brush:py\">import os\nfrom freeswitch import *\n\n# HANGUP HOOK\n#\n# session is a session object\n# what is \"hangup\" or \"transfer\"\n# if you pass an extra arg to setInputCallback then append 'arg' to get that value\n# def hangup_hook(session, what, arg):\ndef hangup_hook(session, what):\n\n\tconsoleLog(\"info\",\"hangup hook for %s!!nn\" % what)\n\treturn\n\n\n# INPUT CALLBACK\n#\n# session is a session object\n# what is \"dtmf\" or \"event\"\n# obj is a dtmf object or an event object depending on the 'what' var.\n# if you pass an extra arg to setInputCallback then append 'arg' to get that value\n# def input_callback(session, what, obj, arg):\ndef input_callback(session, what, obj):\n\n\tif (what == \"dtmf\"):\n\t\tconsoleLog(\"info\", what + \" \" + obj.digit + \"n\")\n\telse:\n\t\tconsoleLog(\"info\", what + \" \" + obj.serialize() + \"n\")\t\t\n\treturn \"pause\"\n\n# APPLICATION\n#\n# default name for apps is \"handler\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# session is a session object\n# args is all the args passed after the module name\ndef handler(session, args):\n\n\tconsoleLog('info', 'Answering call from Python.n')\n\tconsoleLog('info', 'Arguments: %sn' % args)\n\n\tsession.answer()\n\tsession.setHangupHook(hangup_hook)\n\tsession.setInputCallback(input_callback)\n\tsession.execute(\"playback\", session.getVariable(\"hold_music\"))\n\n# FSAPI CALL FROM CLI, DP HTTP etc\n#\n# default name for python FSAPI is \"fsapi\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# stream is a switch_stream, anything written with stream.write() is returned to the caller\n# env is a switch_event\n# args is all the args passed after the module name\n# session is a session object when called from the dial plan or the string \"na\" when not.\ndef fsapi(session, stream, env, args):\n\n\tstream.write(\"w00t!n\" + env.serialize())\n\t\n\n# RUN A FUNCTION IN A THREAD\n#\n# default name for pyrun is \"runtime\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# args is all the args passed after the module name\ndef runtime(args):\n\n\tprint args + \"n\"\n\n# BIND TO AN XML LOOKUP\n#\n# default name for binding to an XML lookup is \"xml_fetch\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# params a switch_event with all the relevant data about what is being searched for in the XML registry.\n#\ndef xml_fetch(params):\n\n\txml = '''\n&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?&gt;\n&lt;document type=\"freeswitch\/xml\"&gt;\n  &lt;section name=\"dialplan\" description=\"RE Dial Plan For FreeSWITCH\"&gt;\n    &lt;context name=\"default\"&gt;\n      &lt;extension name=\"generated\"&gt;\n        &lt;condition&gt;\n         &lt;action application=\"answer\"\/&gt;\n         &lt;action application=\"playback\" data=\"${hold_music}\"\/&gt;\n        &lt;\/condition&gt;\n      &lt;\/extension&gt;\n    &lt;\/context&gt;\n  &lt;\/section&gt;\n&lt;\/document&gt;\n'''\n\n\treturn xml\n<\/pre>\n<p>&nbsp;<\/p>\n<p>\uc608\uc81c\ub85c \uc0ac\uc6a9\ud55c dialplan \uc774\ub2e4. &#8220;5555555&#8221;\ub85c \uc804\ud654\ub97c \uac78\uba74 \uc2a4\ud06c\ub9bd\ud2b8\uac00 \uc0ac\uc6a9\ub41c\ub2e4.<\/p>\n<pre class=\"brush:xml\">&lt;include&gt;\n  &lt;extension name=\"python_test\"&gt;\n    &lt;condition field=\"destination_number\" expression=\"^(5555555)$\"&gt;\n      &lt;!--\n      If you're hosting multiple domains you will want to set the\n      target_domain on these calls so they hit the proper domain after you\n      transfer the caller into the default context. \n      \n      $${domain} is the default domain set from vars.xml but you can set it\n      to any domain you have setup in your user directory.\n\n      --&gt;\n      &lt;action application=\"info\"\/&gt;\n      &lt;action application=\"python\" data=\"mod_fstest.python_example\"\/&gt;\n      &lt;!--&lt;action application=\"set\" data=\"domain_name=$${domain}\"\/&gt;--&gt;\n      &lt;!-- This example maps the DID 5551212 to ring 1000 in the default context --&gt;\n      &lt;!--&lt;action application=\"transfer\" data=\"1000 XML default\"\/&gt;--&gt;\n    &lt;\/condition&gt;\n  &lt;\/extension&gt;\n&lt;\/include&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>\uc791\uc131\ud55c Python \uc2a4\ud06c\ub9bd\ud2b8\ub97c dialplan \uc5d0\uc11c \ud638\ucd9c\ud558\uae30 \uc704\ud574\uc11c\ub294, \ub2f9\uc5f0\ud558\uaca0\uc9c0\ub9cc Dialplan \ub0b4\uc5d0\uc11c \uc5b4\ub5a4 \uc2a4\ud06c\ub9bd\ud2b8\ub97c \ud638\ucd9c\ud560\uc9c0\ub97c \uc9c0\uc815\ud574 \uc8fc\uc5b4\uc57c \ud55c\ub2e4.<\/p>\n<blockquote><p>&lt;action application=&#8221;python&#8221; data=&#8221;foo.bar&#8221;\/&gt;<\/p><\/blockquote>\n<p>\uc704\uc5d0 \uc785\ub825\ud55c <strong>foo.bar<\/strong> \ub294 foo package \uc5d0 \uc788\ub294 bar \ubaa8\ub4c8\uc744 \ud638\ucd9c\ud55c\ub2e4\ub294 \uc124\uc815\uc774\ub2e4. \ub4a4\uc5d0 \ud655\uc7a5\uc790 .py \ub97c \ubd99\uc774\uc9c0 \uc54a\ub3c4\ub85d \uc8fc\uc758\ud558\uc790.<br \/>\n\uc774 \uacbd\uc6b0, \uc0ac\uc6a9\ud558\uac8c \ub418\ub294 \ud568\uc218\ub294 &#8216;handler&#8217; \ud568\uc218\uc774\ub2e4.<\/p>\n<pre class=\"brush:shell\">2014-05-06 17:55:40.838121 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example\n2014-05-06 17:55:40.838121 [DEBUG] mod_python.c:281 Call python script \n2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Answering call from Python.\n2014-05-06 17:55:40.838121 [INFO] switch_cpp.cpp:1293 Arguments:<\/pre>\n<p>handler \ud568\uc218.<\/p>\n<pre class=\"brush:py\"># APPLICATION\n#\n# default name for apps is \"handler\" it can be overridden with &lt;modname&gt;::&lt;function&gt;\n# session is a session object\n# args is all the args passed after the module name\ndef handler(session, args):\n\n\tconsoleLog('info', 'Answering call from Python.n')\n\tconsoleLog('info', 'Arguments: %sn' % args)\n\n\tsession.answer()\n\tsession.setHangupHook(hangup_hook)\n\tsession.setInputCallback(input_callback)\n\tsession.execute(\"playback\", session.getVariable(\"hold_music\"))<\/pre>\n<p>\uc778\uc790 \uac12\uc73c\ub85c session \uacfc args \ub97c \uc785\ub825\ubc1b\ub294\ub2e4.<br \/>\nsession \uc740 python \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 freeswitch interface \uac1d\uccb4\uc774\uba70, args \ub294 \ubaa8\ub4c8 \ud638\ucd9c\uc2dc \ub118\uaca8\uc9c0\ub294 \uc778\uc790\uac12\ub4e4\uc774\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>\ub610\ud55c, fs_cli \uc5d0\uc11c \ubc14\ub85c \uc791\uc131\ud55c python \uc2a4\ud06c\ub9bd\ud2b8\ub97c \ud638\ucd9c\ud560 \uc218 \uc788\ub2e4. \uc774 \uacbd\uc6b0, \uc0ac\uc6a9\ud55c \uba85\ub839\uc5b4\uc5d0 \ub530\ub77c \ud638\ucd9c\ub418\ub294 \ud568\uc218\uac00 \ub2ec\ub77c\uc9c0\ub294\ub370, python \uba85\ub839\uc73c\ub85c \ud638\ucd9c\ud560 \uacbd\uc6b0, \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4, &#8216;fsapi&#8217; \ud568\uc218\uac00 \ubc14\ub85c \ud638\ucd9c\uc774 \ub41c\ub2e4.<\/p>\n<pre class=\"brush:shell\">freeswitch@192.168.200.10@internal&gt; python mod_fstest.python_example\nw00t!\n'Event-Name: API\nCore-UUID: 86d48a48-6f22-475c-89ac-146e6d0217d9\nFreeSWITCH-Hostname: MyDebian\nFreeSWITCH-Switchname: MyDebian\nFreeSWITCH-IPv4: 10.0.2.10\nFreeSWITCH-IPv6: %3A%3A1\nEvent-Date-Local: 2014-05-06%2017%3A43%3A01\nEvent-Date-GMT: Tue,%2006%20May%202014%2015%3A43%3A01%20GMT\nEvent-Date-Timestamp: 1399390981818146\nEvent-Calling-File: switch_loadable_module.c\nEvent-Calling-Function: switch_api_execute\nEvent-Calling-Line-Number: 2406\nEvent-Sequence: 4158\nAPI-Command: python\nAPI-Command-Argument: mod_fstest.python_example\n\n'\n2014-05-06 17:43:01.818146 [NOTICE] mod_python.c:212 Invoking py module: mod_fstest.python_example\n2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:281 Call python script \n2014-05-06 17:43:01.818146 [DEBUG] mod_python.c:284 Finished calling python script<\/pre>\n<p>&nbsp;<\/p>\n<p>\ucc38\uc870 : <a title=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts\" href=\"https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts\" target=\"_blank\">https:\/\/wiki.freeswitch.org\/wiki\/Mod_python#Sample_Python_Scripts<\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc2e4\ud589\ub418\ub294 \uae30\ubcf8 \ud568\uc218 Freeswitch \uc5d0\uc11c Python \uc2a4\ud06c\ub9bd\ud2b8\ub97c \ud638\ucd9c\ud560 \ub54c, \ud638\ucd9c\ud558\ub294 \uc8fc\uccb4\uac00 \uc5b4\ub514\ub0d0\uc5d0 \ub530\ub77c \uc790\ub3d9\uc73c\ub85c \uc2e4\ud589\ub418\ub294 Default \ud568\uc218\uac00 \ub2ec\ub77c\uc9c4\ub2e4. &nbsp; &#8211; Dialplan \ub0b4\uc5d0\uc11c &lt;action application=&#8221;python&#8221; data=&#8221;mod_fstest.python_example&#8221;\/&gt; \uc640 \uac19\uc740 \ud615\uc2dd\uc73c\ub85c \ud638\ucd9c\ub418\ub294 \uacbd\uc6b0. \ud638\ucd9c\ub418\ub294 \uc2a4\ud06c\ub9bd\ud2b8 \ub0b4, handler() \ud568\uc218\uac00 \ud638\ucd9c\ub41c\ub2e4. handler() \ud568\uc218\uc758 \ubaa8\uc2b5\uc740 # &hellip; <a href=\"http:\/\/pchero21.com\/?p=3182\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[15],"tags":[179,313],"_links":{"self":[{"href":"http:\/\/pchero21.com\/index.php?rest_route=\/wp\/v2\/posts\/3182"}],"collection":[{"href":"http:\/\/pchero21.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/pchero21.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/pchero21.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/pchero21.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3182"}],"version-history":[{"count":0,"href":"http:\/\/pchero21.com\/index.php?rest_route=\/wp\/v2\/posts\/3182\/revisions"}],"wp:attachment":[{"href":"http:\/\/pchero21.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/pchero21.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3182"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/pchero21.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}