无法使用Python PJSIP进行两个呼叫和会议

时间:2019-08-31 13:18:28

标签: python sip pjsip

我正在尝试在由pjsip管理的2个星号扩展名之间进行电话会议。 我想打电话给123和124,然后让他们通话。

我已经设置了两个不同的传输方式和两个帐户,这不是强制性的,但这是我正在尝试的方式。无论如何,将一个帐户用于两个通话都很好。

问题是以下代码:

import pjsua
import threading
from time import sleep


def log_cb(level, str, len):
    print str,


class MyAccountCallback(pjsua.AccountCallback):
    sem = None

    def __init__(self, account=None):
        pjsua.AccountCallback.__init__(self, account)

    def wait(self):
        self.sem = threading.Semaphore(0)
        self.sem.acquire()

    def on_reg_state(self):
        if self.sem:
            if self.account.info().reg_status >= 200:
                self.sem.release()


def cb_func(pid) :
    print '%s playback is done' % pid
    current_call.hangup()


# Callback to receive events from Call
class MyCallCallback(pjsua.CallCallback):

    def __init__(self, call=None, dostuff=True):
        pjsua.CallCallback.__init__(self, call)
        self.dostuff=dostuff

    # Notification when call state has changed
    def on_state(self):
        if not self.dostuff:
            return

        global current_call
        global in_call
        print "Call with", self.call.info().remote_uri,
        print "is", self.call.info().state_text,
        print "last code =", self.call.info().last_code, 
        print "(" + self.call.info().last_reason + ")"


        #if self.call.info().media_state == pjsua.MediaState.ACTIVE:
        #    # Connect the call to sound device
        #    call_slot = self.call.info().conf_slot
        #    lib.conf_connect(call_slot, 0)
        #    lib.conf_connect(0, call_slot)
        #    print "Hello world, I can talk!"

        if self.call.info().state == pjsua.CallState.DISCONNECTED:
            current_call = None
            print 'Current call is', current_call

            in_call = False
        elif self.call.info().state == pjsua.CallState.CONFIRMED:
            print "Call Answred"
            another_call = make_call(acc2, dst_uri2, dostuff=False)
            conf_slot = self.call.info().conf_slot
            conf_slot_2 = another_call.info().conf_slot
            i = 0
            while i < 10:
                print '#####################################'
                print '#####################################'
                print 'conf_slot ' + str(conf_slot)
                print 'conf_slot_2 ' + str(conf_slot_2)
                print '#####################################'
                print '#####################################'
                if another_call.info().state == pjsua.CallState.CONFIRMED:
                    i = pjsua.Lib.instance()
                    i.conf_connect(conf_slot, conf_slot_2)
                    i.conf_connect(conf_slot_2, conf_slot)
                else:
                    print '#####################################'
                    print 'FIRST CALL STATE %s' % self.call.info().__dict__
                    print '\n\n'
                    print 'ANOTHER CALL STATE %s' % another_call.info().__dict__
                    print '#####################################'
                    sleep(2)
                    i += 2

            sleep(25)
            self.call.hangup()
            another_call.hangup()
            in_call = False

    # Notification when call's media state has changed.
    def on_media_state(self):
        if self.call.info().media_state == pjsua.MediaState.ACTIVE:
            print "Media is now active"
        else:
            print "Media is inactive"


# Function to make call
def make_call(ac, uri, dostuff=True):
    try:
        print "Making call to", uri
        return ac.make_call(uri, cb=MyCallCallback(dostuff=dostuff))
    except pjsua.Error, e:
        print "Exception: " + str(e)
        return None


lib = pjsua.Lib()

try:
    cfg = pjsua.MediaConfig()
    lib.init(log_cfg = pjsua.LogConfig(level=4, callback=log_cb), media_cfg=cfg)
    t1 = lib.create_transport(pjsua.TransportType.UDP, pjsua.TransportConfig(5081))
    t2 = lib.create_transport(pjsua.TransportType.UDP, pjsua.TransportConfig(5082))
    lib.set_null_snd_dev()
    lib.start()
    lib.handle_events()

    acc_cfg = pjsua.AccountConfig()
    acc_cfg.id = "sip:11111"
    acc_cfg.reg_uri = "sip:localhost"
    #acc_cfg.proxy = [ "sip:PROXY.YOURSIPSERVER.COM;lr" ]
    acc_cfg.auth_cred = [ pjsua.AuthCred("*", "11111", "secret")]


    acc_cb = MyAccountCallback()
    acc = lib.create_account(acc_cfg, cb=acc_cb)
    acc.set_transport(pjsua.Transport(lib, 1))

    acc_cb.wait()

    print "\n"
    print "Registration complete, status=", acc.info().reg_status, \
          "(" + acc.info().reg_reason + ")"


    ##########
    # ACCO 2
    ##########

    acc2_cfg = pjsua.AccountConfig()
    acc2_cfg.id = "sip:11112"
    acc2_cfg.reg_uri = "sip:localhost"
    acc2_cfg.transport_id = t2._id
    # a2cc_cfg.proxy = [ "sip:PROXY.YOURSIPSERVER.COM;lr" ]
    acc2_cfg.auth_cred = [pjsua.AuthCred("*", "11112", "secret")]
    acc2_cb = MyAccountCallback()
    acc2 = lib.create_account(acc2_cfg, cb=acc2_cb)
    acc2.set_transport(t2)
    acc2_cb.wait()
    ###########


    #YOURDESTINATION is landline or mobile number you want to call
    dst_uri = "sip:123@localhost"
    dst_uri2 = "sip:124@localhost"

    in_call = True
    lck = lib.auto_lock()
    current_call = make_call(acc, dst_uri)
    print 'Current call is', current_call
    del lck

    #wait for the call to end before shuting down
    while in_call:
        print('In call')
        sleep(3)
        pass
    #sys.stdin.readline()
    lib.destroy()
    lib = None

except pjsua.Error, e:
    print "Exception: " + str(e)
    lib.destroy()

产生以下结果:

#####################################
In call
#####################################
#####################################
conf_slot 1
conf_slot_2 -1
#####################################
#####################################
#####################################
FIRST CALL STATE {'total_time': 6, 'account': <pjsua.Account instance at 0x7f9482f90ea8>, 'conf_slot': 1, 'sip_call_id': 'de7fe2e7-21c5-4763-a02b-a7a08ab20d02', 'uri': 'sip:11111', 'media_state': 1, 'last_reason': 'OK', 'remote_contact': '<sip:123@127.0.0.1:5060>', 'state': 5, 'contact': '<sip:127.0.0.1:5081;ob>', 'role': 0, 'state_text': 'CONFIRMED', 'media_dir': 3, 'remote_uri': 'sip:123@localhost', 'call_time': 6, 'last_code': 200}



ANOTHER CALL STATE {'total_time': 6, 'account': <pjsua.Account instance at 0x7f9482fa0200>, 'conf_slot': -1, 'sip_call_id': '094b998a-2b0c-42eb-b5ac-0a44251a6566', 'uri': 'sip:11112', 'media_state': 0, 'last_reason': '', 'remote_contact': '', 'state': 1, 'contact': '<sip:127.0.0.1:5082;ob>', 'role': 0, 'state_text': 'CALLING', 'media_dir': 0, 'remote_uri': 'sip:124@localhost', 'call_time': 0, 'last_code': 0}
#####################################

第二个呼叫没有开始。事实并非如此,我认为conf_slot仍为-1,因此不可能桥接:

i.conf_connect(conf_slot, conf_slot_2)
i.conf_connect(conf_slot_2, conf_slot)

任何提示将不胜感激。

1 个答案:

答案 0 :(得分:1)

您的第二通电话似乎没有建立。您混合了很多代码。我建议您尝试使用外部SIP客户端(例如,同理心(https://en.wikipedia.org/wiki/Empathy_(software) + SIP插件))首先使呼叫正常工作

在进行工作以通过会议网桥接听来电时,请尝试使用2个线程来管理2个不同的端点。如果pjsip回调很忙(直到长时间任务结束才使用),其他回调将不会触发,因此无法使其正常工作。

尝试隔离创建自定义类和来自不同线程的呼叫的呼叫/帐户代码。