More on our Kiosk Application. Dynamically loading a form based on your config file.

As in a previous post, I discussed a Kiosk framework that myself and Derek Walters ( another dotnet geek ( and a very smart one at that ) ) licensed to Cox Communications for the rollout of their kiosk bill paying solution in several cities around the country. Since the Kiosk application is a touch screen application, its flow between screens is very structured; however, during the development of a working application we needed an approach that enabled us to dynamically change how the screens flowed.

This was absolutely necessary for us. Without a plug-in style architecture, we would have created a static ( and very fragile ) application where any change would have forced us to go through another round of regression testing. This in turn would push out the delivery date and negate the need for the framework in the firstplace.

In this blog, I want to show a nice approach to wrapping a class around a section of a config file. The use of this class then enabled us to dynamically add screens and/or change the flow of the kiosk application without recompiling.

First, ( a portion of ) the config file.

<?xml version="1.0" encoding="Windows-1252" ?>
<
configuration>
     <configSections>
          <sectionGroup name="plugins">
               <sectionGroup name="forms">
                    <sectionGroup name="scanbill">
                         <section name="plugin" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                         <section name="navigation" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                         <section name="form" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                    </sectionGroup>
                    <sectionGroup name="language">
                         <section name="plugin" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                         <section name="navigation" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                         <section name="form" type="System.Configuration.SingleTagSectionHandler" allowLocation="false" />
                    </sectionGroup>
               </
sectionGroup>
          </sectionGroup>
     </configSections>

     <plugins>
          <forms>
               <scanbill>
                    <plugin assembly="CoxPlugins" class="Cox.Kiosk.Forms.CoxScanBillForm" />
                    <navigation back="language" next="accountinquirywaitform" cancel="start" help="" error="" timeout="start" timeoutvalue="30" touchtocontinueenabled="true"/>
                    <form nextbutton="false" backbutton="true" cancelbutton="true" helpbutton="false" />
               </scanbill>

               <language>
                    <plugin assembly="CoxPlugins" class="Cox.Kiosk.Forms.CoxSelectLanguageForm" />
                    <navigation back="start" next="scanbill" cancel="start" help="" error="" timeout="start" timeoutvalue="30" touchtocontinueenabled="true"/>
                    <form nextbutton="false" backbutton="true" cancelbutton="true" helpbutton="false" />
               </scanbill>

         </forms>
     </plugins>
</configuration>

What we are doing here is setting up the app.config file so that we can use the .net classes to interact with it. The first section, configuration/configSections/sectionGroup[name=plugins]/sectionGroup[name=forms]/sectionGroup[name=scanbill], is setting up the configuration section for the plugins section below.
I will not go into detail on it because you can find out more about setting up a config file via MSDN.

The items I want you to take note of are the attributes of the navigation sections. The back, next, cancel, help, error and timeout attribute values denote another plug in to move to when the user selects one of the buttons on the touch-screen window. For example configuration/plugins/scanbill/navigation[back=languagepoints to the language node under plugins. In other words, when the user is using the kiosk and has navigated to the 'Scan Your Bill Form' and decides to select the Back button the framework will look in the config file and navigate to the language form by interrogating the config file.

Now for the code. The following is a constructor for a class that loads information for a form's config section. Once loaded other classes interact with the information. The code below was actually written by Derek, but it is a pattern we both followed throughout the framework.

namespace Cybral.Kiosk.Configuration
{ 
    ................................................  ................................................
    ................................................
  ................................................

    ................................................  ................................................
    ................................................  ................................................

     public NavConfigReader( string strName )
     {
          string strConfigPath = string.Format( "plugins/{0}/navigation", strName );
          string strCurrentNavName=null;
          strCurrentNavName = strName;
          if( null != strCurrentNavName )
          {
               strCurrentNavName = strCurrentNavName.Substring(  
               strCurrentNavName.LastIndexOf( "/" ) + 1 );
          }
          IDictionary idct = (IDictionary)
          ConfigurationSettings.GetConfig( strConfigPath );
          m_strCurrentNav = strCurrentNavName;
          m_strNextNav = (
string) idct["next"];
          m_strBackNav = (
string) idct["back"];
          m_strCancelNav = (
string) idct["cancel"];
          m_strHelpNav = (
string) idct["help"];
          m_strErrorNav = (
string) idct["error"];
          m_strTimeoutNav = (
string) idct["timeout"];
          m_strActionPlugin = (
string) idct["actionplugin"];
          try
           {
                 m_intTimeoutValue =
                 Int32.Parse( (
string) idct["timeoutvalue"] );
                 // The values in the configuration file are in seconds...
                   // timers typically measure in milliseconds.
                  m_intTimeoutValue *= 1000;
          
 
           catch
            {
                 m_intTimeoutValue = 0;
          

           try
            {
                 string strTrue = Boolean.TrueString.ToLower();
                  m_blnTouchToContinueEnabled =
                  ( strTrue.CompareTo( idct["touchtocontinueenabled"] ) == 0 );
              }
             catch
              {
                   m_blnTouchToContinueEnabled =
true;
               }
       }

 

Well, I am getting tired of writing. Essentially, what we do next is load the control specified in the config file, destroy what is currently there and display the control to the user. There is actually quite a bit involved in this, but the premise is simple enough.

9 Comments

  • Wirespring. You should have left your name. No. We built the framework on our own to see if we could. At the time we were building all the backend interactions with their billing system on an AS/400. We did this using a webservices framework we also developed. The kiosk portion just fell in our lap when a company contracted to deploy it couldn't get it right. We did. We actually have it rolled out in 30 some sites and its bringing in revenue of more then $1 million a month. Its a pretty sweet architecture. Anyway. I can talk about it for days.



    -Mathew Nolton

  • Thanks for the article. We are building a kiosk and have thought along the same lines for dynamic screen flow. I have a seperate but kiosk related question. Did you have multiple devices in this kiosk? Such as a receipt printer, credit card device, cash device, etc. If so, did you follow a pattern for hardware monitoring to ensure these devices were functional? We have been builing a monitoring framework and would be grateful for any insight. Thanks in advance

  • Per your device question. Yes, all of the above.



    Per your monitoring framework. Why bother creating one at all?



    You will find that you want to turn the device off until you actually get to the screen where you interact with it. If you don't the user will be adding money, credit card data, etc to your application via the device before you are ready to deal with it. Additionally, if you wait until you get to the screen that uses the device, then you will find that the need to monitor the device is largely moot (aside from a quick check to see if it is online). You will also find that some devices don't play nice and there is no way to really tell if they are online and working properly.



    HTH,

    Mathew Nolton

  • I agree, not all devices play nice. As well, I believe many device issues will occur to devices while in use (i.e. paper jam ) but if we do monitor the &quot;nice&quot; devices during periods of inactivity we may be able to reduce downtime. At the same time, we can proactively display an out of service screen before a user attempts to use the kiosk. This as opposed to displaying this screen only after they have invested time into the process and opened a screen with a device error.



    Maybe overkill? Your thoughts?

  • Drop me an email so we can take this off-line.

    -Mathew Nolton

  • Tried sending you an email via your contact link but I received a delivery status failure notification.

  • you can use mnolton@cybral.com

  • About being a good blogging citizen.



    I am all for sharing information and it is one of the reasons I keep a blog.



    However, sometimes people take information but are afraid to divulge any themselves. Or they come here, learn what they can and take it offline away from the blog for unknown reasons. Probably because they have their own interests that they are trying to protect. If this is the case with you, then don't post or comment. If I see it happen or I feel you are taking advantage of what I am providing I will delete your comment. Blogging works when people contribute and share information freely.



    -Mathew Nolton

  • We may quote a job on a kiosk application. We're .net developers (websites & custom software) but haven't built for a kiosk before (well, one of us has, but contract cancelled before deployed). This ap would include voice (for blind or poor readers) and Spanish language. Do you have any good reference we could check on?

Comments have been disabled for this content.