Asterisk Office to Cell Phone Transfer

In my previous post I talked about how the idea of using Asterisk and its features to allow moving a home or office bound call to a cell phone. As I thought more about this idea, I thought it was be much cooler to not have to put the other person on hold while the transfer was made. It would be much cooler if the person on the other side never knew that I had changed phones. So, that is what I set out to accomplish.

I used Asterisk 1.2 for this setup. Asterisk 1.4 probably would’ve been better since application maps have been rewritten to work differently. But none the less it works. I used AGI in order to complete the task and all of it could be refined a bit. The idea relies on the extensions in the dial plan matching the names of the devices in sip.conf. Now for the fun.

First thing to do is the AGI script. I opted to use PHP because I knew the language. I also used the phpAGI libraries to make the task simpler to code. So with that said, here is the code:

#!/usr/bin/php
<?php
$asmServer = “localhost”; // Asterisk server
$asmUser = “user”; // Manager user
$asmPassword = “password”; // Manager password

$parkPrefix = “7″; // Change to fit your configuration
$parkingLotContext = “parkedcalls”; // Change to fit your configuration

require(”phpagi/phpagi.php”);
error_reporting(E_ALL);

$agi = new AGI();

// Get channels in the current conversation
$selfChan = $agi->get_variable(”CHANNEL”);
$peerChan = $agi->get_variable(”BRIDGEPEER”);

// Get the extensions of these channels
preg_match(”/\/([^-]*)/”, $selfChan['data'], $matches);
$selfExten = $matches[1];
preg_match(”/\/([^-]*)/”, $peerChan['data'], $matches);
$peerExten = $matches[1];

// Get list or currently parked calls
$asm = new AGI_AsteriskManager();
$asm->connect($asmServer, $asmUser, $asmPassword);
$parkedCalls = $asm->command(”show parkedcalls”);
$pattern = “/(${parkPrefix}[0-9]+)\s+([a-zA-Z]+\/[0-9a-zA-Z\-]+)/”;
preg_match_all($pattern, $parkedCalls['data'], $matches);

// Check the database for entries
$selfFromDatabase = $agi->database_get(”cellphone”, trim($selfExten));
$peerFromDatabase = $agi->database_get(”cellphone”, trim($peerExten));
$agi->database_del(”cellphone”, $selfExten);
$agi->database_del(”cellphone”, $peerExten);

// Set variables for the redirection
if ($selfFromDatabase['result'] == 1) {
$key = array_search($selfFromDatabase['data'], $matches[2]);
$parkedExten = $matches[1][${key}];
$channel = $selfChan['data'];
} else if ($peerFromDatabase['result'] == 1) {
$key = array_search($peerFromDatabase['data'], $matches[2]);
$parkedExten = $matches[1][${key}];
$channel = $peerChan['data'];
}

// Redirect channel to parked extension
if (isset($channel)) {
$agi->verbose(”Redirecting channel ${channel} to ${parkedExten}”,3);
$asm->Redirect($channel, NULL, $parkedExten, $parkingLotContext, 1);
} else {
$agi->verbose(”Redirection failed”,3);
}
?>

There isn’t a whole log of error handling, but then again, this was intended more for proof of concept versus throwing into practice immediately. On my system, I placed this script in the defined agi-bin directory (see asterisk.conf) for my system and called the file moveToCell.php. Make sure to make it executable as well.

The next thing was to create the application map. This was a simple edit in features.conf. I opted to select *9 for my activation code.

[applicationmap]
moveToCell => *9,callee,AGI,moveToCell.php

The [applicationmap] should already be in the features.conf file. Just be sure to place the other line under it. Also, while in the features.conf file, let’s make sure we have parking enabled by making sure parkext => XXX, parkpos => XXX-XXX and context => XXXXX are uncommented. Also note what the prefix of parkpos is and what context parked calls are placed in. The AGI script has configuration for these settings and need to be changed if they are not default. The default settings in the script or “7″ and “parkedcalls”. The variables in the script are $parkPrefix and $parkingLotContext. Make the appropriate changes

The next step is to setup the dial plan to be able to use this new feature and to allow an outside user (the cellphone) to get into the system. In extensions.conf we need to add a global variable in order to activate the feature.

[globals]
DYNAMIC_FEATURES=moveToCell

The next thing to add is the extension and dial plan logic to get the call from the cellphone, get the users extension, add it to the database and place the call in the parking lot. This is going to depend on your setup. I placed my logic in the default context.

exten => 1234,1,Answer()
exten => 1234,n,Read(ext|beep);
exten => 1234,n,Set(DB(cellphone/${ext})=${CHANNEL})
exten => 1234,n,Park()
exten => 1234,n,Hangup()

Now with that all in place we restart Asterisk and are ready to test.

Comments are closed.