Reputation: 3073
I am trying to develop a reminding system that will make an automatic call to remind a person of a specific event. For this I am using Asterisk to make the calls and PHP in order to create a call file for Asterisk. I want the call file to execute 30 seconds after it is added. To do this I set the modified time stamp in the PHP script. Everything works great except that I want to run a check agains a web service to determine if it is still relevant to call the user.
Here is my PHP script
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$request = json_decode(file_get_contents("php://input"));
$tmpcallfile = tempnam("/tmp", "call");
$callfile = tempnam("/var/spool/asterisk/outgoing/", "call");
$fh = fopen($tmpcallfile, "w");
fwrite($fh, "Channel: SIP/voxbeam_outbound/" . $request->{'ToPhoneNumber'} . "\n");
fwrite($fh, "CallerID: " . $request->{'FromPhoneNumber'} . "\n");
fwrite($fh, "MaxRetries: 3\n");
fwrite($fh, "RetryTime: 5\n");
fwrite($fh, "Context: remind_event\n");
fwrite($fh, "Extension: 111\n");
fwrite($fh, "Priority: 1\n");
fwrite($fh, "Archive: Yes\n");
fclose($fh);
touch($tmpcallfile, time()+30);
rename($tmpcallfile, $callfile);
}
?>
And my idea was to simply call the web service using curl in the extensions.conf.
[voxbeam_outbound]
exten => _X.,1,NoOp()
same => n,Answer
same => n,Dial(SIP/voxbeam_outbound/${EXTEN})
[remind_event]
exten => _X.,1,Answer
same => n,Set(status=${CURL(http://localhost/ShouldRemindEvent)})
same => n,GotoIf($["${status:0:1}" != "1"]?10)
same => n,Dial(SIP/voxbeam_outbound/${EXTEN})
same => n,Playback(remind_event)
same => n,Hangup
same => 10,Hangup
I thought that if I would check the web service and then goto 10 to Hangup if the webservice replies with anything other than 1. But for some reason it does call anyway.
For completeness here is also added lines in sip.conf allthough I guess these are actually not relevant:
[voxbeam_outbound]
type=peer
insecure=invite,port
nat=no
canreinvite=no
username=<hidden>
secret=<hidden>
host=<hidden>
context=voxbeam_outbound
So the question is, can I do it simply like this, or would I need to write an AGI script in order to achieve what I want?
I realise that this is a mix between programming and configuration and I believe that this is best fit for stackoverflow instead of superuser because it is an application I am building and since there is programming involved.
EDIT: according to @arheops suggestion I have tried calling with Local
New line in php script, also added a PHONE_NUMBER variable to the final phone number I want to reach, though I can then use it in the dialplan script
fwrite($fh, "Channel: Local/0@remind_event\n");
...
fwrite($fh, "SetVar: PHONE_NUMBER=" . $request->{'ToPhoneNumber'} . "\n");
New remind_event in the dial plan script in extensions.conf
[remind_event]
exten => 0,1,NoOp()
same => n,Dial(SIP/voxbeam_outbound/${PHONE_NUMBER})
same => n,Playback(remind_event)
same => n,Hangup
But it still seem to fail according to the verbose logs of asterisk
Connected to Asterisk 13.16.0 currently running on hostname (pid = 22261)
-- Attempting call on Local/0@remind_event for 111@remind_event:1 (Retry 1)
-- Called 0@remind_event
-- Executing [0@remind_event:1] NoOp("Local/0@remind_event-00000000;2", "") in new stack
-- Executing [0@remind_event:2] Dial("Local/0@remind_event-00000000;2", "SIP/voxbeam_outbound/+467<hidden>") in new stack
== Using SIP RTP CoS mark 5
-- Called SIP/voxbeam_outbound/+467<hidden>
-- SIP/voxbeam_outbound-00000000 is making progress passing it to Local/0@remind_event-00000000;2
-- Local/0@remind_event-00000000;1 is making progress
> 0xffa3a0 -- Probation passed - setting RTP source address to <hidden ip>:15476
-- SIP/voxbeam_outbound-00000000 requested media update control 26, passing it to Local/0@remind_event-00000000;2
-- SIP/voxbeam_outbound-00000000 requested media update control 26, passing it to Local/0@remind_event-00000000;2
-- SIP/voxbeam_outbound-00000000 is ringing
-- Local/0@remind_event-00000000;1 is ringing
-- SIP/voxbeam_outbound-00000000 answered Local/0@remind_event-00000000;2
-- Local/0@remind_event-00000000;1 answered
[Aug 1 12:18:15] WARNING[22326][C-00000001]: pbx.c:4414 __ast_pbx_run: Channel 'Local/0@remind_event-00000000;1' sent to invalid extension but no invalid handler: context,exten,priority=remind_event,111,1
[Aug 1 12:18:15] NOTICE[22326][C-00000001]: pbx_spool.c:460 attempt_thread: Call completed to Local/0@remind_event
-- Channel SIP/voxbeam_outbound-00000000 joined 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
-- Channel Local/0@remind_event-00000000;2 joined 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
-- Channel Local/0@remind_event-00000000;2 left 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
== Spawn extension (remind_event, 0, 2) exited non-zero on 'Local/0@remind_event-00000000;2'
-- Channel SIP/voxbeam_outbound-00000000 left 'simple_bridge' basic-bridge <988269c4-fbe9-439f-b0a9-22af873d5118>
Upvotes: 0
Views: 713
Reputation: 1
I would rather use originate AMI action with local channels and AGI for this purpose. Another great option is ARI, let you do whatever you want to do with the asterisk.
I am using AJAM or phpAMI or PAMI. You must consider that.
Upvotes: 0
Reputation: 3073
Got some great help from the Asterisk community. The main problem was that two contexts were needed, one for each leg of the call.
Here is the extensions.conf file that works. Just add any conditions in the dialplan in message_dial before the Dial command:
[message_dial]
exten => s,1,NoOp()
same => n,Dial(SIP/voxbeam_outbound/${PHONE_NUMBER})
[message]
exten => s,1,NoOp()
same => n,Playback(message)
same => n,Hangup
The call file could look like this
Channel: Local/s@message_dial
CallerID: +46<hidden>
MaxRetries: 3
RetryTime: 15
Context: message
Extension: s
Priority: 1
Archive: Yes
SetVar: PHONE_NUMBER=+46<hidden>
So looking at the final solution it was really straight forward to achieve for anyone skilled in Asterisk.
Upvotes: 0
Reputation: 1112
Call files are great for scheduling, but I would use PHP AGI instead of dialplan to do the web side.
You would have the call file dial a local exten with the target phone number, and any parameters needed to query the web service (user ID, email, etc). Then the AGI executes the curl request, and you can continue to dial from within the AGI. I'm guessing that would be more comfortable for you than dialplan. It would remove the "for some reason it does X" part of your confusion, since you have direct control in PHP over the call, and can log to file from within your AGI script.
You could also do more advanced API queries, such as external APIs that need auth tokens, processing more complex output, etc.
Here are some helpful links to get you started:
AGI library links (I personally prefer PHPAGI)
Upvotes: 1
Reputation: 15259
Your call file have Retry param, so it think call failed and do retry.
You have 3 options here
1) Delete file in case of no need
2) Answer call before hangup.
3) Remove Retry.
Upvotes: 1