Awesome, thanks Andrew, I will have to keep an eye out for that patch. To continue, last night I decided to tackle the business hours and holiday routing on my FreeSWITCH system. It turned out to not be quite as simple with the XML dialplan as I thought. After being up until 1am banging my head against the wall, I finally got the results I was after. I decided I would share what I tried, why I tried them, and the solution I ended with, in hopes of helping other newcomers such as myself.
Goal: To have a single area to modify in order to affect business hours and holiday routing across all extensions. Sources: http://wiki.freeswitch.org/wiki/Dialplan_XML http://wiki.freeswitch.org/wiki/Time_of_Day_routing http://svn.freeswitch.org/svn/freeswitch/trunk/conf/dialplan/default.xml After reading the above documentation of time of day routing, my first thought was that following the main example on http://wiki.freeswitch.org/wiki/Time_of_Day_routing would be wildly inefficient for me. I didn't want to create 3 extensions for every 1 real extension, nor did I want to edit each individual extension if there were adjustments to the hours or holiday schedule. I was filled with hope when I re-read the top of the default.xml dialplan. As it implies that I could simply set a variable at the top of the dialplan that would be accessible to all following extensions. You veterans immediately realize this is silly, but that is what is implied to a newcomer reading the top of the default.xml diaplan. After lots of playing with different ways of trying to get this to work, I went back and re-read http://wiki.freeswitch.org/wiki/Time_of_Day_routing. The bottom of which points out why it won't work the way that it is in the default.xml dialplan, a "classic case of dialplan is parsed all at once." My next attempt was to make a catchall extension at the top of default.xml that would set the ${Status} variable, then pass the originally dial extension into a transfer application, as suggested by the bottom of the Time_of_Day_routing wiki page. This obviously didn't work with a catchall, as it just continued to loop through the catchall. However, it did set the variable and pass through the dialed extension, so I felt I was on the right track. <extension name="buisiness_hours"> <!-- set workdays and business hours here, break=never makes the parser process the rest of the extension to transfer the call --> <condition wday="2-6" hour="7-16" break="never"> <action application="set" data="Status=open"/> <anti-action application="set" data="Status=closed"/> </condition> <condition field="destination_number" expression="^(.*)$"> <action application="transfer" data="$1 XML default"/> </condition> </extension> After trying a few different things with no avail, I realized the catchall extension would work if I just had it jump contexts on transfer! So I moved my catchall to the public.xml, adjusted my OpenZAP context to be public instead of default (which is apparently the default), and viola everything worked flawlessly. Now I just had to add the ability to set ${Status} to closed on holidays. There could be better ways of organizing this, but I just created a holidays directory and included the xml, which added override conditions for holidays. ---------------------------------------------------------------------- public.xml - <include> <!-- Business Hours --> <extension name="buisiness_hours"> <!-- set workdays and business hours here, break=never makes the parser always process the rest of the extension to transfer the call --> <condition wday="2-6" hour="7-16" break="never"> <action application="set" data="Status=open"/> <anti-action application="set" data="Status=closed"/> </condition> <!-- include holidays --> <X-PRE-PROCESS cmd="include" data="holidays/*.xml"/> <condition field="destination_number" expression="^(.*)$"> <action application="transfer" data="$1 XML default"/> </condition> </extension> </include> ---------------------------------------------------------------------- holidays/thanksgiving.xml <include> <!-- Thanksgiving 2009 --> <condition mon="11" mday="26-27" break="never"> <action application="set" data="Status=closed"/> </condition> </include> ---------------------------------------------------------------------- default context extension - <!-- IVR - DID 5651, ext6000 --> <extension name="5651"> <condition field="destination_number" expression="^(5651|6000)$"/> <condition field="${Status}" expression="^open$"> <!-- Check office open/closed status --> <action application="answer"/> <action application="sleep" data="1000"/> <action application="ivr" data="coral_ivr"/> <!-- If open transfer to main menu --> <anti-action application="ivr" data="coral_after_hours_ivr"/> <!-- If not open transfer to after hours menu --> </condition> </extension> ---------------------------------------------------------------------- Call flow breakdown (for those who are new, so you can easily follow what is going on) - In this example, if someone calls the DID ending in 5651, the call is processed by the catchall 'business_hours' extension in the public.xml. The weekday, and hour of day, is checked and ${Status} set accordingly. The holiday conditions that were included are then processed, overriding the ${Status}, setting it to 'closed' if today meets the criteria of a holiday. The call is then transferred to extension 5651, in the default context, of the XML dialplan. In the default context dialplan, extension 5651 is processed, which checks to see if ${Status} = open. If ${Status}=open is true, the extension passes the call to the IVR 'coral_ivr'. If ${Status}=open is false, the extension passes the call to the IVR 'coral_after_hours_ivr'. The catchall in the public context works well for me, because my connection to the PSTN is direct, through OpenZAP. I do not have to use the public context to provide extension security, as the incoming dialed extensions is limited to my known DIDs. I imagine this is not recommended for those who use SIP providers, and need the public context to provide internal and external segregation of your extensions. For these situations, you could probably create a middle-man context with the business hours logic, in which to send all transfers from public to default through. To those experienced users, if I missed something, and am making this much more complicated that it needs to be, please let me know. Or if you see potential errors or problems with my configuration, please let me know. I am new to this after all. Thanks all, especially you FreeSWITCH developers/contributors. I love the clean, efficient, logical design of FreeSWITCH. -Adam -----Original Message----- From: [email protected] [mailto:[email protected]] On Behalf Of Andrew Thompson Sent: Monday, November 23, 2009 11:45 PM To: [email protected] Subject: Re: [Freeswitch-users] Business/holiday hours routing On Mon, Nov 23, 2009 at 08:17:46PM -0600, Brian West wrote: > He's working on it for SVN... I recommended the format and to add the > phases of the moon and zodiac signs just for giggles. > I'll probably get a patch in this week (or early next) I'm thinking of changing the format so that "week of month" becomes its own value so you could compare against mweek as well as wday so thanksgiving + extension becomes something like <condition mweek="4" wday="5-6" month="11"/> If I really get ambitious I'd also like to allow wday="mon-fri" so I don't always forget that days are 1-indexed from sunday :) Andrew _______________________________________________ FreeSWITCH-users mailing list [email protected] http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org _______________________________________________ FreeSWITCH-users mailing list [email protected] http://lists.freeswitch.org/mailman/listinfo/freeswitch-users UNSUBSCRIBE:http://lists.freeswitch.org/mailman/options/freeswitch-users http://www.freeswitch.org
