---
Using a Card Swiper with TrueGUI
Summary:
The card reader reads in multiple lines, such as into a multi-line text box. The problem is knowing when it is done. Because the speed is so fast, watching each character get passing back is a lot of network traffic.
By using the "Modified" event to start the "watching" and then turning off the "Modified" event and "watching" by checking the Lines and the Length every quarter of a second, the traffic is low and behavior better!
Details:
Original Question:
Don't know if you have any ideas here, but I can't seem to figure out a way to get card swiping (credit cards, DL Licenses, etc) to work how I'd like them to.
Currently, I bring up a swipe window (a form), and place the cursor in a text box, which allows multiple lines of input. I can swipe a card in just fine, and the tracks on the card show in this text box.
I can put an "OK" button on the screen that the user can select, but ideally, after the card is swiped, it should know you are done, and take off. I cannot seem to find a property for a text box that will generate a "Leave" event, or anything else I can set that can trigger something to let me know when they are done.
It doesn't seem like a huge deal, but I know we'll get complaints about having to hit a key to tell the system when the swiping is done.
In our non-gui code, I can read in character by character and check for an EOL character, and I'd know when I was done with a track. In addition, we have a property in Metropolis called a "fast field", which means that the field is populated (and return is back to the code) without hitting an ENTER or other key. I'm certain other software packages out there that read cards are able to swipe the card and run with it, without having to register another key signifying you are done.
Do you have any ideas on how this could be accomplished?
More information:
How many lines of text or does it vary by card?
How does "fast field" know when the right amount of data has been entered?
The number of tracks on a credit card is 2 - always. The number of tracks on a DL license # is usually 3, but sometimes 2, but I know by state which one has 2 tracks, and which one has 3, so I'd be able to determine the exact number.
"fast field" knows how many characters are there because in
Metropolis, to define a field on a screen, you enter X amount of underscores together when creating the screen form. The number of underscores you enter is the length of the field. (So there is no 'max field length' value in Metropolis - it's always based on the # of underscores you use). So if you define a field for an employee ID code (for example), and use 3 underscores for it, at runtime you can enter ABC on the keyboard, and right after you enter the "C" key, an automatic ENTER key is triggered (a "Leave" in other words) without having to hit the ENTER key.
More Information:
So the length of each of these tracks on CC or DL is always the same?
No. How I "read" in these tracks before was to continuously get input from a single character field, setup as a fast field. I could read in each character on each track, one at a time, and I was sent an EOL control character when I reached the end of a track. I had to do it this way because I couldn't create a field that was over 130 characters in width, and some tracks (especially on driver's licenses) were more than this. But that took a long time to do, and has always been prone to error (reading one character at a time).
With gui, you can create a text box that allows 1000+ characters in it, so there's no limitation here on how wide a field can be. And so far, my text box does read in all the tracks I swipe in. But my problem is that there is no event triggering, or anything I can set, to let me know when it's 'done'. After swiping the card, the data tracks fill up the text box, and the cursor waits there for more.
I just was curious if you or anyone else has had to deal with card readers, and how you get around the fact that the user (so it seems to me now) has to hit a button, or TAB off the text box field (to generate the 'leave') to signify when the track data has been read.
It's obviously possible, as most other companies (target, best buy, etc) that scan in credit cards don't have to hit some key or whatever to know when it's done. The tracks are read in, and control is automatically back to the program (instead of waiting for something to identify when the tracks are done).
There is a RET character (EOL or whatever) at the end of each
track, and obviously the form sees that, as it puts the two tracks on two lines in the text box. So maybe the issue can be resolved via the AcceptButton property. I'll have to play with this (I'm on a different tangent right now).
Suggestion:
Have to leave this unfinished. For the card swiping, try this:
The Modified event should tell you when something starts changing in the text box.
So perhaps do a Modified event, turn off Modified event. Then ask for the current cursor position or length. In the mean time, more Modified events should have been queued. Loop through the queued Modified events until you get a Data response which would be the current cursor position or length.
If it seems long enough, then go with it. Otherwise sleep a moment and check again. Or turn on Modified again, then check the length again.
Another choice is to check on the last character in the .Text. Haven't tried this but may be able to get the last character based on the length or set the .SelectedStart at length -1, then .SelectedLength at 1, and then GetCharFromPosition
OR I also like your idea of using the Enter key by setting the "Accept" property on the whole form - then you would get that event upon the completion of each "line". I think that would work cleaner, but there are more timing things to worry about.
Here are some of the tests I did to develop the first suggestion:
Current Length:
Debug command: <== { tb.TextLength? }
Data: 45
Length of a specific line:
Debug command: <== { tb.Lines[1].Length? }
Data: 29
Current Cursor:
Debug command: <== { tb.SelectionStart? }
Data: 6
when after the sixth character in a single 13 character line.
I also found the following about getting the text in the TextBox:
Debug command: <== { MyForm.tb.Text? }
Data: Text goes here.
Lots of lines can fit.
***Queued 41 bytes to be sent to the server***
***Transmitted 41 bytes to the server***
***Received 155 bytes from server***
Type code: 2 Message: Text goes here.
***Received 134 bytes from server***
Command: <== { NextEvent? }
?Unknown TrueGUI Error: Lots of lines can fit.
Command: <== { NextEvent? }
**** NOTE: The above did not work that well!! ****
Debug command: <== { MyForm.tb.Lines[1]? }
Data: Lots of lines can fit.
***Queued 24 bytes to be sent to the server***
***Transmitted 24 bytes to the server***
***Received 198 bytes from server***
Type code: 2 Message: Lots of lines can fit.
Command: <== { NextEvent? }
MyForm.tb.Lines[1].Select(6,0) worked if the cursor was not already PAST character 6????
Results:
Thanks for your suggestion about the card swiping. I added a ModifiedChanged event to the text box, which will kick out a single event (just once) when the input in this box begins. At that point, I go in a loop, checking every 0.25 for the existence of track 2. Once I find it the first time, I save the length of line 2, and keep checking it every 0.25 seconds until two consecutive checks of lengths match.
Once that happens, I know I have the track scanned fully. It works well. Of course, if the user types in on the keyboard while the card reader is kicking out the tracks to the field, the track(s) will be invalid, but that's always the case with keyboard wedges (verses USB or another hardware type).
I can use this same logic when we're at points in our software where users could use barcode readers as well. (That device again will scan in something, and functionality should be to move on to the next process, instead of waiting for the user to hit TAB or whatever).
Comments (0)
You don't have permission to comment on this page.