def connect_ari(): try: if not odoo: raise Exception('Odoo not connected.') # Connect only to one server for now :-P url = 'http://{}:{}'.format(HTTP_LISTEN_ADDRESS, HTTP_PORT) logging.debug('ARI connecting to {} as {}:{}'.format( url, HTTP_LOGIN, HTTP_PASSWORD)) ari_client = ari.connect(url, HTTP_LOGIN, HTTP_PASSWORD) if not ari_client: logging.error('ARI client not connected.') return False else: logging.info('Connected to ARI.') return ari_client except HTTPError as e: logging.error('Cannot connect to Asterisk WebSocket: {}'.format( e.message)) except ConnectionError: logging.error( 'Max retries exceeded connecting to Asterisk WebSocket. Try again.' ) except ReadTimeout: logging.error( 'Read timeout connecting to Asterisk WebSocket. Try again.') except socket.error as e: logging.error('Socket error. Try again.')
def setUp(self): """Setup httpretty; create ARI client. """ super(AriTestCase, self).setUp() httpretty.enable() self.serve_api() self.uut = ari.connect('http://ari.py/', 'test', 'test')
def hangup_call(self): server = self.env['asterisk.server.settings'].browse([1]) # Get rid of unicode as ari-py does not handle it. ari_user = str(server.ari_user) ari_pass = str(server.ari_pass) ari_url = str('http://' + server.ip_addr + ':' + server.http_port) try: ari_client = ari.connect(ari_url, ari_user, ari_pass) except ConnectionError: raise ValidationError( 'Cannot connect to Asterisk. Check Settings.') try: ari_chan = ari_client.channels.get(channelId=self.channel_id) ari_chan.hangup() _logger.debug('HANGUP CHANNEL: %s' % self.channel_id) except HTTPError: _logger.warn('CHANNEL NOT FOUND, REMOVING' ' FROM ACTIVE: %s' % self.channel_id) finally: self.session['cancel'] += 1 self.unlink()
def connect_ari(conf): try: url = 'http://{}:{}'.format(conf['host'], conf['http_port']) _logger.debug('ARI connecting to {}'.format(url)) ari_client = ari.connect(url, conf['ari_username'], conf['ari_password']) if not ari_client: _logger.error('ARI client not connected.') return False else: _logger.info('Connected to ARI.') return ari_client except HTTPError as e: _logger.error('Cannot connect to Asterisk WebSocket: {}'.format( e.message)) except ConnectionError: _logger.error( 'Max retries exceeded connecting to Asterisk WebSocket. Try again.' ) except ReadTimeout: _logger.error( 'Read timeout connecting to Asterisk WebSocket. Try again.') except socket.error as e: _logger.error('Socket error. Try again.')
def hangup_call(self): server = self.env['asterisk.server.settings'].browse([1]) # Get rid of unicode as ari-py does not handle it. ari_user = str(server.ari_user) ari_pass = str(server.ari_pass) ari_url = str('http://' + server.ip_addr + ':' + server.http_port) try: ari_client = ari.connect(ari_url, ari_user, ari_pass) except ConnectionError: raise ValidationError( 'Cannot connect to Asterisk. Check Settings.') try: ari_chan = ari_client.channels.get(channelId=self.channel_id) ari_chan.hangup() _logger.debug('HANGUP CHANNEL: %s' % self.channel_id) except HTTPError: _logger.warn( 'CHANNEL NOT FOUND, REMOVING' ' FROM ACTIVE: %s' % self.channel_id) finally: self.session['cancel'] += 1 self.unlink()
def connect_ari(conf): try: ari_client = ari.connect( str(conf['barrier_pbx_ari_url']), str(conf['barrier_pbx_ari_user']), str(conf['barrier_pbx_ari_password']), ) logger.info('Connected to ARI at {}.'.format( conf['barrier_pbx_ari_url'])) return ari_client except HTTPError as e: if e.response.status_code == 503: logger.error('Cannot connect to Asterisk WebSocket. Try again.') except ConnectionError: logger.error( 'Max retries exceeded connecting to Asterisk WebSocket. Try again.' ) except ReadTimeout: logger.error( 'Read timeout connecting to Asterisk WebSocket. Try again.') except socket.error as e: logger.error('Socket error. Try again.')
def aster_connect(chat_id): aster = aster_dict[chat_id] try: client_ast = ari.connect('http://' + str(aster.ip) + ':' + str(aster.port) + '/', str(aster.user), str(aster.pas)) except: bot.send_message(chat_id, "Ошибка соединения") else: bot.send_message(chat_id, "Соединение установлено")
def __init__(self, stasis_control_id): self.client = ari.connect( base_url=ARI_URL, username=ARI_USERNAME, password=ARI_PASSWORD, ) self.bridge_id = str(uuid.uuid4()) self.stt_session_label = stasis_control_id self.dialed_extension = None self.bridge = None signal.signal(signal.SIGTERM, self.apply_bridge_destructor)
def connect(self): print('iniciando conexion') try: return ari.connect(self.base_url, self.username, self.password) print('conectando') logging.info('Connecting ari service successful') except Exception as error: print('error') print(error) logging.error('Error on connect ari service::' + repr(error)) sys.exit()
def main(): logging.debug('Starting %s...', sys.argv[0]) client = ari.connect( base_url=ARI_URL, username=ARI_USERNAME, password=ARI_PASSWORD, ) with application_bridge(client) as bridge: client.on_channel_event('StasisStart', partial(on_stasis_start, bridge=bridge)) client.run(apps=[APPLICATION])
def run(): """run the asterisk application. """ global client while not stopped: try: # if the connection is ever lost, we have to try again and again! client = ari.connect('http://localhost:8088', 'telewall', 'telewall') client.on_channel_event('StasisStart', stasis_start_cb) client.run(apps=APP_NAME) except SystemExit: break except: LOG.exception('problem with ari client') time.sleep(5) # wait 5 sec until retry
def _new_ari_client(self, ari_config, connection_tries, connection_delay): for _ in range(connection_tries): try: return ari.connect(**ari_config) except requests.ConnectionError: logger.info('No ARI server found, retrying in %s seconds...', connection_delay) time.sleep(connection_delay) continue except requests.HTTPError as e: if asterisk_is_loading(e): logger.info('ARI is not ready yet, retrying in %s seconds...', connection_delay) time.sleep(connection_delay) continue else: raise raise ARIUnreachable(ari_config)
def obtain_ari_config(self): """ function to get the configuration of ARI from the config file """ try: self.logger.debug('Inside obtain_ari_config() function') self.ari_host = self.config.get('ari-config', 'ARI_IP') self.ari_port = self.config.get('ari-config', 'ARI_PORT') self.ari_username = self.config.get('ari-config', 'ARI_USERNAME') self.ari_password = self.config.get('ari-config', 'ARI_PASSWORD') self.statis_app_name = self.config.get('ari-config', 'STATIS_APP_NAME') self.client = ari.connect('{0}:{1}/'.format(self.ari_host,self.ari_port)\ ,self.ari_username,self.ari_password) except Exception as e: self.logger.exception("Error while obtaining ARI configuration {}".\ format(e.message))
def connect_ari(): while True: try: global ari_client ari_client = ari.connect( conf['pbx_ari_url'], conf['pbx_ari_user'], conf['pbx_ari_password'], ) logger.info('Connected to ARI.') ari_client.on_channel_event('StasisStart', on_start) ari_client.run(apps='barrier') except WebSocketConnectionClosedException as e: ari_client = None logger.error('WebSocket connection is closed. Exit.') except HTTPError as e: ari_client = None if e.response.status_code == 503: logger.error( 'Cannot connect to Asterisk WebSocket. Trying again.') except ConnectionError: ari_client = None logger.error( 'Max retries exceeded connecting to Asterisk WebSocket. Trying again.' ) except ReadTimeout: ari_client = None logger.error( 'Read timeout connecting to Asterisk WebSocket. Trying again.') except socket.error as e: ari_client = None logger.error('Socket error. Trying again.') except ValueError: # ari_client.run(apps='barrier'): No JSON object could be decoded ari_client = None logger.error('ValueError on connect_ari. Restarting.') # Sleep on errors and reconnect gevent.sleep(ARI_CONNECT_TIMEOUT)
def originate_call(contact): # Generate channel ids chan_id = uuid.uuid1() channelId = '%s-1' % chan_id otherChannelId = '%s-2' % chan_id # ARI originate client = ari.connect('http://*****:*****@dialer' % contact.phone, app='odoo-dialer-%s' % self.id, channelId=channelId, otherChannelId=otherChannelId) # +1 current call channel = self.env['asterisk.dialer.channel'].create({ 'dialer': self.id, 'channel_id': channelId, 'other_channel_id': otherChannelId, 'phone': contact.phone, 'name': contact.name}) self.env.cr.commit()
#!/usr/bin/env python """Short example of how to use bridge objects. This example will create a holding bridge (if one doesn't already exist). Any channels that enter Stasis is placed into the bridge. Whenever a channel enters the bridge, a tone is played to the bridge. """ # # Copyright (c) 2013, Digium, Inc. # from __future__ import print_function import ari client = ari.connect('http://localhost:8088/', 'hey', 'peekaboo') # # Find (or create) a holding bridge. # bridges = [ b for b in client.bridges.list() if b.json['bridge_type'] == 'holding' ] if bridges: bridge = bridges[0] print("Using bridge %s" % bridge.id) else: bridge = client.bridges.create(type='holding') print("Created bridge %s" % bridge.id)
def run(self): """Main thread loop. Condition to terminate: 1) All done. Also terminate Stasis app. 2) Stasis app not ready (when dialer type is stasis) 3) ARI connection error. Also terminate Stasis app. 4) Pause / cancel requested. Also terminate Stasis app. """ self.stasis_app_error.clear() with api.Environment.manage(): try: # Connect to ARI before starting thread. self.ari_client = ari.connect(self.ari_url, self.ari_user, self.ari_pass) while True: try: # Paranoid but sometimes it does not see changes! self.dialer.invalidate_cache() self.session.invalidate_cache() self.env.invalidate_all() # Reset flag on every round self.go_next_call.clear() # Check for cancel request or stasis app error if (self.session.cancel_request or ( self.dialer.dialer_type == 'stasis' and self.stasis_app_error.is_set())): _logger.debug('DIALER: CANCEL / ERROR REQUEST') self.cancel_calls() if self.dialer.dialer_type == 'stasis': self.ari_user_event('exit_request') self.session.state = 'cancelled' self.session.cancel_request = False self.dialer.active_session = None return # Check for pause request elif self.session.pause_request: _logger.debug('DIALER: PAUSE REQUEST') if self.dialer.dialer_type == 'stasis': self.wait_for_last_call() self.ari_user_event('exit_request') self.session.state = 'paused' self.session.pause_request = False return # Check if we can add more calls self.env.cr.execute("""SELECT cdr.id AS cdr_id, cdr.phone AS phone, COALESCE(cdr.name, '') AS name, peer.id AS peer_id, peer.name AS peer_name, route.pattern AS pattern FROM asterisk_dialer_peer peer, asterisk_dialer_route route, asterisk_dialer_cdr cdr WHERE cdr.status = 'queue' AND route.dialer = %s AND cdr.session = %s AND peer.simult > (SELECT COUNT(*) FROM asterisk_dialer_channel chan WHERE peer = peer.id) AND peer.id = route.peer AND cdr.phone LIKE CONCAT(route.pattern,'%%') ORDER BY cdr.id, route.sequence LIMIT 1 """ % (self.dialer.id, self.session.id) ) cdr = self.env.cr.dictfetchall() if cdr: _logger.debug('CDR FOR CALL: %s' % cdr[0]) self.originate_call(cdr[0]) elif self.session.cdr_queue_count == 0: # All done raise StopIteration else: _logger.debug('NO CHANNELS AVAILABLE, SLEEPING.') # Sleep here or be interrupted by hangup self.go_next_call.wait(DIALER_RUN_SLEEP) except StopIteration: _logger.debug('CDR StopIteration.') if self.dialer.dialer_type == 'stasis': self.wait_for_last_call() self.ari_user_event('exit_request') self.session.state = 'done' self.dialer.active_session = None return except (ConnectionError, HTTPError), e: # ARI Error self.session.state = 'error' self.dialer.message_post('ARI ConnectionError: %s' % e.message) _logger.debug(format_exception()) finally:
def setUp(self): super(ClientTest, self).setUp() self.uut = ari.connect('http://ari.py/', 'test', 'test')
#!/usr/bin/env python """Short example of how to use bridge objects. This example will create a holding bridge (if one doesn't already exist). Any channels that enter Stasis is placed into the bridge. Whenever a channel enters the bridge, a tone is played to the bridge. """ # # Copyright (c) 2013, Digium, Inc. # import ari client = ari.connect("http://localhost:8088/", "hey", "peekaboo") # # Find (or create) a holding bridge. # bridges = [b for b in client.bridges.list() if b.json["bridge_type"] == "holding"] if bridges: bridge = bridges[0] print "Using bridge %s" % bridge.id else: bridge = client.bridges.create(type="holding") print "Created bridge %s" % bridge.id def on_enter(bridge, ev): """Callback for bridge enter events.
"""ARI resources may be closed, if an application only needs them temporarily. """ # # Copyright (c) 2013, Digium, Inc. # import ari import logging import sys import thread logging.basicConfig() client = ari.connect('http://localhost:8088/', 'hey', 'peekaboo') # noinspection PyUnusedLocal def on_start(channel, event): """Callback for StasisStart events. On new channels, register the on_dtmf callback, answer the channel and play "Hello, world" :param channel: Channel DTMF was received from. :param event: Event. """ on_dtmf_handle = None def on_dtmf(channel, event):
#!/usr/bin/env python # -*- coding: utf-8 -*- # #Принимаем звонок, играем гудки 8 секунд, пототм делаем hangup # import ari import logging import threading import uuid logging.basicConfig(level=logging.ERROR) client = ari.connect('http://10.248.52.139:8088', 'mell', '123456') channel_timers = {} def stasis_end_cb(channel, ev): """Handler for StasisEnd event""" print "Channel %s just left our application" % channel.json.get('name') timer = channel_timers.get(channel.id) if timer: timer.cancel() del channel_timers[channel.id] def stasis_start_cb(channel_obj, ev): """Handler for StasisStart event""" def answer_channel(channel, playback): """Callback that will actually answer the channel"""
def run_stasis_app(): def stasis_start(channel, ev): pass def call_not_connected(): pass def application_replaced(app): pass def user_event(channel, ev): if ev['eventname'] == 'go_next_call': print 'PUSHING FOR NEXT CALL' go_next_call.set() elif ev['eventname'] == 'exit_request': client.close() def hangup_request(channel, ev): # Update current calls dialer_channel = self.env['asterisk.dialer.channel'].search( [('channel_id', '=', channel.json.get('id'))]) if dialer_channel: dialer_channel.unlink() self.env.cr.commit() # Update cdr cdr = self.env['asterisk.dialer.cdr'].search([('channel_id','=','%s' % channel.json.get('id'))]) if cdr: cdr.write({'status': 'ANSWER', 'end_time': datetime.datetime.now()}) self.env.cr.commit() if last_call.is_set(): # This is the last call, exit. print 'WOW, LAST CALL. CLOSING.' client.close() # Awake to go next call go_next_call.set() new_cr = sql_db.db_connect(self.env.cr.dbname).cursor() uid, context = self.env.uid, self.env.context with api.Environment.manage(): self.env = api.Environment(new_cr, uid, context) try: client = ari.connect('http://localhost:8088', 'dialer', 'test') client.on_channel_event('StasisStart', stasis_start) client.on_event('ApplicationReplaced', application_replaced) client.on_channel_event('ChannelUserevent', user_event) client.on_channel_event('ChannelHangupRequest', hangup_request) stasis_app_ready.set() client.run(apps='odoo-dialer-%s' % self.id) except Exception, e: # on client.close() if e.args[0] == 104: pass else: print 'Exception', e try: client.close() except: pass # Terminate thread run and let run dialer know about it. stasis_eneded.set() return finally:
def connect(host, username, password): return ari.connect(host, username, password)
def setUp(self): super().setUp() self.ari = ari.connect(**self.ari_config()) self.reset_ari()
def setUp(self): super().setUp() until.return_(self.ari_is_up, timeout=5) self.ari = ari.connect(**self.ari_config()) self.reset_ari()
def ari_is_up(self): return ari.connect(**self.ari_config())
#!/usr/bin/env python import ari import logging logging.basicConfig(level=logging.ERROR) client = ari.connect("http://localhost:8088", "asterisk", "asterisk") # find or create a holding bridge bridges = [candidate for candidate in client.bridges.list() if candidate.json["bridge_type"] == "holding"] if bridges: bridge = bridges[0] print "Using bridge %s" % bridge.id else: bridge = client.bridges.create(type="holding") print "Created bridge %s" % bridge.id def stasis_start_cb(channel_obj, ev): """Handler for StasisStart event""" channel = channel_obj.get("channel") print "Channel %s just entered our application, adding it to bridge %s" % (channel.json.get("name"), bridge.id) channel.answer() bridge.addChannel(channel=channel.id) bridge.startMoh() def stasis_end_cb(channel, ev):
def run_stasis_app(self): context = self.env.context uid = self.env.uid cr = sql_db.db_connect(self.env.cr.dbname).cursor() exit_request = False with api.Environment.manage(): self.env = env = api.Environment(cr, uid, context) def playback_started(playback, ev): # Update playback start time channel_id = ev['playback']['target_uri'].split(':')[1] cdr = env['asterisk.dialer.cdr'].search([('channel_id','=','%s' % channel_id)]) cr.commit() if cdr: cdr.write({'playback_start_time': datetime.datetime.now()}) cr.commit() def playback_finished(playback, ev): # Update playback_end_time channel_id = ev['playback']['target_uri'].split(':')[1] cdr = env['asterisk.dialer.cdr'].search([('channel_id','=','%s' % channel_id)]) cr.commit() if cdr: cdr.playback_end_time = datetime.datetime.now() cr.commit() # Hangup now! client.channels.get(channelId=channel_id).hangup() def stasis_start(channel, ev): channel.answer() play_file = 'demo-thanks' channel.play(media='sound:%s' % play_file) def stasis_end(channel, ev): print "%s has left the application" % channel.json.get('name') # Update current calls dialer_channel = env['asterisk.dialer.channel'].search( [('channel_id', '=', channel.json.get('id'))]) cr.commit() if dialer_channel: print 'Removing channel', dialer_channel['channel_id'] dialer_channel.unlink() cr.commit() # Update cdr cdr = env['asterisk.dialer.cdr'].search([('channel_id','=','%s' % channel.json.get('id'))]) cr.commit() if cdr: cdr.write({'status': 'ANSWER', 'end_time': datetime.datetime.now()}) cr.commit() if exit_request: # This is the last call, exit. client.close() cr.close() def hangup_request(channel, ev): print 'CHANNEL HANGUP REQUEST, DIALER ID', self.id def user_event(channel, ev): if ev['eventname'] == 'exit_request': print 'ARI exit request for dialer id: %s' % self.id exit_request = True client = ari.connect('http://localhost:8088', 'dialer', 'test') client.on_channel_event('StasisStart', stasis_start) client.on_channel_event('StasisEnd', stasis_end) client.on_channel_event('ChannelHangupRequest', hangup_request) client.on_channel_event('ChannelUserevent', user_event) client.on_playback_event('PlaybackStarted', playback_started) client.on_playback_event('PlaybackFinished', playback_finished) try: client.run(apps='odoo-dialer-%s' % self.id) except Exception, e: if e.args[0] == 104: # on client.close() pass else: raise
parser.add_argument("calls_count", help="Calls count", type=int) parser.add_argument("-cps", default=3, help="Calls per second (default: 3)", type=int) parser.add_argument("-call-to", default="112", help="Number to call (default: 112)") parser.add_argument("-asterisk.common-ip", default="127.0.0.1", help="Tester asterisk.common ip (default: 127.0.0.1)") parser.add_argument("-branch-test", default="master", help="Branch that you want to test (default: master)") args = parser.parse_args() args.branch_test = args.branch_test + "-sip-kamailio.stage.sphaera.ru" logging.basicConfig(level=logging.ERROR) client = ari.connect("http://{}:8088".format(args.asterisk_ip), "asterisk.common", "asterisk.common") for i in range(1, args.calls_count + 1): print("Call number {}".format(i)) endpoint = "PJSIP/kamailio/sip:{}@{}".format(args.call_to, args.branch_test) client.channels.originate(endpoint=endpoint, context="testing", callerId="test", extension=i) time.sleep(1 / args.cps)
#!/usr/bin/python import ari # Change your Asterisk access details here url = 'http://localhost:8088' username = '******' password = '******' client = ari.connect(url, username, password) # Callback for StasisStart event def on_start_cb(channel, event): c = channel.get('channel') print "%s has entered the application" % c.json.get('name') number = c.json.get('dialplan')['exten'] print "Number is %s" % number c.play(media='sound:your') c.play(media='sound:number') c.play(media='sound:is') c.play(media='digits:' + number) c.continueInDialplan() # Callback for StasisEnd event def on_end_cb(channel, event): print "%s has left the application" % channel.json.get('name')
def on_dccmsg(self, c, e): c.privmsg("You said: " + e.arguments[0]) def do_command(self, e, cmd): nick = e.source channel = e.target c = self.connection if 'monkey' in cmd: monkey_time() elif 'call' in cmd: uri = cmd.replace('call', '').strip() place_call(uri) client = ari.connect('http://neutron.jcn-labs.net:8088', 'vuc-conf', 'digiumtacos') #client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk') channel_count = 0 channels = [] irc_bot = IRCBot('vuc_asterisk_bot', 'chat.freenode.net') conf_bridge = None try: conf_bridge = client.bridges.get(bridgeId='vuc') except: pass if not conf_bridge: conf_bridge = client.bridges.create(type='mixing,dtmf_events', bridgeId='vuc', name='vuc')
def getClient(): client = ari.connect('server:port', 'login', 'password') return client
class StasisThread(AriOdooSessionThread): """ Terminate conditions: 1) No more calls to originate and no more channels are expected to come into Stasis: wait for the last call to hangup and exit. 2) Origination thread exits due to Pause / Cancel Ignore errors: 1) On answer / playback / hangup events """ def run(self): def user_event(channel, ev): if ev['eventname'] == 'exit_request': # Immediate exit self.ari_client.close() def on_dtmf_received(channel, ev): try: if (self.dialer.create_lead_on_key_press and ev.get('digit') == '*'): _logger.debug('DTMF * press on channel: %s' % channel.get('channelId')) except HTTPError, e: # Just ignore errors _logger.warn('DTMF RECEIVE ERROR: %s' % str(e)) _logger.error(format_exception()) def stasis_start(channel, ev): def answer_channel(channel): def playback_finished(playback, event): def hangup(): try: channel.hangup() except HTTPError: # The call was hangup on other side pass t = threading.Timer(1, hangup) t.start() try: channel.answer() playback_id = str(uuid.uuid4()) playback = channel.play(channelId=channel.id, media='sound:%s' % self.sound_file) playback.on_event('PlaybackFinished', playback_finished) except HTTPError: # The call was hangup on other side pass # Stasis start t = threading.Timer(1, answer_channel, [channel]) t.start() # Run if self.dialer.dialer_type != 'stasis': _logger.debug('STASIS APP NOT STARTING.') return with api.Environment.manage(): try: self.ari_client = ari.connect(self.ari_url, self.ari_user, self.ari_pass) self.sound_file = os.path.splitext( self.dialer.sound_file.get_full_path()[0])[0] self.ari_client.on_channel_event('StasisStart', stasis_start) self.ari_client.on_channel_event('ChannelUserevent', user_event) self.ari_client.on_channel_event('ChannelDtmfReceived', on_dtmf_received) self.ari_client.run(apps='dialer-%s-session-%s' % (self.dialer.id, self.session.id)) except (ConnectionError, WebSocketConnectionClosedException) as e: # Asterisk crash or restart? # Try to get OriginationThread for thread in threading.enumerate(): if (thread.name == 'OriginationThread-%s' % self.dialer.id and thread.is_alive()): _logger.debug( 'SETTINGS stasis_app_error IN ORIGINATION THREAD.') thread.stasis_app_error.set() _logger.debug('STASIS: WebSocketConnectionClosedException ' '- exiting Stasis thread.') _logger.debug(format_exception()) return except Exception as e: # on ari_client.close() we are here :-) Ugly :-) if (hasattr(e, 'args') and type(e.args) in (list, tuple) and e.args and e.args[0] == 104): pass else: raise finally: try: _logger.debug('STASIS FINALLY CLOSING.') self.cursor.close() self.ari_client.close() except: pass
#!/usr/bin/env python import logging import requests import ari import threading logging.basicConfig(level=logging.ERROR) client = ari.connect('http://10.10.10.109:8088', 'asterisk', 'asterisk') channel_timers = {} def safe_hangup(channel): """Safely hang up the specified channel""" try: channel.hangup() print "Hung up {}".format(channel.json.get('name')) except requests.HTTPError as e: if e.response.status_code != requests.codes.not_found: raise e def safe_bridge_destroy(bridge): """Safely destroy the specified bridge""" try: bridge.destroy() except requests.HTTPError as e: if e.response.status_code != requests.codes.not_found: raise e
def run(self): """Main thread loop. Condition to terminate: 1) All done. Also terminate Stasis app. 2) Stasis app not ready (when dialer type is stasis) 3) ARI connection error. Also terminate Stasis app. 4) Pause / cancel requested. Also terminate Stasis app. """ self.stasis_app_error.clear() with api.Environment.manage(): try: # Connect to ARI before starting thread. self.ari_client = ari.connect(self.ari_url, self.ari_user, self.ari_pass) while True: try: # Paranoid but sometimes it does not see changes! self.dialer.invalidate_cache() self.session.invalidate_cache() self.env.invalidate_all() # Reset flag on every round self.go_next_call.clear() # Check for cancel request or stasis app error if (self.session.cancel_request or (self.dialer.dialer_type == 'stasis' and self.stasis_app_error.is_set())): _logger.debug('DIALER: CANCEL / ERROR REQUEST') self.cancel_calls() if self.dialer.dialer_type == 'stasis': self.ari_user_event('exit_request') self.session.state = 'cancelled' self.session.cancel_request = False self.dialer.active_session = None return # Check for pause request elif self.session.pause_request: _logger.debug('DIALER: PAUSE REQUEST') if self.dialer.dialer_type == 'stasis': self.wait_for_last_call() self.ari_user_event('exit_request') self.session.state = 'paused' self.session.pause_request = False return # Check if we can add more calls self.env.cr.execute("""SELECT cdr.id AS cdr_id, cdr.phone AS phone, COALESCE(cdr.name, '') AS name, peer.id AS peer_id, peer.name AS peer_name, route.pattern AS pattern FROM asterisk_dialer_peer peer, asterisk_dialer_route route, asterisk_dialer_cdr cdr WHERE cdr.status = 'queue' AND route.dialer = %s AND cdr.session = %s AND peer.simult > (SELECT COUNT(*) FROM asterisk_dialer_channel chan WHERE peer = peer.id) AND peer.id = route.peer AND cdr.phone LIKE CONCAT(route.pattern,'%%') ORDER BY cdr.id, route.sequence LIMIT 1 """ % (self.dialer.id, self.session.id)) cdr = self.env.cr.dictfetchall() if cdr: _logger.debug('CDR FOR CALL: %s' % cdr[0]) self.originate_call(cdr[0]) elif self.session.cdr_queue_count == 0: # All done raise StopIteration else: _logger.debug('NO CHANNELS AVAILABLE, SLEEPING.') # Sleep here or be interrupted by hangup self.go_next_call.wait(DIALER_RUN_SLEEP) except StopIteration: _logger.debug('CDR StopIteration.') if self.dialer.dialer_type == 'stasis': self.wait_for_last_call() self.ari_user_event('exit_request') self.session.state = 'done' self.dialer.active_session = None return except (ConnectionError, HTTPError), e: # ARI Error self.session.state = 'error' self.dialer.message_post('ARI ConnectionError: %s' % e.message) _logger.debug(format_exception()) finally:
#!/usr/bin/env python import ari import logging import threading logging.basicConfig(level=logging.ERROR) client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk') # find or create a holding bridge holding_bridge = None # Announcer timer announcer_timer = None def find_or_create_bridge(): """Find our infinite wait bridge, or create a new one Returns: The one and only holding bridge """ global holding_bridge global announcer_timer if holding_bridge: return holding_bridge bridges = [candidate for candidate in client.bridges.list() if candidate.json['bridge_type'] == 'holding']
backupCount=40) log_formatter = logging.Formatter( '%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s') handler.setLevel(logging.INFO) handler.setFormatter(log_formatter) log.addHandler(handler) disposition_convert = {'User busy': 'BUSY', 'User alerting, no answer': 'BUSY'} app = Flask(__name__) app.config['SECRET_KEY'] = 'xxxxx' socketio = SocketIO(app) # , async_mode='eventlet') pool = eventlet.GreenPool() ARIclient = ari.connect('http://localhost:3766/', 'servApiTester', 'xxxxxxxxx') DB_lock = False Allcl_lock = False Allcl = dict() EndpointEvents = dict() IpWhiteList = [] TotallCalls = 0 class AutoClient: def __init__(self, sid, endpoint, cid, pinCode): self.autoCall = True self.incoming = False self.timeout = 59 self.sid = sid
# Also, I want to avoid that the originate call be processed too (loop) #if chanType != "PJSIP": # avoid process when channel type is PJSIP # I'm using PJSIP/2000 for my tests, but you should consider using ChanType != "PJSIP" if chanType == "PJSIP/2000": # process when channel is PJSIP/2000 playback_id = str(uuid.uuid4()) playback = channel.playWithId(playbackId=playback_id, media='sound:poc/support_team') playback.on_event('PlaybackFinished', playback_finished) print "queueapp started at %s" % time.strftime("%c") print "Asterisk ARI - connecting" client = ari.connect('http://localhost:8088', ari_user, ari_secret) client.on_channel_event('StasisStart', stasis_start_cb) print "XMPP Server - connecting" xmpp = XMPP(xmppUser, xmppSecret, pubsubDomain) xmpp.connect() xmpp.process(block=False) print "DB PostgreSQL - connecting" db = DBPgsql(db_name, db_host, db_user, db_secret) print "Waiting for calls..." client.run(apps='queueapp')
from gevent.monkey import patch_all; patch_all() from gevent.event import Event import logging from requests.exceptions import HTTPError, ConnectionError import socket import time logging.basicConfig() # Important! # Otherwise you get No handlers could be found for # logger "ari.client" ARI_URL = 'http://192.168.56.101:8088/ari' ARI_USER = '******' ARI_PASSWORD = '******' client = ari.connect(ARI_URL, ARI_USER, ARI_PASSWORD) def run(): try: client.run('originator') except socket.error as e: if e.errno == 32: # Broken pipe as we close the client. pass except ValueError as e: if e.message == 'No JSON object could be decoded': # client.close() pass def originate(endpoint=None, callerid=None, context=None, extension=None, priority=None, timeout=None): # Go! evt = Event() # Wait flag for origination
digit)[-2:] == '90': # обработка двойных нажатий print(90) self.dtmf = '' else: self.dtmf = self.dtmf + digit except HTTPError as e: # Ignore 404's, since channels can go away before we get to them if e.response.status_code != requests.codes.not_found: raise # def playback_finish(playback, event): # print('Остановлен проигрышь информационного файла', playback, event) client = ari.connect('http://192.168.0.111:8088/', 'home', '******') def on_start(channel, event): pprint(('event: {0}'.format(event))) c = Channel() # обработка канала # dtmf ожидание ответа и проигрыш файлов channel['channel'].answer() playback = channel['channel'].play(media='sound:demo-congrats') channel['channel'].play(media='sound:taxi/ivr2') channel['channel'].hold() # слушатель нажатий dtmf channel['channel'].on_event('ChannelDtmfReceived', c.on_dtmf)
#!/usr/bin/env python import ari import logging import threading import uuid logging.basicConfig(level=logging.ERROR) client = ari.connect('http://localhost:8088', 'asterisk', 'asterisk') channel_timers = {} def stasis_end_cb(channel, ev): """Handler for StasisEnd event""" print "Channel %s just left our application" % channel.json.get('name') timer = channel_timers.get(channel.id) if timer: timer.cancel() del channel_timers[channel.id] def stasis_start_cb(channel_obj, ev): """Handler for StasisStart event""" def answer_channel(channel, playback): """Callback that will actually answer the channel""" print "Answering channel %s" % channel.json.get('name') playback.stop() channel.answer()
def _start_client(self): LOG.debug('starting ari') self.client = ari.connect('http://localhost:8088', 'telewall-tester', 'telewall-tester')