building your first ari app - mark · pdf filebuilding your first ari app ... • astricon...
TRANSCRIPT
![Page 1: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/1.jpg)
Building Your First ARI App
117,612 Calls Later
Mark Ingles Oct 14, 2015 Astricon 2015
![Page 2: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/2.jpg)
Thank You!•
• Joshua Colp – Sr. Dev at Digium
• Nir Simionovich – Greenfield Tech phpari.org
2
![Page 3: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/3.jpg)
About Mark Ingles• 15 years writing PHP (or 1 year 15x)
• Former Sysadmin
• Asterisk User for 8 Years
• Business Owner – Printing - like Vistaprint but for established businesses
3
![Page 4: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/4.jpg)
Already Using ARI?
4
![Page 5: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/5.jpg)
Overview• High Level Ideas And Common Pitfalls
• PHPARI “Basic Stasis Application Template” and Reacting to Events
• Dialing, Bridging, Recording, Sounds In A “Power Dialer” Application
5
![Page 6: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/6.jpg)
High Level Ideas• One Process Reacts To Events • Another To Send Requests
6
Asterisk Emits Events
ARI App Receives
ARI App Processes
ARI App Sends
Requests
Send Requests
Asterisk Processes
![Page 7: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/7.jpg)
7
ws://localhost:8088/ari/events?api_key=asterisk:asterisk&app=hello-world
Looks like you want to add a prefix or /ari in http.conf Not sure? “core set debug 2” from the Asterisk CLI:
HTTP Request URI is /ari/channels/1443501398.rep-mark match request [ari/channels/1443501398.rep-mark] with handler [httpstatus] len 10 match request [ari/channels/1443501398.rep-mark] with handler [static] len 6 match request [ari/channels/1443501398.rep-mark] with handler [ari] len 3 Match made with [ari]
Common Setup Pitfall “prefix” in http.conf
![Page 8: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/8.jpg)
Any Created Resource Gets An ID
8
$response = $channels->originate($ENDPOINT, array( "app" => 'miDialer', "appArgs" => 'IsRep', "callerId“ => $MyCallerID, "timeout" => 10, "channelId" => $NewChannelID, ));
Asterisk can return events with this channel BEFORE it returns a response to this request.
![Page 9: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/9.jpg)
Use A Library• PHPARI
9
All of the heavy lifting is done. • Websockets • Encryption • REST Client • JSON Encoding/Decoding • Logging • Event Handling
![Page 10: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/10.jpg)
High Level Ideas• Dial/Originate goes to Dialplan OR ARI
10
Wiki is updated now. (Oct 2015)
• ARI/Stasis REPLACES dialplan apps
![Page 11: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/11.jpg)
11
![Page 12: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/12.jpg)
Channel Doesn’t Enter ARI Until Answered
12
originate($channelid);
add_to_bridge($bridgeid, $channelid);
This Does NOT work. You have to wait until the StasisStart event, then react to it and add the channel to the bridge.
#1 Pitfall
![Page 13: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/13.jpg)
Reacting To Events
13
$this->Events->on('StasisStart', function ($event) { $channels()->channel_answer($event->channel->id);
}
$this->Events->on('ChannelEnteredBridge', function ($event) {
echo "channel: " . $event->channel->id . " entered bridge: " . $event->bridge->id);
}
Events Happen FAST – no way to get Channel Info on ChannelDestroyed or StasisEnd events
![Page 14: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/14.jpg)
Call Detail Records No “DST” Set
14
DST is from the dialplan.
Solution: Log yourself in whatever format you need. (sql, csv)
INSERT INTO CallLog SET ID=NULL, CallStart=$callstart, ChannelID=$channelid
StasisStart or ChannelEnteredBridge UPDATE CallLog SET CallPickup=$callpickup WHERE ChannelID=$channelid
ChannelDestroyed UPDATE CallLog SET CallEnd=$callend WHERE ChannelID=$channelid
![Page 15: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/15.jpg)
Snoop, Not Chanspy Playbacks Queue
15
Snoop creates a new channel that can listen (spy) or whisper (speak) to another channel.
Playbacks queue a sound file to be played to a channel or bridge.
Record works on all audio in a bridge.
![Page 16: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/16.jpg)
New Sounds Aren’t Updated
16
module reload sounds
If you upload or record new sounds, this has to be run from the CLI, not the ARI.
![Page 17: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/17.jpg)
Our Power Dialer1. Dialing from a CRM 2. Started with “Drag to Dial” 3. Moved To “Click To Dial” 4. Moved To “Dial Me When Ticket Opened”
in CRM
• Rev 1. ARI Dialer Begins Calling When Previous Call Hungup
• Rev 2. ARI Dialer Leaves Pre-Recorded Voicemail When Told By Human
17
![Page 18: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/18.jpg)
Our Power DialerPrerequisites
• Asterisk 13+ Setup With ARI Enabled • Web Server with PHP 5.4+ • Recordings Of Voicemail Messages • MySQL Database For Logging • CRM Access via Database or CURL
18
![Page 19: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/19.jpg)
19
![Page 20: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/20.jpg)
20
![Page 21: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/21.jpg)
Our Power DialerFunctionality
1. Dial Customer Service Rep 2. Call From Highest->Lowest Priority (changes) 3. If Rep Hears VM Greeting, Leave Prerecorded
VM and Dial Next User 4. Log/Record All Calls 5. Notify Rep Of What’s Happening (audio/visual)
21
![Page 22: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/22.jpg)
Our Power DialerResults
Click To Dial (and variations) Avg 30 Calls/Hour Dialer Avg 60 Calls/Hour, Max 90 Calls/Hour
PS – No Dialplan
22
![Page 23: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/23.jpg)
Originate (to ARI App)
How It Works 1 – Call Rep
23
$channels = new channels($phpari); # call the rep- only give the rep 10 seconds to respond $response = $channels->originate( $ENDPOINT, array( "app" => 'miDialer', "appArgs" => 'IsRep, "callerId" => $_SESSION['MyCallNum'], "timeout" => 10, "channelId" => $_SESSION['MyChannelID'], ), array('CALLERID(name)' => 'Phone Dialer') );
![Page 24: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/24.jpg)
Check BridgesHow It Works 2 - Call A Client 1/4
24
$channels = new channels($phpari); $bridges = new bridges($phpari); # check for the rep dialed in, and nobody else in the bridge $repready = 0; $custinbridge = 0; $bd = $bridges->details('bridge-' . $_SESSION['KUsername']); if(is_array($bd)) { foreach($bd['channels'] as $bchannel) { if($bchannel == $_SESSION['MyChannelID']) { $repready = 1; } else { # someone else in bridge $custinbridge = 1; } # if my channel } # foreach channel } # is bridge
![Page 25: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/25.jpg)
Setup VariablesHow It Works 2 - Call A Client 2/4
25
if(0 == $repready OR 1 == $custinbridge) { echo 'Need To Be Dialed In And Hungup With Last Client'; return false; } # get bridged with the rep by the stasis app #$ENDPOINT = 'PJSIP/17275608297@flowroute'; $ENDPOINT = sprintf(OUTBOUNDTECH, $PhoneNum); $callerid = $_SESSION['MyCallNum']; $calleridname = $_SESSION['CIDName']; $newchannelid = time() . '.client-' . $user . '.' . rand();
![Page 26: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/26.jpg)
Originate (to ARI App)How It Works 2 - Call A Client 3/4
26
$response = $channels->originate( $ENDPOINT, array( "app" => 'miDialer', "appArgs " => 'IsOutBound,RepUserName-' . $_SESSION['User'], "callerId" => $callerid, "timeout" => 50, "channelId“ => $newchannelid, ), array('CALLERID(name)' => $calleridname) );
![Page 27: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/27.jpg)
Logging / RingingHow It Works 2 - Call A Client 4/4
27
# log the call - add to call log table $sql = "INSERT INTO CallLog SET ID=NULL, CallStart=:CallStart, ChannelID=:ChannelID, PhoneNum=:PhoneNum, Rep=:Rep, TicketID=:TicketID, CIDNum=:CIDNum"; # finally, play ringing to rep $channels->channel_ringing_start($mychannelid);
![Page 28: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/28.jpg)
SoundsHow It Works - 3 Leave A Voicemail 1/6
28
# leave a prerecorded voicemail for a product # (clipped) get ticket to know which voicemail $sounds = new sounds($phpari); $soundfile = $_SESSION['User'] . '-' . $vmtype; # make sure sound is actually there if(!$sounds->detail($soundfile)) { echo 'Cant Find Voicemail to Play'; return false; }
![Page 29: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/29.jpg)
Stop RecordingHow It Works - 3 Leave A Voicemail 2/6
29
$channels = new channels($phpari); $bridges = new bridges($phpari); $bridgeid = 'bridge-' . $_SESSION['KUsername']; $bdetails = $bridges->details($bridgeid); foreach($bdetails['channels'] as $bchannel) { if($bchannel != $_SESSION['MyChannelID']) { # this must be the cust's channel, since the bridge should only have 2 channels, the rep, and the cust $VMChannelID = $bchannel; # stop recording the rep's bridge, create a new bridge to record both sides of leaving the VM $recordings = new recordings($phpari); $recordings->live(‘stop‘, $VMChannelID); # remove the channel from the rep’s bridge $bridges->remove_channel($bridgeid, $VMChannelID);
![Page 30: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/30.jpg)
TALK_DETECT()How It Works - 3 Leave A Voicemail 3/6
30
$bridges->create( 'mixing', 'bridge-' . $VMChannelID, 'bridge-' . $VMChannelID );
$bridges->addchannel('bridge-' . $VMChannelID, $VMChannelID, ''); # set a variable on the channel of the sound to play $channels->setVariable($VMChannelID, 'miVMtoPlay', $soundfile);
# wait for 2.1 seconds of silence $channels->setVariable($VMChannelID, 'TALK_DETECT(set)', '2100');
![Page 31: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/31.jpg)
ChannelTalkingFinished
How It Works - 3 Leave A Voicemail 4/6
31
# now that talking has stopped, play a voicemail $vmsound = $channels()->getVariable($event->channel->id, 'miVMtoPlay');if($vmsound) { # play it to the bridge so we can record it $bd = $bridges()->details('bridge-' . $event->channel->id); if(FALSE != $bd) { # check to see if we are already playing it sometimes long pauses in greetings will start playback $pbd = $playbacks()->get_playback('miVMtoPlay' . $event->channel->id); if(FALSE != $pbd) { # already playing, restart it- TODO: possibly put a limit on this $playbacks()->control(
'miVMtoPlay' . $event->channel->id, ‘RESTART');
} }
![Page 32: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/32.jpg)
ChannelTalkingFinished
How It Works - 3 Leave A Voicemail 5/6
32
# queue the sound to play on the bridge
$bridges()->playbackstart( 'bridge-' . $event->channel->id, 'sound:custom/' . $vmsound['value'], 'custom', 0, 1000, 'miVMtoPlay' . $event->channel->id);
We need the ID on the Sound so we know what to do when it’s over.
![Page 33: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/33.jpg)
PlaybackFinished
How It Works - 3 Leave A Voicemail 6/6
33
# once we leave the message, hangup the call if('miDialer' == $event->application AND strpos($event->playback->id, 'miVMtoPlay') !== FALSE) { $delchannelid = preg_replace('/bridge:bridge-(.*)/', '$1', $event->playback->target_uri);
# hang up customer channel $channels()->delete($delchannelid); # bridge with the same name as the channel recorded- dump that too $recordings()->live('stop', $delchannelid); $bridges()->delete('bridge-' . $delchannelid);}
![Page 34: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/34.jpg)
ChannelHangupRequest
End Recording When Hungup
34
# The channel is already gone by the time we see the request $repname = preg_replace('/\d+\.rep-(\w+?)\.\d+/', '$1', $event->channel->id);$bd = $bridges()->details('bridge-' . $repname);if(is_array($bd)) { foreach($bd['channels'] as $bchannel) { # hangup anyone else in the bridge- the rep is already gone $this->phpariObject->channels()->channel_delete($bchannel); # stop and store recording $this->phpariObject->recordings()->live(‘stop‘, $bchannel); } # foreach channel } # bridge
![Page 35: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/35.jpg)
ChannelLeftBridge
Audio Notifications
35
# Play a goodbye sound when the client hangs up This is a good place to catch a hangup because we know the channel id and the bridge it left. The channel is probably already destroyed, we don’t have much to work with. If the channel left a client "vm" bridge, we dont need to playbridge-1424374586.client-jessicam.33525 <- sample vm bridge id
if(stripos($event->channel->id, '.CLIENT-') !== FALSE AND stripos($event->bridge->id, '.CLIENT-') === FALSE) { $channels()->channel_playback(
$event->bridge->channels[0], 'sound:goodbye', NULL, NULL, NULL, 'goodbye');
} });
![Page 36: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/36.jpg)
StasisStartCall Comes Into ARI App (Rep or Client)
36
# answer the channel $channels()->answer($event->channel->id);# create the bridge this rep will use to talk to their customers foreach($event->args as $arg) { if(preg_match('/^RepUserName-(.*)$/', $arg, $m)) { $bridgeid = 'bridge-' . $m[1]; }}
# this is an outbound call to a client, just add to bridge if(is_array($event->args) AND in_array('IsOutBound', $event->args)) { $bridges()->addchannel($bridgeid, $event->channel->id, '');}# this is the rep coming in, create bridge, add to bridge if(is_array($event->args) AND in_array('IsRep', $event->args)) { # can check for a bridge instead delete/recreate $bridges()->delete($bridgeid); $bridges()->create('mixing', $bridgeid, $bridgeid); $bridges()->addchannel($bridgeid, $event->channel->id, ''); }
![Page 37: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/37.jpg)
ChannelEnteredBridge
Call Goes Into Bridge (Rep or Client)
37
# stop ringing on other channel. foreach($event->bridge->channels as $bchannel) { if($event->channel->id != $bchannel) { $channels()->channel_ringing_stop($bchannel); }
# if this is a client, start recording the bridge if(stripos($event->channel->id, '.CLIENT-') !== FALSE) {# if it's a new voicemail bridge, save with a diff name to not clobber the old one we still might not have finished recording $recordingname = $event->channel->id . 'vm'; $bridges()->record($event->bridge->id, $recordingname, ‘wav', 0, 0, ‘fail', FALSE, 'none'); # update the call log $sql = "UPDATE CallLog SET CallPickup=$callpickup
WHERE ChannelID=:ChannelID";
![Page 38: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/38.jpg)
ChannelDestroyed
Busy or Bad Number Notification
38
# finish the call log $sql = "UPDATE CallLog SET CallEnd=:CallEnd WHERE ChannelID=:ChannelID";
# stop any ringing - only happens if the far end never picks up $repname = preg_replace('/\d+\.client-(\w+?)\.\d+/', '$1', $event->channel->id);
$channellist = $this->phpariObject->channels()->list();foreach($channellist as $channel) { # stop any ringing if we're dialing out $channels()->channel_ringing_stop($channel['id']); # if its ringing, let the rep know it hung up- TODO: more "causes" if('Ringing' == $event->channel->state OR 'Unallocated (unassigned) number' == $event->cause_txt OR 'User busy' == $event->cause_txt) { $channels()->playback($channel['id'], 'sound:number-not-answering', NULL, NULL, NULL, 'notanswering'); } else { # its connected and recording, stop recording $recordings()->live('stop', $event->channel->id); }}
![Page 39: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/39.jpg)
Resources• Asterisk Docs Wiki • Swagger Interface http://ari.asterisk.org (set allowed_origins=http://ari.asterisk.org in ari.conf)
• #asterisk or #asterisk-ari on Freenode (only about 10 of us in ari)
• Asterisk Users Mailing List • Asterisk App Dev Mailing List • PHPARI.org / github • Astricon Talks • (Half of this year’s talks and 2014 still good)
39
![Page 40: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/40.jpg)
40
![Page 41: Building Your First ARI App - Mark · PDF fileBuilding Your First ARI App ... • Astricon Talks • (Half of this year’s talks and 2014 still good) 39. 40. 41](https://reader033.vdocuments.us/reader033/viewer/2022051601/5abeb1ee7f8b9a8e3f8d5a48/html5/thumbnails/41.jpg)
41
Everyone here has the sense that right now is one of those moments when we are influencing the future.
Steve Jobs 1985 1970s “Bluebox" Phone Hardware Manufacturer
One More Thing