首页 > 其他分享 >基于jssip封装的软电话功能模块SoftPhoneForWebrtc.ts

基于jssip封装的软电话功能模块SoftPhoneForWebrtc.ts

时间:2023-01-30 17:45:10浏览次数:36  
标签:SoftPhoneForWebrtc log ua jssip ts session ._ console data

SoftPhoneForWebrtc.ts  :   import JsSIP from 'jssip' // 自定义数据进行通信的socket事件 function selfSocketEvent(data) {   if (window.$ak.socketMyself) {     window.$ak.socketMyself.emit('selfEvent', {       externalNo: `webrtc-${localStorage.getItem('clientPhone')}`, //客户号       internalNo: localStorage.getItem('seatCode'), //坐席号       msgContent: data,     })   } } let vm = null // JsSIP.debug.enable('JsSIP:Transport JsSIP:RTCSession*') import eventBus from '@/util/Bus' const sendThis = (_this) => {   vm = _this }
function SoftPhone() {   this.version = '0.1'   this.session = null   this.ua = null   this.logEnable = true   this.URI = null   this.SIP_SCHEME = 'sip'   this.localStream = null   this.remoteMedia = null   this.localMedia = null   this._contactUri = ''   this.socket = null   this.messager = null   this.flowList = []   this._init() } export { sendThis, SoftPhone }
SoftPhone.prototype = {   _init() {     this._initSoftPhoneObject()   },   _initSoftPhoneObject() {     //JSSIP参数修改,FreeSWITCH要求session_expires会话间隔大于120s     // Session-Expires这个字段的值必须要大于Min-SE,否则就认为会话结束。     // 所以你最初应该将Session-Expires设置一个比较大的值,或者就直接不用Session-Expires字段     JsSIP.C.SESSION_EXPIRES = 3600     JsSIP.C.MIN_SESSION_EXPIRES = 3600   },   _bindUAEvent(ua) {     ua.on('registered', (data) => this._UAEventHandler('registered', data))     ua.on('unregistered', (data) => this._UAEventHandler('unregistered', data))     ua.on('registrationFailed', (data) =>       this._UAEventHandler('registrationFailed', data)     )     ua.on('registrationExpiring', () => this._registrationExpiring())     ua.on('connecting', (data) => this._UAEventHandler('connecting', data))     ua.on('connected', (data) => this._UAEventHandler('connected', data))     ua.on('disconnected', (data) => this._UAEventHandler('disconnected', data))     ua.on('newRTCSession', (data) => this._newRTCSessionHandler(data))     ua.on('newMessage', (data) => this._UAEventHandler('newMessage', data))     ua.on('sipEvent', (data) => this._UAEventHandler('sipEvent', data))     ua.on('newInfo', (data) => this._UAEventHandler('newInfo', data))   },   _UAEventHandler(status, data) {     if (this.logEnable && console && typeof console.log == 'function') {       console.log('%c=======' + status + '=======', 'color:blue')     }     if (status == 'connected') {       console.log('软电话已经连接')       this.session = data.session     }     if (status == 'newInfo') {       console.log('来新消息了')     }     if (status == 'sipEvent') {       console.log('触发了sipEvent事件')     }   },   _newRTCSessionHandler(data) {     this.session = data.session     this._bindRTCSessionEvent(this.session)   },   _registrationExpiring() {     console.log('注册超时,重新再注册一次')     this.ua.register()   },   _bindRTCSessionEvent(session) {     ;[       'newInfo',       'peerconnection',       'connecting',       'sending',       'progress',       'accepted',       'confirmed',       'ended', //已建立的通话结束时触发。       'failed',       'newDTMF',       'hold',       'unhold',       'muted',       'unmuted',       'reinvite',       'update',       'refer',       'replaces',       'sdp',       'getusermediafailed',       'peerconnection:createofferfailed',       'peerconnection:createanswerfailed',       'peerconnection:setlocaldescriptionfailed',       'peerconnection:setremotedescriptionfailed',     ].forEach((key) =>       session.on(key, (data) => {         this._RTCSessionEventHandler(key, data)       })     )   },   _RTCSessionEventHandler(status, data) {     if (this.logEnable && console && typeof console.log == 'function') {       console.log('%c*******' + status + '*******', 'color:green')       this.flowList.push(status)     }     switch (status) {       case 'peerconnection:createanswerfailed':         console.log('peerconnection:createanswerfailed')         break       case 'peerconnection':         this._peerconnectionEventHandler(data)         break       case 'accepted':         this._acceptedEventHandler(data)         break       case 'progress':         // 客户端的呼叫只有走到了progress阶段,坐席侧的振铃才应该被弹出来         selfSocketEvent('progress')         console.log('========progress=======')         break       case 'failed':         vm.onCallFail()         selfSocketEvent('')         this.remoteMedia.pause()         this.localMedia.pause()         break       case 'confirmed':         // 设置坐席状态为通话中         console.log('%c*******' + '通话中' + '*******', 'color:green')         vm.isTaking = true         eventBus.$emit('_isTaking', true)         break       case 'ended':         // 设置坐席状态为未在通话中         vm.isTaking = false         eventBus.$emit('_isTaking', false)         this._endedEventHandler(data)         break       case 'muted':         eventBus.$emit('_muteSucess')         break       case 'unmuted':         eventBus.$emit('_unmutedSucess')         break     }   },   // 已建立的通话结束时触发。   _endedEventHandler(data) {     console.log('已挂机')     vm.callEnded()   },   _peerconnectionEventHandler(data) {},   _acceptedEventHandler() {     var self = this     this.remoteMedia.srcObject = this.session.connection.getRemoteStreams()[0]     this.localMedia.srcObject = this.session.connection.getRemoteStreams()[0]     let constraints = {       audio: true,       video: false,     }     navigator.mediaDevices       .getUserMedia(constraints)       .then(function(stream) {         self.getLocalMedia(stream)       })       .catch(function(err) {         console.log(err)       })   },   _createMediaDOM(id, dom) {     var div = document.createElement('div')     div.style.width = '0'     div.style.height = '0'     var audio = document.createElement('AUDIO')     audio.id = id     audio.setAttribute('autoplay', 'autoplay')     div.appendChild(audio)     document.body.appendChild(div)     this[dom] = audio   },   setMediaObj(remote, local) {     remote && (this.remoteMedia = remote)     local && (this.localMedia = local)     !this.remoteMedia && this._createMediaDOM('_remoteMedia', 'remoteMedia')     !this.localMedia && this._createMediaDOM('_localMedia', 'localMedia')   },   getLocalMedia(stream) {     this.session.connection.addStream(stream)   },   toSipURI(number) {     return new JsSIP.URI(this.SIP_SCHEME, number, this.URI.host).toString()   },   toContactURI(number) {     return new JsSIP.URI(this.SIP_SCHEME, number, this.URI.host, null, {       transport: 'ws',     }).toString()   },   captureLocalMedia() {     let constraints = {       audio: true,       video: false,     }     navigator.mediaDevices       .getUserMedia(constraints)       .then((stream) => console.log(stream))       .catch((err) => console.log(err))   },   /**    * 注册    * @param sipUser 用户名    * @param sipPwd 密码    * @param sipServer 服务地址    */   register(sipUser, sipPwd, sipServer) {     return new Promise((resolve, reject) => {       this.setMediaObj()       if (sipUser == '' || sipPwd == '' || sipServer == '') {         return       }       this.URI = JsSIP.Grammar.parse(sipServer, 'Request_URI')       this._contactUri = this.toContactURI(sipUser)       var _sipUser = this.toSipURI(sipUser)       var socket = new JsSIP.WebSocketInterface(sipServer)       this.socket = socket       var configuration = {         sockets: [socket],         uri: _sipUser,         password: sipPwd,         register: false,         contact_uri: this._contactUri,         register_expires: 3600, //注册有效时间         connection_recovery_max_interval: 3600 * 24 * 1000,         connection_recovery_min_interval: 3600 * 24 * 1000,         no_answer_timeout: 120,       }       this.ua = new JsSIP.UA(configuration)       // console.log(this.ua._configuration, 'ua配置')       this._bindUAEvent(this.ua)       this.ua.start()       this.ua.register()       this.ua.on('registered', (data) => resolve(data))       this.ua.on('registrationFailed', (data) => reject(data))     })   },   /**    * 注销    */   unregister() {     if (this.ua) {       this.ua.unregister()       this.ua.stop()     }     return true   },   /**    * 外呼    * @param dtmfNumber 被叫号码    */   placeCall(seatNumber) {     this.flowList = []     var sipNumber = this.toSipURI(seatNumber)     var eventHandlers = {       confirmed: function(data) {         console.log('电话接通confirmed')         vm.onCallReceive()       },       ended: function(data) {         console.log('通话结束ended')       },     }     var options = {       eventHandlers: eventHandlers,       mediaConstraints: { audio: true, video: false },     }     this.session = this.ua.call(sipNumber, options)   },   /**    * 接听    */   answer() {     this.remoteMedia.loop = true     this.localMedia.loop = true     this.remoteMedia.volume = 1     this.localMedia.volume = 1     this.remoteMedia.play()     this.localMedia.play()     var options = {       mediaConstraints: { audio: true, video: false },     }     this.session.answer(options)   },   /**    * 挂机    */   reject() {     if (this.session) {       this.session.terminate()     }   },   /**    * 保持    */   hold() {     this.session.hold()   },   /**    * 拾回    */   retrieveHold() {     this.session.unhold()   },   /**    * 静音    */   mute(e) {     this.session.mute()     if (e === '坐席') {       this.remoteMedia.pause()     }     if (e === '客户') {       this.localMedia.pause()     }   },   /**    * 取消静音    */   unmute(e) {     this.session.unmute()     if (e === '坐席') {       this.remoteMedia.play()     }     if (e === '客户') {       this.localMedia.play()     }   },   // 清空flowList   clearFlow() {     this.flowList = []   },   /**    * 二次拨号    * @param dtmfNumber 二次拨号号码    */   dtmf(dtmfNumber) {     console.log(dtmfNumber)     this.session.sendDTMF(dtmfNumber)   },   /**    * 设置在线    */   setReady() {     if (this.ua && !this.ua.isRegistered()) {       this.ua.register()     }   },   /**    * 设置离线    */   setNoDisturb() {     if (this.ua && this.ua.isRegistered()) {       this.ua.unregister()     }   },   /**    * 电话转接    */   transfer(number) {     var sipNumber = this.toSipURI(number)     this.session.refer(sipNumber)   }, }

标签:SoftPhoneForWebrtc,log,ua,jssip,ts,session,._,console,data
From: https://www.cnblogs.com/shidawang/p/17076800.html

相关文章