Retrieving data with APAX

Async Professional ActiveX (APAX) is designed to communicate through serial and Winsock ports.  Some of our customers use semi-automated processes such as file transfer protocols to transfer data, but many times the developer needs to know the actual data that is being transmitted.

A little background info

APAX supports RS232, RS485 and TCP/IP (via Winsock) serial communications.  The broadest definition of serial communications includes anything that transmits or receives data in a serial fashion, where one bit follows another in a single stream over one wire.  In parallel communications, by contrast, many bits are sent in parallel over many wires.  In the context of computing, the serial data that we transmit and receive is framed by start and stop bits that mark the beginning and end of each character in the data stream.  Depending on your requirements, you may have 5, 6, 7 or 8 data bits enclosed within those start and stop bits.

Getting the data

When you're receiving data in APAX, your program obtains the data via the OnRXD or the OnDataTrigger events.  In a perfect world, these events would provide the sequence of characters as a null-terminated string, Pascal-style string, array of characters, etc, but this isn't a perfect world, it's ActiveX.  We can't use a null-terminated string because the received data may very well contain null characters, we can't use Pascal-style strings because not all ActiveX containers support that data type, same thing for arrays, or other data types.  All that's left is a Variant.

A variant, by definition, is a data type for all variables that are not explicitly declared as some other type.  It can be a string, a number, a widget, just about anything.  APAX uses the Variant as an array of characters (without explicitly defining that type).  Since the compiler doesn't know that we're sending an array of chars, it doesn't know how to translate this Variant into an array of chars, so we need to do that ourselves.

Finally, some code...

Let's take a look at how the OnRXD event is defined for Visual Basic:

 

Private Sub Apax1_OnRXD(ByVal Data As Variant)

 

End Sub

 

All that the compiler knows now is that Data is some kind of data, with a type of Variant.  The Data parameter is created using the Delphi VarArrayCreate method, which creates a variant array containing Delphi Char types since the Async Professional Active X control is created using Delphi.  The compiler doesn't know that it is an array of characters; it's still an array of variants as far as it's concerned.  The compiler makes a fairly accurate guess for a default type; it treats it as a byte. 

Let's modify our OnRXD event a bit to display the received chars.  If you haven't done this already, create a new project, add an APAX control, and a ListBox, and create the OnRXD event handler.  Since this is an array, we can use the LBound and UBound methods to determine the lower and upper bounds of the array, then walk the array to get the byte values contained in the array:

 

Private Sub Apax1_OnRXD(ByVal Data As Variant)

  Dim i As Integer

  For i = LBound(Data) To UBound(Data)

    List1.AddItem (Data(i))

  Next

End Sub

 

Run this, open a port (preferably a port with a modem attached) and enter "AT" into the terminal window.  You should see the "AT" as the command is echoed by the modem, then the modem's "OK" response in the terminal window.  Now, look over at the ListBox, you should also see the decimal representation of the characters. The decimal representation of the bytes in the array is valid data, but it's harder to work with than the characters they represent.  To convert the decimal values to their corresponding characters, use the Chr method as follows:

 

Private Sub Apax1_OnRXD(ByVal Data As Variant)

  Dim i As Integer

  For i = LBound(Data) To UBound(Data)

    List1.AddItem (Chr(Data(i)))

  Next

End Sub

Hey, I've got data!

Now that you have the character representation of the data, you can process it easily using a variety of methods.  Consider, if you will, a situation where you want to get the modem's ID information.  That usually won't be required, unless you're doing something that requires a particular modem, but it's an easy one to implement. All you need is a modem.  The modem will return its ID information in response to the "ATI3" command, and the format of the reply will vary greatly between modems. Since different modems return different responses, we'll need to look for the terminating <CR><LF>OK<CR><LF> string to determine when the response is complete. 

Go ahead and create a new project (this will be in VB6, but the idea is the same for all compilers).  Add an APAX control, a button control and a ListBox control to the form.  To make things easier to see, we'll do everything in code.  In the button's Click event handler, we'll open the port, set up a data trigger for the response and then send out the "ATI3" command from the OnPortOpen event.  When setting up the data trigger as in the code below (using AddDataTrigger), passing in the IncludeStrings parameter as False will strip out the “ATI3” and also the “OK” automatically.  The OnDataTrigger event handler will fire when the response is detected, and we'll write the modem's ID info to the ListBox. The OnDataTrigger event is similar to the OnRXD event the way that the data comes in. The OnDataTrigger event below will strip out the carriage returns and the line feeds since they don’t display in the ListBox very well.  If there are any other unwanted characters, then they can also be stripped out in the same way as the 255 characters below. In my case, the modem seemed to put this character in front of the modem description and the ListBox did not have a recognizable character to represent it. After adding the description to the ListBox, there is also a display to the title bar telling the size of the packet/data coming into the OnDataTrigger event. 

 

Private Sub Command1_Click()

  Apax1.AddDataTrigger "ATI3*" & Chr(13) & Chr(10) & "OK" & Chr(13) & Chr(10),

                                         0, 0, False, True

  Apax1.PortOpen

End Sub

When the port opens, the OnPortOpen event will fire. This would be a good place to put the AT command out the port.

 

Private Sub Apax1_OnPortOpen()

  Apax1.PutString "ATI3" & Chr(13) & Chr(10)

End Sub

 

Private Sub Apax1_OnDataTrigger(ByVal Index As Long, ByVal Timeout As Boolean, ByVal Data As Variant, ByVal Size As Long, ReEnable As Boolean)

  Dim I As Integer

  Dim S As String

  Select Case ServerState

    Case 0

      For I = 1 To Size

        If Data(I) <> 13 Then

          If Data(I) <> 255 Then

            If Data(I) <> 10 Then

              S = S & Chr(Data(I))

            End If

          End If

        End If

      Next I

  End Select

  List1.AddItem (S)

  Caption = "Size = " & Size 

End Sub

 

This site is not affiliated, endorsed, or otherwise associated with the entity formerly known as TurboPower Software. The owners and maintainers of Aprozilla.com were merely meager employees of the aforementioned organization, providing this site out of the pure goodness of their collective hearts. SourceForge.net Logo

Last updated: July 22, 2003.