valrecx
valrecx

Reputation: 469

Running javascript inside rest api

I'm working on asterisk. I managed to call an external api using dialplan. Now I want to run a javascript inside that api function, because I need to notify a browser that someone is calling. What I'm thinking is that I can do that using node.js. I don't want to use ajax polling cause it is bad.

The following are the process when someone is calling

Call -> Trigger dialplan -> Call external api via AGI method -> run javascript websocket event inside api -> notify browser.

Is that possible? or there is much better way.

Upvotes: 0

Views: 1199

Answers (2)

zichen.L
zichen.L

Reputation: 370

You said that "want to notify a browser that someone is calling", so I think the Web Socket is the solution you are looking for.

WebSocket is defined as a two-way communication between the servers and the clients, which mean both the parties, communicate and exchange data at the same time.

The Asterisk 17 Events REST API describes that WebSocket connection used for events, here is an example to generate a WebSocket connection in CLI Asterisk.

Here is my situation tested:

enter image description here

The http server node has 2 roles:

  1. be a WebSocket client, it gets messages from the server Asterisk via ARI (Aterisk Rest Interface).
  2. be a http server that attaches socket.io, it notifies some informations to all socket.io clients

1. Create a user in /etc/asterisk/ari.conf

Here I defined a user 'toto' with password 'pass1'

enter image description here

2. app.js

npm install websocket socket.io

var http = require('http');
var fs = require('fs');

// Loading the index.html file displayed to the client (browser)
var httpserver = http.createServer(function(req, res) {
    fs.readFile('./index.html', 'utf-8', function(error, content) {
        res.writeHead(200, {"Content-Type": "text/html"});
        res.end(content);
    });   
});


// create a ws connection to the server asterisk
const WebSocket = require('ws');
const ws_client = new WebSocket('ws://192.168.141.235:8088/ari/events?api_key=toto:pass1&app=hello&subscribeAll=true');


// ws_client listens to the event 'error' for getting errors 
// when the server asterisk has some socket connection problems
ws_client.on('error',function error(error){ 
    console.log(error);
})

// create an instance socket.io attached to http server
var io_httpserver = require('socket.io')(httpserver);


//listens all clients which connect to the socket 'mysocket', 
//in this case we have only one client (sokcet.io_client_1) in index.html
io_httpserver.sockets.on('connection', function (mysocket) {
    // ws_client listens to the event 'message' for getting data of the server asterisk
    ws_client.on('message',function show(data){
        //send data to all clients which listen to the custom event 'titi' 
        mysocket.emit('titi',data); 
    })
  });

httpserver.listen(8080);

3. index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Socket.io</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
    </head>

    <body>
        <h1>Real time application</h1>
        <table id="one" class="table table-dark">
            <thead>
                <tr>
                  <th scope="col">date</th>
                  <th scope="col">endpoints</th>
                  <th scope="col">states</th>
                </tr>
              </thead>
              <tbody>
              </tbody>
        </table>
        <script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
        <script>
         var tab = document.getElementById('one');
         var sokcet_io_client_1 = io.connect('http://localhost:8080');
            sokcet_io_client_1.on('titi', function(data) {
                console.log(data)
                var obj = JSON.parse(data);
                if(obj.type=="DeviceStateChanged"){
                    var date = obj.timestamp.split('.')[0].replace("T", "  ");
                    tab.insertAdjacentHTML('beforeend', '<td>'+date+'</td><td>'+obj.device_state.name+'</td><td>'+obj.device_state.state+'</td>');
                }
                })

        </script>
    </body>
</html>

Finally load app.js :

node app.js

Result: enter image description here

Upvotes: 0

Matt Jordan
Matt Jordan

Reputation: 2884

The answer is "yes" - but it also depends on the API you want to use, and what you're attempting to accomplish.

Asterisk has three "main" APIs: AMI, AGI, and ARI. AMI and AGI have existed for a long time; ARI - the Asterisk REST Interface - is relatively new. To quote from the Asterisk wiki:

Not long into the project, two application programming interfaces (APIs) were added to Asterisk: the Asterisk Gateway Interface (AGI) and the Asterisk Manager Interface (AMI). These interfaces have distinct purposes:

  1. AGI is analogous to CGI in Apache. AGI provides an interface between the Asterisk dialplan and an external program that wants to manipulate a channel in the dialplan. In general, the interface is synchronous - actions taken on a channel from an AGI block and do not return until the action is completed.
  2. AMI provides a mechanism to control where channels execute in the dialplan. Unlike AGI, AMI is an asynchronous, event driven interface. For the most part, AMI does not provide mechanisms to control channel execution - rather, it provides information about the state of the channels and controls about where the channels are executing

Unlike AMI and AGI, ARI is all about letting you write your own dialplan applications. If you're interested in it, I highly suggest you check out the wiki page linked above.

The API you choose should be based on what you're looking to accomplish. Since you're looking to do a call pop, you really could do that either AMI (by listening for some event trigger) or through ARI (by having the channel enter the Stasis dialplan application, executing a custom node.js ARI application).

There are node.js libraries for both APIs:

AMI

ARI

Upvotes: 1

Related Questions