Search code examples
phpasteriskagi

Call files, cancel call if webservice say so


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>

Solution

  • Got some great help from the Asterisk community. The main problem was that two contexts were needed, one for each leg of the call.

    • One context to make the call with Dial (message_dial below)
    • Another context to play the sound file. (message below)

    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.