The need:

A client of mine wants his Asterisk based PBX to be aware of office hours. Simple stuff, he wants the callers not to ring the phones and not to listen the music when there is nobody to answer the call.

Problem:

The office has 09:00-13:00, 14:00-19:00/Mon-Fri opening hours and this is the easy part because these rarely change and are “fixed”. What about extra ? Holidays? meetings? corporate parties?

Solution:

I could actually give to the client some FTP to add/remove holidays, or I could do that in database and let him manage it with 3 html pages. But on the other hand, why should I reinvent the wheel instead of using something that works?

It was a couple of month since I’ve opened a google apps for them and by now all the office uses google’s calendar to manage their agenda. Cool, let’s move the holidays there too!!!

The final target is to let our managers to manage holidays and like that via Google Calendar. If there is Christmas then they just hit “add event”, set it to 2 days duration and click “Save”. Asterisk will pull this event and will not ring the office phones.

Note: the code and configurations below are just Quick&Dirty stuff that works for me. YMMV.

First, let us do the simple stuff, I define a macro that checks the fixed working hours and if the office is closed then it sends the call into “Our offices are closed, please call us from Mon….. or leave us a message. Thank you” context (off-closed)

[macro-timecheck]
;the two gotos below check if it is not getting dark outside
;I don't know if it works with midnight jump, so split it in two
;just in case
exten => s,1,GotoIfTime(00:00-09:00,*,*,*?off-closed,s,1)
exten => s,2,GotoIfTime(19:00-00:00,*,*,*?off-closed,s,1)
;the one below check if the office has gone to lunch
exten => s,3,GotoIfTime(13:00-14:00,*,*,*?off-closed,s,1)
;and this one will fire if there is happy happy joy joy weekend
exten => s,4,GotoIfTime(*,sat-sun,*,*?off-closed,s,1)

so far so good

[somewhereinincoming]
exten => s,1,Macro(timecheck)

works
now then, to the real business, first let us retrieve the today’s events list using Google’s XML access to calendar:

load( $feed );

//get all
$entries = $doc->getElementsByTagName( "entry" );
//and iterate
foreach ( $entries as $entry ) {
  $titles = $entry->getElementsByTagName( "title" );
  $title = $titles->item(0)->nodeValue;
//this title is useless here, but can be used for
//example with TTS, so you can make asterisk
//say "We are closed because of $title"
  $times =
    $entry->getElementsByTagName( "when" );
  $startTime =
    $times->item(0)->getAttributeNode("startTime")->value;
  $startTime =
    (date( "H", strtotime( $startTime ) ) * 60 )
    + date( "i", strtotime( $startTime ) );
  $endTime =
    $times->item(0)->getAttributeNode("endTime")->value;
  $endTime =
    (date( "H", strtotime( $endTime ) ) * 60 )
    + date( "i", strtotime( $endTime ) );
//the stuff above gives me start/end time of the entry
//in minutes since midnight
  if ( $now >= $startTime && $now <= $endTime ) {     //and I get here if my $now falls into that interval     //so I will echo positive and exit     echo "YES";     exit;   } } ?>

adding it to the macro:

;execute the script and set the variable
;HDAYS to the value printed by script
exten => s,5,Backticks(HDAYS,/full/path/to/php /full/path/to/scriptabove.php)
;jump to "off-closed" if YES
exten => s,6,GotoIf($["${HDAYS}" = "YES" ]?off-closed,s,1)

and by now it works and everybody is happy!!!!

Note: The system is debian x86, asterisk 1.4, php5.2, google calendar url is private

4 Thoughts on “Getting Asterisk to speak with Google Calendar

  1. Matthew74 on February 20, 2011 at 7:22 pm said:

    This might be more obvious than I can see right now, but I don’t see anywhere that you set your google calendar location. Is there a missing piece to this?

    • Anonymous on February 20, 2011 at 8:11 pm said:

      well, it is obvious in the context 🙂 you just fetch it with http, when you go to the calendar settings you can find a link to XML “feed”, there is probably some lines before load( $feed ) I did not include, but loading xml from internet should be trivial. Would paste it but have no access to the system anymore. I would also check the gdata python bindings if there is a cleaner way to achieve it. There wasn’t at the time of the posting.

  2. Matthew74 on February 20, 2011 at 7:22 pm said:

    This might be more obvious than I can see right now, but I don’t see anywhere that you set your google calendar location. Is there a missing piece to this?

    • well, it is obvious in the context 🙂 you just fetch it with http, when you go to the calendar settings you can find a link to XML “feed”, there is probably some lines before load( $feed ) I did not include, but loading xml from internet should be trivial. Would paste it but have no access to the system anymore. I would also check the gdata python bindings if there is a cleaner way to achieve it. There wasn’t at the time of the posting.

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation