Article · · 5 min read
Telling a barcode scanner from a person typing
How a small Windows tool counts every barcode scan during a stocktake without taking keys away from the accounting program, using nothing but the time between keystrokes.
During a stocktake in UkrSklad, the operator scans goods into a document, and the program shows the total in hryvnias, not in pieces. Nobody knows how many items are in the current box, and a mistake means recounting the shelf. The accounting program could not change, so I built a counter that sits next to it.
A scanner is just a fast keyboard
A USB barcode scanner presents itself as a keyboard. It types the digits of the code and presses Enter. That means there is no scanner API to read; there is only keyboard input, the same as a person typing a search query in the same window.
Listen, don't steal
The counter uses a low-level Windows keyboard hook. It sees every key, but it does not consume it, so UkrSklad still receives its digits and works exactly as before. The only keys the counter does take are its own hotkeys: F12 for a new batch, F9 to undo the last scan, F10 to export, F8 to pause.
Timing is the whole trick
A scanner types a whole code at 10 to 30 milliseconds per key and ends with Enter. A person rarely goes faster than about 120 milliseconds per key. So the rule is simple: only a burst of fast keys ending in Enter counts as a scan.
# simplified
if key == ENTER and len(buffer) >= MIN_DIGITS and max(gaps_ms) <= SCANNER_MAX_GAP:
count(buffer) # a scan
buffer.clear() # anything slower was a person typingNothing gets lost
Every scan is appended to a journal on disk immediately, and a snapshot is written every 20 scans. If the power goes out or the laptop restarts, the next launch restores all counters. Resetting first exports and archives the old journal; nothing is ever deleted for good.
Getting the numbers back in
At the end, the counts go to Excel and CSV with barcode, name and quantity, in a shape UkrSklad imports through its own document import. I deliberately do not write into its database directly; that could break the program's internal registers.
The limit, written down
The rule depends on typing speed. A scanner configured to send keys slowly would not be recognised until the threshold is adjusted in the config, and the console mode shows every keystroke with its timing to make that easy.