Modified:
/wiki/ModulePhone.wiki
=======================================
--- /wiki/ModulePhone.wiki Fri Jul 30 17:16:14 2010
+++ /wiki/ModulePhone.wiki Sun Feb 19 09:02:33 2012
@@ -1,146 +1,2 @@
-#summary Provides the phone interactive voice response (IVR) functionality
of the OBA system
-#labels GettingStarted,Tutorial,Phone
-
-<wiki:toc />
-
-= Introduction =
-
-OneBusAway has a phone number you can call to have real-time arrival
information read to you over the phone. Systems that provide such
functionality are typically called Interactive Voice Response (IVR)
systems. We describe the implementation details of our system below.
-
-= The Phone Server Architecture =
-
-Let's walk through what happens when you make a phone call into the
system. When you place a call, it gets converted into VOIP and is
connected to our [http://www.asterisk.org/ Asterisk] server. Asterisk is
kind of like Apache httpd for phone calls. Asterisk accepts the call and
passes it off to a Java daemon that will service the actual call. This is
kind of like a CGI script in the web world. That Java daemon entry point
is in the `onebusaway-phone` module, specifically the class:
-{{{
-org.onebusaway.phone.PhoneServerMain
-}}}
-
-All the server does is wire up a bunch of beans using Spring, including
the appropriate listeners for incoming calls. See the Spring context file
for more details:
-{{{
-src/main/resources/org/onebusaway/phone/application-context.xml
-}}}
-
-For the most part, you don't need to worry about too many of the previous
steps, but it helps to know what's going on.
-
-= Generating Call Responses with an MVC Framework =
-
-I wrote a library called [http://code.google.com/p/probablecalls/
probable-calls] that I use to manage the task of generating a phone tree,
handling actions, and generating responses to the user. It's kind of like
[http://www.opensymphony.com/xwork/ xwork] and [http://struts.apache.org/
Struts] for phone calls, which are used for handling actions and generating
results for web requests in OneBusAway.
-
-The general idea is that a phone key presses by the user get mapped to
Action classes in the actions package:
-{{{
-org.onebusaway.phone.actions.*
-}}}
-The action is responsible for calling OneBusAway service methods to
perform the appropriate action and gather any result objects. The action
then passes of to a template class that is responsible for generating all
the text that will be read to the user. All the templates can be found in
the following package:
-{{{
-org.onebusaway.phone.templates.*
-}}}
-In an MVC world, we'd call that these templates the View layer while the
Actions are in the Control layer and all the result object passed between
the View and the Control is the Model.
-
-The mapping between Actions and Templates is setup in the following file:
-{{{
-src/main/resources/org/onebusaway/phone/xwork.xml file
-}}}
-
-= An Example Request =
-
-When a call first comes into the system, the "/welcome" action path is
initially request (as configured in the "agiEntryPoint" bean in the
application-context.xml file). We consult our action mapping document to
see how the Action is wired up:
-{{{
-<action name="/welcome" class="org.onebusaway.phone.actions.DefaultAction">
- <result>/welcome</result>
-</action>
-}}}
-The "/welcome" action is just mapped to the DefaultAction, since it
doesn't really do anything. Instead, the result is more important. The
result is named "/welcome" as well, which maps to
-{{{
-org.onebusaway.phone.templates.WelcomeTemplate
-}}}
-Note the @AgiTemplateId("/welcome") at the top of WelcomeTemplate...
that's where the /welcome result connection is made.
-
-The WelcomeTemplate configure a number of mappings between user key
presses and next actions:
-{{{
-addAction("1", "/stop/index");
-addAction("2", "/find_your_stop");
-addAction("3", "/bookmarks/index");
-addAction("4", "/bookmarks/manage");
-addAction("5", "/most_recent");
-addAction("6", "/search/index");
-}}}
-It then adds a message to be read to the user:
-{{{
-addMessage(Messages.WELCOME_ACTION);
-}}}
-Note that messages are typically just keys in a message class. In this
case, it's the
-{{{
-org.onebusaway.phone.templates.Messages
-}}}
-class. Where are the actual message strings defined? Check out the
-{{{
-src/main/resources/org/onebusaway/phone/templates/package_en_US.properties
-}}}
-file. This defines the message strings for the en_US locale (US English)
and gives us the ability to define messages for other languages if need be.
-
-The template fires off the messages to be read to the user. The user can
then press a key to determine the next action. Most users will press "1" so
that they can enter a stop id and hear real-time arrival information for
that stop. That key press is mapped to the "/stop/index" action.
Consulting our action mapping again, we see:
-{{{
-<action name="/stop/index"
class="org.onebusaway.phone.actions.DefaultAction">
- <result>/stop/index</result>
-</action>
-}}}
-Again, we don't need to do any real processing at this point, so we use
the DefaultAction again and map to the "/stop/index" result, which is
defined in the
-{{{
-org.onebusaway.phone.templates.stops.IndexTemplate
-}}}
-template class. It just reads a message asking the user to enter their
stop number followed by the # sign. When the user does, the result is sent
to the "/stop/byCode" action, setting the "stopCode" parameter of the
action to the stop id entered by the user.
-
-The action mapping for the "/stop/byCode" action looks like:
-{{{
-<action name="/stop/byCode"
class="org.onebusaway.phone.actions.schedule.StopForCodeAction">
- <result type="chain">/stop/arrivalsAndDeparturesForStopId</result>
- <result name="input">/stop/invalidStopNumber</result>
- <result
name="needDefaultSearchLocation">/stop/needDefaultSearchLocation</result>
-</action>
-}}}
-
-Here we finally have an action that does some actual work. In this case,
the StopForCodeAction does a search for a StopBean with stop code entered
by the user. Assuming the StopBean is found, control is passed of to the
default result, which in this case is a chain result:
-{{{
-<result type="chain">/stop/arrivalsAndDeparturesForStopId</result>
-}}}
-A chaining result passes control to another action instead of a result
template. In this case, the action mapping looks like:
-{{{
-<action name="/stop/arrivalsAndDeparturesForStopId"
class="org.onebusaway.phone.actions.schedule.ArrivalsAndDeparturesForStopIdAction">
- <result>/stop/arrivalsAndDepartures</result>
-</action>
-}}}
-The `ArrivalsAndDeparturesForStopIdAction` consults the StopBean and looks
for arrival and departure information for that stop. Here, control is
finally passed to a a template which constructs the text for reading the
real-time arrival information to the user.
-
-= Running the Phone Server =
-
-Before you can run the phone server, you need to do some setup. In the
following directory:
-{{{
-src/main/default-resources
-}}}
-you'll find two files:
-{{{
-data-sources.xml
-pronunciations.xml
-}}}
-These two files are responsible for setting up the various data-sources
used by the phone server and also setting up some pronunciation hints for
tricky to say words.
-
-Copy both of these files into your
-{{{
-src/main/resources
-}}}
-directory.
-
-At this point, you can launch the phone server by running the following
main class:
-{{{
-org.onebusaway.phone.PhoneServerMain
-}}}
-
-If all goes well, the server should startup with no exceptions.
-
-Normally, to actually use the phone service would require setting up
Asterisk and a VOIP client. It's a major hassle.
-
-To make things easier, I've added a VERY simple phone client that you can
run to interact with the phone service itself. It doesn't do any
text-to-speech. Instead, it just prints the text from the server and let's
you press keys to control the call.
-
-To run the simple phone client, run:
-{{{
-org.onebusaway.phone.client.SimplePhoneClient
-}}}
+#labels Deprecated
+Moved to
https://github.com/OneBusAway/onebusaway-application-modules/wiki/onebusaway-phone