YAYPM:Bridge and then redirect after a hangup
From Yate Documentation
This script is given as an example, don't forget to change some information such as yate's extmodule binding ip address and port.
This script will :
- 1 - make a phone call to 'jmfoucher'
- 2 - play a sound to 'jmfoucher'
- 3 - wait for DTMF "1"
- 4 - after "1" is pressed, 'toto' will be called
- 5 - when toto answers, toto and jmfoucher will be bridged
- 6 - if one of them hangs up, then the other one will be transferred to a new channel
- 7 - a sound will be attached to this new channel
- 8 - once the sound is finished, the new channel will be hangup
#!/usr/bin/python
from twisted.internet import reactor, defer
from yaypm import TCPDispatcherFactory, AbandonedException
from yaypm.flow import go, getResult
from yaypm.utils import ConsoleFormatter
import logging, yaypm
logger = logging.getLogger("test3")
class myTest(object):
def __init__(self, client):
logger.debug(">>> myTest.__init__()")
self.client = client
self.run()
def run(self):
logger.debug(">>> myTest.run()")
go(self.test())
def WatchDisconnected(self, id):
logger.debug(">>> myTest.WatchDisconnected()")
try:
#while True:
# logger.debug("dans True du WatchDisconnected")
end = self.client.onmsg("chan.hangup",
lambda m: m["id"] == id, autoreturn = True)
yield self.client.onmsg("chan.disconnected",
lambda m : m["id"] == id,
until=end,
autoreturn=False
)
disconnected = getResult()
disconnected.ret("true")
myid = disconnected['id']
execute = self.client.msg("chan.masquerade",
{"message": "call.execute",
"id": myid,
"callto": "dumb/",
}
)
yield execute.dispatch()
if not getResult():
logger.warn("La redirection de myid)
else:
logger.debug("La redirection marche comme sur des roulettes :)")
peerid = execute["peerid"]
self.client.msg("chan.masquerade",
{"message" : "chan.attach",
"id": peerid,
"source": "wave/play/../../sounds/wp_star_seller_ask.wav",
"notify": peerid,
}
).enqueue()
go(self.WatchNotify(peerid))
except AbandonedException, e:
logger.debug("Call id)
def WatchNotify(self, id):
logger.debug(">>> myTest.WatchNotify()")
try:
#while True:
# logger.debug("dans True du WatchNotify")
end = self.client.onmsg("chan.hangup",
lambda m: m["id"] == id, autoreturn = True)
yield self.client.onmsg("chan.notify",
lambda m : m['id'] == id,
until=end,
)
notify = getResult()
if notify:
notify.ret(True)
if notify['reason'] == 'eof':
yield self.client.msg("call.drop", {"id": id}).dispatch()
getResult()
except AbandonedException, e:
logger.debug("Call id)
def test(self):
logger.debug(">>> myTest.test()")
firsttime = True
yield self.client.installMsgHandler("call.route", prio = 50)
getResult()
yield self.client.installWatchHandler("call.answered")
getResult()
#yield self.client.installWatchHandler("chan.disconnected")
#getResult()
yield self.client.installWatchHandler("chan.hangup")
getResult()
execute = self.client.msg("call.execute",
{"callto": "dumb/",
"caller": "appelant",
"target": "jmfoucher",
})
yield execute.dispatch()
if not getResult():
logger.warn("can't create monitor connection on jmfoucher")
monitor = None
else:
logger.debug("can monitor jmfoucher")
try:
end = self.client.onwatch(
"chan.hangup",
lambda m, callid = execute["id"] : m["id"] == callid)
yield self.client.onwatch(
"call.answered",
lambda m : m["id"] == execute["targetid"],
until = end)
getResult()
logger.debug("Monitor connection answered.")
dumbid = execute["id"]
monitorid = execute["targetid"]
callid = execute["id"]
logger.debug("callid = s" % (callid, monitorid))
self.client.msg("chan.masquerade",
{"message" : "chan.attach",
"id": callid,
"source": "wave/play/../../sounds/wp_star_seller_ask.wav"}).enqueue()
logger.debug("le son est parti")
while True:
logger.debug("dans le while True")
yield self.client.onmsg(
"chan.dtmf",
lambda m : m["id"] == monitorid,
end)
dtmf = getResult()
logger.debug("Dtmf dtmf["text"])
dtmf.ret(True)
if dtmf["text"] == "1":
if firsttime:
firsttime = False
logger.warn("on attache le son sur callid)
self.client.msg("chan.masquerade",
{"message" : "chan.attach",
"id": callid,
"source": "wave/play/../../sounds/wp_star_seller_wait.wav"}).enqueue()
execute = self.client.msg("call.execute",
{"callto": "dumb/",
"caller": "jmfoucher",
"target": 'toto'})
yield execute.dispatch()
if not getResult():
logger.debug("FAILURE")
else:
logger.debug("SUCCESS")
callid2 = execute["id"]
targetid2 = execute["targetid"]
logger.debug("callid=s" % (callid, monitorid))
logger.debug("callid2=s" % (callid2, targetid2))
end = self.client.onmsg("chan.hangup",
lambda m, callid = targetid2 : m["id"] == callid, autoreturn = True)
yield self.client.onwatch("call.answered",
lambda m : m["targetid"] == callid2, until = end)
answered = getResult()
logger.debug("answered= answered)
logger.debug("on appelle self.conf")
logger.debug("callid = s" % (callid, callid2))
connect = self.client.msg(
"chan.connect",
{"id": monitorid,
"targetid": targetid2})
yield connect.dispatch()
if getResult():
logger.debug("connect SUCCESS")
else:
logger.debug("connect FAILURE")
go(self.WatchDisconnected(monitorid))
go(self.WatchDisconnected(targetid2))
#yield yate.msg("call.drop", {"id": targetid}).dispatch()
#getResult()
except AbandonedException, e:
logger.debug("Call callid)
def start(host, port):
logger.debug("dans start")
local_addr = remote_addr = host
local_port = remote_port = port
#go(route(yate))
def start_client(client_yate):
logger.debug("client started");
myTest(client_yate)
installSignalHandlers = 1
client_factory = TCPDispatcherFactory(start_client)
reactor.connectTCP(local_addr, local_port, client_factory)
if __name__ == _main_:
hdlr = logging.StreamHandler()
formatter = ConsoleFormatter('%(name)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
yaypm.logger.addHandler(hdlr)
yaypm.logger.setLevel(logging.DEBUG)
#yaypm.flow.logger_flow.setLevel(logging.DEBUG)
yaypm.logger_messages.setLevel(logging.DEBUG)
yaypm.logger_messages.setLevel(logging.INFO)
logger.setLevel(logging.DEBUG)
logger.addHandler(hdlr)
#f = TCPDispatcherFactory(start)
#reactor.connectTCP("192.168.4.87", 5039, f)
start("192.168.4.87", 5039)
reactor.run()
See also