YAYPM

From Yate Documentation
Revision as of 15:16, 19 November 2012 by Dana (Talk | contribs)

Jump to: navigation, search

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

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.

YAYPM Installation

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 extmodule documentation for more information.

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)

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.

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.
...

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"]
...

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.

Examples

Personal tools
Namespaces

Variants
Actions
Preface
Configuration
Administrators
Developers