如何将 Asterisk ARI 与 socket.io 和 Node.js 一起使用
Posted
技术标签:
【中文标题】如何将 Asterisk ARI 与 socket.io 和 Node.js 一起使用【英文标题】:How to use Asterisk ARI with socket.io & Node.js 【发布时间】:2016-01-02 07:27:24 【问题描述】:最近开始接触星号、Linux、node.js 和最近的 socket.io,以便我最终可以为星号制作实时 Web 应用程序。
所以作为一个有根据的猜测,Node.js 有点像 Asterisk 和 Socket 之间的中间人。但我不知道如何通过 socket.io 将信息从星号提取到网页。
我一直在研究 socket.io 并且在如何将它们相互链接上已经不知所措了几天,这样我就可以记录停滞中发生的事件或在电话会议中拉出当前通话,只是任何事情在这一点上,由于据我所知 ARI 相对较新,因此很难弄清楚。
我在下面链接了 3 个文件,让您了解所做的工作,bridge-mixed.js 是基于星号 ARI 文档中给出的示例。
我可以通过node.js运行文件,拨打我在extensions.conf文件中指定的分机号,当第一个用户进入会议时播放音乐,一旦超过1个用户进入则停止音乐。
至于其他两个文件,它只是一个基本的 socket.io 应用程序,已通过 YouTube 指南逐步完成以了解其工作原理。
我只需要一个简单的例子来说明如何塑造它们或使它们一起工作,就可以开始为星号制作实时 Web 应用程序了。
即使我能够以某种方式通过 socket.io 和 Node.js 将停滞事件拉到网页上。
希望你们能提供一些见解或指导,因为此刻我真的迷失了。
bridge-mixed.js
/*jshint node:true*/
'use strict';
var ari = require('ari-client');
var util = require('util');
var chanArr =[];
ari.connect('http://localhost:0001', 'asterisk', 'asterisk', clientLoaded);
// handler for client being loaded
function clientLoaded (err, client)
if (err)
throw err;
// find or create a holding bridge
var bridge = null;
client.bridges.list(function(err, bridges)
if (err)
throw err;
bridge = bridges.filter(function(candidate)
return candidate.bridge_type === 'mixing';
)[0];
if (bridge)
console.log(util.format('Using bridge %s', bridge.id));
else
client.bridges.create(type: 'mixing', function(err, newBridge)
if (err)
throw err;
bridge = newBridge;
console.log(util.format('Created bridge %s', bridge.id));
);
);
// handler for StasisStart event
function stasisStart(event, channel)
console.log(util.format(
'Channel %s just entered our application, adding it to bridge %s',
channel.name,
bridge.id));
channel.answer(function(err)
if (err)
throw err;
bridge.addChannel(channel: channel.id, function(err)
chanArr.push(channel)
if (err)
throw err;
//If else statement to start music for first user entering channel, music will stop once more than 1 enters the channel.
if(chanArr.length <= 1)
bridge.startMoh(function(err)
if (err)
throw err;
);
else
bridge.stopMoh(function(err)
if (err)
throw err;
);
);
);
// handler for StasisEnd event
function stasisEnd(event, channel)
chanArr = null;
console.log(util.format(
'Channel %s just left our application', channel.name));
client.on('StasisStart', stasisStart);
client.on('StasisEnd', stasisEnd);
client.start('bridge-hold');
那么下面是一个非常基本的socket.io功能和html页面:
app.js
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
nicknames = [];
server.listen(0001);
app.get('/', function (req, res)
res.sendfile(__dirname + '/index.html');
);
io.sockets.on('connection', function (socket)
socket.on('new user', function (data, callback)
if (nicknames.indexOf(data) != -1)
callback(false);
else
callback(true);
socket.nickname = data;
nicknames.push(socket.nickname);
updateNicknames();
);
function updateNicknames()
io.sockets.emit('usernames', nicknames);
socket.on('send message', function (data)
io.sockets.emit('new message',
msg : data,
nick : socket.nickname
);
);
socket.on('disconnect', function (data)
if (!socket.nickname)
return;
nicknames.splice(nicknames.indexOf(socket.nickname), 1);
updateNicknames();
);
);
index.html
<html>
<head>
<title> Chat with socket.io and node.js</title>
<style>
#chat
height:500px;
#contentWrap
display:none;
#chatWrap
float:left;
border:1px #000 solid;
.error
color:red;
.whisper
color:gray;
font-style:italic;
</style>
</head>
<body>
<div id="nickWrap">
<p>Enter a Username</p>
<p id="nickError"></p>
<form id="setNick">
<input size="35" id="nickname"></input>
<input type="submit"></input>
</form>
</div>
<div id="contentWrap">
<div id="chatWrap">
<div id="chat"></div>
<form id="send-message">
<input size="35" id="message"></input>
<input type="submit"></input>
</form>
</div>
<div id="users"></div>
</div>
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.6.js"></script>
<script>
jQuery(function($)
var socket = io.connect();
var $nickForm = $('#setNick');
var $nickError = $('#nickError');
var $nickBox = $('#nickname');
var $users = $('#users');
var $messageForm = $('#send-message');
var $messageBox = $('#message');
var $chat = $('#chat');
$nickForm.submit(function(e)
e.preventDefault();
socket.emit('new user', $nickBox.val(), function(data)
if(data)
$('#nickWrap').hide();
$('#contentWrap').show();
else
$nickError.html('That username is already taken! Try Again.');
);
$nickBox.val('');
);
socket.on('usernames', function(data)
var html ='';
for(i=0; i < data.length; i++)
html += data[i] + '<br/>'
$users.html(html);
);
$messageForm.submit(function(e)
e.preventDefault();
socket.emit('send message', $messageBox.val(), function(data)
$chat.append('<span class="error"><b>' + data + "</span><br/>");
);
$messageBox.val('');
);
socket.on('new message', function(data)
$chat.append('<span class="msg"><b>' + data.nick + ': </b>' + data.msg + "</span><br/>");
);
socket.on('whisper', function(data)
$chat.append('<span class="whisper"><b>' + data.nick + ': </b>' + data.msg + "</span><br/>");
);
);
</script>
</body>
</html>
【问题讨论】:
【参考方案1】:因此,经过一些尝试和错误,可以通过有效地合并 bridge-mixed.js 和 app.js 文件让它们一起工作。完成此操作后,我可以开始通过 ARI 客户端访问星号端的信息,并开始通过 socket.io 将其传递给充当星号前端的实时 Web 应用程序。
当前发布的代码只是将当前调用者姓名附加到网页,但它是一个基本示例,它应该是一个很好的垫脚石,看看你可以用它做什么,因为那里的信息可以很容易地开始使用JQuery 开始做所有好事......例如静音呼叫,桥接从会议中踢出的用户。这些是目前正在进行的工作,将来会更新。
我希望这对某人有所帮助。
app.js(ARI 客户端和 Socket.io 服务器端)
ARI 函数和 socket.io 服务器端。
var ari = require('ari-client');
var util = require('util');
var chanArr = [];
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
//ARI client
ari.connect('http://localhost:8088', 'asterisk', 'asterisk', clientLoaded);
function clientLoaded(err, client)
if (err)
throw err;
// find or create a holding bridges
var bridge = null;
client.bridges.list(function (err, bridges)
if (err)
throw err;
bridge = bridges.filter(function (candidate)
return candidate.bridge_type === 'mixing';
)[0];
if (bridge)
console.log(util.format('Using bridge %s', bridge.id));
else
client.bridges.create(
type : 'mixing'
, function (err, newBridge)
if (err)
throw err;
bridge = newBridge;
console.log(util.format('Created bridge %s', bridge.id));
);
);
// handler for StasisStart event
function stasisStart(event, channel)
console.log(util.format(
'Channel %s just entered our application, adding it to bridge %s',
channel.name,
bridge.id));
channel.answer(function (err)
if (err)
throw err;
bridge.addChannel(
channel : channel.id
, function (err)
var id = chanArr.push(channel.name)
console.log("User: " + channel.name);
if (err)
throw err;
//If else statement to start music for first user entering channel, music will stop once more than 1 enters the channel.
if (chanArr.length <= 1)
bridge.startMoh(function (err)
if (err)
throw err;
);
else
bridge.stopMoh(function (err)
if (err)
throw err;
);
);
);
// handler for StasisEnd event
function stasisEnd(event, channel)
chanArr = null;
console.log(util.format(
'Channel %s just left our application', channel.name));
client.on('StasisStart', stasisStart);
client.on('StasisEnd', stasisEnd);
client.start('bridge-hold');
//Socket.io logic here
server.listen(3009, function ()
console.log('listening on *:3009');
);
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res)
res.sendfile(__dirname + "/testPage.html");
);
io.sockets.on('connection', function ()
updateSip();
);
function updateSip()
io.sockets.emit('sip', chanArr);
testPage.html
Web 应用程序前端。
<html>
<head>
<title> Chat with socket.io and node.js</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.0/css/bootstrap-toggle.min.css" rel="stylesheet">
<link href="/css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-header">
<div class="navbar-brand">Asterisk ARI Test Application</div>
</div>
<div id="navbar" class="navbar-collapse collapse">
</div>
</nav>
<div class="main-bridge">
<div class="container">
<div class="jumbotron content-A">
<form class="test-ari">
<p class="lead">Enter the number you want to call.</p>
<div class="input-group input-group-lg">
<input type="tel" class="form-control" placeholder="Phone Number" aria-describedby="sizing-addon1" required="" />
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Call Back Now</button>
</span>
</div>
</form>
</div>
</div>
</div>
<div class="secondary-bridge" id="sip">
<h3 class="conf-head">Conference call</h3>
<div class="panel panel-default ">
<div class="panel-heading " >
<h3 class="panel-title"><div id="sip"></div></h3>
</div>
<div class="panel-body">
<input type="checkbox" data-on="Voice" data-off="Muted" checked data-toggle="toggle" data-onstyle="success" data-offstyle="danger">
<button class="btn btn-default kick" id="kick" data-toggle="modal" data-target="#myModal" type="submit">Kick</button>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Kick user</h4>
</div>
<div class="modal-body">
Are you you want to kick this user?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-primary">Yes</button>
</div>
</div>
</div>
</div>
<footer class="footer">
<p>© User 2015</p>
</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.0/js/bootstrap-toggle.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.6.js"></script>
<script src="/js/test.js"></script>
</body>
</html>
test.js
Socket.io 客户端和其他一些 JQuery。
jQuery(function ($)
var socket = io.connect();
var $sip = $('#sip');
socket.on('sip', function (data)
var sip = '';
for (i = 0; i < data.length; i++)
sip += data[i] + '<br/>'
$sip.append('<h3 class="conf-head">Conference call</h3> \
<div class="panel panel-default ">\
<div class="panel-heading " >\
<h3 class="panel-title">' + sip + '</h3>\
</div>\
<div class="panel-body">\
<input type="checkbox" data-on="Voice" data-off="Muted" checked data-toggle="toggle" data-onstyle="success" data-offstyle="danger">\
<button class="btn btn-default kick" id="kick" data-toggle="modal" data-target="#myModal" type="submit">Kick</button>\
</div>\
</div>');
);
$('.kick').click(function ()
$('#myInput').focus()
);
);
【讨论】:
我正在使用这个例子,但是当我打电话时我没有收到任何结果。wscat -c "ws://localhost:8088/ari/events?api_key=user:secret&app=my-app"
我收到了.. 你知道为什么吗?以上是关于如何将 Asterisk ARI 与 socket.io 和 Node.js 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
为啥Adjusted rand index(ARI)优于rand index(RI)以及如何从公式中直观理解ARI