Adding AMI Funtions Atxfer, SendDTMF and CancelAtxfer to php-asmanager.php

There are some very handy functions for AMI described in Digium docs that are not included in FreePBX’s Asterisk Manager Class (php-asmanager.php), which is, IMHO an essential tool for FreePBX development and customization.

I needed them for a project where I have to put call control buttons on the client’s CRM form. (Actually and FOP2 mini-browser frame.) They have about 500 agents and over 1000 queues, and each queue only has a half dozen or so other escalation and up-sell queues they can transfer to. When an agent gets a call, I have to populate a SELECT from which the agent will select the queue or extension to transfer the call, and the blind or attended transfer method.

I was trying all manner of unusual solutions, all resulting in very UNelegant code, until I decided to try to add them into php-asmanager.php. Should have started there, it was far easier than I thought. Which led me to wonder WHY they weren’t there in the first place. Oversight? More likely doing this is considered a bad idea for some reason, so Schmooze didn’t do it. The code below seems to be working fine, but is this all going to blow up in my face?

I hope someone knowledgable will let me know if I have a gun aimed at my foot. Here’s what I did to php-asmanager.php:

	function Atxfer($channel, $exten, $context, $priority) {
		return $this->send_request('Atxfer', array('Channel'=>$channel, 'Exten'=>$exten,
								'Context'=>$context, 'Priority'=>$priority));
	}
	
	function CancelAtxfer($channel) {
		return $this->send_request('CancelAtxfer', array('Channel'=>$channel));
	}
	
	function PlayDTMF($channel, $digit) {
		return $this->send_request('PlayDTMF', array('Channel'=>$channel, 'Digit'=>$digit));
	}

When I say this is working correctly I mean that I see stuff that looks normal to my non-expert eyes when monitoring AMI transactions in the CLI with “> manager set debug on”

However, I’m sure you have to send the correct channel to Atxfer and CancelAtxfer. When I send the inbound (from-pstn or from-trunk) channel, it seems to bridge all three parties. Being curious, I experimented with PlayDTMF to do the transfers the old reliable way: feature codes on the agent phone. The code below shows how I implemented it. I left in the original code that used Atxfer and CancelAtxfer so someone might tell me what I did wrong there.

$act=$_REQUEST['action'];
$ext=$_REQUEST['tgtExt'];
$CallData=$_SESSION['CallData'];
switch ($act) {
	case 'Blind':
		$res=$astman->Redirect($CallData['chan'],'',$ext,'from-queue','1');
		break;
	case 'Attended':
		$dtmf='*2' . $ext;
		$digits=str_split($dtmf);
		$i=0;
		foreach($digits as $digit) {
			$i++;
			// agent channel is the ";2" channel from 'core show channels concise'
			$out=$astman->PlayDTMF($CallData['AgentChan'],$digit);
			$res.="$i. sent $digit, got " . implode(':',$out) . ", ";
		}
		logit("CA-Atxfer DTMF: $res");	
	//		$res=$astman->Atxfer($CallData['chan'],$ext,'ext-queues','1');
		break;
	case 'Cancel':
		$dtmf='*5';
		$digits=str_split($dtmf);
		$i=0;
		foreach($digits as $digit) {
			$i++;
			$out=$astman->PlayDTMF($CallData['AgentChan'],$digit);
			$res.="$i. sent $digit, got " . implode(':',$out) . ", ";
		}
		logit("CA-CXL-Atxfer DTMF: $res");	
	//		$res=$astman->CancelAtxfer($CallData['chan']);
		break;
	case 'HangUp':
		// agent channel is the ";2" channel from 'core show channels concise'
		$res=$astman->Hangup($CallData['AgentChan']); 
		break;
	default:
		echo "Invalid Action!";
		exit(0);
}

The DTMF method is working fine, but I would like to debug the Atxfer method. Anyone have an idea?

Well, this doesn’t work so well after all. It seems to do a blind transfer even with the SendDTMF solution trying to emulate sending feature codes for an attended transfer. The feature codes work as expected when dialed on the soft phone, Still trying to figure out what gets messed up when DTMFs are sent by AMI.

We only add functions when we need them or they are requested by users.

There’s an important principle that I’d like to mention (because Andrew hopped over it). From a Risk Mitigation perspective, adding features and functions to your software because you can (but don’t have to) presents testing and QA problems that are self-inflicted. Since none of the FreePBX programs and packages use these functions, adding them and making sure they work with every tested release is adding time and risk to the release process that could derail a release or (worse yet) introduce a bug that is unrelated to the actual operation of the software.

On the other hand, adding a stub function that would allow the addition of these functions (like a *_custom config file) would allow you to add the functionality without having to worry about an update with every release. This was the recommended approach for the changes that I submitted for the Chan-SCCP-B updates to “asteriskinfo”. If you wanted to, you could submit a feature request that allows for the addition of “local code” to the AMI interface which could be useful to other developers in the future.

php-astmanager.php is a class. So you can simply extend the class to add custom methods to it.

1 Like

You certainly can add to it, but I’ve heard it said that just because you can doesn’t mean you should. Those functions don’t really work as expected. They return the expected response but not the expected result. If I ever get it working the way it should I’ll update this post.