Thursday, October 23, 2008

Zinc COMPort Phone Dialer Freezes

Background

A photo of the building directory kiosk and phone handset which uses my application built with Flash and Zinc.The same touch-screen kiosk I previously wrote about requires phone dialing capabilities since the purpose it serves is a Building Directory in the lobby of a government office building.

I used MDM Zinc because I can retain all source code in Actionscript (Flash), yet utilize the computer's modem to dial phone numbers via the Zinc COMPort API (whose phone numbers are retrieved from an MS SQL database via Zinc's ODBC API).

At the start of this project while evaluating Zinc as an option, the first thing I did was create a phone dialer prototype using Flash and Zinc to prove it would work. It worked perfectly. But when integrating it into the system at the tail end of the project and adding some robustness to it, I ran into a hitch that caused the Zinc-compiled application to crash.

Problem

In order to gracefully recover should the modem throw a "No Carrier" or "No Dialtone" error, I wanted to hang-up the line then alert the user of this error. However, when invoking the hang-up immediately when Flash is asynchronously notified, the Zinc-compiled application freezes indefinitely.

Example
Part of the constructor of my PhoneDialer AS3 class
mdm.COMPort.onCOMPortData = function(e:Object)
{
   var data:String = StringUtil.trim(e.data);

   logger.logLine("onCOMPortData() - timeCode: " +
      e.timeCode + ", data: " + data + ".");

   if (data == "NO CARRIER")
   {
      hangUp(); //freezes here

      dispatchEvent(new PhoneDialerEvent(
         PhoneDialerEvent.NO_CARRIER));
   }
   else if (data == "NO DIALTONE")
   {
      hangUp(); //freezes here

      dispatchEvent(new PhoneDialerEvent(
         PhoneDialerEvent.NO_DIALTONE));
   }
   else if (data == "OK")
   {
      //Dial was successful!
      dispatchEvent(new PhoneDialerEvent(
         PhoneDialerEvent.OK));
   }
};

Method in my PhoneDialer class:
public function hangUp()
{
   if (!pickedUp)
      throw new AlreadyHungUpException();

   logger.logLine("Closing COMPort.");

   mdm.COMPort.close(); //actually freezes here

   pickedUp = false;
}


Solution

The solution was to not invoke mdm.COMPort.close() within the onCOMPortData handler. Instead, I alert the user of the error which also instructs him/her to click the Cancel button on the Dialing screen. Then the cancel button invokes hangUp(), which works without a hitch.

Also one other item of interest: even though Zinc was designed to support Actionscirpt 3, the first line of code above, mdm.COMPort.onCOMPortData = fuction(... triggers a warning when compiling to SWF - "Warning: 1072: Migration issue: Class is not a dynamic class. Instances cannot have members added to them dynamically." Since this is just a warning, it does not cause any problems during run-time, but it's interesting that they did not switch to use the standard addEventListener method of event-handling that has been implemented as a standard across AS3 components.

Conclusion

In a perfect world, this error would never happen if the kiosk were always connected to the phone line and the phone line were to always provide a dial tone. But since those are possibilities, the application is now robust because it properly recovers from those scenarios instead of crashes.

No comments:

Post a Comment

Was this post helpful? Do you have questions about it? Do you want to share your own programming blog? I'd love to read your feedback.

Note: Only a member of this blog may post a comment.