It's free software day again at Nerd Vittles, and today we're updating our Telephone Reminder System for Asterisk® to version 3. The original system let you schedule reminders for future events and, when the appointed date and time arrived, Asterisk swung into action and placed a call to the number you designated to deliver your customized reminder message. Today we add the bells and whistles that just about everyone using the original application requested. Now you can set up recurring reminders that call daily or on weekdays as well as weekly, monthly, and annually. This means it can be used to wake you up in the morning, or to remind Granny to take her medicine every day, or to remind your Little League team of practice times and locations, or to remind you and your customers of scheduled and recurring events.
The smarts for the original system already have been incorporated into our TeleYapper 2.5 Voice Messaging System. But that's a real-time system meaning it begins calling immediately after you choose a group of people to call. This phone reminder system is different in that you can schedule the calls for the near or distant future, you can specify different numbers for the calls, and you can customize the recorded messages for each call. In short, it's perfect for appointment reminders, birthday reminders, anniversary reminders, and anything else you want to remember. All it takes is a phone call to set up each reminder. There's no web page to fill in and no database required to manage the reminders. You can schedule as many reminders per phone number as your little fingers care to dial! And, in our next article, we'll show you how to use a single entry from the new Asterisk Telephone Reminder System to contact a small or large group of people on a recurring basis.
Prerequisites. We've tested version 3 of our appointment reminder system with ISO-installed versions of Asterisk@Home 2.5 and TrixBox 1.2.3 in addition to the Nerd Vittles VMware builds of TrixBox 1.2.3. If you wish to use it with later versions of TrixBox or with a "pure Asterisk" system (not 1.4!), then you shouldn't have any problems. It won't work with version 1.x of Asterisk@Home or 1.4 releases of Asterisk. Post a comment if you have problems. You also will need a system which includes PHP to run this application. We've tested it with PHP 4.3.9, but PHP 5 systems probably will function without many changes in the underlying code. You should be able to install this project and get everything working in under 30 minutes. For those using our VMware TrixBox builds or our Linux PBX-in-a-Flash script for TrixBox 1.2.3 which can be downloaded at the top of this page, we'll walk you through the 5-minute upgrade drill so that you can take advantage of the new Version 3 recurring reminders feature set. If you're installing Telephone Reminders for the first time, complete installation instructions are available on our Best of Nerd Vittles site.
How It Works. The reminder system is actually quite simple to use. You dial extension 1-2-3 on your Asterisk system, enter your password, and then you'll be prompted to record a reminder message. Next you enter the phone number, date, and time for delivery of the reminder message. Finally, you're prompted whether to schedule a single reminder or recurring reminders (weekdays, daily, weekly, monthly, or annually). When the appointed date and time arrives, Asterisk will place the call to the number you specified using your default dialing rules and will play the customized reminder when the call is answered. If the call is not answered, the call will be repeated n number of times with a delay between calls of x minutes before giving up on the call. You'll get an email with the call reminder setup if desired. You also get to configure the number of retries and the delay between calls. Finally, end of the month recurring reminders pose a special problem. Why? Because not all months end on the same numbered day. January has 31, February has 28, April has 30. You get the idea. So the default behavior is as follows, If you schedule monthly reminders on the last day of any month, then we assume you want the reminders delivered on the last day of every month. You can alter this behavior by setting a flag in the reminder.php script if you want monthly reminders to always be delivered on the 28th day of the month, for example.
Finally, a word about failed calls. Reminders are important to most folks, or you wouldn't be scheduling them. So failed calls are problematic. On the one hand, you don't want to overburden your phone system placing thousands of reminder calls just because the calls continue to fail. You may have entered an incorrect phone number, for example. So our middle-of-the-road solution to failed calls is this. You can tell the system how many times to repeat the call and how much time to eat up between attempts. If the call still fails, non-recurring reminders will be deleted from the system. But the reminder message is preserved as well as the recurring reminder for the next date on which to place the call. If you look in /var/lib/asterisk/sounds/custom on your system, you will see some custom sound files (such as the reminder prompts which all begin with reminder). In addition, you will see the actual reminder messages for each of your reminders. The naming convention is HourMinute.Date.PhoneNumber.gsm. If you see entries in this directory with dates before today's date, those are failed call reminders. You can play the sound files on most computers by simply double-clicking on the files. You can delete old reminders for a specific date while logged in as root on your Asterisk system with a command like this:
rm -f /var/lib/asterisk/sounds/custom/*.20060123.*.gsm
Be sure you don't delete today's reminder messages or messages with a future date, or your entire reminder system will be toast!
Here are the components that make up the complete system:
Limitations. There are a few limitations you need to be aware of. First, you can't schedule delivery of a reminder within the first 5 minutes after midnight each night. That's when the reminder system does its housekeeping. Second, you must schedule reminders at least 5 minutes after you place your call to set up the reminder. This gives the system ample time to generate the configuration files it needs and to put them in the right places. Third, the current reminder system does not fully support simultaneous scheduling of multiple reminders. The current system uses unique names to identify sound files generated by multiple simultaneous callers. However, it still is theoretically possible for two different callers to schedule two reminders for the same phone number and the same reminder time and to do so at the exact same time. This would cause one of the reminders to be discarded. We just wanted to alert you to this remote possibility. But we hasten to add that the chance of this happening is pretty small even in a very large Asterisk system with hundreds of users.
License. This software is licensed for your use under a Creative Commons Attribution-ShareAlike 2.5 license. Before using this software, please read the terms of the license. A Plain English version of the license is available here. You may not charge a fee for something we are giving you for free. Finally, we ask that you preserve our copyright notice in any copies of the software you make. The same applies to derivative works. If you do not accept the terms of the license, do not use the software. Even if you accept the terms of the license, keep in mind that BY USING THIS SOFTWARE, YOU ASSUME ALL RISKS OF USE AND NO WARRANTIES EXPRESS OR IMPLIED ARE PROVIDED WITH THIS FREE SOFTWARE INCLUDING FITNESS FOR A PARTICULAR USE AND MERCHANTABILITY. In short, it's up to you to determine, at your own risk, whether this software meets your needs. Don't assume that it will, and don't assume that the code is error-free. It's probably not.
The Game Plan. In today's article, we're going to walk you through upgrading a system on which you already have installed an earlier version of our Telephone Reminders system. As mentioned, if you're installing the software for the first time, stop here and use our Best of Nerd Vittles tutorial. To get the Reminder System upgraded, we're first going to move all of the code into the proper places. This includes the modifications to the dialplan contexts, installation of a new Allison voice prompts, and installation of the upgraded PHP/AGI scripts. Then we'll walk you through configuring the system. And finally we'll schedule a reminder to make sure everything went according to plan.
Modifying Your Dialplan. Step #1 is to replace some code that's already in your dialplan. The original contexts in extensions_custom.conf looked like this. Find ALL of this code (toward the bottom of the extensions_custom.conf file or, for TrixBox systems, extensions_trixbox.conf in the /etc/asterisk directory on your system) and delete it. The contexts to delete are the following: reminder, reminder2, reminder3, reminder4, reminder5, reminder6, reminder7, reminder8, reminder9, remindem, and remindem2. Replace the deleted contexts with this version 3.0 code.
For Step #2, make sure the following code snippet is still located in the top section of extensions_custom.conf in the [from-internal-custom] context or, for TrixBox systems, extensions_trixbox.conf in the [from-internal-trixbox] context:
exten => 123,1,Answer
exten => 123,2,Wait(1)
exten => 123,3,Authenticate(12345678)
exten => 123,4,Goto(reminder,s,1)
If, for some reason, you already are using extension 1-2-3 on your Asterisk system for some other purpose, then simply adjust the 123 extension in the four lines above to another number that works on your system. This is the number you will dial to schedule reminders. Line 3 is important as well. This is where you set a password for scheduling reminders on your system. Anyone that knows the password can schedule reminders. Simply replace 12345678 with a password that's secure enough for you to sleep well.
Finally, a head's up. When you do the cut-and-paste, double-check the long lines of code such as h,1 in [reminder9] and be sure all of the text ends up on a single line. Otherwise, things won't work correctly. Once you've added the two sections of code above, save your new config file and reload Asterisk.
Installing Reminder Voice Prompts. These voice prompts are free for the taking subject to the terms of the license agreement, and they're all the same as version 2.5 except there is a new reminder6.gsm. Just log into your Asterisk server as root and enter the following command to install the new voice prompt:
chmod 664 reminder*.gsm
chown asterisk:asterisk reminder*.gsm
If you need all of the voice prompts, then use these commands instead:
unzip nv-reminder3_voice.zip (be sure to overwrite existing files!)
chmod 664 reminder*.gsm
chown asterisk:asterisk reminder*.gsm
rm -f nv-reminder3_voice.zip
Installing the Reminder PHP/AGI Scripts. Now we're getting to the new code for version 3. While you're still logged in as root, let's install the final pieces of code that you'll need to get things working. Just execute the commands below:
mv reminder.php reminder25.php
mv run_reminders run_reminders.25
mv checkdate.php checkdate25.php
mv checktime.php checktime25.php
chmod 775 reminder.php
chown asterisk:asterisk reminder.php
chmod 775 check*.php
chown asterisk:asterisk check*.php
chmod 777 run_reminders
chown asterisk:asterisk run_reminders
chmod 777 run_recurring
chown asterisk:asterisk run_recurring
Creating Reminders Directories. While you're still logged in as root, create the following directories to store your reminders until the day arrives to execute them. Just issue the following commands. You should already have the reminders directory, but it won't hurt execute the command again just to be sure.
Setting Up the Crontab Entries. Now we need to set up the cron jobs to actually move reminders and recurring reminders into the Asterisk call processing directory on the day they are scheduled to run. Be very careful here. If you already have a working Telephone Reminders system, then there will already be an entry for run_reminders. For the new system to work, you MUST adjust the time that the run_reminders script executes so that it occurs AFTER the run_recurring script each day. While logged in as root, edit the crontab file: nano -w /etc/crontab. Be sure you typed the exit command in the last step, or you'll be logged in as asterisk instead of root. And you won't be able to edit the file! Now insert the following commands at the bottom of the crontab file and delete the existing run_reminders entry if you have one. Each command below should go on its own line.
0 0 * * * root /var/lib/asterisk/agi-bin/run_recurring >/dev/null 2>&1
3 0 * * * root /var/lib/asterisk/agi-bin/run_reminders >/dev/null 2>&1
Once you've added the two news lines and deleted the existing run_reminders line, save your changes: Ctrl-X, Y, then press Enter. Whew! That's it for the Reminder code. Now let's configure the system, and you'll be all set.
Configuring the Reminder System. To configure the reminder system, you'll need to edit the reminder.php script while logged in as root: nano -w /var/lib/asterisk/agi-bin/reminder.php. You'll notice a section of variables at the top of the file that looks like this:
$debug = 1;
$newlogeachdebug = 1;
$emaildebuglog = 0;
$email = "yourname@yourdomain" ;
$trunk = "local" ;
$callerid = "6781234567" ;
$acctcode= "Reminder" ;
This is the only section of code you ought to mess with. When we update the code, we'll assume everything else has been left intact. Be very careful when editing this file. Don't remove any semicolons or quotation marks, or nothing will work! Here's a quick run-down on what each of the above variables does:
Once you've configured the Reminder System to meet your needs, save your changes: Ctrl-X, Y, then press Enter. HINT: You may want to start with the defaults which will work well for most folks.
Scheduling A Reminder. We're ready to take the Reminder System for a trial run at this juncture. Make sure you've reloaded your Asterisk system, and then dial 123 from an extension on your system. Enter the password you set up for your system and then press the pound key.
Entering a Reminder Message. You'll first be prompted to record a reminder message. This is the message that will be played when someone answers the reminder call. If you're not scheduling this reminder for yourself, then the message ought to explain who's calling and what the purpose of the call is. Once you've recorded your message, press the pound key to end the recording. You can replay or rerecord the reminder if desired while you're in this step of the reminder creation process.
Entering the Callback Number. When prompted for the reminder callback number, there are a couple of things to keep in mind. First, if you've specified "local" as the trunk to use for reminders in the reminder.php script, then the phone numbers can be entered in any format supported by your dialplan. Press the pound key after entering the appropriate number. The calls will be placed using the trunks specified in your dialplan rules. The one exception is extensions on your local Asterisk system since these can't be routed by Asterisk@Home or TrixBox systems using your outbound calls dialplan rules. The way we handle extensions is by examining the length of the phone number. At the top of reminder.php, you can specify the maximum number of digits for local extensions by setting $extensionmaxdigits. So long as the callback number is less than or equal to this number of digits, the system has the smarts to correctly route the call to a local extension.
If you have designated a particular trunk for placement of reminder calls, then you'll need to make certain that the format of the phone numbers entered for reminders on your system matches a dial string supported for this outbound trunk in your dialplan. For example, if this trunk requires that calls be entered with a 1 and then an area code and 7-digit number, then that is the only format that should be used for entering callback numbers in your reminder system. Again, the one exception is calls to local extensions. So long as the number of a local extension is entered with less than or equal the number of digits set for the $extensionmaxdigits variable in reminder.php, the call will be routed properly to the local extension regardless of the trunk setting.
Finally, here's a shortcut that can be used if the phone you're using to schedule the reminder is the same one on which you want to get the reminder callback. In this case, just press the pound key when prompted for the number to which to deliver the reminder message. This will set the callback number as the caller ID of the phone you used to schedule the call. If it's a local extension, then the caller ID will be set to the local extension number of the phone from which you placed the reminder scheduling call. Just be sure your $extensionmaxdigits is set correctly or calls to local extensions will fail.
Entering the Date of the Reminder. Once you accept the reminder message, you'll be prompted to enter the date on which this reminder will be delivered. Dates are entered using a four-digit year, then a two-digit month, and then a two-digit day using the time zone of the Asterisk system running the Telephone Reminders System. There is some error correction but not much. You obviously can't schedule reminders in the past! And you don't need to press the pound key after entering the eight digits. Beginning in version 2.5, you now can press the pound key (#) instead of entering an 8-digit date, and the system will set the reminder date to today. Once you've entered a date, the system will tell you what date you entered including the day of the week. If the entry is correct, just press 1 to move on.
Entering the Time of the Reminder. Now you'll be prompted to enter the delivery time for your reminder. Times are entered as a two-digit hour and two-digit minute using the time zone of the Asterisk system running the Telephone Reminders System. For times less than 1200, you will be prompted whether you meant AM or PM. For those that understand military time, you can avoid this step by entering times using the format: 1345 which means 1:45 p.m. You don't need to press the pound key after entering the four-digit time for delivery of your reminder. Keep in mind that you cannot schedule a reminder for delivery in the first five minutes after midnight. Other times "in the midnight hour" should be entered in the format: 0045 which means 12:45 a.m. Keep in mind that reminder times always must be at least 5 minutes in the future. Finally, you cannot schedule two reminders for the exact same date and time for delivery to the same phone number. Once you enter a delivery time, the system will play back both the date and time for the reminder as a precaution. Press 1 to accept your entries.
Entering Recurring Reminders. Beginning with version 3, you now will be prompted whether to schedule (1) a single reminder, (2) a recurring reminder every weekday (M-F), (3),a recurring reminder every day, (4) a recurring reminder every week, (5) a recurring reminder every month, or (6) a recurring reminder every year. Once you make a selection, your reminder will be scheduled. If you choose an option other than 1 through 6, a single reminder will be scheduled.
Where Reminders Are Stored. There are actually two files that make up each reminder: the .call file which places the actual call and the .gsm file which is the reminder message itself. The file naming convention is HourMinute.Date.PhoneNumber with either a .call or .gsm extension. The sound files are all stored in /var/lib/asterisk/sounds/custom. For recurring reminders, duplicates of the .call script and the .gsm message are stored in /var/spool/asterisk/recurring with the date of the next recurring reminder. At midnight on the next scheduled date, the two files are copied to the /var/spool/asterisk/reminders and /var/lib/asterisk/sounds/custom folders respectively. Then the next scheduled reminder date is set in the two filenames. For single reminders, prior to the delivery date of the reminder message, the .call file is stored in /var/spool/asterisk/reminders. Then, at 12:03 am on the date the reminder is scheduled for delivery, the run_reminders script in /var/lib/asterisk/agi-bin moves the affected .call files to /var/spool/asterisk/outgoing. The .call files in the outgoing directory are reviewed every minute of the day by Asterisk. By examining the time stamp of the file, Asterisk looks for a match with the current hour and minute of the day. Once the time for the call arrives, Asterisk processes the .call script and places the call. All dialing retries are handled internally by Asterisk with no user or program control so it's important to set your default values correctly in the reminder.php script as explained above. Once the .call file is processed, Asterisk discards the file whether the call was successful or not. As noted above, the reminder message file is only discarded if the call is completed successfully. So, from time to time, you do need to review the contents of /var/lib/asterisk/sounds/custom and discard reminder messages, if any, with dates in the past. Note also that, if you begin scheduling a reminder and change your mind and hang up after recording a reminder message, that recorded message will still exist in /var/lib/asterisk/sounds/custom.
Finally, a word of caution about the reminder message files: be very careful in deleting these files. The message files and .call files are linked by filename only, and there is no error detection or correction if the message file gets discarded before the time for the reminder call arrives. What would happen in such a situation is the call would be placed, someone would answer, Allison would say "please hold for an important reminder," and then there would be a brief silence followed by Allison saying "to repeat this reminder, press 1; otherwise, press 2" which is not entirely helpful. To delete a recurring reminder, delete both the .call and .gsm files from /var/spool/asterisk/recurring. Note that the .call file will have an additional extension which tells the recurring type, e.g. .daily, .weekly, etc.
Reminder and Wakeup Call Processing. It has been documented that flooding Asterisk with a bunch of .call scripts simultaneously can cause some of the scripts to be discarded without being executed. We hope this has been resolved in Asterisk 1.2.4, but just be alert to the possibility of a problem if multiple calls are scheduled at exactly the same time to different numbers.
When you're first getting started with the reminder system, it's probably a good idea to fire up Asterisk's Command Line Interface (CLI): asterisk -rvvvvv. Then you can watch as the reminders are scheduled and reminder calls are placed. Just schedule a reminder for five minutes from the time you begin the reminder call, and you'll be all set to give it a whirl. By default, there's also a reminder log file produced for the last reminder call placed. You can display this file with the following command: cat /var/log/asterisk/reminder.txt.
For Programmers Only. If you're just getting into PHP and AGI programming with Asterisk, then have a second look at reminder.php. In particular, take a look at the section of code that begins with parse agi headers into array. As best we can tell, our initial tutorial on Telephone Reminders was the first version of this subroutine written in PHP that actually worked. We've tried to repeat our success here. If you review the log file (reminder.txt), you will see a listing of all the AGI headers which are passed by Asterisk to PHP. But this is the first code we've seen that correctly reads the headers into variables where you can actually retrieve the content. We call it a feature. For example, the commented out line ($tmp = $agi['dnid']) shows the syntax to retrieve the DNID value from Asterisk. Just make a mental note that the parse AGI headers code in reminder.php actually works. Some of our previous code inherited the mistakes of others, but we've now taken the time to get this functioning properly because we needed it for something else. Here's the complete list of AGI headers that can be saved to variables in your PHP code should the need ever arise:
read: agi_request: reminder.php
read: agi_channel: SIP/204-6a1a
read: agi_language: en
read: agi_type: SIP
read: agi_uniqueid: 1138010325.1367
read: agi_callerid: "Line2" <204>
read: agi_dnid: 123
read: agi_rdnis: unknown
read: agi_context: reminder9
read: agi_extension: h
read: agi_priority: 2
read: agi_enhanced: 0.0
You'll also want to take note of a little quirk in Asterisk (compared to some PBXs). To decipher the extension which actually placed a call, you must parse the agi_channel variable for the data between the slash and hyphen characters since the DNID (dialed number identifier) returns the extension being called (as opposed to the originating extension) when an internal call is placed. Here's one PHP approach to get the answer which in this case happens to be extension 204. Regex wizards could probably save a line of code, but who cares.
$CallingID = substr(stristr($agi['channel'],"/"),1);
$CallingID = substr($CallingID,0,strrpos($CallingID,"-"));
Web Interface to Telephone Reminders. We've built a very simple web page that will let you review which reminders are pending on your system. Recurring reminders are NOT yet included excepted those scheduled for delivery today. You can access the web page directly at http://192.168.0.111/reminders/ using the IP address of your Asterisk system. To install the Telephone Reminders web interface, log into your Asterisk system as root and then issue the following commands:
Be advised that we are just getting started with a web interface to the Telephone Reminders application. Stay tuned for loads of additional features!
Security Reminder. If you plan to open the Asterisk web interface on your system to the public Internet, make sure to take security precautions to reduce the risk of a stranger trashing your system or running up your phone bill. Just click here and search for our articles on security to get your system up to speed.
Hot Tip! O'Reilly's must-have book, Asterisk: The Future of Telephony, is still available for free download here under a Creative Commons license. This is a cleaned up version of the original PDF which fixes pagination and compresses the file size to 3.9MB using Acrobat's Reduce File Size tool. Requires at least Acrobat 4 to load. Special thanks to Alexander Burke for all the hard work cleaning this up.
Email Delivery of Reminders. Assuming you have email messaging working on your Asterisk system, Telephone Reminders has the ability to deliver an email copy of reminders to the recipient in addition to a phone call. Be advised that, if the phone call is never completed, the email copy of the reminder will not be delivered. The reason for this is because Asterisk never passes the call to the context which handles delivery of the email message until the call is connected. So ... no connection, no email. However, if the recipient has an answering machine or voice mail, that would trigger delivery of the email message.
Once you've installed the new contexts to support email messaging, step two is registering email addresses for extensions and phone numbers to which you want email reminders delivered. Log in to your Asterisk server as root, and start up the Command Line Interface (CLI): asterisk -r. For each extension and phone number for which you want to activate email reminders, enter a command at the CLI prompt that looks like this: database put EMAIL 6781234567 email@example.com where 6781234567 is the phone number of the reminder recipient and firstname.lastname@example.org is the recipient's email address. You can display all existing EMAIL addresses that have been entered into your Asterisk database with this command: database show EMAIL. If you need to modify an existing entry, simply delete it and reenter it. To delete an existing entry, use the following syntax: database del EMAIL 6781234567.
MIME-Construct: Wherefore Art Thou? A Linux utility, MIME-Construct, made it easy to convert images (like faxes) to PDF documents and also facilitated the emailing of just about any other document including reminder messages. Unfortunately, it came up missing in TrixBox, and it's difficult to install because of all the Linux dependencies. So here's a simple solution that restores the original functionality of MIME-construct thanks to the programming genius of Rob Thomas. Since Rob's fax-process.pl code (included in freePBX) mimics the old MIME-construct application, the simple solution was just to tweak it a bit for Nerd Vittles and TrixBox compatibility and then copy a renamed version into the PATH (remember the DOS PATH!) on your Linux box. Log in as root and issue these commands, and you'll be back in the mime-construct business with TrixBox:
chmod +x mime-construct
Nerd Vittles Demo Hot Line (courtesy of les.net). You now can take a number of Nerd Vittles projects for a test drive... by phone! The current demos include (1) MailCall for Asterisk with password 1111 (retrieve your email by phone), (2) NewsClips for Asterisk (latest news headlines in dozens of categories), (3) Weather Forecasts by U.S. Airport Code, and (4) Weather Forecasts by U.S. ZIP Code. You're not prompted for #4 yet, but it does work! Just call our number (shown in the left margin) and take any or all of them for a spin. The sound quality may not be perfect due to performance limitations of our ancient Intel 386 demo machine. But the price is right.
Nerd Vittles Fan Club Map. Thanks for visiting! We hope you'll take a second and add yourself to our Frappr World Map compliments of Google. In making your entry, you can choose an icon: guy, gal, nerd, or geek. For those that don't know the difference in the last two, here's the best definition we've found: "a nerd is very similar to a geek, but with more RAM and a faster modem." We're always looking for the best BBQ joints on the planet. So, if you know of one, add it to the map while you're visiting as well.
Some Recent Nerd Vittles Articles of Interest...