@fobya

Как переадресовать вызов asterisk на nodejs приложение?

В рамках частной подсети 10.12.0.0/24 есть два сервера
1) 10.12.0.130 - на нем установлен asterisk и два номера - 1000 и 1001
2) Nodejs приложение на сервере 10.12.0.30
Если для обоих номеров использовать linphone - связь без проблем устанавливается, но если для номера 1000 указать клиент AsteriskAgi (nodejs приложение) звонок приходит - но данные ( голос ) не передаются
В чем может быть проблема?
Использовать AsteriskAgi необязтельно
Файл extensions.conf:
[internal]
   exten => 1000,1,AGI(agi://10.12.0.30:5062)
   exten => 1001,1,Dial(PJSIP/1001,20)
   exten => 1002,1,Dial(PJSIP/1002,20)
   exten => 1003,1,Dial(PJSIP/1002,20)

pjsip.conf:
[1003]
type=endpoint
context=internal
disallow=all
allow=ulaw
auth=auth1003
aors=1003

[auth1003]
type=auth
auth_type=userpass
password=1003p
username=1003

[1003]
type=aor
max_contacts=1



[1000]
type=endpoint
context=internal
disallow=all
allow=ulaw
auth=auth1000
aors=1000

[auth1000]
type=auth
auth_type=userpass
password=1000p
username=1000

[1000]
type=aor
max_contacts=1

[1001]
type=endpoint
context=internal
disallow=all
allow=ulaw
auth=auth1001
aors=1001

[auth1001]
type=auth
auth_type=userpass
password=1001p
username=1001

[1001]
type=aor
max_contacts=1


[1002]
type=endpoint
context=internal
disallow=all
allow=ulaw
auth=auth1002
aors=1002

[auth1002]
type=auth
auth_type=userpass
password=1002p
username=1002

[1002]
type=aor
max_contacts=1

Связь между всеми номерами по linphone работает нормально, но AGI - нет.
Буду рад если поможете разобраться или посоветуете другую архитектуру.
P.S. Не знаю как мониторить RTP пакеты, но в логах asterisk CLI бесконечно много спамит строка
Got RTP packet from 10.12.0.22:33639 (type 00, seq 002087, ts 635031636, len 000640)

Полный код nodejs приложения:
const AGIServer = require('asteriskagi');
const express = require('express');
const bodyParser = require('body-parser');
const { spawn } = require('child_process');

const app = express();
app.use(bodyParser.json());

let currentCall = null;

// Настройка AGI сервера
const agi = new AGIServer({port: 5062}); // Server (optional port, default: 4573)

console.log(agi)
agi.on("call", async (call) => {
    const {
        remoteServer,
        uniqueid,
        context,
        extension,
        priority,
        calleridname,
        callerid,
        channel,
    } = call;

    console.log(`Incoming call from: ${callerid}`);
    console.log(`Call details: ${JSON.stringify({ remoteServer, uniqueid, context, extension, priority, calleridname, callerid, channel })}`);

    // Сохранение текущего вызова
    currentCall = call;

    call.on("hangup", () => {
        console.log(`Hangup  ${remoteServer}/${channel}`);
        currentCall = null;
    });

    call.on("error", (err) => {
        console.error(`ERROR: ${remoteServer}/${channel}: ${err}`);
        currentCall = null;
    });

    // Убираем автоматический ответ на вызов
    await call.Answer();

    console.log('NEW CALL!!!');
    call.on('data', (data) => {
        try {
            console.log('Received data from call');
        console.log(data); // Логирование данных
        ffmpegProcess.stdin.write(data);
        } catch (error) {
            console.log(error)
        }
    });
    await call.Playback("beep");

    await call.SayDigits('1234');
    // console.log('Said digits 1234');
    // console.log(call)
    // console.log(call['_events'])
    // console.log(call.AGI)
});

// HTTP-сервер для обработки запросов
app.post('/answer', async (req, res) => {
    if (currentCall) {
        const call = currentCall;

        try {
            await call.Answer();
            console.log('Call answered');

            // Использование ffmpeg для воспроизведения аудио через устройство
            const audioOutputDevice = req.body.audioOutputDevice || 'default'; // Получение устройства из запроса или использование устройства по умолчанию
            console.log(`Using audio output device: ${audioOutputDevice}`);

            const ffmpegProcess = spawn('ffmpeg', [
                '-f', 's16le', 
                '-ar', '8000', 
                '-ac', '1', 
                '-i', '-', 
                '-f', 'alsa', 
                audioOutputDevice
            ]);

            ffmpegProcess.stdin.on('error', (error) => {
                console.error('Error writing to ffmpeg stdin:', error);
            });

            ffmpegProcess.stderr.on('data', (data) => {
                console.error(`ffmpeg stderr: ${data}`);
            });

            ffmpegProcess.on('close', (code) => {
                console.log(`ffmpeg process exited with code ${code}`);
            });

            call.on('data', (data) => {
                console.log('Received data from call');
                console.log(data); // Логирование данных
                ffmpegProcess.stdin.write(data);
            });

            call.on('end', () => {
                console.log('Call ended');
                ffmpegProcess.stdin.end();
            });

            res.status(200).send('Call answered');
        } catch (err) {
            console.error('Error answering call:', err);
            await call.Hangup();
            res.status(500).send('Error answering call');
            currentCall = null;
        }
    } else {
        res.status(400).send('No incoming call to answer');
    }
});
// Запуск HTTP-сервера
app.listen(4000, () => {
    console.log('HTTP server listening on port 4000');
});

call.on('data') не вызывается
  • Вопрос задан
  • 109 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы