Debugging Hardware in Production: How We Solved Dual-Barcode Interleaving on Industrial Handheld Scanners published
Debugging Hardware in Production: How We Solved Dual-Barcode Interleaving on Industrial Handheld Scanners When building web applications for desktop or mobile screens, we often assume input devices behave politely. An i
Debugging Hardware in Production: How We Solved Dual-Barcode Interleaving on Industrial Handheld Scanners
When building web applications for desktop or mobile screens, we often assume input devices behave politely. An input event fires, characters arrive sequentially, and the string matches what the user entered.
Take that same web app into an export consolidation warehouse in Guangzhou, run it inside a rugged Android PDA scanner, and that assumption disintegrates.
Here is the story of how a real-world physical barcode label created an elusive 28-digit ghost tracking number, and how we engineered a deterministic, carrier-agnostic algorithm in TypeScript to de-interleave scan collisions in real time.
1. The Physical Anomaly: Dual-Barcode Thermal Waybills
In Chinaβs domestic parcel network (Yunda, SF Express, ZTO, etc.), waybills often feature two separate barcodes printed on the same thermal label:
- A primary horizontal Code 128 / Code 39 barcode across the top.
- A secondary vertical routing barcode along the side or bottom.
Under high-speed sorting conditions, warehouse workers don't pause to aim with precision. They sweep an optical 2D imager across the parcel.
When the imager's field of view intersects both barcodes, high-speed scan engines decode both symbols almost simultaneously. Because most industrial PDAs transmit data via a virtual keyboard wedge (dispatchKeyEvent or InputMethodService), the hardware buffers and fires character inputs in rapid bursts.
What Actually Happened in Production:
- Expected tracking number:
465851384718642(15 digits) - What the intake form received:
4654865518358143781487614826(28 digits)
At first glance, it looks like random numeric noise. But if you decompose the string into alternating odd and even indices, a clear mathematical pattern emerges:
text
Full stream: 4 6 5 4 8 6 5 5 1 8 3 5 8 1 4 3 7 8 1 4 8 7 6 1 4 8 2 6
Odd index: 4 5 8 5 1 3 8 4 7 1 8 6 4 2 -> 465851384718642 (15 digits: The real waybill!)
Even index: 6 4 6 5 8 5 1 3 8 4 7 1 8 6 -> 64658513847186 (13 digits: Truncated duplicate scan)
The scan engine had interleaved two concurrent decodes character-by-character into a single rapid keyboard burst!
2. Why Naive Fixes Failed
Before writing algorithms, team discussions usually produce three common suggestions:
"Configure the scanner hardware to read only one barcode at a time."
Reality: In contract logistics, warehouses operate dozens of device models from different manufacturers (Urovo, Zebra, Chainway, Honeywell) running custom Android ROMs. Relying on manual field hardware configuration across hundreds of workers is fragile.
"Hardcode courier prefix and length rules."
Reality: Couriers frequently update numbering schemes, add sub-carriers, or introduce new routing codes. A hardcoded courier dictionary creates maintenance debt and breaks whenever a new parcel format is introduced.
"De-bounce or throttle keystrokes in onChange."
Reality: Running aggressive de-duplication on every keystroke prefix breaks normal human keyboard entry. If an operator types a genuine number with consecutive digits, an over-eager filter can silently truncate real data.
3. The Solution: Carrier-Agnostic De-Interleaving
We solved this at the software input layer by isolating the completion trigger (scanner Enter or Blur event) and applying a deterministic de-interleaving algorithm.
Here is a simplified TypeScript implementation of how we extract the true base tracking number:
/**
* Detects and repairs interleaved concurrent barcode scans.
* Recovers the base number when two rapid scans interlace alternating characters.
*/
export function splitInterleavedScan(input: string): string {
const clean = input.trim();
// Scans below minimum tracking length are untouched
if (clean.length < 16) {
return clean;
}
// Decompose into odd and even character streams
let streamA = "";
let streamB = "";
for (let i = 0; i < clean.length; i++) {
if (i % 2 === 0) {
streamA += clean[i];
} else {
streamB += clean[i];
}
}
// Case 1: Stream A is the full tracking number, Stream B is a duplicate prefix
if (streamA.startsWith(streamB) && streamA.length >= 10) {
return streamA;
}
// Case 2: Stream B is the full tracking number, Stream A is a duplicate prefix
if (streamB.startsWith(streamA) && streamB.length >= 10) {
return streamB;
}
// Safety Boundary: If there is any mathematical ambiguity, do not guess.
return clean;
}
Edge Cases Handled:
Consecutive identical repeats: Standard duplicate bursts (AB1234AB1234) are collapsed separately using regex-based cycle detection.
Ambiguity Guard: If the decomposed streams do not cleanly form a prefix/subset relationship of each other, the algorithm leaves the raw string intact. We never guess and corrupt valid tracking numbers.
4. Architectural Lessons from Warehouse Software
Solving this bug highlighted three core engineering principles for industrial software:
1. Hardware Input is Dirty Data
Treat barcode scanners, serial scale interfaces, and optical sensors like unvalidated public API endpoints. Never write incoming hardware streams directly to persistent storage without validation and normalization layers.
2. Edge Processing over Cloud Latency
On a busy warehouse sorting line, workers process parcels at an intake rate of 1 parcel every 3 to 5 seconds. Sending video streams or raw scans to cloud endpoints for parsing introduces round-trip network lag. Real-time de-interleaving, dimensioning, and OCR must run locally on the client or edge device.
3. Progressive Isolation
Keep low-level hardware sanitization isolated from domain logic. The barcode normalization module lives as a pure, dependency-free TypeScript library covered by comprehensive automated tests, making it easily shareable across native Android wrappers and desktop web clients.
Wrapping Up
Building software for physical operations bridges the gap between clean code and dirty industrial realities. When optical imagers, thermal printers, and network dead-zones collide, robust client-side software architecture is what keeps the supply chain moving.
Have you encountered strange hardware quirks or keyboard-wedge edge cases in production? Share your war stories in the comments below!

We build TikTrake, an edge-first consolidation warehouse and cross-border freight management platform.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.