VoIP & Telecommunications

Integrating AMI (Asterisk Manager Interface) for Real-Time Call Control

November 30, 2024 4 min read By Amey Lokare

Integrating AMI (Asterisk Manager Interface) for Real-Time Call Control

The Asterisk Manager Interface (AMI) provides powerful real-time control over PBX operations. I've built several systems that use AMI for live call monitoring, dynamic routing, and automated call handling.

🎯 What is AMI?

AMI is a TCP/IP interface that allows external applications to:

  • Monitor calls in real-time
  • Control calls (answer, hangup, transfer)
  • Execute dialplan applications
  • Receive events (call start, end, status changes)
It's essential for building custom call center dashboards, automated systems, and integration with external applications.

🏗 Architecture

``` Laravel Application → AMI Client (PHP) → Asterisk AMI → Real-time Events ```

Components

1. AMI Client: PHP library to connect to Asterisk 2. Event Listener: Receives real-time events 3. Action Sender: Sends commands to Asterisk 4. Database: Stores call data and statistics

💻 Implementation

1. Install AMI Client Library

```bash composer require pami/pami ```

2. Connect to AMI

```php // app/Services/AsteriskAMI.php use PAMI\Client\Impl\ClientImpl as PamiClient;

class AsteriskAMI { private $client;

public function __construct() { $this->client = new PamiClient([ 'host' => config('asterisk.ami_host'), 'port' => config('asterisk.ami_port'), 'username' => config('asterisk.ami_username'), 'secret' => config('asterisk.ami_secret'), 'connect_timeout' => 10000, 'read_timeout' => 10000, ]);

$this->client->open(); }

public function disconnect() { $this->client->close(); } } ```

3. Listen for Events

```php public function listenForEvents() { while (true) { $event = $this->client->waitEvent();

if ($event instanceof \PAMI\Message\Event\NewchannelEvent) { $this->handleNewCall($event); }

if ($event instanceof \PAMI\Message\Event\HangupEvent) { $this->handleCallEnd($event); }

if ($event instanceof \PAMI\Message\Event\BridgeEvent) { $this->handleCallBridge($event); } } }

private function handleNewCall($event) { Call::create([ 'channel' => $event->getChannel(), 'caller_id' => $event->getCallerIDNum(), 'started_at' => now(), 'status' => 'ringing', ]);

// Broadcast to dashboard broadcast(new CallStarted($event))->toOthers(); } ```

4. Send Actions

```php public function answerCall($channel) { $action = new \PAMI\Message\Action\OriginateAction($channel); $action->setContext('default'); $action->setExtension('s'); $action->setPriority(1);

$response = $this->client->send($action); return $response->isSuccess(); }

public function hangupCall($channel) { $action = new \PAMI\Message\Action\HangupAction($channel); $response = $this->client->send($action); return $response->isSuccess(); }

public function transferCall($channel, $extension) { $action = new \PAMI\Message\Action\RedirectAction($channel); $action->setContext('internal'); $action->setExtension($extension); $action->setPriority(1);

$response = $this->client->send($action); return $response->isSuccess(); } ```

📊 Real-Time Dashboard Integration

Backend: Broadcast Events

```php // app/Events/CallStatusChanged.php class CallStatusChanged implements ShouldBroadcast { public $call;

public function broadcastOn() { return new Channel('calls'); }

public function broadcastAs() { return 'call.status.changed'; } }

// In AMI listener broadcast(new CallStatusChanged($call))->toOthers(); ```

Frontend: Display Live Calls

```javascript Echo.channel('calls') .listen('.call.status.changed', (e) => { updateCallStatus(e.call); }); ```

🔍 Common AMI Events

Call Events

  • NewchannelEvent: New call initiated
  • NewstateEvent: Call state changed (ringing, answered)
  • BridgeEvent: Calls bridged (connected)
  • HangupEvent: Call ended
  • DialEvent: Dial attempt started

Channel Events

  • PeerStatusEvent: SIP peer status changed
  • RegistryEvent: SIP registration event
  • VarSetEvent: Channel variable set

🚀 Advanced Use Cases

1. Call Queue Monitoring

```php public function monitorQueue($queueName) { $action = new \PAMI\Message\Action\QueueStatusAction($queueName); $response = $this->client->send($action);

return [ 'waiting' => $response->getKey('Waiting'), 'agents' => $response->getKey('Members'), ]; } ```

2. Dynamic Call Routing

```php public function routeCall($callerId, $destination) { // Check business rules if ($this->isBusinessHours()) { $extension = $this->getAvailableAgent(); } else { $extension = 'voicemail'; }

$this->transferCall($destination, $extension); } ```

3. Call Recording Control

```php public function startRecording($channel) { $action = new \PAMI\Message\Action\MonitorAction($channel); $action->setFile('recording-' . time()); $action->setFormat('wav');

$this->client->send($action); } ```

⚡ Performance Optimization

1. Connection Pooling

Reuse AMI connections:

```php class AMIConnectionPool { private $connections = [];

public function getConnection() { if (empty($this->connections)) { $this->connections[] = new AsteriskAMI(); } return array_pop($this->connections); }

public function releaseConnection($connection) { $this->connections[] = $connection; } } ```

2. Event Filtering

Only process relevant events:

```php if ($event->getEventType() === 'Newchannel' && $event->getChannelState() === '6') { // Ringing // Process only ringing calls } ```

3. Async Processing

Process events in background:

```php // Queue event processing ProcessAMIEvent::dispatch($event); ```

🔒 Security Considerations

1. AMI Authentication

```ini

/etc/asterisk/manager.conf

[admin] secret = strong_password_here deny = 0.0.0.0/0.0.0.0 permit = 127.0.0.1/255.255.255.255 read = system,call,log,verbose,command,agent,user write = system,call,log,verbose,command,agent,user ```

2. Rate Limiting

Limit AMI actions per second:

```php if (Cache::get("ami_rate_limit") > 100) { throw new Exception("Rate limit exceeded"); } Cache::increment("ami_rate_limit", 1, now()->addSecond()); ```

💡 Real-World Example

I built a call monitoring dashboard:

1. AMI Listener: Receives all call events 2. Database: Stores call records in real-time 3. WebSocket: Broadcasts updates to dashboard 4. Dashboard: Shows live calls, queue status, agent availability 5. Alerts: Notifies on call failures or long wait times

Result: Real-time visibility into all PBX operations, instant alerts, and comprehensive call analytics.

🎓 Key Takeaways

  • AMI provides powerful real-time control
  • Event-driven architecture scales well
  • Filter events to reduce processing load
  • Queue processing for heavy operations
  • Secure AMI access with proper authentication

Conclusion

AMI integration enables powerful real-time call control and monitoring. Combined with Laravel broadcasting, you can build sophisticated call center dashboards and automated systems that respond instantly to call events.

Comments

Leave a Comment

Related Posts