PABX da Simples IP
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

434 lines
12 KiB

"use strict";
//
// Na Documentação incluir os sites da simplesip.com.br no Content-Security-Policy
//
const UASimplesIP = (function () {
function carregandoScriptSimpleSIP(url, callback) {
let script = document.createElement("script");
script.src = url;
script.async = true; // Asynchronous loading
script.onload = function () {
if (typeof callback === "function") {
callback();
}
// Clean up after script execution
script.onload = script.onerror = null;
document.head.removeChild(script);
};
script.onerror = function () {
// Handle errors
console.error("Error loading script:", url);
if (typeof callback === "function") {
callback(new Error("Error loading script"));
}
// Clean up after script execution
script.onload = script.onerror = null;
document.head.removeChild(script);
};
document.head.appendChild(script);
}
carregandoScriptSimpleSIP("./appWebrtc/simplesiplib.js", (error) => {
if (!error) {
console.log("::: Script loaded successfully!");
} else {
console.error(":::: Failed to load script:", error);
}
});
class EventEmitter {
constructor() {
this.events = {};
}
on(eventName, listener) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(listener);
}
emit(eventName, ...args) {
if (this.events[eventName]) {
this.events[eventName].forEach((listener) => listener(...args));
}
}
off(eventName, listener) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(
(fn) => fn !== listener
);
}
}
}
const eventoSip = new EventEmitter();
function Autenticacao(PROTOCOLO, SERVIDOR, PORTA, NOME, RAMAL, SENHA) {
this.PROTOCOLO = PROTOCOLO;
this.SERVIDOR = SERVIDOR;
this.PORTA = PORTA;
this.NOME = NOME;
this.RAMAL = RAMAL;
this.SENHA = SENHA;
}
const _Autenticacao = new Autenticacao();
const incomingCallAudio = new window.Audio(
"https://cdn.pixabay.com/download/audio/2021/08/04/audio_bb630cc098.mp3?filename=short-success-sound-glockenspiel-treasure-video-game-6346.mp3"
);
const outgoingCallAudio = new window.Audio(
"https://cdn.pixabay.com/download/audio/2022/03/14/audio_461a4fb0c4.mp3?filename=phonesound-65797.mp3"
);
const endCallAudio = new window.Audio(
"https://cdn.pixabay.com/download/audio/2022/03/17/audio_5eaa35a92e.mp3?filename=mobile_phone_hanging_up-94525.mp3"
);
incomingCallAudio.loop = true;
outgoingCallAudio.loop = true;
const localAudio = new window.Audio();
localAudio.autoplay = true;
const remoteAudio = new window.Audio();
remoteAudio.autoplay = true;
let phone;
let session;
let peerConnection = null;
function iniciandoAutenticacaonoPBX() {
const socket = new SimpleSIP.WebSocketInterface(
_Autenticacao.PROTOCOLO +
"://" +
_Autenticacao.SERVIDOR +
":" +
_Autenticacao.PORTA +
"/ws"
);
const configuration = {
uri: "sip:" + _Autenticacao.RAMAL + "@" + _Autenticacao.SERVIDOR,
password: _Autenticacao.SENHA,
sockets: [socket],
session_timers: false,
no_answer_timeout: 180,
hack_via_tcp: false,
hack_via_ws: true,
display_name:
_Autenticacao.NOME !== null ? _Autenticacao.NOME : _Autenticacao.RAMAL,
user_agent: "UASimpleSIP 1.2.0",
contact_uri:
"sip:" +
_Autenticacao.RAMAL +
"@" +
_Autenticacao.SERVIDOR +
";transport=" +
_Autenticacao.PROTOCOLO,
pcConfig: {
iceServers: [
{
urls: "stun:stun.l.google.com:19302",
},
{
urls: "stun:stun1.l.google.com:19302",
},
{
urls: "stun:stun2.l.google.com:19302",
},
],
},
};
if (configuration.uri && configuration.password) {
phone = new SimpleSIP.UA(configuration);
phone.on("registrationFailed", function (ev) {
console.log("Registering on SIP server failed with error: " + ev.cause);
configuration.uri = null;
configuration.password = null;
});
phone.on("newRTCSession", function (ev) {
const newSession = ev.session;
if (session) {
session = null;
}
//Para quando estou criando uma conexao, ou seja, estou realizando uma ligacao
if (newSession.connection) {
peerConnection = newSession.connection;
console.log("criou peerConnection", peerConnection);
}
//Para quando estou recebendo uma conexao
newSession.on("peerconnection", (event) => {
peerConnection = event.peerconnection;
console.log("recebeu o peerConnection", peerConnection);
});
//RECEBENDO UMA CHAMADA
if (newSession.direction === "incoming") {
incomingCallAudio.play();
eventoSip.emit("incomingcall", newSession.remote_identity.uri.user);
newSession.on("ended", () => {
session = null;
remoteAudio.srcObject = null;
incomingCallAudio.pause();
eventoSip.emit("home");
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
});
newSession.on("failed", () => {
session = null;
remoteAudio.srcObject = null;
incomingCallAudio.pause();
eventoSip.emit("home");
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
});
} else {
//REALIZANDO UMA CHAMADA
eventoSip.emit("outgoingcall");
newSession.on("ended", () => {
session = null;
remoteAudio.srcObject = null;
incomingCallAudio.pause();
eventoSip.emit("home");
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
});
newSession.on("failed", () => {
session = null;
remoteAudio.srcObject = null;
incomingCallAudio.pause();
eventoSip.emit("home");
if (peerConnection) {
peerConnection.close();
peerConnection = null;
}
});
}
//QUANDO FINALIZA UMA CHAMADA
newSession.on("ended", () => {
remoteAudio.srcObject = null;
session = null;
endCallAudio.play();
eventoSip.emit("confirmedEnded");
});
//QUANDO UMA CHAMADA EH REJEITADA
newSession.on("failed", () => {
incomingCallAudio.pause();
outgoingCallAudio.pause();
remoteAudio.srcObject = null;
session = null;
eventoSip.emit("home");
});
newSession.on("confirmed", function (event) {
// Verifica se session.connection esta definida
if (peerConnection) {
//Obter as tracks locais
const senders = peerConnection.getSenders();
const localStream = new MediaStream();
senders.forEach((sender) => {
if (sender.track) {
localStream.addTrack(sender.track);
}
});
//Atribuir ao localAudio
localAudio.srcObject = localStream;
//Volume definido para nao se ouvir, mas caso futuramente precise de midia de video, ja esta pronto.
localAudio.volume = 0;
//Obter as tracks remotas
const receivers = peerConnection.getReceivers();
const remoteStream = new MediaStream();
receivers.forEach((receiver) => {
if (receiver.track) {
remoteStream.addTrack(receiver.track);
}
});
remoteAudio.srcObject = remoteStream;
remoteAudio.volume = 1;
}
//PAUSA TODOS OS AUDIOS DE FEEDBACK
incomingCallAudio.pause();
outgoingCallAudio.pause();
eventoSip.emit("incall", newSession.remote_identity.uri.user);
});
newSession.on("newDTMF", function (event) {
console.log("DTMF recebido:", event.dtmf.tone);
});
newSession.on("icecandidate", function (event) {
if (
event.candidate.type === "srflx" &&
event.candidate.relatedAddress !== null &&
event.candidate.relatedPort !== null
) {
event.ready();
}
});
session = newSession;
});
phone.on("registered", function (e) {
eventoSip.emit("statusChange", "registered");
});
phone.on("unregistered", function (e) {
eventoSip.emit("statusChange", "unregistered");
});
phone.on("registrationFailed", function (e) {
eventoSip.emit("statusChange", "registrationFailed");
});
phone.on("connected", function (e) {
eventoSip.emit("statusChange", "connected");
});
phone.on("disconnected", function (e) {
eventoSip.emit("statusChange", "disconnected");
});
phone.start();
}
}
//Finalizar chamada
eventoSip.on("endCall", () => {
if (session) {
eventoSip.emit("confirmedEnded");
session.terminate();
session = null;
}
});
//Transferir diretamente a chamada
eventoSip.on("transferir", (data) => {
if (session) {
session.refer(data);
}
});
//Mutar chamada
eventoSip.on("mute", () => {
if (session) {
session.mute();
console.log(session?.isMuted());
}
});
//Desmutar chamada
eventoSip.on("unmute", () => {
if (session) {
session.unmute();
console.log(session?.isMuted());
}
});
//Enviar DTMF
eventoSip.on("enviarDTMF", (data) => {
if (session) {
session.sendDTMF(data);
}
});
//Aceitar chamada
eventoSip.on("accepted", (data) => {
try {
if (session) {
session.answer({
mediaConstraints: {
audio: true,
video: false,
},
});
eventoSip.emit("incall");
}
} catch (error) {
console.error("Erro ao aceitar chamada: ", error);
}
});
eventoSip.on('loginAutomatico', event => {
if(UASimplesIP.config){
console.log(UASimplesIP.config)
iniciandoAutenticacaonoPBX();
}
})
function ativaDebug(value) {
value === true
? SimpleSIP.debug.enable("SimpleSIP:*")
: SimpleSIP.debug.disable("SimpleSIP:*");
}
return {
config: _Autenticacao,
start: function () {
if (
_Autenticacao.PROTOCOLO === undefined ||
_Autenticacao.SERVIDOR === undefined ||
_Autenticacao.RAMAL === undefined ||
_Autenticacao.SENHA === undefined
) {
console.error(
":::: Configura<EFBFBD><EFBFBD>o do Usu<EFBFBD>rio Inv<EFBFBD>lida para Autentica<EFBFBD><EFBFBD>o no PBX !"
);
} else {
ativaDebug(false);
iniciandoAutenticacaonoPBX();
}
},
realizaUmaChamada: (numero) => {
const mediaConstraintsCall = {
audio: true,
video: false,
};
phone
? phone.call(numero, mediaConstraintsCall)
: eventoSip.emit("error");
},
ativaDebug: (value) => {
ativaDebug(value);
},
unregister: () => {
phone
? phone.unregister()
: console.warn("Sem ramal cadastrado para apagar");
},
estouRegistradonoPBX: () => {
console.log("estouRegistradonoPBX ::: " + phone.isRegistered());
},
simplesipEvento: eventoSip,
help: function () {
console.log("========================================================");
console.log("=== Unified Communications - Simples Ip - Version 1.2 ===");
console.log("========================================================");
},
};
})();