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