YAYPM
(→Waiting for messages) |
(→Watching messages) |
||
(7 intermediate revisions by one user not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | Yet Another Yate Python Module. It allows to write YATE modules in PYTHON. PYTHON modules comunicate with YATE core via external protocol or run in python interperter embedded in pymodule. | + | YAYPM - Yet Another Yate Python Module. It allows to write YATE modules in PYTHON. PYTHON modules comunicate with YATE core via external protocol or run in python interperter embedded in pymodule. |
===Base concept=== | ===Base concept=== | ||
Line 14: | Line 13: | ||
* [[YAYPM Installation on windows]] | * [[YAYPM Installation on windows]] | ||
+ | |||
+ | ===How to run it in practice=== | ||
+ | |||
+ | YAYPM uses Twisted. Twisted is quite large library and it loads quite slow (1-2s on PIII/700), which makes using YAYPM for IVR, via channeled extmodule problematic. More efficient way is to run it as a channelless script and use DumbChannel (see below). This way is also more memory efficient as all calls are handled in one process. | ||
+ | |||
+ | ====Extmodule==== | ||
+ | |||
+ | extmodule.conf via TCP | ||
+ | |||
+ | [listener A] | ||
+ | type=tcp | ||
+ | addr=0.0.0.0 | ||
+ | port=5039 | ||
+ | role=global | ||
+ | |||
+ | ====TCP Connector==== | ||
+ | |||
+ | f = TCPDispatcherFactory(start) | ||
+ | reactor.connectTCP("localhost", 5039, f) | ||
+ | reactor.run() | ||
+ | |||
+ | ====Pipes Connector==== | ||
+ | |||
+ | It is also possible to use extmodule pipe transport. In that case StandardIO transport must be used: | ||
+ | |||
+ | p = TCPDispatcher(start) | ||
+ | stdio.StandardIO(p) | ||
+ | reactor.run() | ||
+ | |||
+ | Consult [[External Module|extmodule]] documentation for more information. | ||
===Connecting to YATE=== | ===Connecting to YATE=== | ||
Line 115: | Line 144: | ||
: when in call, usually, one does not want to wait for an event infinitely. Until parameter allow to specify another deferred which when fired will trigger errback and stop the wait. | : when in call, usually, one does not want to wait for an event infinitely. Until parameter allow to specify another deferred which when fired will trigger errback and stop the wait. | ||
− | + | ||
+ | '''See also''' | ||
* [[YAYPM:Simple IVR]] | * [[YAYPM:Simple IVR]] | ||
Line 121: | Line 151: | ||
* [[YAYPM:Bridge and then unbridge]] | * [[YAYPM:Bridge and then unbridge]] | ||
* [[YAYPM:Bridge and then redirect after a hangup]] | * [[YAYPM:Bridge and then redirect after a hangup]] | ||
+ | |||
+ | [[Category:Extmodule]] [[Category:YAYPM]] [[Category:Programmers]] [[Category:Scripting]] [[Category:IVR]] |
Latest revision as of 13:53, 4 November 2013
YAYPM - Yet Another Yate Python Module. It allows to write YATE modules in PYTHON. PYTHON modules comunicate with YATE core via external protocol or run in python interperter embedded in pymodule.
Contents |
[edit] Base concept
YAYPM base concept - deferred - comes from Twisted framework. Twisted project is very well documented, so look there for in-depth explanations of deferreds and its asynchronous programming model, as it won't be repeated here.
For the needs of this tutorial it is enough to say that, deferred is a promise to carry a computation in case of occurence of a specified event. What will be computed is defined by adding success and failure callbacks.
YAYPM allows to create deferreds for specified YATE messages.
[edit] YAYPM Installation
[edit] How to run it in practice
YAYPM uses Twisted. Twisted is quite large library and it loads quite slow (1-2s on PIII/700), which makes using YAYPM for IVR, via channeled extmodule problematic. More efficient way is to run it as a channelless script and use DumbChannel (see below). This way is also more memory efficient as all calls are handled in one process.
[edit] Extmodule
extmodule.conf via TCP
[listener A] type=tcp addr=0.0.0.0 port=5039 role=global
[edit] TCP Connector
f = TCPDispatcherFactory(start) reactor.connectTCP("localhost", 5039, f) reactor.run()
[edit] Pipes Connector
It is also possible to use extmodule pipe transport. In that case StandardIO transport must be used:
p = TCPDispatcher(start) stdio.StandardIO(p) reactor.run()
Consult extmodule documentation for more information.
[edit] Connecting to YATE
There are two ways: via external protocol and embedded python interpreter:
if __name__ == "__main__": f = TCPDispatcherFactory(start) reactor.connectTCP("localhost", 5039, f) installSignalHandlers = 1 elif __name__ == "__embedded_yaypm_module__": yaypm.embededStart(start) installSignalHandlers = 0 reactor.run(installSignalHandlers)
[edit] Waiting for messages
In YAYPM program connection with YATE is represented by instance of class Dispatcher. Its method onmsg creates deferreds whose callbacks will be fired when a message comes from YATE:
def onmsg(self, name, guard = lambda _: True, until = None, autoreturn = False):
Where:
- name
- name of YATE message to fire on
- guard
- one argument boolean function, that defines additional conditions that message must fulfill to trigger the deffered
- until
- when in call, usually, one does not want to wait for an event infinitely. Until parameter allow to specify another deferred which when fired will trigger errback and stop the wait.
- autoreturn
- kind of syntactic sugar, when set to true, before firing callbacks message will be returned automaticly
So, for example:
... d = yate.onmsg("call.route", lambda m: m["called"] == "ivr") ...
creates deferred that will fire its callback on message "call.route" with "called" attribute set to "ivr", and:
... end = yate.onmsg("chan.hangup", lambda m : m["id"] == callid, autoreturn = True) d = yate.onmsg("call.answered", lambda m : m["targetid"] == callid, until = end) ...
wait for call.answered with "targetid" set to "callid" until call termination i.e.: arrival of chan.hangup with "id" set to callid.
[edit] Sending messages
Dispatcher's method msg creates messages:
... notify = yate.msg("chan.notify", {"targetid": notify}) ...
There are two ways to send message asynchronously and synchronously. The latter one returns a result:
... notify = yate.msg("chan.notify", {"targetid": notify}) #asynchronously notify.enqueue() #or synchronously d = notify.dispatch() # d is a deferred that will fire when message is processed by yate. Its callback will be given information whether is was processed successfully. ...
[edit] Answering messages
To return a message use Message ret method. It is possible to pass return value:
... route.ret(True, "dumb/") ...
There is a subtle difference between Message classes created by TCPDispatcher and EmbeddedDispatcher. Messages created by TCPDispatcher are normal python objects. Messages created by EmbeddedDispatcher are just proxies to true YATE messages. So they may be accessed only as long as underlying YATE message exists. That means that some programms that works well with TCPDispatcher might not work with EmbeddedDispatcher:
... #That is possible with TCPDispatcher but will raise an Exception with EmbeddedDispatcher: route.ret(True, "dumb/") print route["called"] ...
[edit] Watching messages
Difference in onwatch and onmsg is that deferred created with onwatch fires after message is processed:
def onwatch(self, name, guard = lambda _: True, until = None):
Where:
- name
- name of YATE message to fire on
- guard
- one argument boolean function, that defines additional conditions that message must fulfill to trigger the deffered
- until
- when in call, usually, one does not want to wait for an event infinitely. Until parameter allow to specify another deferred which when fired will trigger errback and stop the wait.
See also