\section{Introduction} The Asterisk Calendaring API aims to be a generic interface for integrating Asterisk with various calendaring technologies. The goal is to be able to support reading and writing of calendar events as well as allowing notification of pending events through the Asterisk dialplan. There are three calendaring modules that ship with Asterisk that provide support for iCalendar, CalDAV, and Microsoft Exchange Server calendars. All three modules support event notification. Both CalDAV and Exchange support reading and writing calendars, while iCalendar is a read-only format. \section{Configuring Asterisk Calendaring} All asterisk calendaring modules are configured through calender.conf. Each calendar module can define its own set of required parameters in addition to the parameters available to all calendar types. An effort has been made to keep all options the same in all calendaring modules, but some options will diverge over time as features are added to each module. An example calendar.conf might look like: \begin{astlisting} \begin{verbatim} [calendar_joe] type = ical url = https://example.com/home/jdoe/Calendar user = jdoe secret = mysecret refresh = 15 timeframe = 600 autoreminder = 10 channel = SIP/joe context = calendar_event_notify extension = s waittime = 30 \end{verbatim} \end{astlisting} \subsection{Module-independent settings} The settings related to calendar event notification are handled by the core calendaring API. These settings are: \begin{description} \item[autoreminder] This allows the overriding of any alarms that may or may not be set for a calendar event. It is specified in minutes. \item[refresh] How often to refresh the calendar data; specified in minutes. \item[timeframe] How far into the future each calendar refresh should look. This is the amount of data that will be visible to queries from the dialplan. This setting should always be greater than or equal to the refresh setting or events may be missed. It is specified in minutes. \item[channel] The channel that should be used for making the notification attempt. \item[waittime] How long to wait, in seconds, for the channel to answer a notification attempt. \end{description} There are two ways to specify how to handle a notification. One option is providing a context and extension, while the other is providing an application and the arguments to that application. One (and only one) of these options should be provided. \begin{description} \item[context] The context of the extension to connect to the notification channel \item[extension] The extension to connect to the notification. Note that the priority will always be 1. \end{description} or \begin{description} \item[app] The dialplan application to execute upon the answer of a notification \item[appdata] The data to pass to the notification dialplan application \end{description} \subsection{Module-dependent settings} Connection-related options are specific to each module. Currently, all modules take a url, user, and secret for configuration and no other module-specific settings have been implemented. At this time, no support for HTTP redirects has been implemented, so it is important to specify the correct URL--paying attention to any trailing slashes that may be necessary. \section{Dialplan functions} \subsection{Read functions} The simplest dialplan query is the CALENDAR\_BUSY query. It takes a single option, the name of the calendar defined, and returns "1" for busy (including tentatively busy) and "0" for not busy. For more information about a calendar event, a combination of CALENDAR\_QUERY and CALENDAR\_QUERY\_RESULT is used. CALENDAR\_QUERY takes the calendar name and optionally a start and end time in "unix time" (seconds from unix epoch). It returns an id that can be passed to CALENDAR\_QUERY\_RESULT along with a field name to return the data in that field. If multiple events are returned in the query, the number of the event in the list can be specified as well. The available fields to return are: \begin{description} \item[summary] A short summary of the event \item[description] The full description of the event \item[organizer] Who organized the event \item[location] Where the event is located \item[calendar] The name of the calendar from calendar.conf \item[uid] The unique identifier associated with the event \item[start] The start of the event in seconds since Unix epoch \item[end] The end of the event in seconds since Unix epoch \item[busystate] The busy state 0=Free, 1=Tentative, 2=Busy \item[attendees] A comma separated list of attendees as stored in the event and may include prefixes such as "mailto:". \end{description} When an event notification is sent to the dial plan, the CALENDAR\_EVENT function may be used to return the information about the event that is causing the notification. The fields that can be returned are the same as those from CALENDAR\_QUERY\_RESULT. \subsection{Write functions} To write an event to a calendar, the CALENDAR\_WRITE function is used. This function takes a calendar name and also uses the same fields as CALENDAR\_QUERY\_RESULT. As a write function, it takes a set of comma-separated values that are in the same order as the specified fields. For example: \begin{astlisting} \begin{verbatim} CALENDAR_WRITE(mycalendar,summary,organizer,start,end,busystate)= "My event","mailto:jdoe@example.com",228383580,228383640,1) \end{verbatim} \end{astlisting} \section{Dialplan Examples} \subsection{Office hours} A common business PBX scenario is would be executing dialplan logic based on when the business is open and the phones staffed. If the business is closed for holidays, it is sometimes desirable to play a message to the caller stating why the business is closed. The standard way to do this in asterisk has been doing a series of GotoIfTime statements or time-based include statements. Either way can be tedious and requires someone with access to edit asterisk config files. With calendaring, the adminstrator only needs to set up a calendar that contains the various holidays or even recurring events specifying the office hours. A custom greeting filename could even be contained in the description field for playback. For example: \begin{astlisting} \begin{verbatim} [incoming] exten => 5555551212,1,Answer exten => 5555551212,n,GotoIf(${CALENDAR_BUSY(officehours)}?closed:attendant,s,1) exten => 5555551212,n(closed),Set(id=${CALENDAR_QUERY(office,${EPOCH},${EPOCH})}) exten => 5555551212,n,Set(soundfile=${CALENDAR_QUERY_RESULT(${id},description)}) exten => 5555551212,n,Playback($[${ISNULL(soundfile)} ? generic-closed :: ${soundfile}]) exten => 5555551212,n,Hangup \end{verbatim} \end{astlisting} \subsection{Meeting reminders} One useful application of Asterisk Calendaring is the ability to execute dialplan logic based on an event notification. Most calendaring technologies allow a user to set an alarm for an event. If these alarms are set on a calendar that Asterisk is monitoring and the calendar is set up for event notification via calendar.conf, then Asterisk will execute notify the specified channel at the time of the alarm. If an overrided notification time is set with the autoreminder setting, then the notification would happen at that time instead. The following example demonstrates the set up for a simple event notification that plays back a generic message followed by the time of the upcoming meeting. calendar.conf. \begin{astlisting} \begin{verbatim} [calendar_joe] type = ical url = https://example.com/home/jdoe/Calendar user = jdoe secret = mysecret refresh = 15 timeframe = 600 autoreminder = 10 channel = SIP/joe context = calendar_event_notify extension = s waittime = 30 \end{verbatim} \end{astlisting} \begin{astlisting} \begin{verbatim} [calendar_event_notify] exten => s,1,Answer exten => s,n,Playback(you-have-a-meeting-at) exten => s,n,SayUnixTime(${CALENDAR_EVENT(start)}) exten => s,n,Hangup \end{verbatim} \end{astlisting} \subsection{Writing an event} Both CalDAV and Exchange calendar servers support creating new events. The following example demonstrates writing a log of a call to a calendar. \begin{astlisting} \begin{verbatim} [incoming] exten => 6000,1,Set(start=${EPOCH}) exten => 6000,n,Dial(SIP/joe) exten => h,1,Set(end=${EPOCH}) exten => h,n,Set(CALENDAR_WRITE(calendar_joe,summary,start,end)=Call from ${CALLERID(all)},${start},${end}) \end{verbatim} \end{astlisting}