O'Reilly Emerging Telephony

oreilly.comSafari Books Online.Conferences.
advertisement
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA
AddThis Social Bookmark Button

Print Subscribe to Telephony Subscribe to Newsletters

Out-Of-Office Processing with Asterisk
Pages: 1, 2

Step 1.5: Converting Time Strings to Epoch Time

In the previous section, I assumed an AGI function that would convert a time specification into an epoch time. The current development version of Asterisk adds the STRPTIME function as a gateway to the operating system's function of the same name, but I am not using the current development version. Rather than upgrade, I chose to write a short AGI program in Perl to handle the conversion for me.



The program assumes the time string is followed by a time-string specifier beginning with the % character. To separate the time from the specifier, it joins all the arguments together and takes everything to the left of the first % as the time. It then uses the Time::Piece function to convert the string into an epoch time. Time::Piece is smart enough to process a string with trailing white space, so there is no need to clean up after it.

# Asterisk AGI program as interface to STRPTIME() C library function
#
# Matthew Gast
#
# This program takes as arguments a time string format and a specification
# in standard C function calls, split by the pipe character ("|") and
# returns the epoch as an Asterisk channel variable

use strict;

use Asterisk::AGI;
use Time::Piece;

my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();

$AGI->verbose("strptime AGI converter started.\n",1);

# Create time string and specifier from the arguments
my $argumentline=join(' ',@ARGV);
my @splitargs=split(/%/,$argumentline);
my $time = $splitargs[0];
my $spec = '%' . join('%',@splitargs[1..$#splitargs]);

$AGI->verbose("Will get epoch of --$time-- with specification --$spec--\n",1);

my $t = Time::Piece->strptime($time,$spec);
my $epoch = $t->epoch;
my $offset = $t->tzoffset;

$AGI->verbose("UTC epoch value is $epoch \n",1);
$AGI->verbose("Offset to local time is $offset\n",1);
$epoch = $epoch - $offset;
$AGI->verbose ("TZ-corrected value is $epoch, setting RESULT_EPOCH\n",1);
$AGI->set_variable("RESULT_EPOCH",$epoch);

exit(0);

Step 2: Checking Out-of-Office Status

Once the epoch time for the return to the office is in AstDB, it's easy to handle. Every time an extension would be dialed, the current time should be checked against the return time. For reuse purposes, I have defined a macro named checkoutofoffice that takes the extension as an argument.

The flow through the macro is straightforward. If no record in the out-of-office database exists, the extension should ring normally. It is only when a record exists and the time is in the future that the extension should be marked as out of the office. The macro sets the SILENT_RING variable as a meta-control. Different SIP devices have different ways to suppress rings, so I use the SILENT_RING channel variable to tell the final step in connecting an extension to use the appropriate method for the SIP device in question. The macro also sets the OUTOFOFFICE variable so that rather than a silent ring, the device can be prevented from ringing at all.

macro checkoutofoffice (ext) {
// This macro checks whether or not an extension users is "out of the office,"
// and therefore, should not be rung.
//
// Input:  Extension number to check.
// Output: Sets the SILENT_RING and OUTOFOFFICE channel variables to true
//         if the user of that extension is out of the office.

Set(NAME=macro-checkoutofoffice);
NoOp(${NAME} - started);

    if ( ${DB_EXISTS(ooo/${ext})} ) {
        Gosub(db-exists);
    } else {
        NoOp(${NAME} - No OOO record found for ${ext});
    };
    goto end;

  db-exists:
       NoOp(${NAME} - OOO record found for ${ext});
    Set(OOO_UNTIL=${DB(ooo/${ext})});
    if ( ${EPOCH} < ${OOO_UNTIL} ) {
        NoOp(${NAME} - ${ext} is out of the office - no ring);
        Set(__SILENT_RING=true);
        Set(__OUTOFOFFICE=true);
    } else {
        NoOp(${NAME} - ${ext} is back in the office - ring active);
    };
    Return;

  end:
    // finish
    NoOp(${NAME} - ended);
};

Any extension that should have out-of-office processing then needs to call the out-of-office check before connecting the call. A very simple example would be the following extension code, which checks the out-of-office status and prevents connecting the call if the extension is marked as away:

1001 => {
    &checkoutofoffice(${EXTEN});
    if (${ISNULL(${OUTOFOFFICE})}) {
        // continue to connect call
        Dial(SIP/1001,20);
    } else {
        NoOp(Extension ${EXTEN} is out of the office, no connection attempt);
    };
    Voicemail(u1001);
};

My Asterisk system implements a "follow-me" system that rings multiple extensions in turn. One of the advantages to skipping over a home extension when I am out of the office is that callers will more quickly reach me.

Matthew Gast is the director of product management at Aerohive Networks responsible for the software that powers Aerohive's networking devices.


Return to O'Reilly Emerging Telephony.


Comments on this article
Full Threads Oldest First

Showing messages 1 through 1 of 1.

  • Dave Mabe photo Cool solution
    2006-09-26 06:06:12  Dave Mabe | O'Reilly AuthorO'Reilly Blogger [View]

    Matthew - nice article. I took a similar approach to the same problem except I used a motion detector in my office to determine whether the ooo message should be played or not. It appears in the latest Make magazine.

    I like your approach!


Search Emerging Telephony

Search

Tagged Articles

Be the first to post this article to del.icio.us

Sponsored Resources

  • Inside Lightroom
Advertisement
Sign up today to receive special discounts,
product alerts, and news from O'Reilly.
Privacy Policy >
View Sample Newsletter >
  • Youtube
  • http://www.youtube.com/OreillyMedia
  • Twitter
  • Subscribe
  • View All RSS Feeds >
O'Reilly Media

800-889-8969 or 707-827-7019
Monday-Friday 7:30am-5pm PT
©2011, O'Reilly Media, Inc.
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
  • About O'Reilly
  • Academic Solutions
  • Contacts
  • Customer Service
  • Careers
  • Press Room
  • Privacy Policy
  • Terms of Service
  • Writing for O'Reilly
  • Community
  • Authors
  • Forums
  • Membership
  • Newsletters
  • RSS Feeds
  • User Groups
  • Partner Sites
  • makezine.com
  • makerfaire.com
  • craftzine.com
  • igniteshow.com
  • PayPal Developer Zone
  • O'Reilly Insights on Forbes.com