New features for telephony currently in use at KCLS
[Evergreen.git] / docs / TechRef / Telephony / telephony-setup-guide.txt
1 Setting up Telephone Notices with Evergreen
2 ===========================================
3
4 [abstract]
5 What is this document good for?
6 -------------------------------
7 This is telephony based on Asterisk and Action/Trigger for Evergreen 2.2 and up.
8
9 If you've never done this before, you should *really* read this document all the way through before you begin, so that you have some idea of what to expect and how much time to schedule for it.
10
11 This document should lead you through getting overdue telephone notices set up for Evergreen.  This document is long, but it's not comprehensive.  It does not cover everything you need to know about Asterisk, for example, or Action/Trigger or Cron or several other things.  It assumes you're bringing some knowledge to the table and that you're willing and able to search for information you don't have at hand. You must be prepared to solve small problems along the way.
12
13 Once you've set up overdue notices, you should get the general idea of how to set up additional notices, like notices for holds available. The last section of this document contains some parting information on what you can expect to differ between those notices and overdue notices.
14
15 Hardware
16 --------
17 Get a dedicated computer running Linux and make sure it meets any system requirements for Asterisk. 1 modernish CPU, 1 GB memory is plenty for most
18 applications.  More is always better.
19
20 Make sure that the system running Evergreen (specifically, the utility box if you're dealing with a multi-server environment that has a utility box specifically for Action/Trigger stuff) has network connectivity to the box running Asterisk.  At minimum it needs to be able to reach that Asterisk machine via TCP port 10080.  Do not let the whole Internet talk to your Asterisk box via TCP port 10080.  iptables is your friend.
21
22 If you're using analog telephony (you're connecting to the Public Switched Telephone Network), you'll need an actual physical computer.
23
24 For digital telephony, a virtual machine may suffice.
25
26 NOTE: Ask the Asterisk community whether they generally recommend using virtual machines to host Asterisk.
27
28 There are three main ways you can make phone calls with Asterisk.
29
30 . *plain old phone lines* - If you have to connect to plain old analog single-channel phone lines, you can use a card from Digium like the
31 AEX400 series to connect to up to four of those lines at once.  You need an FXO
32 module for each line you want to connect to the system (so the card itself is not enough).  Plain old phone lines are the worst choice on this list.  Usually with these, Asterisk thinks the conversation in outgoing calls has begun as soon as the other end starts *ringing.*  This is really suboptimal.
33 . *PRI interface or similar* - If your institution has this kind of service from a telephone company, or if they already have a PBX or some other such device that can offer channels for outbound dialing over a T1 interface, look into a card like the Digium TE121.  Make very sure you understand what kind of phone network you're going to connect it to, and that your selected card can talk to it.  This will often require coordination with a telephone company or PBX vendor to get working, but it provides a better platform that plain old phone lines.
34 . *VoIP service with SIP or IAX protocols* - Digital telephony.  Easiest to
35 deal with by far, and also provides the richest set of information to Asterisk about whether calls complete properly, whether busy signals occur, etc.  Requires no special hardware, just an internet connection.  Your institution will purchase this service from some other company.  Specifically, the institution should look for VoIP SIP providers (not library SIP, telephony SIP).  SIP is pretty easy to deal with.
36
37 If your project is at the stage where you can still recommend how your institution will achieve telephony connectivity , go with option 3 (voip service). You'll be glad you did.
38
39 Install Asterisk, Perform Test Calls
40 ------------------------------------
41
42 First things first
43 ~~~~~~~~~~~~~~~~~~
44 The first thing you need is a server dedicated to running Asterisk and
45 Festival.  Asterisk is an open source PBX.  Festival is for speech synthesis.
46
47 We'll talk about setting up Festival in a later step.  Strictly speaking, you might not need Festival if your institution doesn't
48 need its notice message to contain truly dynamic parts (such as reading a
49 list of overdue titles).  Asterisk can read numbers aloud by itself, and if
50 you need notices to choose between a finite set of possiblities of things to
51 say, you can just make or acquire recordings of each of those things and
52 choose between them with logic either in the Action/Trigger template or in
53 the Asterisk dialplan (for example, reading the name of a library branch
54 where a circulation is overdue).  More on this later.
55
56 As of this writing, you want any version of Asterisk within the 1.4, 1.6 or 1.8 series.
57
58 Basic outbound call testing
59 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
60 Install asterisk.  If you're using a Debian-based distro, try installing
61 Asterisk with apt.  If not, you may wind up installing it from source.  That's
62 ok. Installing Asterisk from source is easy;  it follows the typical +./configure && make && make install+ pattern, and that's about it.  For more information on installing Asterisk, just google it.
63
64 NOTE: If asterisk-1.6.2.18-accountcode.patch from the Evergreen source applies cleanly to whatever version of Asterisk you wind up installing, you may want to use it.  For reporting/auditing purposes, the Account field is a good place to shove data when using Asterisk call files and Call Detail Records, and that patch makes it possible to store more than a few bytes there.  Other fields (like userdata) don't necessary make it to the Call Detail Record in the event of outbound calls not reaching their destination (like when they result in busy signals).
65
66 Configure asterisk for full logging.  When running asterisk, you should get matter in +/var/log/asterisk/full+ on a typically configured system.
67
68 Be sure you also installed DAHDI if you're using analog hardware to place phone calls (there are even cases when you want to install it for digital calling; grep Asterisk documentation for "timing source").
69 When in doubt, just install it.  Maybe your package manager already did for you.
70
71 If using analog telephony, get your hardware configured and make sure you can see the things that you're supposed to see with +/usr/sbin/dahdi_tool+ (typical install location, but look around if needed) and the command "dahdi show channels" in the Asterisk interactive console.  I'm handwaving over the specifics here.  There's a wealth of information avaiable online about how to do this.
72
73 If using digital telephony, preferably with the SIP protocol, get that configured in asterisk and make sure your SIP channel(s) is/are up.  Again, more specifics on this are available online.
74
75 By the way, if you're not comfortable already, now is the time to get comfortable with Asterisk and making changes to its configuration.  I have not successfully used FreePBX or AsteriskHome or any of the friendly metapackages.  In my experience, these just get in your way and make Asterisk behave differently than otherwise documented.
76
77 Make sure asterisk is running.
78
79 In your dialplan (+/etc/asterisk/extensions.conf+), add a context that looks like the following.  If you're not comfortable yet with the meanings of "context," "extension," "module," and "dialplan" in Asterisk, go back and learn more about Asterisk before proceeding.
80
81 -------------------------------------------------------
82 [just-a-test]
83 exten => 10,1,Verbose(entering the just-a-test context)
84 exten => 10,n,Answer
85 exten => 10,n,SayNumber(10)
86 exten => 10,n,SayDigits(987654321)
87 exten => 10,n,Playback(vm-goodbye)
88 exten => 10,n,Hangup
89 -------------------------------------------------------
90
91 Reload your dialplan. You should be able to do this with the "dialplan reload"
92 command in the asterisk interactive console.
93
94 Make sure the pbx_spool asterisk module is running.
95
96 Edit a file in your home directory on the Asterisk machine.  Give it any name you like. Make its contents match the following.
97
98 -------------------------------------------------------
99 Channel: X
100 Context: just-a-test
101 Extension: 10
102 Callerid: 7701234567
103 MaxRetries: 1
104 RetryTime: 60
105 WaitTime: 30
106 Archive: 1
107 -------------------------------------------------------
108
109 Choose a phone number where you can be reached for this test call, such as your desk phone number.  Let's pretend that's 770-555-1212. Now replace the "X" in the first line with something like "SIP/mytrunk/7705551212" if you've configured SIP and named your trunk "mytrunk," or with something like "DAHDI/1/17705551212" if using analog hardware (the 1 between the slashes here means channel 1.)
110
111 Exactly what to replace that X with will vary a lot depending on circumstances.  If you're in a situation where you're not directly connected to the outside telephone network, but are rather behind some other PBX equipment or something, you may have to prepend a 9 to the number you wish to dial, or something like that. Whether or not to add a 1 before dialing the main phone number is also a matter of circumstance.  Sometimes you'll even be able to dial 7 digit phone numbers by themselves!
112
113 NOTE: I'm sorry I've obviously written the above from a North America-centric perspective; somebody else feel free to correct this.
114
115 When you think you've got something subsituted for X that might work, do the following as root:
116
117 -------------------------------------------------------
118 cp yourfile /tmp
119 chown asterisk /tmp/yourfile
120 mv /tmp/yourfile /var/spool/asterisk/outgoing
121 -------------------------------------------------------
122
123 You might think that three step operation looks silly, but it's important that you not copy your "call file" (that's what we're calling the file you just composed) directly into +/var/spool/asterisk/outgoing+.  The copy operation may not be finished when Asterisk reads in the file to make a call.  By using a move operation instead (atomic) you make sure Asterisk doesn't see the file until it's completely there.
124
125 If you've got the right stuff, and I've glossed over a lot of detail above, so you may very well not get it on the first try, you should get a phone call at your desk, and you should hear a woman's voice count down from ten to one and say goodbye.
126
127 When you get the call, check whether your caller ID actually shows "7701234567" or whatever you entered for that line in your call file.  Not all phone service providers actually let you set the caller ID here!  Your institution probably wants the outgoing caller ID on these notices to be set to some phone number where patrons should call in. Don't promise your institution that you can actually make that happen until you test it!
128
129 Testing a Call with Festival
130 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132 If you don't need Festival (because perhaps you don't need to for the outbound notices to contain arbitrary strings like lists of item titles), move on to the next section in this document. But it's not that hard, and it does come in handy, so I recommend you keep going here.
133
134 Install festival.  Packages exist for any reasonable distro.
135
136 Follow the instructions at http://www.voip-info.org/wiki/view/Asterisk+festival+installation .  Within that document, just follow method 1 ("the easiest way") for installing Festival for Asterisk usage.
137
138 Edit the "just-a-test" context in your dialplan so that it now reads like this:
139
140 -------------------------------------------------------
141 [just-a-test]
142 exten => 10,1,Verbose(entering the just-a-test context)
143 exten => 10,n,Answer
144 exten => 10,n,SayDigits(123)
145 exten => 10,n,Festival(Testing testing one two three)
146 exten => 10,n,Playback(vm-goodbye)
147 exten => 10,n,Festival(Goodbye)
148 exten => 10,n,Hangup
149 -------------------------------------------------------
150
151 Reload your dialplan, and follow the steps as in the previous test to respool your call file for another outbound call.
152
153 When you answer this call, you should hear a nice lady's voice say "one two three," a less nice male-ish voice say "testing testing one two three," the nice lady say "goodbye", and the less nice male say "goodbye."
154
155 When you hear this test, you have festival configured correctly.
156
157 Deploy Perl scripts connecting Evergreen to Asterisk
158 ----------------------------------------------------
159 You've got to set up two Perl scripts now.  These two scripts are involved in getting call files from Evergreen to Asterisk.  Evergreen basically generates a
160 call file via an Action/Trigger template and then ships it off to the Asterisk machine.  More on that later.
161
162 For now, the important thing is that Evergreen will send call files to your Asterisk machine on TCP port 10080 via XML-RPC.  One of these two Perl scripts I'm talking about has the job of listening for those deliveries.
163
164 Find the +Open-ILS/src/asterisk/pbx-daemon+ directory in the tarball for whatever version of Evergreen you installed, or from a checkout of the master branch.  From there, copy the two .pl files to +/usr/local/bin+ and the one .conf file to +/usr/local/etc+.
165
166 Try to run the command +eg-pbx-mediator.pl -c /usr/local/etc/eg-pbx-daemon.conf+.  It probably won't work the first time.  Read whatever error messages you get, and use your distribution's package manager or CPAN to install any missing perl dependencies (like Config::General and RPC::XML).  Rinse and repeat until the script runs without errors.  Use sudo or su to run it as the user "nobody." Once eg-pbx-mediator.pl is running, background it and get it out of your sight.
167
168 From the utility box, make sure you can telnet to your Asterisk box on port 10080.  If you can't get a connection, there's a either a firewall in your way or some other network layer problem.  Resolve that before continuing.
169
170 Now try to run +eg-pbx-allocator.pl -c /usr/local/etc/eg-pbx-daemon.conf+.  Follow the same process as above to install any missing dependencies or fix any errors.  This script is not a daemon, so it should exit immediately (and silently) when it's configured correctly.  We're going to want to run it via cronjob eventually, but we'll set that up in a later step.
171
172 What does each script do, you ask?  Basically eg-pbx-mediator.pl listens for call files from Evergreen and drops them off in +/var/tmp+.  eg-pbx-allocator.pl will move a given number of call files from +/var/tmp+ into +/var/spool/asterisk/outgoing+.  The reason there are two separate scripts doing this is so that you can schedule eg-pbx-allocator.pl to run (via cron) only during times when you want to be calling patrons (like during the day, and not on Sundays).
173
174 Getting your call script together
175 ---------------------------------
176 Now you need to determine what your notifications should say.  There are not useful defaults for this in Evergreen yet.
177
178 We know we can do overdue notices and hold available notices.  There are other "hooks" (see your Action/Trigger vocabulary) off which we could build other event definitions.  Chart your own course here and please share your results with the community!
179
180 For an overdue notice, for example, you need to decide (or get the
181 institution to decide) literally word for word what you want the message to
182 say.
183
184 Generic example:
185
186 -------------------------------------------------------
187 This is the Example Consortium calling on behalf of Example Branch 1 to inform
188 you that you have <number> overdue item(s).  The following titles are overdue:
189 <titles of overdue items>.  For more information, please call Example Branch 1
190 at <branch's phone number>.  Thank you.
191 -------------------------------------------------------
192
193 And then you need to create or obtain a similar script for hold available notices.
194
195 The following two subsections cover how to write a very basic dialplan and how to record sound files for a custom script.
196
197 Expanding your dialplan
198 ~~~~~~~~~~~~~~~~~~~~~~~
199
200 Now it's time to create more complete dialplans that reflect your call scripts.
201
202 In +/etc/asterisk/extensions.conf+, add a new context like the following.  This follows our example call script above, and assumes you installed and set up Festival.
203
204 -------------------------------------------------------
205 [overdue-notice]
206 exten => 11,1,Verbose(started in eg-overdue-notice)
207 exten => 11,n,Answer
208 exten => 11,n,Festival(This is the)
209 exten => 11,n,Festival(${root_ou_name})
210 exten => 11,n,Festival(calling on behalf of the)
211 exten => 11,n,Festival(${ou_name})
212 exten => 11,n,Festival(to inform you that you have)
213 exten => 11,n,SayNumber(${items})
214 exten => 11,n,GotoIf($[0${items} > 1]?20:25)     ; spaces important
215 exten => 11,20,Festival(overdue items.)          ; this is plural
216 exten => 11,n,Goto(30)
217 exten => 11,25,Festival(overdue item.)           ; this is singular
218 exten => 11,n,Goto(30)
219 exten => 11,30,Festival(The following titles are overdue)
220 exten => 11,n,Festival(${titles})
221 exten => 11,n,Festival(For more information please call)
222 exten => 11,n,Festival(${ou_name})
223 exten => 11,n,Festival(at)
224 exten => 11,n,SayDigits(${ou_phone})
225 exten => 11,n,Festival(Thank you.)
226 exten => 11,n,Hangup
227 -------------------------------------------------------
228
229 There are several things to bear in mind about the above dialplan.  It's extremely simple in that it doesn't attempt answering machine detection and it doesn't offer the called party any way to repeat part of the message.  If you're using plain-old-phone-lines (as opposed to a PRI card or digital telephony) this message will actually play to the ringback tone instead of waiting for a human to answer!  Furthermore, it's going to read everything in a hard-to-understand robot voice.
230
231 It will, however, serve its purpose in testing whether our call script will work.
232
233 Compose a new call file like this:
234
235 -------------------------------------------------------
236 Channel: X
237 Context: overdue-notice
238 Extension: 11
239 Callerid: 7701234567
240 MaxRetries: 1
241 RetryTime: 60
242 WaitTime: 30
243 Archive: 1
244 Set: rout_ou_name=Example Consortium
245 Set: ou_name=Example Branch 1
246 Set: ou_phone=4045551212
247 Set: items=2
248 Set: titles=Harry Potter. The Da Vinci Code.
249 -------------------------------------------------------
250
251 where you substitute "SIP/blah/somenumber" or "DAHDI/N/somenumber" for X as in the earlier example in this document.
252
253 Spool the file as per previous instructions. Does the message being read to you over the phone match the script you have?  If so, great.  Otherwise, do not continute until you get it right.
254
255 Repeat this process to create a hold-available notice, assuming your institution wants one.  You'll create a similar chunk of dialplan, but you'll just change the messages and logic to reflect your script for hold-available notices rather than your script for overdue notices.
256
257 Recording Sounds
258 ~~~~~~~~~~~~~~~~
259 Now to get rid of the robot voice.  For all the static parts of your call script (represented in the dialplan by lines that call Festival() without using any variables for arguments such as +${items}+), you can ask your institution to have somebody record wave files saying these phrases.  Or maybe by the time you read this document Evergreen will have some standard dialplans and matching sound files.  Or you may have to do the voice work yourself.
260
261 'Audacity' is a great open source application for recording and editing sound files.  Avoid clipping and introducing noisy artifacts.  How to record good audio is obviously outside the scope of this document, but anybody can do it.  Export Microsoft-style wav files, at 44100hz/16-bit.
262
263 Once you have your wave files of all the parts of the dialplan recorded, you'll need to turn them into GSM files for Asterisk.
264
265 Use sox to convert your WAV files to GSM.  sox is available on every serious Linux distro. For a single file, do this:
266
267 -------------------------------------------------------
268 sox infile.wav -r 8000 -c 1 outfile.gsm  resample -ql
269 -------------------------------------------------------
270
271 Put the above command inside a for loop to handle all your WAVs at once.  I leave that as an exercise for the reader.
272
273 Make sure your can play the product by running:
274 -------------------------------------------------------
275 play outfile.gsm
276 -------------------------------------------------------
277
278 It'll sound relatively lo-fi, but as long as you can hear yourself, that'll do.  It'll probably sound more natural through a phone handset than it does through your workstation's speakers.
279
280 Ideally you will have given your GSM files names that easily map to the strings of text that you have spoken in each file.  Place these files in +/var/lib/asterisk/sounds+ on the Asterisk server.  Then replace all of the static Festival calls in your dialplans with lines that look like this:
281
282 -------------------------------------------------------
283 exten => 11,n,Playback(For-more-information-please-call)
284 -------------------------------------------------------
285
286 The above assumes that there is a file at +/var/lib/asterisk/sounds/For-more-information-please-call.gsm+.
287
288 Reload your dialplan. Re-run the test from end of the section "expanding your dialplan."  You should hear your own voice replacing the hard-to-understand robot voice for all but the dynamic parts of the message.
289
290 Action/Trigger Event Definitions
291 --------------------------------
292
293 It's time to create Action/Trigger Event Definitions (rows in the action_trigger.event_defintion table) for the notifications you want.
294
295 Setting up the event definition itself
296 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297
298 There should be a stock example event definition linked to the the "checkout.due" hook.  For your overdue notices, you can just adjust this *if* you're going to be setting up overdue notices for the entire system or consortia using the Evergreen instance.
299
300 If, on the other hand, you're setting up telephone notifications just for a certain branch or system, go ahead and create a new event definition, and make extra sure that its owner field contains the ID of the highest org unit that you want to be involved in your notifications, and no higher.
301
302 Make your event definition look like the following. Columns I haven't mentioned can be left on their default values.
303
304 -------------------------------------------------------
305 active          | t
306 owner           | N     -- where N is the top org unit where you want notices
307 name            | Overdue Telephone Notification For Blah Library System
308 hook            | checkout.due
309 validator       | CircIsOverdue
310 reactor         | ProcessTemplate       -- sic! just while we're testing
311 delay           | 5 seconds
312 delay_field     | due_date
313 group_field     | usr
314 template        | test                  -- sic! just while we're testing
315 granularity     | Telephony
316 -------------------------------------------------------
317
318 The above isn't really enough to get the job done, but we're going to do this in baby steps.
319
320 Now make sure you have rows in action_trigger.environment that point to your event_definition (i.e., they have the correct event_definition ID in the "event_def" column) with the following three values for "path".
321
322 -------------------------------------------------------
323 target_copy.call_number.record.simple_record
324 usr.settings
325 circ_lib
326 -------------------------------------------------------
327
328 Once that's done, here's a simple template.  The more you want to change it, the more comfortable you'll need to be with Template Toolkit Syntax. Try setting the "template" column of your action_trigger.event_definition row to this:
329
330 -------------------------------------------------------
331 [%-
332
333 # Get a usable phone number.
334 phone = target.0.usr.day_phone | replace('[^0-9]', '');
335
336 IF phone.length == 7;
337   chan = 'DAHDI/r1/' _ phone;
338 ELSIF phone.length == 10;
339   chan = 'DAHDI/r1/1' _ phone;
340 ELSE;
341   ";noop bad phone number: '" _ phone _ "'"; STOP;
342 END;
343
344 branchname = target.0.circ_lib.shortname | lower;
345 branchphone = target.0.circ_lib.phone | replace('[^0-9]','');
346 -%]
347 Channel: [% chan %]
348 Context: overdue-notice
349 Extension: 11
350 MaxRetries: 2
351 RetryTime: 300
352 WaitTime: 30
353 Archive: 1
354 Set: eg_user_id=[% target.0.usr.id %]
355 Set: items=[% target.size %]
356 Set: branchname=[% branchname %]
357 Set: branchphone=[% branchphone %]
358 Set: titlestring=[%
359   titles = [];
360   FOR circ IN target;
361     t = circ.target_copy.call_number.record.simple_record.title;
362     t = t | replace('[^a-zA-Z0-9]',' '); # commas and things break Festival
363     titles.push(t);
364   END;
365   titles.join(". ");
366 %]
367
368 [%#
369   # Make sure this template ends with some line feeds! You don't want the
370   # "Set: titlestring=blah" line to be the last thing in the output without
371   # a linefeed (this, combined with things that happen later, will lead to
372   # callfiles that Asterisk cannot parse).
373 %]
374
375 -------------------------------------------------------
376
377 Around the middle, notice the lines where the template defines a variable "chan".  Make sure that "chan" is getting set to something that will actually work for placing a call with your system.  It may start with DAHDI or it may start with SIP, and the middle part will vary as well.  It all depends on what you had to put in your test call files earlier in order to be able to place test calls.
378
379 Enough about the template for now. Let's run some test events and see if we can generate a correct callfile from this template.
380
381 Testing some events for call file generation
382 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
383
384 On your institution's utility server, change to the opensrf user and issue the following command.
385
386 NOTE: For a busy institution that might have lots of overdue circulations (> 1000) you should take care to do this at some point in the day that won't disrupt other important processes on the utility box.  This could take a while (hours, potentially).
387
388 -------------------------------------------------------
389 /openils/bin/action_trigger_runner.pl --run-pending --process-hooks --granularity Telephony --granularity-only
390 -------------------------------------------------------
391
392 When that command finishes, you should have some rows in your *action_trigger.event* table where the "event_def" column matches the ID of the telephony event definition you just set up and the "state" column is "complete".
393
394 If you have rows where "event_def" is right but the state is not "complete," investigate that as you would any action trigger problem.  Otherwise your event rows will have numbers in the "template_output" column.  Pick some of those values from the "template_output" column, and for each of those values select the row from the *action_trigger.event_output* table with the matching ID.
395
396 The value of the "data" column of your event output rows should look like a callfile that matches the format of the callfiles you successfully tested in earlier sections of this document.  If you're not getting something that looks like a callfile that should work, make adjustments until you do.  Once you think you have something that might work, try pasting it into a text editor, substituting your own phone number for the one generated from the patron record, and spooling that as a callfile on the Asterisk system.  In theory you should hear a complete overdue notice.
397
398 Finishing touches
399 -----------------
400
401 Revalidation
402 ~~~~~~~~~~~~
403
404 TODO: Explain how to use revalidator_uri in +eg-pbx-daemon.conf+ to revalidate events that have been waiting for the allocator for a while right before we actually attempt to spool their callfiles with Asterisk, so patrons don't get stale overdue notices and such.
405
406 Patch AstCall.pm
407 ~~~~~~~~~~~~~~~~
408
409 If you're using a version of Evergreen earlier than 2.1.0, take the following commit from the Evergreen git repository and apply it on your utility server: e2d50e9f062c.
410
411 /openils/conf/opensrf.xml
412 ~~~~~~~~~~~~~~~~~~~~~~~~~
413
414 On the utility server edit +/openils/conf/opensrf.xml+ so that the <telephony> section looks like this:
415
416 -------------------------------------------------------
417 <telephony>
418     <enabled>1</enabled>    <!-- I think this setting isn't actually used -->
419     <driver>SIP</driver>    <!-- Always make this SIP, no matter what. -->
420         <channels>          <!-- This isn't used but must be here anyway. -->
421                 <channel>1</channel>
422                 <channel>2</channel>
423         </channels>
424     <host>A.B.C.D</host>    <!-- for A.B.C.D, enter the IP of Asterisk box -->
425     <port>10080</port>      <!-- default, little reason to change this -->
426     <user>evergreen</user>  <!-- not actually used -->
427     <pw>evergreen</pw>      <!-- not actually used -->
428 </telephony>
429 -------------------------------------------------------
430
431 Yes, I realize most of that config is ridiculous, especially how it expects you to have "SIP" as the driver even when you're using analog hardware. The config was shaped by earlier designs for A/T-based telephony that have been superseded. We should fix this, but don't worry: it's your event definition template that really spells out DAHDI or SIP, anyway.
432
433 Of course, somebody should clean up the config and the code that uses it to reflect what we really need, and then ideally update this document.  Thanks in advance.
434
435 Services to restart
436 ~~~~~~~~~~~~~~~~~~~
437 Restart the open-ils.trigger and the opensrf.settings services on the utility box.  If you don't usually restart specific services like that, restarting all the services on the utility box is fine.
438
439 Make your event definition use the AstCall reactor
440 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
441 Remember the event definition you made for telephone notices a few steps ago?  Change the value of its "reactor" column from 'ProcessTemplate' to 'AstCall'.
442
443 Init scripts for the Asterisk box
444 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
445
446 If you installed Asterisk from source instead of from a distro package, look in the source tarball for sample init scripts.  Choose the one appropriate for your distro, put it in place, run 'chkconfig' or 'update-rc.d' or whatever's appropritate for your distro, and make sure you can start and stop Asterisk with that init script now.
447
448 For festival, I think on Debianesque distros you will have installed this from a package, but if you're on something Redhat-ish and you need an init script, the following will probably work.
449
450 Festival:
451 -------------------------------------------------------
452 #!/bin/sh
453 #
454 # festival:     Festival Text-to-Speech server
455 #
456 # chkconfig:    - 26 89
457 # description:  Festival Text-to-Speech server
458 #
459
460 # Source function library.
461 . /etc/rc.d/init.d/functions
462
463 start()
464 {
465         mkdir -p /var/log/festival
466         mkdir -p /var/run/festival
467         cd /var/run/festival
468         echo -n $"Starting festival: "
469         nohup festival_server -l /var/log/festival &
470         echo
471 }
472
473 stop()
474 {
475         echo -n $"Shutting down festival: "
476         festival_server_control -l /var/log/festival exit
477         echo
478 }
479
480 # See how we were called.
481 case "$1" in
482   start)
483         start
484         ;;
485   stop)
486         stop
487         ;;
488   restart|reload)
489         stop
490         start
491         ;;
492   status)
493         status festival_server
494         ;;
495   *)
496         echo $"Usage: $0 {start|stop|restart|reload}"
497         exit 1
498 esac
499
500 exit 0
501 -------------------------------------------------------
502
503 For eg-pbx-mediator.pl, use this init script.  Actually you should change it to run the mediator as the 'nobody' user instead of as the 'root' user, but I haven't got around to that yet.
504
505 -------------------------------------------------------
506 #!/bin/sh
507 #
508 # eg-pbx-mediator:      Daemon to listen for call files from Evergreen
509 #
510 # chkconfig:    - 62 38
511 # description:  Daemon to listen for call files from Evergreen
512 #
513
514 PIDFILE=/var/run/eg-pbx-mediator.pid
515
516 start()
517 {
518         echo -n "Starting eg-pbx-daemon: "
519         /usr/local/bin/eg-pbx-mediator.pl -c /usr/local/etc/eg-pbx-daemon.conf &
520         echo
521         echo $! > $PIDFILE
522 }
523
524 stop()
525 {
526         echo -n "Shutting down eg-pbx-daemon: "
527         [ -r $PIDFILE ] && kill `cat $PIDFILE `
528         echo
529 }
530
531 # See how we were called.
532 case "$1" in
533   start)
534         start
535         ;;
536   stop)
537         stop
538         ;;
539   restart|reload)
540         stop
541         start
542         ;;
543   *)
544         echo $"Usage: $0 {start|stop|restart|reload}"
545         exit 1
546 esac
547
548 exit 0
549
550 -------------------------------------------------------
551
552 Cron job for eg-pbx-allocator.pl
553 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
554
555 On the asterisk machine, create a cron job (or more than one) for root to run the eg-pbx-allocator.pl script.  The idea is to run this script every minute during the "call window", or the period of time during which your institution is okay with calls going out.  Make sure you communicate with your institution and find out when this window is!
556
557 Here's an example from root's crontab on Anytown Public Library's Asterisk box:
558
559 -------------------------------------------------------
560 # Call window for Anytown Public Lib: 930am - 630pm Mon-Sat
561 # The three lines below here do this.
562 * 10-17 * * 1-6 /usr/local/bin/eg-pbx-allocator.pl -c /usr/local/etc/eg-pbx-daemon.conf
563 0-29 18 * * 1-6 /usr/local/bin/eg-pbx-allocator.pl -c /usr/local/etc/eg-pbx-daemon.conf
564 30-59 9 * * 1-6 /usr/local/bin/eg-pbx-allocator.pl -c /usr/local/etc/eg-pbx-daemon.conf
565 -------------------------------------------------------
566
567 So you see how those three cron lines togeter run the allocator every minute within Anytown's 930am - 630pm Mon-Sat call window.
568
569 Cron job for action_trigger_runner.pl
570 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
571
572 On the utility server, create a cronjob as opensrf to run action_trigger_runner.pl with the particular arguments we need for telephony notices.  If you're just doing overdue notices, most (but not all) Evergreen systems calculate overdues at midnight, so you 'could' have this cronjob run just once per day, some time in the wee hours.
573
574 On the other hand, if you're eventually going to run telephony notices for holds available, too, then you want to run action_trigger_runner.pl with our arguments more often.  Run it at the same frequency as you run the general --run-pending call, but slightly offset.  For example, if you have a general "Run all pending A/T events every half hour" cronjob that does things every hour at :00 and :30, then perhaps use this for your telephony --run-pending job:
575
576 -------------------------------------------------------
577 # Runs all pending telephony A/T events every half hour (offset by 10 min)
578 10,40 * * * * . ~/.bashrc && /openils/bin/action_trigger_runner.pl --osrf-config /openils/conf/opensrf_core.xml --run-pending --process-hooks --granularity Telephony --granularity-only
579 -------------------------------------------------------
580
581 Holidays
582 ~~~~~~~~
583 TODO: Write this section
584
585 Rollover failed notices
586 ~~~~~~~~~~~~~~~~~~~~~~~
587 TODO: Write this section
588
589 Congratulations!
590 ~~~~~~~~~~~~~~~~
591
592 Congratulations!  In a perfect world, telephone overdue notices for your institution are now live.  If you're not quite there, but you followed this document carefully, you should at least be close, and maybe with some clever troubleshooting you'll get there soon.
593
594 What to do differently for hooks like hold.available
595 ----------------------------------------------------
596
597 For your event definition where the hook is "hold.available", be sure you make the "validator" column "HoldIsAvailable".
598
599 Also, hold.available is an "active hook" as opposed to a passive one (like checkout.due) in Action/Trigger parlance.  I suppose the only thing that you really need to know about it is that events for hold.available, once you set up an event definition, will appear all throughout the day, unlike the events for checkout.due, which will typically appear all at once sometime shortly after midnight.
600
601 This may have implications for load scheduling.  That might mean changes to the cron job on the Asterisk machine that runs eg-pbx-allocator.pl, or changes to the queue_limit value in +/usr/local/etc/eg-pbx-daemon.conf+, or other things.  Telephony is an adventure.
602
603 The target for a hold.available hook is a hold, unlike a checkout.due hook for which the target is a circ, so for your event_definition's environment, notice change 'circ_lib' to 'pickup_lib'.  Then within your event_defintion's template, make the same substitution and any other reasonable changes in light of the fact that now target is an array of holds, whereas before it was an array of circs.
604
605 Troubleshooting and support
606 ---------------------------
607
608 Troubleshooting post-go-live
609 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
610
611 Want to see what's your telephony system is doing?  The best things you can do are these.
612
613 TODO: Explain how info from Account in a callfile winds up in CSV, and why it's good and helpful.
614
615 - Activate one of the cdr modules that come with Asterisk.  Call Detail Records wind up in either a CSV file or a database table depending on which module you activate.  You can even have the cdr_pgsql.so module put that database table in the same postgres database as Evergreen itself uses.  A cdr databse table will have one row per call made, with lots of information about what the phone number was and what happened with the call.  This information will be less reliable if you're using analog hardware, but is better if you're using digital telephony (VoIP).
616 - Check +/var/log/asterisk/full+.  grep around in this file to learn how to find all kinds of good information.
617 - Run the interactive Asterisk console.  On the asterisk server, as root, run */usr/sbin/asterisk -rvvvvvvvvvv* .  Watch things happen in real time.
618 - Consult the Evergreen database to see what kinds of notices have been generated.  The following is an example query to see if any telephone notices went out regarding Harry Potter (assuming you kept the titlestring part in your event definition template):
619 -------------------------------------------------------
620 SELECT atev.id
621 FROM action_trigger.event_definition atevdef
622 JOIN action_trigger.event atev ON (atev.event_def = atevdef.id)
623 JOIN action_trigger.event_output ateo ON (ateo.id = atev.template_output)
624 WHERE ateo.data ILIKE '%harry potter%';
625 -------------------------------------------------------
626 - Want to know what hold available events have been generated for a given user? Try a query like this:
627 -------------------------------------------------------
628 SELECT atev.id,atev.state,ateo.data
629 FROM action_trigger.event atev
630 JOIN action_trigger.event_definition atevdev ON (atevdef.id = atev.event_def)
631 LEFT JOIN action_trigger.event_output ateo ON (ateo.id = atev.template_output)
632 JOIN action.hold_request ahr ON (ahr.id = atev.target)
633 WHERE atevdef.hook = 'hold.available' and ahr.usr = <yourusridhere>;
634 -------------------------------------------------------
635
636 Stopping and restarting notices
637 -------------------------------
638
639 Is the system going haywire, and you need to stop outbound notices until you can figure out what's going on?  The following two steps are enough to stop notices in their tracks:
640
641 . Comment out the cron jobs for *eg-pbx-allocator.pl* in root's crontab on the Asterisk machine.
642 . +/etc/init.d/asterisk+ stop
643
644 Restarting notices is basically the obvious opposite of the above two steps, BUT you may wish to clear out previously queued notices first (or you may not, this just depends on what you're trying to accomplish and why you stopped notices in the first place).  For Evergreen telephony, there's a two-stage queuing system in play.  Files first go to +/var/tmp+ and then to +/var/spool/asterisk/outgoing+ so look for call files there and delete some if appropriate.
645
646 Clearing out queued notices
647 ---------------------------
648
649 Sometimes something will have happened (perhaps Evergreen has been used in offline mode for a while) and the system will have generated a lot of pending notices for overdues and holds that aren't actually correct.  Remember that overdue notices are produced typically just after midnight, and hold available notices are produced all the time.  Fixing wrong overdues or wrong hold shelving does NOT automatically recall any generated notices, so if there's some big disruptive event that's happened, it may be wise to clear out pending notices.  It's even better if you can do this before the call window opens for the day.
650
651 To remove queued notices (this is irrevocable!), just do
652
653 +rm /var/tmp/EG*.call+
654
655 +rm /var/spool/asterisk/outgoing/*+
656
657 You could move these files somewhere instead of deleting them if you think there's some chance you might not actually want to delete them all.