Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   помогите с асинхронными событиями nodejs+websockets+библиотечка nami (https://javascript.ru/forum/node-js-io-js/62194-pomogite-s-asinkhronnymi-sobytiyami-nodejs-websockets-bibliotechka-nami.html)

stonecone 29.03.2016 07:50

помогите с асинхронными событиями nodejs+websockets+библиотечка nami
 
Добрый день!
Не нашел на сайте раздела для новичков, поэтому пишу сюда.
В общем задача сгенерировать звонок от оператора на астериске.
Взял nodejs + websockets + nami (https://github.com/marcelog/Nami

т.е. структура такая:

[WS-Client] --- [Node.js + WS + NAMI] --- [Asterisk AMI]

я склепал тестовый myserver.js для node и вот тут столкнулся с так сказать архитектурной проблемой
код прилагаю
var logger = require(__dirname + "/node_modules/nami/node_modules/log4js").getLogger('Nami.App');
var http = require('http');
var WebSocketServer = require('ws');
var namiLib = require(__dirname + '/node_modules/nami/src/nami.js');
var call = require('./call');
var clients = {};

var namiConfig = {
    host: '192.168.1.2',
    port: '5038',
    username: 'amiuser',
    secret: 'amipass'
};

var nami = new namiLib.Nami(namiConfig);

nami.logger.setLevel("OFF");
process.on('SIGINT', function() {
    nami.close();
    process.exit();
});

nami.on('namiConnectionClose', function (data) {
    logger.debug('Reconnecting...');
    setTimeout(function () { nami.open(); }, 5000);
});

nami.on('namiLoginIncorrect', function () {
    logger.fatal("Invalid Credentials");
    process.exit();
});

nami.on('namiEvent', function (event) {
    //logger.debug('Got Event: ' + util.inspect(event));
    //if (event.get("ActionID") !== undefined) {
        logger.debug(util.inspect(event));
    //}
    //logger.debug("hehe");
});
nami.on('namiInvalidPeer', function (data) {
    logger.fatal("Invalid AMI Salute. Not an AMI?");
    process.exit();
});

nami.on('namiConnected', function(event){
    console.log("nami connected");
});
nami.open();

var webSocketServer = new WebSocketServer.Server({
    port: 8081
});

webSocketServer.on('connection', function (ws) {
    ws.on('message', function (message) {
        msg = JSON.parse(message);
        var newcall = new call.Call(ws);
        clients[newcall.actionid] = newcall;
        if ( msg.action === "call" && phoneIsValid(msg.phonenumber) && opNumIsValid(msg.operatornumber) ) {
            var action = new namiLib.Actions.Originate();
            action.channel = "Local/" + msg.operatornumber + "@local-calls";
            action.callerid = msg.phonenumber;
            action.priority = "1";
            action.timeout = "30000";
            action.context = "callcenter";
            action.exten = msg.phonenumber;
            action.ActionID = newcall.actionid;
            action.async = "yes";
            nami.send(action, function (response) {

            });
            respmsg = {
                type: "status",
                status: "Calling " + msg.phonenumber
            };
            ws.send(JSON.stringify(respmsg));
        }
        ws.on('close', function() {
            delete clients[newcall.actionid];
        });
    });
});

var server = http.createServer(function (request, response){
    var headers = request.headers;
    var method = request.method;
    var url = request.url;
    var body = [];
    request.on('error', function (err) {
        console.error(err);
    }).on('data', function (chunk) {
        body.push(chunk);
    }).on('end', function () {
        body = Buffer.concat(body).toString();
    });

    response.on('error', function(err){
        console.error(err);
    });

    response.statusCode = 200;
    response.setHeader('Content-Type', 'application/json');

    var responseBody = {
        headers: headers,
        method: method,
        url: url,
        body: body
    };

    response.write(JSON.stringify(responseBody));
    response.end();

}).listen(8085);

function phoneIsValid(phone) {
    if ( phone ) {
        regex = /^89\d{9}$/;
        return phone.match(regex);
    }
    return false;
}

// operator number must be 1XX or 2XX
function opNumIsValid(phone) {
    if ( phone ) {
        return phone.match(/^[12]{1}[0-9]{2}$/);
    }
    return false;
}

в общем я не пойму следующее - у меня есть
webSocketServer.on('connection', function (ws) {});

и внутри я навешиваю на события действия. Прекрасно.
Также есть всевозможные
nami.on({});

в них я навешиваю действия при получении чего-то от астериска.
А как мне навешать в nami.on передать что-то в вебсокет, ведь вебсокет в отдельном объекте. В общем я похоже даже не могу правильно словами выразить )))
Как мне повешать в
nami.on('namiEvent', function(event){});

отправку в вебсокет? Фильтры я уж догадаюсь сделать.
Я не понимаю как мне связать эти два разных объекта.
Как правильно это сделать по структуре, объясните пожалуйста.
Я новичок, но не полный нуль.
Спасибо!

Max Power 01.04.2016 02:27

> Я новичок, но не полный нуль.
> Спасибо!

Да пожалуйста! А что вы сделали чтобы локализовать проблему? Вангую - ни один нормальный чел не полезет в 130-страничный листинг с локальной проблемой и какой-то спец либой, которую из русскоговорящих знают двое.

ramauf 17.04.2016 20:15

ты решил вопрос? у меня то же самое, поясню короче
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
function handler (req, res) {
/*тут разный код*/
}
io.on('connection', function (socket) {
/*тут разный код*/
});
var timer = setInterval(function(){
/*как отсюда вызвать socket.emit?*/
});

ramauf 17.04.2016 20:16

ты решил вопрос? у меня то же самое, поясню короче
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
function handler (req, res) {
/*тут разный код*/
}
io.on('connection', function (socket) {
/*тут разный код*/
});
var timer = setInterval(function(){
/*как отсюда вызвать socket.emit?*/
});



да и еще при этом онлайн может быть 100 юзверей, т.е. заводить таймер внутри io.on('connection'.... разумно ли? 0_о

помогите решить!!!!!

stonecone 18.04.2016 10:35

ramauf,
нет не решил еще
взял Стояна Стефанова "Javascript шаблоны", читаю про шаблоны "Посредник" и "Прокси", думаю где-то здесь.
Это какая-то стандартная несложная схема должна быть.
Просто форумчанин который мне ответил до тебя не понял моего вопроса. Как разберусь отпишу сюда обязательно.

stonecone 19.04.2016 10:43

в общем я сделал так:
1. создал объект call (звонок), это по сути связка "JS клиент подключенный к websocket" (храню в свойстве сокет) ---- "id звонка который запросил клиент" (храню в свойствах actionid и uniqueid)
2. создал массив clients, куда складываю объекты из п. 1.
3. при инициации клиентом звонка (мне клиент не нужен на стадии подключения, я с ним не собираюсь общаться помимо звонков) создаю объект из п. 1 и кладу его в массив клиентов. При отключении клиента удаляю объект звонка из массива. Тут все инициируется со стороны вебсокетов, со стороны js клиента.
4. при окончании звонка (их неск вариантов) отправляю статус JS клиенту и опять же удаляю объект звонка из массива. А тут вызов происходит со стороны AMI, т.е. есть со стороны астериска. Всё.
у тебя это будет выглядеть как-то так
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
// создай и подключи класс Клиент вот тут Илья все классно объясняет: [url]http://www.youtube.com/watch?v=g740J-RyoR4&index=5&list=PLDyvV36pndZFWfEQpNixIHVvp191Hb3Gg[/url] 
var сlient = require(./client);
// массив с твоими клиентами, можно тут хранить имена, сокеты и айди если надо, сам нарисуй объект со свойствами которые тебе нужны
clients = [];
function handler (req, res) {
/*тут разный код*/
}
io.on('connection', function (socket) {
 // при подключении создаешь объект Клиент и кладешь его в массив клиентов
 client = new client.Client(ws);
/*тут разный код*/
});
var timer = setInterval(function(){
/*как отсюда вызвать socket.emit?*/
// тут шлешь своим клиентам сообщения если я тебя правильно понял
clients.forEach(function(client, i, clients){
    msg = {
        type: "status",
        status: "originatefailed"
    };
    ws.send(JSON.stringify(msg));
});
});


правда у тебя socket.io, я использовал ws, но суть та же - нужно хранилище клиентов-сокетов
на лучшее решение не претендую, могут быть ошибки в коде, но идея думаю ясна

ramauf 19.04.2016 19:32

точно точно, посмарел код на стороннем двиге и тоже пришел к выводу, что надо заводить глобальную переменную и туда складывать, пасиб за подсказку!


Часовой пояс GMT +3, время: 02:11.