Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # $Id$
- import sys, os, time
- import pjsua as pj
- from serial import Serial
- print ("Hello, this is "+sys.argv[0]+" by Sokoloff with parameters:")
- for param in sys.argv:
- print (param)
- if len(sys.argv) < 9:
- print ("run: python2.7 softphone.py dtmf1 dtmf2 account password domain port serial_port serial_speed")
- exit(0)
- dtmf1=sys.argv[1]
- dtmf2=sys.argv[2]
- domain=sys.argv[5]
- port=sys.argv[6]
- account=sys.argv[3]
- password=sys.argv[4]
- PJSUA_CALL_SEND_DTMF_DURATION_DEFAULT=120
- current_call = None
- number = None
- call = None
- def dial_dtmf(self, digits):
- lck = self._lib().auto_lock()
- try:
- self.dial_dtmf(digits+"#")
- ser.write(":OK\r\n")
- except:
- ser.write(":STUCK\r\n")
- def log_cb(level, str, len):
- print("[LC] Says: \r\n"+ str)
- if "SIP/2.0 100 Trying" in str:
- for node in str.split("\n"):
- if "To: <sip:" in node:
- tmp=node.split("@")[0]
- global number
- nr=tmp.split(":")[2]
- if nr.isdigit():
- if account in nr:
- number="SELF\r\n"
- else:
- number=nr
- else:
- number="SELF\r\n"
- print("[LC] DETECTING INCOMING TO "+number)
- class IncomingCallCallback(pj.CallCallback):
- def __init__(self, call=None):
- pj.CallCallback.__init__(self, call)
- def on_state(self):
- print ("[ICC] CALL STATE ", self.call.info().state_text)
- print ("[ICC] LAST CODE ", self.call.info().last_code)
- print ("[ICC] INFORMATION (" + self.call.info().last_reason + ")")
- if "CONNECTING" in self.call.info().state_text:
- global number
- print ("[ICC] INFORMATION NUM IS (" + str(number) + ")")
- if "DISCONNCTD" in self.call.info().state_text:
- global current_call
- global ser
- global number
- current_call = None
- number = None
- if "Clear by analog" in self.call.info().last_reason:
- ser.write(":OK\r\n")
- else:
- ser.write(":CANCEL\r\n")
- def on_media_state(self):
- global lib
- if self.call.info().media_state == pj.MediaState.ACTIVE:
- call_slot = self.call.info().conf_slot
- lib.conf_connect(call_slot, 0)
- lib.conf_connect(0, call_slot)
- print ("[ICC] ON_MEDIA_STATE SAYS THAT WE CAN TALK")
- def on_dtmf_digit(self,digit):
- print("[ICC] DTMF detected! Signal="+digit)
- if dtmf1 in digit:
- ser.write(":OPEN1\r\n")
- if dtmf2 in digit:
- ser.write(":OPEN2\r\n")
- class OutgoingCallCallback(pj.CallCallback):
- def __init__(self, call=None):
- pj.CallCallback.__init__(self, call)
- def on_state(self):
- print ("[OCC] CALL STATE ", self.call.info().state_text)
- print ("[OCC] LAST CODE ", self.call.info().last_code)
- print ("[OCC] INFORMATION (" + self.call.info().last_reason + ")")
- if "DISCONNCTD" in self.call.info().state_text:
- global current_call
- global ser
- global number
- current_call = None
- number = None
- ser.write(":CANCEL\r\n")
- def on_media_state(self):
- global lib
- if self.call.info().media_state == pj.MediaState.ACTIVE:
- call_slot = self.call.info().conf_slot
- lib.conf_connect(call_slot, 0)
- lib.conf_connect(0, call_slot)
- print ("[OCC] ON_MEDIA_STATE SAYS THAT WE CAN TALK")
- global current_call
- if "CONNECTING" in self.call.info().state_text:
- ser.write(":TALK\r\n")
- def on_dtmf_digit(self,digit):
- print("[OCC] DTMF detected! Signal="+digit)
- if dtmf1 in digit:
- ser.write(":OPEN1\r\n")
- if dtmf2 in digit:
- ser.write(":OPEN2\r\n")
- class SipAccountCallback(pj.AccountCallback):
- def __init__(self, acc):
- pj.AccountCallback.__init__(self, acc)
- def onRegState(self, prm):
- print ("[SAC] REG STATE CHANGED: " + prm.reason)
- def on_incoming_call(self, call):
- global current_call
- if current_call:
- call.answer(486, "Busy")
- ser.write(":BUSY\r\n")
- return
- print "[SAC] INCOMING CALL FROM: ", call.info().remote_uri
- current_call = call
- current_call.set_callback(IncomingCallCallback(current_call))
- global ser
- ser.write(":"+str(number)+"\r\n")
- #need to answer! waiting :talk from serial
- try:
- #init pjsua and serial port
- lib = pj.Lib()
- ser = Serial()
- lib.init(log_cfg = pj.LogConfig(level=6, callback=log_cb))
- transport = lib.create_transport(pj.TransportType.UDP)
- ser.baudrate = sys.argv[8]
- ser.port = sys.argv[7]
- lib.start()
- ser.open()
- if not ser.isOpen():
- raise SystemExit
- #init sip account
- acc_conf = pj.AccountConfig(domain = domain+':'+port, username = account, password = password, display = account)
- acc_conf.id ="sip:"+account
- acc_conf.reg_uri ='sip:'+domain
- acc_conf.ka_data = '\r\n'
- acc_conf.ka_interval = 15
- acc_callback = SipAccountCallback(acc_conf)
- acc = lib.create_account(acc_conf,cb=acc_callback)
- acc.set_callback(acc_callback)
- #listen for incoming or serial commands
- while True:
- #monitoring registration status
- t=0
- while acc.info().reg_status !=200:
- print ("[MAIN] Registering... Now status is `" + acc.info().reg_reason + "` COUNTER = "+str(t))
- t=t+1
- if t == 20:
- sys.exit(1)
- if acc.info().reg_status !=200:
- ser.write(":REGTRY\r\n")
- else:
- ser.write(":REGSUCC\r\n")
- time.sleep(1)
- read_serial = ser.readline()
- # incoming from serial
- if ":talk" in read_serial:
- if number and current_call:
- current_call.answer(200,"Ok")
- ser.write(":OK\r\n")
- if ":cancel" in read_serial:
- if current_call:
- current_call.hangup(603, "Hangup talk reason: Reset by serial with :cancel", None )
- if call:
- call.hangup(603, "Hangup ringing reason: Reset by serial with :cancel", None )
- ser.write(":OK\r\n")
- number = None
- current_call = None
- call = None
- if ":open1" in read_serial:
- dial_dtmf(current_call,dtmf1)
- if ":open2" in read_serial:
- dial_dtmf(current_call,dtmf2)
- if ":busy" in read_serial:
- #Added 12/05/2021
- print(":busy")
- if call:
- call.answer(486, "Busy")
- call.hangup(603, "Hangup ringing reason: Reset by serial with :busy", None )
- if current_call:
- current_call.hangup(603, "Hangup talk reason: Reset by serial with :busy", None )
- ser.write(":OK\r\n")
- else:
- ser.write(":ERR_NO-CALL-NOW\r\n")
- if ":0" in read_serial:
- if acc.info().reg_status !=200:
- ser.write(":OK\r\n")
- else:
- ser.write(":OK\r\n")
- ser.write(":CANCEL\r\n")
- else:
- num = read_serial.split(":")
- if len(num) > 1:
- mnum=num[1].replace("\r\n","")
- if mnum.isdigit():
- print("[MAIN] ANALOG -> SIP CALL. RINGING TO "+mnum)
- call = acc.make_call("sip:"+mnum+"@"+domain+":"+port, OutgoingCallCallback())
- if call:
- ser.write(":OK\r\n")
- else:
- ser.write(":NOTFOUND\r\n")
- except pj.Error, e:
- print ("Exception: " + str(e))
- if lib:
- lib.destroy()
- lib = None
- ser.close()
- finally:
- time.sleep(1)
- if current_call:
- current_call.hangup(603,"Terminate call. Reason: Terminating softphone.", None)
- if call:
- call.hangup(603,"Hangup call. Reason: Terminating softphone.", None)
- if lib:
- lib.destroy()
- lib = None
- if ser:
- ser.close()
- sys.exit(1)
Add Comment
Please, Sign In to add comment