Asterisk tips simple wake-up call

Yet another wake-up call implementation


I put together this perl/AGI script instead of installing one of the others for these reasons:
  • No cron job required
  • Works the same way as the PSTN "built-in" wake-up service has "always" worked here in Sweden

When the script is installed, wake-up calls are scheduled, cancelled, and reviewed by dialling the following extensions:
  • *55*HHMM# set a wake-up call at HH:MM,
  • #55*HHMM# cancel the wake-up call at HH:MM,
  • #55# cancel all wake-up calls,
  • *#55# reads back your pending wake-up calls.

All times use a 24 hour clock, and refer to some point within the next 24 hours. At the scheduled time, Asterisk calls you back and plays a sound file. If you do not answer, it makes two retries in five minute intervals.

It turns out this does not work with most SIP phones, since they believe that the pound sign terminates the number being called. I use this for my Zap phones at home. Of course, you could use some alternative extensions for your Sip phones, either by modifying the script, or, if you want the script to work with the standard extensions for Zap phones, by adding extension patterns that just Goto the extensions above. Maybe the section "Pound sign trouble" below helps.

I run this script on FreeBSD; maybe some paths need to be changed for Linux?

BTW, In Sweden, the extension *#55*HHMM# tells you if you have a call scheduled for the indicated time, but I added the *#55# extension instead.

extensions.conf
exten => _*55*XXXX#,1,AGI(wakeup-call.pl) ; Set wake-up call
exten => _#55#,1,AGI(wakeup-call.pl) ; Cancel all
exten => _#55*XXXX#,1,AGI(wakeup-call.pl) ; Cancel specific
exten => _*#55#,1,AGI(wakeup-call.pl) ; Check status


The variables at the top of the perl script might need some tweaking.

wakeup-call.pl
#!/usr/local/bin/perl -wT

# Added by Suretec Systems Ltd. - http://www.suretecsystems.com - 14/05/2006
use warnings;
use strict; 

my $callfiledir="/var/spool/asterisk/outgoing";
my $originateContext = 'home-out';
my $tmpdir = '/var/tmp'; # must be on same file system as $callfiledir
my $wakeupFile = 'tt-monkeys';
my $confirmFile = 'auth-thankyou';

use Asterisk::AGI;
use Time::Local;
use IO::File;
use File::Temp qw/ tempfile /;

my $AGI = new Asterisk::AGI;
$AGI->setcallback(\&callback);
sub callback() { exit; }

my %agiEnv = $AGI->ReadParse();

my ($caller) = $agiEnv{callerid} =~ /<(\d+)>/;
if (!defined $caller) {
    ($caller) = $agiEnv{callerid} =~ /(\d+)/;
}

$extension = $agiEnv{extension};
$extension =~ s/\%23/\#/g;         # unquote pound sign

$AGI->answer();
sleep 1;

if (!defined $caller) {
    print STDERR "Could not get caller id for wakeup call\n";
    $AGI->stream_file('tt-somethingwrong');
} elsif ($extension eq "#55#") {
    foreach my $fn (<$callfiledir/wakeup.$caller.*.call>)
    {
        unlink $fn;
    }
    $AGI->stream_file($confirmFile);
} elsif ($extension eq "*#55#") {
    my $foundOne = 0;
    foreach my $fn (<$callfiledir/wakeup.$caller.*.call>)
    {
        $foundOne = 1;
        my ($hour, $minute) = $fn =~ /\.(\d{2})(\d{2})\.call/;
        $AGI->say_number($hour);
        $AGI->say_number($minute);
    }
    if (!$foundOne) {
        $AGI->stream_file('dir-nomatch');
    }
} elsif ($extension =~ /^[\#\*]55\*\d{4}\#$/) {
    my $set = $extension =~ /^\*/;
    my ($hour, $minute) = ($extension =~ /^[\#\*]55\*(\d{2})(\d{2})\#$/);

    if ($hour > 23 || $minute > 59) {
        $AGI->stream_file('privacy-incorrect');
        $AGI->hangup();
        exit;
    }

    my $filename = sprintf("%s/wakeup.%s.%02d%02d.call",
                           $callfiledir,
                           $caller,
                           $hour,
                           $minute);
    if ($set) {
        my ($fh, $tmpfilename) = tempfile(DIR => $tmpdir);
        if (!$fh) { die $!; }
        print $fh "Channel: Local/$caller@"."$originateContext\n";
        print $fh "MaxRetries: 2\nRetryTime: 240\nWaitTime: 60\n";
        print $fh "Application: Playback\n";
        print $fh "Data: $wakeupFile\n";
       # print $fh "Callerid: *55*\n";
        print $fh "Callerid: \"Wakeup service\" <*55*>\n";
# i added the name to caller id number feel free to delete/change it if its broken - LuisManson
        flush $fh;

        my ($sec,$nowMin,$nowHour,$mday,$mon,$year,$wday,$yday) =
            localtime(time);
        if ($hour < $nowHour || $hour == $nowHour && $minute < $nowMin) {
            ($sec,$nowMin,$nowHour,$mday,$mon,$year,$wday,$yday) =
                localtime(time + 24 * 3600);
        }
        my $callTime = timelocal(0,$minute,$hour,$mday,$mon,$year);

        utime $callTime, $callTime, $tmpfilename;
        rename $tmpfilename, $filename;
        close $fh;
    } else {
        unlink $filename;
    }

    $AGI->stream_file($confirmFile);
} else {
    $AGI->stream_file('tt-somethingwrong');
}

$AGI->hangup();


Pound sign trouble


At least one SIP phone (Siemens Gigaset SL75 WLAN) seems to quote the # sign and puts the three characters "%23" in the dial string instead. If that is the case, just add the following lines to the dialplan:

extensions.conf
exten => _*55*XXXX%23,1,AGI(wakeup-call.pl) ; Set wake-up call
exten => _%2355%23,1,AGI(wakeup-call.pl) ; Cancel all
exten => _%2355*XXXX%23,1,AGI(wakeup-call.pl) ; Cancel specific
exten => _*%2355%23,1,AGI(wakeup-call.pl) ; Check status


The script also has to handle unquoting, something that I actually added to the script now. Se the comment "unquote pound sign".

If anyone knows if the quoting is something that Siemens came up with, or if it is part of the SIP standard, then please edit this text appropriately!

See Also


Yet another wake-up call implementation


I put together this perl/AGI script instead of installing one of the others for these reasons:
  • No cron job required
  • Works the same way as the PSTN "built-in" wake-up service has "always" worked here in Sweden

When the script is installed, wake-up calls are scheduled, cancelled, and reviewed by dialling the following extensions:
  • *55*HHMM# set a wake-up call at HH:MM,
  • #55*HHMM# cancel the wake-up call at HH:MM,
  • #55# cancel all wake-up calls,
  • *#55# reads back your pending wake-up calls.

All times use a 24 hour clock, and refer to some point within the next 24 hours. At the scheduled time, Asterisk calls you back and plays a sound file. If you do not answer, it makes two retries in five minute intervals.

It turns out this does not work with most SIP phones, since they believe that the pound sign terminates the number being called. I use this for my Zap phones at home. Of course, you could use some alternative extensions for your Sip phones, either by modifying the script, or, if you want the script to work with the standard extensions for Zap phones, by adding extension patterns that just Goto the extensions above. Maybe the section "Pound sign trouble" below helps.

I run this script on FreeBSD; maybe some paths need to be changed for Linux?

BTW, In Sweden, the extension *#55*HHMM# tells you if you have a call scheduled for the indicated time, but I added the *#55# extension instead.

extensions.conf
exten => _*55*XXXX#,1,AGI(wakeup-call.pl) ; Set wake-up call
exten => _#55#,1,AGI(wakeup-call.pl) ; Cancel all
exten => _#55*XXXX#,1,AGI(wakeup-call.pl) ; Cancel specific
exten => _*#55#,1,AGI(wakeup-call.pl) ; Check status


The variables at the top of the perl script might need some tweaking.

wakeup-call.pl
#!/usr/local/bin/perl -wT

# Added by Suretec Systems Ltd. - http://www.suretecsystems.com - 14/05/2006
use warnings;
use strict; 

my $callfiledir="/var/spool/asterisk/outgoing";
my $originateContext = 'home-out';
my $tmpdir = '/var/tmp'; # must be on same file system as $callfiledir
my $wakeupFile = 'tt-monkeys';
my $confirmFile = 'auth-thankyou';

use Asterisk::AGI;
use Time::Local;
use IO::File;
use File::Temp qw/ tempfile /;

my $AGI = new Asterisk::AGI;
$AGI->setcallback(\&callback);
sub callback() { exit; }

my %agiEnv = $AGI->ReadParse();

my ($caller) = $agiEnv{callerid} =~ /<(\d+)>/;
if (!defined $caller) {
    ($caller) = $agiEnv{callerid} =~ /(\d+)/;
}

$extension = $agiEnv{extension};
$extension =~ s/\%23/\#/g;         # unquote pound sign

$AGI->answer();
sleep 1;

if (!defined $caller) {
    print STDERR "Could not get caller id for wakeup call\n";
    $AGI->stream_file('tt-somethingwrong');
} elsif ($extension eq "#55#") {
    foreach my $fn (<$callfiledir/wakeup.$caller.*.call>)
    {
        unlink $fn;
    }
    $AGI->stream_file($confirmFile);
} elsif ($extension eq "*#55#") {
    my $foundOne = 0;
    foreach my $fn (<$callfiledir/wakeup.$caller.*.call>)
    {
        $foundOne = 1;
        my ($hour, $minute) = $fn =~ /\.(\d{2})(\d{2})\.call/;
        $AGI->say_number($hour);
        $AGI->say_number($minute);
    }
    if (!$foundOne) {
        $AGI->stream_file('dir-nomatch');
    }
} elsif ($extension =~ /^[\#\*]55\*\d{4}\#$/) {
    my $set = $extension =~ /^\*/;
    my ($hour, $minute) = ($extension =~ /^[\#\*]55\*(\d{2})(\d{2})\#$/);

    if ($hour > 23 || $minute > 59) {
        $AGI->stream_file('privacy-incorrect');
        $AGI->hangup();
        exit;
    }

    my $filename = sprintf("%s/wakeup.%s.%02d%02d.call",
                           $callfiledir,
                           $caller,
                           $hour,
                           $minute);
    if ($set) {
        my ($fh, $tmpfilename) = tempfile(DIR => $tmpdir);
        if (!$fh) { die $!; }
        print $fh "Channel: Local/$caller@"."$originateContext\n";
        print $fh "MaxRetries: 2\nRetryTime: 240\nWaitTime: 60\n";
        print $fh "Application: Playback\n";
        print $fh "Data: $wakeupFile\n";
       # print $fh "Callerid: *55*\n";
        print $fh "Callerid: \"Wakeup service\" <*55*>\n";
# i added the name to caller id number feel free to delete/change it if its broken - LuisManson
        flush $fh;

        my ($sec,$nowMin,$nowHour,$mday,$mon,$year,$wday,$yday) =
            localtime(time);
        if ($hour < $nowHour || $hour == $nowHour && $minute < $nowMin) {
            ($sec,$nowMin,$nowHour,$mday,$mon,$year,$wday,$yday) =
                localtime(time + 24 * 3600);
        }
        my $callTime = timelocal(0,$minute,$hour,$mday,$mon,$year);

        utime $callTime, $callTime, $tmpfilename;
        rename $tmpfilename, $filename;
        close $fh;
    } else {
        unlink $filename;
    }

    $AGI->stream_file($confirmFile);
} else {
    $AGI->stream_file('tt-somethingwrong');
}

$AGI->hangup();


Pound sign trouble


At least one SIP phone (Siemens Gigaset SL75 WLAN) seems to quote the # sign and puts the three characters "%23" in the dial string instead. If that is the case, just add the following lines to the dialplan:

extensions.conf
exten => _*55*XXXX%23,1,AGI(wakeup-call.pl) ; Set wake-up call
exten => _%2355%23,1,AGI(wakeup-call.pl) ; Cancel all
exten => _%2355*XXXX%23,1,AGI(wakeup-call.pl) ; Cancel specific
exten => _*%2355%23,1,AGI(wakeup-call.pl) ; Check status


The script also has to handle unquoting, something that I actually added to the script now. Se the comment "unquote pound sign".

If anyone knows if the quoting is something that Siemens came up with, or if it is part of the SIP standard, then please edit this text appropriately!

See Also


Created by: staffanu, Last modification: Tue 20 of Nov, 2007 (09:48 UTC)
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+