Node.js ARI Client -- Channel Events
Node.js ARI Client: Channel Events
A minimal Node.js application that connects to the Asterisk REST Interface, listens for channel events, and controls the call lifecycle: ring the channel, answer after 2 seconds, play silence, then hang up after 4 seconds.
Requirements
- ARI enabled in Asterisk (see ARI Setup and Stasis Application)
- Node.js installed on the Asterisk server or a host that can reach port 8088
ari-clientnpm package
package.json
}
channel-state.js
'use strict';
var ari = require('ari-client');
var util = require('util');
var timers = {};
ari.connect('http://localhost:8088', 'asterisk', 'asterisk', clientLoaded);
function clientLoaded(err, client) {
if (err) { throw err; }
function stasisStart(event, channel) {
console.log(util.format(
'Channel %s has entered the application', channel.name));
// Ring the channel immediately
channel.ring(function(err) { if (err) throw err; });
// Answer after 2 seconds
var timer = setTimeout(function() {
console.log(util.format('Answering channel %s', channel.name));
channel.answer(function(err) { if (err) throw err; });
channel.startSilence(function(err) { if (err) throw err; });
// Hang up after 4 more seconds
timers[channel.id] = setTimeout(function() {
console.log(util.format('Hanging up channel %s', channel.name));
channel.hangup(function(err) { if (err) throw err; });
}, 4000);
}, 2000);
timers[channel.id] = timer;
}
function stasisEnd(event, channel) {
console.log(util.format(
'Channel %s just left our application', channel.name));
var timer = timers[channel.id];
if (timer) {
clearTimeout(timer);
delete timers[channel.id];
}
}
function channelStateChange(event, channel) {
console.log(util.format(
'Channel %s is now: %s', channel.name, channel.state));
}
client.on('StasisStart', stasisStart);
client.on('StasisEnd', stasisEnd);
client.on('ChannelStateChange', channelStateChange);
client.start('channel-state');
}
Dialplan
[from-trunk]
exten => 1000,1,NoOp(Sending to ARI channel-state app)
same => n,Stasis(channel-state)
same => n,Hangup()
How it works
- ari.connect(): Establishes a WebSocket connection to Asterisk's ARI endpoint. The three arguments after the URL are the ARI username and password from
ari.conf. - StasisStart: Fires when a channel enters the
Stasis()dialplan application. This is the entry point for your application logic. Thechannelobject provides methods likering(),answer(),hangup(),play(), andstartSilence(). - StasisEnd: Fires when the channel leaves Stasis (hung up, or
Stasis()exits). Clean up timers and resources here to avoid memory leaks. - ChannelStateChange: Fires on state transitions (Ring, Up, Down, etc.). Useful for logging and for driving UI updates in real-time applications.
- client.start('channel-state'): Subscribes to events for the named Stasis application. The name must match the argument passed to
Stasis()in the dialplan. - Timer cleanup: The
timersmap tracks pendingsetTimeouthandles per channel ID. OnStasisEnd, any pending timer is cleared so the app doesn't attempt to operate on a channel that no longer exists.
Tips
- Install and run:
npm install && node channel-state.js. - Replace
channel.startSilence()withchannel.play({media: 'sound:hello-world'})to play a sound file instead of silence. - For production, use the
async/awaitAPI (ari-clientsupports promises) instead of callback-style error handling. - Bridge two channels together with
client.bridges.create()andbridge.addChannel()to build a simple call-routing application. - Monitor the WebSocket connection for disconnects and implement automatic reconnection logic for reliability.
User Notes
No notes yet. Be the first to contribute a tip or example.
Contribute a note
Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.