From: kurtasbestos on
Hi -

I have a fileevent/vwait loop that watches a USB barcode scanner.
Everything in our office uses barcodes on stickers that we print out,
and we have no problems dealing with any weirdness that may arise when
using those. Recently we started working with a client that has their
own barcodes, and for reasons I'm too lazy to explain I'm unable to
print their labels and have to rely on what they send us. In cases
where a barcode was too long to print onto the sticker, or it's just
plain unreadable by our crappy scanner, I need the user to be able to
manually type in the barcode. I had the client create and send me a
"blank" barcode (which reads as "bcid_blank" as opposed to the normal
pattern of something like "bcid_12345") so that when the user scans
it, the program will catch it and let them type in the barcode that
they actually want to run.

Here's where the whole barcode scanner loop thing gets set up (minus
any extraneous details of our system that probably aren't relevant).
#*****# Marks the part I'm having problems with; I'll describe that in
further detail below.

----------------------------------------------------------------------
#!/usr/bin/tcl

# various definitions and such go here...

set did [open "/dev/ttyUSB2" r]
fconfigure $did -buffering line -blocking 0
puts "Listening to barcode scanner"
fileevent $did readable [list ScannerHandler $did]
puts "starting server..."
BarcodeServer $port
puts "server started, ready for scan and load."

vwait forever

proc BarcodeServer {port} {
# this proc deals with what happens to the barcodes AFTER they've
already been successfully scanned
# so it's not really relevant to the current discussion... or
maybe it is, since it kicks off another fileevent for dealing with
those
}

proc ScannerHandler {did} {
# this proc watches the barcode scanner and puts the scanned
barcode in the global $scanned_barcode if it is legitimate
if { $scanned_barcode == "bcid_blank" } {
#*****#
puts "You scanned the blank barcode."
puts "Please enter the barcode you want to run:"
gets stdin scanned_barcode
# error checking and such goes here and works just fine...
}
if { barcode_is_valid $scanned_barcode } {
# normal stuff happens here...
}
}

----------------------------------------------------------------------

Please note that there are a couple other procs in there that deal
with the barcodes themselves, but they all work fine and don't
interfere with what I'm attempting to do (as far as I can tell), so I
didn't include them here.

Basically, I'm stuck at the #*****#. I've tried a number of different
things to get input from the user, but when they hit enter, nothing
happens. I've tried turning blocking on the pipe to $did, I've tried
flushing $did, I've tried starting a new fileevent stdin readable, and
I've even tried popping up a tk window to collect the information.

Hopefully I didn't leave out anything TOO important, and I apologize
if I over-explained. I greatly appreciate any help offered.

Kurt
From: Harald Oehlmann on
On 14 Apr., 22:14, kurtasbestos <kurtasbes...(a)gmail.com> wrote:
> proc ScannerHandler {did} {
>      # this proc watches the barcode scanner and puts the scanned
> barcode in the global $scanned_barcode if it is legitimate
>      if { $scanned_barcode == "bcid_blank" } {
>           #*****#
>           puts "You scanned the blank barcode."
>           puts "Please enter the barcode you want to run:"
>           gets stdin scanned_barcode
>           # error checking and such goes here and works just fine...
>      }
>      if { barcode_is_valid $scanned_barcode } {
>           # normal stuff happens here...
>      }
>
> }
> Basically, I'm stuck at the #*****#.  I've tried a number of different
> things to get input from the user, but when they hit enter, nothing
> happens.  I've tried turning blocking on the pipe to $did, I've tried
> flushing $did, I've tried starting a new fileevent stdin readable, and
> I've even tried popping up a tk window to collect the information.

Hello Kurt,
just brainstormin:
- try your stdin-part in a linear proc - does it work ?
- take care that you catch evrything within a filevent routine.
If it fails once, the fileevent will be canceld (IMHO even puts
commands)
- IMHO your fileevent will not work like that. You need to read from
the channel did first.
- Loop within the fileevent over a gets - there might be multiple
lines in the buffer
(I only use buffering none and read $did to get all data in the
buffer at once)
- As it is an usb device, one may unplug it so read and even eof may
give an error
- IMHO the program design is not very straightforward.
The "get the data if not barcode" should be out of the file event.
- About your remarks what you tried: I would try to flush/make
blocking the
channel stdin, not $did
- Sample handler function:

proc ScannerHandler {did} {
while 1 {
if {[catch { set scanned_barcode [read $did] } errMsg]} {
puts "Read error $errMsg - closing channel"
catch {close $did}
return
}
if { $scanned_barcode eq "bcid_blank" } {
puts "You scanned the blank barcode."
puts "Please enter the barcode you want to run:"
if {[catch {gets stdin scanned_barcode} errMsg]} {
puts "Input error"
}
# error checking and such goes here and works just fine...
}
if { barcode_is_valid $scanned_barcode } {
# normal stuff happens here...
}
if {[eof $did]} {
return
}
}
}

Hope this helps,
Harald