Sunday, December 12, 2010

Asterisk 1.8 Calendaring with text to speech reading out your calendar info

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.
NOTE: This is for Debians alike. Please modify accordingly for your own distros.
What we are attempting here to do is to read the calendar event on an and in this example/setup a Google Calendar using its iCal link and read the event to the user of his latest schedule.
The Google iCal is currently set to a public accessible link showing Malaysian holidays: (IN HTML FORMAT)
Part 1 – Getting calendar for ical to work on Asterisk
You need to get Asterisk 1.8.
Go to your preferred source directory, extract Asterisk source
1) wget
2)  tar -zxvf libical-0.44.tar.gz
3 cd libical-0.44
4) ./configure
5) make && make install
6) apt-get install libneon27 # or use yum
7) apt-get install libneon27-dev # or use yum
8)  (Re)compile and install asterisk (not going to show how here), do a “make menuselect” to ensure that Calendar and Internet Calendar Icalendar is enabled/selected
9) nano /etc/asterisk/calendar.conf # add a sample, like below from google’s malaysia holidays ical file
type = ical
url =
refresh = 15
timeframe = 1576800

Part 2 – Getting festival (the free text to speech engine), parts taken off a guide from here
1) apt-get install festival # install it with apt or yum
2) nano /etc/festival.scm # modify some configs on how to parse the audio files
3) Add the following inside this file (below), check to ensure the texts are properly copied, i had issues with that causing festival not to start and listen on TCP port 1314.
;; Enable access to localhost (needed by debian users)
(set! server_access_list '("localhost\\.localdomain" "localhost"))

;; set italian voice (comment the following 2 lines to use british_american)
;;; Command for Asterisk begin

(define (tts_textasterisk string mode)
"(tts_textasterisk STRING MODE)
Apply tts to STRING. This function is specifically designed for
use in server mode so a single function call may synthesize the string.
This function name may be added to the server safe functions."
(let ((wholeutt (utt.synth (eval (list 'Utterance 'Text string)))))
(utt.wave.resample wholeutt 8000)
(utt.wave.rescale wholeutt 5)
(utt.send.wave.client wholeutt)))

;;; Command for Asterisk end
4) Copy the init script (so it will auto run next time you reboot)
5) cp /usr/share/doc/festival/examples/festival.init /etc/init.d/festival
6) chmod +x /etc/init.d/festival
7)  update-rc.d festival defaults
8) nano /etc/default/festival # add the line below inside
10) nano /etc/asterisk/festival.conf # configure asterisk to use festival, make sure that cache directory exists and permission are okay
festivalcommand=(tts_textasterisk "%s" 'file)(quit)\n

11)  /etc/init.d/festival start # start festival
12)  netstat -an |grep 1314 # it must exist with TCP listening on, otherwise, can try starting it manually to see any error # /usr/bin/festival --server --script /etc/festival.scm   this is also good for debugging if the text file is sent to the festival server from asterisk
12) Now, create some dialplans in /etc/asterisk/extensions.conf or anywhere related (like in freepbx would be /etc/asterisk/extension_custom.conf)
exten => gc*cal,1,Answer
exten => gc*cal,n,Set(i=${MATH(${EPOCH}+1576800,int)}) ; 1576800 is about half a year EPOCH
exten => gc*cal,n,NoOp(Math func addon is ${i})
exten => gc*cal,n,Set(id=${CALENDAR_QUERY(myholidays,${EPOCH},${i})})
exten => gc*cal,n,NoOp(Event NoOp ${CALENDAR_QUERY_RESULT(${id},summary)})
exten => gc*cal,n,Set(es=$[${CALENDAR_QUERY_RESULT(${id},summary)}])
exten => gc*cal,n,Set(es=$[${CALENDAR_QUERY_RESULT(${id},summary)}])
exten => gc*cal,n,Festival(Event type is)
exten => gc*cal,n,Festival(${es})
exten => gc*cal,n,Set(epochstart=${CALENDAR_QUERY_RESULT(${id},start)})
exten => gc*cal,n,set(startdate=${STRFTIME(${epochstart},,%A%t %e%t %B%t %G%t)})
exten => gc*cal,n,set(starttime=${STRFTIME(${epochstart},,%H%t %M%t)}) 
exten => gc*cal,n,Festival(start date)
exten => gc*cal,n,Festival(${startdate})
exten => gc*cal,n,Festival(start time)
exten => gc*cal,n,Festival(${starttime} hours)
exten => gc*cal,n,Set(epochend=${CALENDAR_QUERY_RESULT(${id},end)})
exten => gc*cal,n,set(enddate=${STRFTIME(${epochend},,%A%t %e%t %B%t %G%t)})
exten => gc*cal,n,set(endtime=${STRFTIME(${epochend},,%H%t %M%t)}) 
exten => gc*cal,n,Festival(end date)
exten => gc*cal,n,Festival(${enddate})
exten => gc*cal,n,Festival(end time)
exten => gc*cal,n,Festival(${endtime} hours)
exten => gc*cal,n,Hangup

13) Remember to restart asterisk at least once for all these to work, as we are loading the calendar module and dialplans in it.
14) You would need a phone that’s capable to dial letters (or change that dialplan to dial a number instead like exten => 1000
15) Dial from your phone gc*cal
Post a Comment