PickUp (in pickupgroup) with callerid

Hello,
I’m trying to devise a way to allow users to determine who is calling before answering the call in pickup group (they cannot see who is calling, because the telephone ringing is not theirs).

I thought the easiest way would be AGI script on special extension (that users would use to pick up calls in pickup group, instead of *8). The problem is, I cannot seem to find a way to determine who is calling before actually using PickUp to fetch the call. And after executing PickUp command, my AGI script (understandably) loses the connection with user station and cannot send the message anymore (besides, I still don’t have caller id at that point), so it terminates.

It would seem that I need to determine the callerid before actually issuing PickUp command. I could not find any way to determine whether there is a call ringing on specific pickupgroup. Is there a way to get list of currently ringing extensions or at least all currently active channels in the AGI? Some AGI equivalent of “core show channels”, you might say. Of course, better ideas for implementing this are very much welcome.

Thank you!

Not explicitly for just an AGI, but more in general:

You could use function CHANNLES for determining channels in state ringing (core show function CHANNELS).
These informations could be combined with the same pickupgroup (as a member-variable of the affected SIP-peers) and the CALLERID, You’re interested in is part of the variables of the ringing channel(s).
After gatehering these informations together You may send a SIP-Info-Message to the phones in the group.

Another approch would be the usage of AMI-Events for ChannelState (Ringing) where You’ll also find both, the ringing peer and the CALLERID which could then be combined with the phones in the same pickupgroup and could be used to send out a SIP-Info-Message.

Depending on the phone model You’re using the job could be done by daemon-scripts sending XML to the phones in case of the interesting events (this should work at least for SNOM,AAstra and Polycom-phones)

Thank you for your answer! How would I make CHANNELS function return only ringing channels? In documentation, I could only find the way to filter by regular expression, but I am not sure if output contains state of the channel (I cannot see it there).

I can work around it, by getting list of current channels and then using CHANNEL function on them to determine their state, but from your answer I understood, that it should be possible to get list of ringing channels only.

Thanks again.

My post wasn’t correct until the end, 'cause it was just my rememberance without having a specific code example by my side:
You’ll need a combination of CHANNELS, IMPORT and CHANNEL to get this work (Code untestet, not sure wheter the properties callgroup and state will be delivered, instead of state BRIDGEPEER could be used which shoud be empty for a ringing channel. Instead of callgroup You may determine this by using SIPPEER for the Channel-peername).
In adddition You’ll need to differentiate between phones in ringing inbound state (CALLs from outside) and phones which are trying to establish a outbound call - actually I have no idea how to catch this as I don’t remember wheter the context/extension where the channel resides (or the last extension executed or something simular ffor making this decision) is accessible or not):

//Set MChannel to a List of active SIP-Channels Set(MChannel=${CHANNELS(SIP\/)}); Set(i=0); Set(CL=); nextchannel: Set(i=$[${i}+1]); Set(MyChannel=${CUT(MChannel," ",${i})}); if ("X${MyChannel}"!="X") { //MyChannel contains a specific Channel now and we could determine it's vars Set(MyState=${IMPORT(${MyChannel},state)}); if ("${MyState}"="RINGING") { Set(MyCallgroup=${IMPORT(${MyChannel},callgroup)}); Set(MyCID=${IMPORT(${MyChannel},CALLERID(num))}); // escape from LOOP if MyCallgroup=CHANNEL(callgroup) if ("${MyCallgroup}"="${CHANNEL(MyCallgroup)}") { goto pickupable; } } goto nextchannel; } // Nothing to pickup NoOP(No matching channel found); Hangup; pickupable: // Place the info Logic as well as the pickup here

Ah yes, I understand now - it certainly can be done this way. Thanks a lot for your help!

It would be even easier if You already know the extension which will need to be explored for the pickup and if You could be sure, that the phone, trying to pickup the call is entitled to do so (while sending i.e. *8{Extensiontobepickuped} to the server and making sure that this only could be done if callgroup of the ringing phone is part of the pickupgroup of the phone trying to pickup the call). Assuming the extensions are all SIP-based it could be:

_*8X. => { //Set MChannel to a List of active SIP-Channels Set(MChannel=${CHANNELS(SIP\/${EXTEN:2})}); Set(i=0); nextchannel: Set(i=$[${i}+1]); Set(MyChannel=${CUT(MChannel," ",${i})}); if ("X${MyChannel}"!="X") { //MyChannel contains a specific Channel now and we could determine it's vars Set(MyState=${IMPORT(${MyChannel},state)}); if ("${MyState}"="RINGING") { Set(MyCID=${IMPORT(${MyChannel},CALLERID(num))}); goto pickupable; } goto nextchannel; } // Nothing to pickup NoOP(No matching channel found); Hangup; pickupable: // Place the info Logic as well as the pickup here }

My example before had one mistake: If You’re unsure about the entitlement of the phone trying to pickup the call You’ll need to compare the callgroup of the ringing phone with the pickupgroup of the phone trying to pickup the call. As pickupgroup may contain a list of groups this comparison may be a bit tricky …

Just in case anyone was wondering how to implement this in perl AGI. I believe the idea is generally the same for other AGI implementations as well - unfortunately, I couldn’t find a way to get IMPORT to work in perl AGI module, so I had to work around it a bit. Perhaps it will be useful to someone else as well.

$AGI->answer();
$callgroup = $AGI->get_variable("CHANNEL(callgroup)"); #retrieve callgroup of the phone that wants to pick up the call
$tmp = $AGI->get_variable("CHANNELS(SIP\/.*)"); #get us all currently active SIP channels
@channels = split(" ", $tmp); #split them into array
foreach (@channels) {
	$currentChannel = $_;
	$channelStatus = $AGI->channel_status($currentChannel);
	if ($channelStatus != 4) { #checks whether the channel is ringing
		next; #if not, we don't care for it
	}

	$extension = $AGI->get_full_variable('${EXTEN}', $currentChannel);
	$callerId = $AGI->get_full_variable('${CALLERID(all)}', $currentChannel);
	$callerId =~ s/"/'/g; #asterisk gets confused with double quotes and space
    
    #couldn't find better way to determine callgroup of remote channel/extension
	$myQuery = "select callgroup from sip where name = $extension limit 1";
	$execute = $connect->query($myQuery);
	$currentCallgroup = $execute->fetchrow();

	if (int($currentCallgroup) != int($callgroup)) { #if our callgroup is not matching the one of currently ringing channel
		next; #we don't want to pick up such call
	}

	$AGI->exec('SendText', $callerId . " (1 - confirm)"); #send the text message with callerid to our phone

	$choice = $AGI->get_data("pickup-confirm", "10000", "1"); #wait for user confirmation
	if (int($choice) != 1) { #user opted not to pick up the call
	        $AGI->hangup();
	        exit;
	}
	$AGI->exec('PickUp',$extension); #user confirmed to pick up the call
}
$AGI->hangup(); #hang up
exit(10);

I couldn’t find a way to get callgroup of the remote channel (without IMPORT function). So I am peeking into database table (asterisk realtime) for that, even though I don’t really like doing it that way.