ScanMemo is a simple but powerful barcode scanning application; it takes one significant step over the demo apps in that it records scans, and doesn't merely display them on screen. This is still a hacker-level app -- which means that while the UI isn't pretty, it is a useful piece of a complex system.
The name comes from the original design intent: in order to simplify interfacing with other tools, I thought it would be easier to drop the scans into a memo pad. It turns out that creating my own database is both more correct and simpler to implement.
This app was built with GCC (from the Debian prc-tools
package.) Screen shots were made with xv
and
pose
(Save Screen doesn't seem to do anything as of
2.1d29-1.) Note that Symbol
does not yet "support" GCC -- the stub library that they provide
is a CodeWarrior ".Lib" file -- but they have released a
ScanMgr.o
through DIKU which I've sucessfully linked this app with. If
you're still interested in the reverse-engineering effort, there
remain some notes on the project
that might be of use in a future conversion.
I've rebuilt 0.03 (it now has a small icon, and there were minor non-visible build-environment changes.) I've also confirmed that this works not only with the SPT1700 but also with the CSM-150 Symbol "Springboard" scanner card for the Visor Handspring. The CSM-150 is a much cheaper solution for apps that don't need full armoring - and you can store the app and data in the 2M onboard the CSM-150 - they appear on insertion and you can run them directly.
One issue: the CSM-150 driver will try and grab a user-selected set of buttons as "trigger" buttons, but only in apps that open the scanner device. If you're running AppHack (a HackMaster plugin that lets you bind apps to two sequential button presses) then it simply doesn't take effect. Turning off AppHack fixes the problem, but isn't really acceptable; I'll add a "scan" screen-button to the next version of ScanMemo.
The downloads have been updated to 0.03, which has had the debugging dumps removed from the display and a "shelf code" popup added (so you can "name" an entire shelf and then advance along the numbers as you scan; I'll add a "next shelf" button later.) I haven't had time to update the screenshots or usage example, but scan-cvt.pl now recognizes and emits two new fields, the Shelf Number and the Bar Code Type (see the Symbol SDK for the meaning of the values for now.)
Initial screen. The [ ]
regions at the top are
debugging labels; the [ ]
at the bottom is a status
indicator which shows how many records are stored (after each
scan.) The Tag:
field is editable and is stored with
each scan; to label a batch of things, fill in the tag field
first, then scan them all. Unsuccessful scans are stored
(with a value of NR
) which can be useful for logging
timestamps or for separating batches of scans.
Source is not available right now, but only because I've only worked on it for a few days and it is embarassingly primitive. If you really want it anyway, I'd suggest looking at the BarCode section of the O'Reilly Palm Programming book; if you're still interested, go ahead and email me.
No Scanner? 0 steps, not 6
in the
bottom status line.
On a working machine you should just see the interface and
here two short high beeps.Scans-KtnT.pdb
as downloaded by
pilot-xfer
and emits CSV, HTML, or XML.As a worked example, consider the library application. We want to scan a few shelves of books and then get them on line somehow.
scanmemo.prc
.6!!!!!!!!
status
indicating successful initialization.Tag:
field; for example,
Tag: thok tech 1
Begin scanning. Just aim at the EAN code and push the scan buttons; you should see the green light and hear a beep, and you should see, for a first book, something like
t:3023627682 0201877007 type: 22(16) Tag: thok tech 1 Scan: 0201877007
Saved record 1 size 27
The first is a seconds-since-1904 PalmOS-style (well,
MacOS-style really) timestamp; the second line is the scan
result, which is also in the Scan:
field. The
type:
is an internal type tag for what barcode was
seen; 22 decimal (0x16 hex) is documented in
ScanMgrDef.h
as BCTYPE_BOOKLAND_EAN
which is
what we expect. The last line tells us that it saved this
record in the internal database; that's it! We can move on to
the next book. Don't worry about scan errors, we can filter
them out later.
Tag
, in this case to thok tech 2
. Scan some
more. For this example, we get as far as record 14 size
27
(the size is likely to be a constant if you're
scanning a bunch of the same type of bar code and not changing
the size of the tag field.)Now that we have the data, we need to upload it. Hook up
the cradle or cable, go into HotSync
, start up
pilot-xfer
on the Unix side:
PILOTPORT=/dev/pilot PILOTRATE=115200 pilot-xfer -f Scans-KtnT
and then activate HotSync
to let pilot-xfer
slurp down the file. You should see something like:
Waiting for connection on /dev/pilot (press the HotSync button now)... Connected Fetching 'Scans-KtnT.pdb'... OK Fetch done.
Now run perl scan-cvt.pl Scans-KtnT.pdb
. You
should see basic comma-separated-value output like this:
940869730, "thok tech 2", "020163337X" 940869727, "thok tech 2", "0079113362" 940869721, "thok tech 2", "0937175641" 940869715, "thok tech 2", "1565922220" 940869708, "thok tech 2", "1565920562" 940869598, "thok tech 1", "0471597562" 940869596, "thok tech 1", "NR" 940869596, "thok tech 1", "NR" 940869592, "thok tech 1", "0201563274" 940869588, "thok tech 1", "0198537379" 940869584, "thok tech 1", "NR" 940869578, "thok tech 1", "0134327179" 940869569, "thok tech 1", "0201403633" 940869282, "thok tech 1", "0201877007"
Note that the first column is a Unix-style timestamp,
based in 1970, not a PalmOS-style one. The second
column is your tag, the third is the scan itself.
* If you find HTML easier to work with (there are some clever
ways to parse an HTML table into an SQL database via
perl
using the DBI DataBase Interface packages) then
you can instead use perl scan-cvt.pl Scans-KtnT.pdb html
which generates output like
<table>
<tr><th>Tag</th><th>Scan</th><th>Unix Time</th></tr>
<tr>
<td>thok tech 2</td>
<td>020163337X</td>
<td>940869730</td>
</tr>
...
which formats like this:
Tag | Scan | Unix Time |
---|---|---|
thok tech 2 | 020163337X | 940869730 |
thok tech 2 | 0079113362 | 940869727 |
thok tech 2 | 0937175641 | 940869721 |
thok tech 2 | 1565922220 | 940869715 |
thok tech 2 | 1565920562 | 940869708 |
thok tech 1 | 0471597562 | 940869598 |
thok tech 1 | NR | 940869596 |
thok tech 1 | NR | 940869596 |
thok tech 1 | 0201563274 | 940869592 |
thok tech 1 | 0198537379 | 940869588 |
thok tech 1 | NR | 940869584 |
thok tech 1 | 0134327179 | 940869578 |
thok tech 1 | 0201403633 | 940869569 |
thok tech 1 | 0201877007 | 940869282 |
And for buzzword compliance (XML will save the web!) choose
perl scan-cvt.pl Scans-KtnT.pdb xml
and get output
of the form
The DTD for this is self-evident, and for most XML tools,
unnecessary.
* Working with the raw data, we can do a few processing
tricks; grep -v '"NR"'
to strip out the
unsuccessful scans, sort -n
to sort into timestamp
order (it is an artifact of the PalmOS database handling code
that records are naturally added in reverse order, so you see
in these examples the most-recent scans first.)
* Now that we have the data, we need one more trick to get
meaning out of it. To start with the biggest hammer, we use
YAZ (Yet Another Z39.50 package) to bounce our ISBN off of
the Library Of Congress:
#!/bin/sh
ISBN=$1
HOST=z3950.loc.gov:7090
DB=VOYAGER
yaz-1.4pl2/client/client -m marc-record.$ISBN tcp:$HOST
base $DB
format sutrs
attributeset bib1
elements F
find @attr 1=7 "$ISBN"
show
quit
EOF
Note in particular that this script actually shows the record
in text form to standard output, but the marc-record.*
file
actually has a raw USMARC electronic card-catalog entry, which
is what we really want.
* What do we do with a MARC record if we're not already a
library? Use perl, of course. First, use
perl -MCPAN -e 'get MARC'
to download the latest MARC package, then
perl -I ~/.cpan/build/MARC-0.91/ -e 'use MARC; $x=MARC->new("marc-record.0079113362"); $x->output({file=>">marc-output.txt",format=>"ascii"});'
and we have a nice text-formatted card catalog entry.
Tweaking the last bit to say
{file=>">marc-output.html",format=>"html"}
gives primitive html (a little bit nicer than the
ascii
format if you're dumping this out onto a web
page); better yet,
{file=>">marc-output.xml",format=>"xml"}
gives heavily-tagged XML output, which is probably more
suitable for futher processing and searching than the raw MARC
record was.
Whew. Lots of detail; at this point, you could take any of the above data and dump it into a database, or a big web page, or build a sophisticated signout and reservation system. I'm not sure how far I'll go with that part, but the pieces described here are well on the way...