我有一个示例应用程序(Node Js,Socket.io,ngrok),用于从NexmoLive Call获取实时数据流。当我尝试打开客户端时,我们能够从控制台中的WebSocket节点使用voicebase转录获取数据socket,服务器套接字关闭,ngrok获取502 BadGateway
例外,我已添加下面的服务器和套接字代码
Socket.js
var socket = io("https://0302de8a.ngrok.io");
var actionItems = []
var beginTakingAction = false
var strOut;
socket.on('transcript', function(x) {
var div = $('div.transcription')
div.html(x);
console.log("transcript " + x);
if (!scrolling) {
div.scrollTop(div[0].scrollHeight);
}
})
socket.on('action', function(x) {
console.log('sending action',x);
actionItems.push(x)
$('div.action').html(actionItems[actionItems.length-1]);
})
socket.on('sentiment', function(x) {
sentimentChart.update(x)
})
socket.on('nlp', function(x) {
wordLengthDistChart.update(x.wordLenghDist);
posTagDistChart.update(x.posTagDist);
})
socket.on('keywords', function(x) {
keywordChart.update(x)
})
socket.on('status', function(status) {
$('div.status').html("status: " + status);
if (status == "connected") {
sentimentChart.reset()
keywordChart.reset()
wordLengthDistChart.reset()
posTagDistChart.reset()
$('div.transcription').html('');
}
})
服务器
require('dotenv').config()
var express = require('express')
var app = express()
var bodyParser = require('body-parser');
var Nexmo = require('nexmo');
var Promise = require('bluebird');
var util = require("util");
const winston = require('winston')
var executed = false;
var didStart = false
var USER_NUMBER = ""
var WEB_SOCKET = 'ws://' + process.env.WEB_SOCKET_URL + '/socket';
var SMS_TEXT = "View the transcription service here: " + "http://" + process.env.WEB_SOCKET_URL;
var converstationIDs = [];
var connectedUsers = [];
var nexmo = new Nexmo({
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
applicationId: process.env.APPLICATION_ID,
privateKey: __dirname + '/' + process.env.PRIVATE_KEY_PATH
},
{ debug: process.env.NEXMO_DEBUG }
);
winston.level = process.env.LOG_LEVEL
var calls = Promise.promisifyAll(nexmo.calls);
app.set('port', process.env.PORT || 8080)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
winston.log('debug', 'env vars', process.env);
app.get('/answer', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
winston.log('info', 'answer route called', req.body);
reset()
var url = require('url');
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
connectedUsers.push(query.from);
winston.log('debug', 'adding user to sms list', connectedUsers);
if (process.env.SINGLE_USER) {
winston.log('debug', 'In single user mode');
var json = [
{
"action": "connect",
"eventUrl": [
"https://call-dev.url.net/events"
],
"from": process.env.NEXMO_NUMBER,
"endpoint": [
{
"type": "websocket",
"uri": WEB_SOCKET,
"content-type": "audio/l16;rate=16000",
"headers": {
"app": "audiosocket"
}
}
]
}
]
winston.log('info', 'conference JSON', json);
res.send(json)
return
}
if (process.env.TO_NUMBER) {
var json = [
{
"action": "talk",
"text": "Calling user"
},
{
"action": "conversation",
"name": process.env.CONFERENCE_NAME,
"endOnExit": "true"
}
]
var to = {
type: 'phone',
number: process.env.TO_NUMBER,
}
winston.log('info', 'answer JSON', json);
dial(to, process.env.NEXMO_NUMBER, req.headers.host, function (result) {
winston.log('info', 'dial result', result);
res.send(json)
})
} else {
var baseURL = "http://" + req.headers.host;
var json = [
{
"action": "talk",
"text": "Please enter a phone number to call, press the pound key when complete",
"bargeIn": "false"
},
{
"action": "input",
"submitOnHash": true,
"timeOut": 60,
"maxDigits": 20,
"eventUrl": [baseURL + "/events_ivr"]
},
{
"action": "conversation",
"name": process.env.CONFERENCE_NAME,
"endOnExit": "true",
}
]
winston.log('info', 'answer JSON', json);
res.send(json)
}
})
app.get('/conference', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
var url = require('url');
var url_parts = url.parse(req.url, true);
var query = url_parts.query;
var json = [
{
"action": "talk",
"text": "Dialing into the conference now",
},
{
"action": "conversation",
"name": process.env.CONFERENCE_NAME,
"startOnEnter": "false"
}
]
winston.log('info', 'conference JSON', json);
res.send(json)
})
app.post('/events_ivr', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
winston.log('info', 'events_ivr', req.body);
var baseURL = req.headers.host;
var number = req.body.dtmf;
var from = req.body.from;
USER_NUMBER = number
if (number == '' || number.length < 11) {
winston.log('debug', 'could not get dtmf number', number);
var json = [
{
"action": "talk",
"text": "Sorry, I did not get that phone number. Goodbye"
}
]
res.send(json);
} else {
var to = {
type: 'phone',
number: number,
}
dial(to, process.env.NEXMO_NUMBER, baseURL, function (result) {
winston.log('info', 'IVR Dial result', result);
})
res.sendStatus(200);
}
});
app.post('/events', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
winston.log('info', 'events', req.body);
var baseURL = req.headers.host;
var from = req.body.from;
if (req.body.status == "answered") {
converstationIDs.push(req.body.uuid);
winston.log('debug', 'adding converstaion uuid', converstationIDs);
if (req.body.to != process.env.NEXMO_NUMBER && req.body.to != WEB_SOCKET) {
connectedUsers.push(req.body.to);
winston.log('debug', 'adding user to sms list', connectedUsers);
}
if (req.body.to == USER_NUMBER || req.body.to == process.env.TO_NUMBER) {
var to = {
type: 'websocket',
uri: WEB_SOCKET,
"content-type": "audio/l16;rate=16000",
"headers": {
"app": "audiosocket"
}
}
winston.log('debug', 'calling websocket', req.body);
dial(to, from, baseURL, function (result) {
winston.log('debug', 'called websocket', result);
sendAllSms(SMS_TEXT, function () {
winston.log('info', 'all sms sent');
})
})
res.sendStatus(200);
return
}
}
else if (req.body.status == "completed") {
winston.log('debug', 'called ended', req.body);
winston.log('debug', 'calling hangup');
performHangup()
}
res.sendStatus(200);
});
var performHangup = (function () {
return function () {
winston.log('debug', "executed " + executed + " didStart " + didStart)
if (!executed && !didStart) {
didStart = true
hangupCalls(function () {
executed = true;
winston.log('info', 'hangup complete');
})
}
};
})();
process.on('unhandledRejection', (reason) => {
winston.log('error', 'unhandledRejection', reason)
});
;
app.listen(process.env.PORT || 8080, function () {
winston.log('info', 'Nexmo Phone app listening on port ' + (process.env.PORT || 8080))
})
function dial(to, from, serverURL, callback) {
var json = {
to: [to],
from: {
type: 'phone',
number: from
},
answer_url: ['http://' + serverURL + '/conference'],
event_url: ['http://' + serverURL + '/events', 'http://' + process.env.WEB_SOCKET_URL + '/events']
}
winston.debug('debug', 'dial JSON', json);
calls.createAsync(json).then(function (res) {
winston.log('debug', 'call created', res)
callback(res)
})
}
function hangupCalls(callback) {
Promise.each(converstationIDs, function (converstationID) {
return new Promise(function (resolve, reject) {
calls.updateAsync(converstationID, { action: 'hangup' })
.then(function (resp) {
setTimeout(function () {
winston.log('info', 'hangup result: for id: ' + converstationID, resp)
resolve();
}, 2000)
})
});
})
.then(function (allItems) {
winston.log('debug', 'all items', allItems)
callback();
})
}
function terminate(callback) {
winston.log('debug', 'calling terminate');
var request = require('request');
request({
url: 'http://' + process.env.WEB_SOCKET_URL + '/terminate',
method: 'POST',
json: true,
headers: { 'content-type': 'application/json' },
}, (err, res, body) => {
winston.log('debug', 'terminate called');
callback()
})
}
function sendAllSms(message, callback) {
Promise.each(connectedUsers, function (phoneNumber) {
return new Promise(function (resolve, reject) {
sendSMS(phoneNumber, SMS_TEXT, function (resp) {
setTimeout(function () {
winston.log('info', 'sending sms to phoneNumber: ' + phoneNumber, resp)
resolve();
}, 1000)
})
});
})
.then(function (allItems) {
winston.log('debug', 'all items', allItems)
callback();
})
}
function sendSMS(phoneNumber, message, callback) {
var https = require('https');
var data = JSON.stringify({
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET,
to: phoneNumber,
from: process.env.NEXMO_NUMBER,
text: message
});
var options = {
host: 'rest.nexmo.com',
path: '/sms/json',
port: 443,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data)
}
};
var req = https.request(options);
req.write(data);
req.end();
var responseData = '';
req.on('response', function (res) {
res.on('data', function (chunk) {
responseData += chunk;
});
res.on('end', function () {
callback(JSON.parse(responseData))
});
});
}
function reset() {
connectedUsers.length = 0
converstationIDs.length = 0;
executed = false;
didStart = false
}
socket.on('action', function(x) {
console.log('sending action',x);
actionItems.push(x)
$('div.action').html(actionItems[actionItems.length-1]);
})
socket.on('sentiment', function(x) {
sentimentChart.update(x)
})
socket.on('nlp', function(x) {
wordLengthDistChart.update(x.wordLenghDist);
posTagDistChart.update(x.posTagDist);
})
socket.on('keywords', function(x) {
keywordChart.update(x)
})
socket.on('status', function(status) {
$('div.status').html("status: " + status);
if (status == "connected") {
sentimentChart.reset()
keywordChart.reset()
wordLengthDistChart.reset()
posTagDistChart.reset()
$('div.transcription').html('');
}
})
控制台
+ socket.io@2.0.4
updated 1 package in 2.522s
PS D:\workspace projects\new\Nexmo-RTS-Voicebase\WS-node> npm start
> ws-node@1.0.0 start D:\workspace projects\new\Nexmo-RTS-Voicebase\WS-node
> node app.js
info: Server listening on :8000
info: handleRequest /
info: loading index
info: port
info: handleRequest /public/voicebase.png
info: handleRequest /public/nexmo.png
info: handleRequest /public/js/charts.js
info: handleRequest /public/js/socket.js
info: A client is connected!
info: handleRequest /favicon.ico
events.js:183
throw er; // Unhandled 'error' event
^
Error: This socket is closed
at Socket._writeGeneric (net.js:726:18)
at Socket._write (net.js:786:8)
at doWrite (_stream_writable.js:387:12)
at writeOrBuffer (_stream_writable.js:373:5)
at Socket.Writable.write (_stream_writable.js:290:11)
at Socket.write (net.js:704:40)
at WebSocketRequest.accept (D:\workspace projects\new\Nexmo-RTS-Voicebase\WS-node\node_modules\websocket\lib\WebSocketRequest.js:450:21)
at WebSocketServer.handleUpgrade (D:\workspace projects\new\Nexmo-RTS-Voicebase\WS-node\node_modules\websocket\lib\WebSocketServer.js:216:19)
at emitThree (events.js:141:20)
at Server.emit (events.js:217:7)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! ws-node@1.0.0 start: `node app.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the ws-node@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
NGROK错误
答案 0 :(得分:0)
这仅在您的服务器未运行时发生;。