123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /**
- * 对象方式的培训助手JS,以对象的方式初始化trainingHelper
- * 示例代码如下:
- * @author Asy
- * @time 2020-12-25 14:36
- */
- (function ($) {
- var $this; // 当前对象
- var ua;
- var session;
- var oNotifICall;
- var ringtone = null;
- var ringBackTone = null;
- var keyboard = null;
- var oSipSessionCall;
- // sipPhone处理
- mySipPhone = {
- init: function (options) {
- // 可供外部调用的方法和属性
- var o = $.extend({
- uri: "", // sip服务器的IP和端口
- wss: "", // webSocket 地址
- user: "", // sip分机号
- pwd: "", // 分机号密码
- callNumber: "", // 培训默认外呼号码
- options: {
- audioBW: '', // 设置音频带宽
- videoBW: '', // 设置视频带宽
- ice: '', // ICE穿透NAT/防火墙
- stunUrl: '', // STUN穿透
- turnUrl: '', // TURN穿透
- turnUserName: '', // TURN用户名
- turnCredential: '' // TURN证书
- },
- connecting: function (evt) {}, // webSocket连接中
- connected: function (evt) {}, // webSocket已连接
- disconnected: function (evt) {}, // webSocket连接断开
- registered: function (evt) {}, // SIP注册成功
- unregistered: function (evt) {}, // SIP未注册
- registrationFailed: function (evt) {}, // SIP注册失败
- busy: function (evt) {}, // 线路忙
- ringing: function (num) {}, // 呼入振铃,参数为呼入号码
- progress: function (localStream) {}, // 外呼处理中
- dialing: function (evt) {}, // 外呼中
- confirmed: function (evt) {}, // 外呼已确认
- accepted: function (callType, evt) {}, // 呼叫接通,callType:inbound 呼入,outbound 呼出
- stream: function (callType, localStream, remoteStream) {}, // 获取到数据流,callType:inbound 呼入,outbound 呼出
- failed: function (callType, evt) {}, // 呼叫失败,callType:inbound 呼入,outbound 呼出
- ended: function (callType, evt) {}, // 呼叫结束,callType:inbound 呼入,outbound 呼出
- refer: function (evt) {} // 转接
- }, options);
- $this = this;
- $this.data('mySipPhone', o);
- },
- /** 获取注入的数据和事件 */
- getData: function () {
- var o = $this.data('mySipPhone');
- return o;
- },
- /** 注册SIP */
- register: function () {
- try {
- // 如果当前已经注册过,则直接跳过
- if(ua){
- return false;
- }
- var o = mySipPhone.getData();
- // 启用浏览器消息通知
- if (window.webkitNotifications && window.webkitNotifications.checkPermission() != 0) {
- window.webkitNotifications.requestPermission();
- }
- var socket = new PhoneJs.WebSocketInterface(o.wss);
- socket.onconnect = function () {
- console.log('mySipPhone:webSocket连接中');
- };
- var configuration = {
- sockets: [socket],
- uri: o.user + '@' + o.uri,
- password: o.pwd,
- authorization_user: o.user,
- display_name: o.user,
- register: false, // dont't automatic register
- trace_sip: true
- //connection_recovery_max_interval: 30,
- //connection_recovery_min_interval: 2,
- };
- ua = new PhoneJs.UA(configuration);
- if (o.options.videoBW != undefined && o.options.videoBW != '') {
- ua.setVideoBandwidth(o.options.videoBW);
- }
- if (o.options.audioBW != undefined && o.options.audioBW != '') {
- ua.setAudioBandwidth(o.options.audioBW);
- }
- ua.on('connecting', function (e) {
- o.connecting(e);
- });
- ua.on('connected', function (e) {
- o.connected(e);
- ua.registrator().setExtraHeaders([
- 'X-Foo: x-bar'
- ]);
- ua.register(); // connect to SIP server
- });
- ua.on('disconnected', function (e) {
- o.disconnected(e);
- });
- ua.on('registered', function (e) {
- o.registered(e);
- });
- ua.on('unregistered', function (e) {
- o.unregistered(e);
- });
- ua.on('registrationFailed', function (e) {
- o.registrationFailed(e);
- });
- ua.on('newRTCSession', function (e) {
- session = e.session;
- var count = Object.keys(ua._sessions).length;
- if (count > 1) {
- var extraHeaders = ['X-Foo: foo', 'X-Bar: bar'];
- var status_code = "486";
- var reason_phrase = "BUSY HERE";
- var opts = {
- 'extraHeaders': extraHeaders,
- 'status_code': status_code,
- 'reason_phrase': reason_phrase
- };
- session.terminate(opts);
- o.busy(e);
- } else {
- if (session.direction == 'incoming') {
- mySipPhone._startRingtone($('[name="ringtone"]').val());
- var sRemoteNumber = (session.remote_identity._display_name || session.remote_identity._user ||
- 'unknown');
- o.ringing(sRemoteNumber);
- mySipPhone.showNotification(sRemoteNumber);
- session.on('peerconnection', function (e) {
- var peerconnection = session.connection;
- peerconnection.addEventListener('addstream', function (e) {
- var localStream = peerconnection.getLocalStreams()[0];
- o.stream("inbound", localStream, e.stream);
- });
- });
- session.on('progress', function (e) {
- console.log('Call progress event <i>呼入振铃...</i>');
- var peerconnection = session.connection;
- peerconnection.addEventListener('addstream', function (e) {
- var localStream = peerconnection.getLocalStreams()[0];
- o.stream("inbound", localStream, e.stream);
- });
- });
- session.on('failed', function (e) {
- session = null;
- mySipPhone._stopRingtone();
- o.failed("inbound", e);
- });
- session.on('ended', function (e) {
- session = null;
- o.ended("inbound", e);
- });
- session.on('accepted', function (e) {
- mySipPhone._stopRingtone();
- o.accepted("inbound", e);
- });
- }
- }
- });
- ua.start();
- } catch (e) {
- console.error(e);
- }
- },
- /**
- * 签出
- **/
- unregister: function () {
- if (ua) {
- ua.stop(); // shutdown all sessions
- ua = null;
- }
- },
- /**
- * 来电应答
- **/
- answer: function (videoEnabled) {
- try {
- var o = mySipPhone.getData();
- if (session) {
- var optAnswer = {
- 'mediaConstraints': {
- 'audio': true,
- 'video': videoEnabled
- }
- };
- var stunUrl = o.options.stunUrl;
- var turnUrl = o.options.turnUrl;
- var turnUserName = o.options.turnUserName;
- var turnCredential = o.options.turnCredential;
- if (stunUrl && stunUrl.length > 0) {
- optAnswer.pcConfig = {
- iceServers: [{
- urls: [stunUrl]
- }]
- };
- }
- if (turnUrl && turnUrl.length > 0) {
- if ((turnUserName && turnUserName.length > 0) && (turnCredential && turnCredential.length > 0)) {
- if (optAnswer.pcConfig && optAnswer.pcConfig.iceServers) {
- optAnswer.pcConfig.iceServers.push({
- 'urls': turnUrl,
- 'username': turnUserName,
- 'credential': turnCredential
- });
- } else {
- optAnswer.pcConfig = {
- iceServers: [{
- 'urls': turnUrl,
- 'username': turnUserName,
- 'credential': turnCredential
- }]
- };
- }
- } else {
- if (optAnswer.pcConfig && optAnswer.pcConfig.iceServers) {
- optAnswer.pcConfig.iceServers.push({
- 'urls': turnUrl
- });
- } else {
- optAnswer.pcConfig = {
- iceServers: [{
- 'urls': turnUrl
- }]
- };
- }
- }
- }
- session.answer(optAnswer);
- } else {
- alert('错误 : No session');
- }
- } catch (error) {
- console.error(error);
- }
- },
- /**
- * 外呼
- * @param videoEnabled true 表示视频外呼,false 表示语音外呼
- * @param callNum 外呼的号码
- * */
- call: function (videoEnabled, callNum) {
- try {
- var o = mySipPhone.getData();
- var eventHandlers = {
- 'progress': function (data) {
- // 制造振铃
- mySipPhone._startRingbackTone();
- var localStream = null;
- if(videoEnabled){
- var peerconnection = session.connection;
- localStream = peerconnection.getLocalStreams()[0];
- }
- o.progress(localStream);
- },
- 'failed': function (data) {
- session = null;
- mySipPhone._stopRingbackTone();
- o.failed("outbound", data);
- },
- 'confirmed': function (data) {
- o.confirmed(data);
- },
- 'ended': function (data) {
- session = null;
- o.ended("outbound", data);
- },
- 'connecting': function (data) {
- o.dialing(data);
- },
- 'accepted': function (data) {
- mySipPhone._stopRingbackTone();
- o.accepted("outbound", data);
- },
- 'refer': function (data) {
- o.refer(data);
- }
- };
- var options = {
- 'eventHandlers': eventHandlers,
- 'extraHeaders': ['X-Foo: foo', 'X-Bar: bar', 'video : ' + videoEnabled],
- 'mediaConstraints': {
- 'audio': true,
- 'video': videoEnabled
- },
- 'rtcOfferConstraints': {
- offerToReceiveAudio: 1,
- offerToReceiveVideo: 1
- }
- };
- var stunUrl = o.options.stunUrl;
- var turnUrl = o.options.turnUrl;
- var turnUserName = o.options.turnUserName;
- var turnCredential = o.options.turnCredential;
- //var pcConfig = { iceServers: [ { urls : [ iceServer ] } ] };
- if (stunUrl && stunUrl.length > 0) {
- options.pcConfig = {
- iceServers: [{
- urls: [stunUrl]
- }]
- };
- }
- if (turnUrl && turnUrl.length > 0) {
- if ((turnUserName && turnUserName.length > 0) && (turnCredential && turnCredential.length > 0)) {
- if (options.pcConfig && options.pcConfig.iceServers) {
- options.pcConfig.iceServers.push({
- 'urls': turnUrl,
- 'username': turnUserName,
- 'credential': turnCredential
- });
- } else {
- options.pcConfig = {
- iceServers: [{
- 'urls': turnUrl,
- 'username': turnUserName,
- 'credential': turnCredential
- }]
- };
- }
- } else {
- if (options.pcConfig && options.pcConfig.iceServers) {
- options.pcConfig.iceServers.push({
- 'urls': turnUrl
- });
- } else {
- options.pcConfig = {
- iceServers: [{
- 'urls': turnUrl
- }]
- };
- }
- }
- }
- session = ua.call(callNum, options);
- var peerconnection = session.connection;
- peerconnection.addEventListener('addstream', function (e) {
- console.log("===========外呼");
- var localStream = peerconnection.getLocalStreams()[0];
- o.stream("outbound", localStream, e.stream);
- });
- } catch (error) {
- console.error(error);
- }
- },
- // holds or resumes the call
- hold: function () {
- if (session) {
- var bHold = session.isOnHold();
- if (bHold.local) {
- console.log('unhold');
- session.unhold();
- } else {
- console.log('hold');
- session.hold();
- }
- }
- },
- // Mute or Unmute the call
- mute: function () {
- if (session) {
- var bMute = session.isMuted();
- if (bMute && bMute.audio) {
- console.log('unmute');
- session.unmute({
- 'audio': true, // Local audio is muted
- 'video': true // Local audio is not muted
- });
- } else {
- console.log('mute');
- session.mute({
- 'audio': true, // Local audio is muted
- 'video': true // Local audio is not muted
- });
- }
- }
- },
- // terminates the call (SIP BYE or CANCEL)
- hangUp: function () {
- if (session) {
- var extraHeaders = ['X-Foo: foo', 'X-Bar: bar'];
- var options = {
- 'extraHeaders': extraHeaders
- };
- session.terminate(options);
- }
- },
- // 发送按键给服务器
- sendDTMF: function (c) {
- if (oSipSessionCall && c) {
- if (oSipSessionCall.dtmf(c) == 0) {
- try {
- if(keyboard == null){
- keyboard = new Audio();
- keyboard.src = "./sounds/dtmf.wav";
- }
- keyboard.play();
- } catch (e) {
- console.error(e);
- }
- }
- }
- },
- /**
- * 当有来电时展示消息提醒
- * @param s_number 来电号码
- * */
- showNotification: function (s_number) {
- // permission already asked when we registered
- if (window.webkitNotifications && window.webkitNotifications.checkPermission() == 0) {
- if (oNotifICall) {
- oNotifICall.cancel();
- }
- oNotifICall = window.webkitNotifications.createNotification('images/sipml-34x39.png', 'Incaming call',
- 'Incoming call from ' + s_number);
- oNotifICall.onclose = function () {
- oNotifICall = null;
- };
- oNotifICall.show();
- }
- },
- // transfers the call
- transfer: function (transferNum) {
- if (session) {
- if (transferNum == undefined || transferNum == null || transferNum == '') {
- transferNum = prompt('请输入转接号码', '');
- }
- if (transferNum != undefined && transferNum != "") {
- session.refer(transferNum);
- }
- }
- },
- consult: function (number) {
- if (session) {
- if (number == undefined || number == null || number == '') {
- number = prompt('请输入咨询号码', '');
- }
- if (number != undefined && number != "") {
- // TODO 发起三方通话
- session.refer(number);
- }
- }
- },
- meeting: function (number) {
- if (session) {
- if (number == undefined || number == null || number == '') {
- number = prompt('请输入咨询号码', '');
- }
- if (number != undefined && number != "") {
- // TODO 发起三方通话
- session.refer(number);
- }
- }
- },
- monitor: function (number) {
- if (session) {
- if (number == undefined || number == null || number == '') {
- number = prompt('请输入咨询号码', '');
- }
- if (number != undefined && number != "") {
- // TODO 发起三方通话
- session.refer(number);
- }
- }
- },
- _startRingtone: function (num) {
- try {
- /*
- if(ringtone == null){
- ringtone = new Audio();
- ringtone.loop = true;
- if(num == 2 )
- ringtone.src = "../../sounds/3.wav";
- else if(num == 3 )
- ringtone.src = "../../sounds/4.wav";
- else
- ringtone.src = "sounds/ringtone.mp3";
- }
- */
- //ringtone.play();
- } catch (e) {
- console.error(e);
- }
- },
- _stopRingtone: function () {
- try {
- if(ringtone != null) {
- ringtone.pause();
- }
- } catch (e) {
- console.error(e);
- }
- },
- _startRingbackTone: function () {
- try {
- if(ringBackTone == null){
- ringBackTone = new Audio();
- ringBackTone.loop = true;
- ringBackTone.src = "../../sounds/ringbacktone.wav";
- }
- //ringBackTone.play();
- } catch (e) {
- console.error(e);
- }
- },
- _stopRingbackTone: function () {
- try {
- if(ringBackTone != null){
- ringBackTone.pause();
- }
- } catch (e) {
- console.error(e);
- }
- }
- }
- $.fn.mySipPhone = function (method) {
- if (mySipPhone[method]) {
- return mySipPhone[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else if (typeof method === 'object' || !method) {
- return mySipPhone.init.apply(this, arguments);
- } else {
- $.error('Method ' + method + ' does not exist on mySipPhone');
- }
- };
- })(jQuery)
|