Change QR-Code function label from "2D-Code" back to "QR-Code"

The function keeps reading all 2D-code types (QR-Code, MicroQRCode, RMQRCode,
DataMatrix, Aztec, PDF417) as requested. The label is now "QR-Code" per the
client's preference for their terminology. Added clarifying comments explaining
the intentional mismatch between the name and the supported formats, since the
hardware labels use DataMatrix (not QR). Updated README and test accordingly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-29 14:50:24 +02:00
co-authored by Claude Opus 5
parent 2d7778cea8
commit 3907204209
3 changed files with 30 additions and 28 deletions
+24 -25
View File
@@ -5,7 +5,7 @@ beim physischen Sortieren am Tisch anleitet: Modul vor die Kamera halten, die
App nennt den Stapel. App nennt den Stapel.
Vor dem Scannen wählt der Nutzer eine von drei Funktionen — Strichcode, Vor dem Scannen wählt der Nutzer eine von drei Funktionen — Strichcode,
2D-Code oder Text erkennen (siehe „Funktionsweise" unten). Jede Funktion nutzt QR-Code oder Text erkennen (siehe „Funktionsweise" unten). Jede Funktion nutzt
ausschließlich ihre eigene Quelle; anders als früher weicht die App nicht mehr ausschließlich ihre eigene Quelle; anders als früher weicht die App nicht mehr
automatisch auf Texterkennung aus, wenn kein Code gefunden wird. automatisch auf Texterkennung aus, wenn kein Code gefunden wird.
@@ -65,21 +65,20 @@ keine Daten verlassen das Gerät.
| Funktion | Liest | Laufende Suche | Texterkennung | | Funktion | Liest | Laufende Suche | Texterkennung |
|---|---|---|---| |---|---|---|---|
| **Strichcode** | Code128, Code39, Code93, ITF, EAN-13, EAN-8, UPC-A, UPC-E, Codabar | ja | nein | | **Strichcode** | Code128, Code39, Code93, ITF, EAN-13, EAN-8, UPC-A, UPC-E, Codabar | ja | nein |
| **2D-Code** | QRCode, MicroQRCode, RMQRCode, DataMatrix, Aztec, PDF417 | ja | nein | | **QR-Code** | QRCode, MicroQRCode, RMQRCode, DataMatrix, Aztec, PDF417 | ja | nein |
| **Text erkennen** | keine Codes | nein | ja, auf Knopfdruck | | **Text erkennen** | keine Codes | nein | ja, auf Knopfdruck |
2D-Code" liest neben den QR-Varianten auch DataMatrix, Aztec und PDF417. QR-Code" heißt auf Wunsch des Auftraggebers „QR-Code", liest aber bewusst
Ursprünglich war die Funktion (damals „QR-Code" beschriftet) auf QR nicht nur QR-Varianten, sondern auch DataMatrix, Aztec und PDF417. Der
beschränkt; am Gerät zeigte sich, dass sie damit auf der eigenen Ware nichts Grund: Die 2D-Codes auf den RAM-Etiketten sind DataMatrix, nicht QR — eine
fand, weil die 2D-Codes auf den RAM-Etiketten DataMatrix sind. Die auf QR beschränkte Funktion fände auf dieser Ware nichts. Die interne
Beschriftung wurde daraufhin auf „2D-Code" geändert, damit sie nicht mehr Kennung heißt weiterhin `qrcode` (aus historischen Gründen, siehe
verspricht, was sie nicht meint. Die interne Kennung heißt weiterhin `src/scan-modes.js`), und der Name ist Absicht — es ist der Wunsch des
`qrcode` (aus historischen Gründen, siehe `src/scan-modes.js`) — daran Auftraggebers für seinen Sprachgebrauch.
ändert die Erweiterung nichts.
„Modul scannen" erscheint nur in „Text erkennen" — in „Strichcode" und „Modul scannen" erscheint nur in „Text erkennen" — in „Strichcode" und
2D-Code" sucht die App ohnehin laufend, ein Knopf ohne Texterkennung hätte QR-Code" sucht die App ohnehin laufend, ein Knopf ohne Texterkennung hätte
dort nichts zu tun. Der Zielrahmen hebt sich in „Strichcode" und „2D-Code" dort nichts zu tun. Der Zielrahmen hebt sich in „Strichcode" und „QR-Code"
hervor, sobald ein passender Code im Bild ist; in „Text erkennen" bleibt er hervor, sobald ein passender Code im Bild ist; in „Text erkennen" bleibt er
schlicht, weil dort nichts laufend erkannt wird. Ein Wechsel der Funktion schlicht, weil dort nichts laufend erkannt wird. Ein Wechsel der Funktion
während des Sortierens (z. B. bei gemischter Ware) gilt sofort: laufende während des Sortierens (z. B. bei gemischter Ware) gilt sofort: laufende
@@ -89,7 +88,7 @@ keine Daten verlassen das Gerät.
nach dem Fortsetzen (siehe Punkt 5 unten) und erst danach die Funktionswahl nach dem Fortsetzen (siehe Punkt 5 unten) und erst danach die Funktionswahl
— die Kamera startet in jedem Fall erst, nachdem beides geklärt ist. — die Kamera startet in jedem Fall erst, nachdem beides geklärt ist.
Technisch bekommen „Strichcode" und „2D-Code" eine Texterkennung Technisch bekommen „Strichcode" und „QR-Code" eine Texterkennung
hineingereicht, die sofort leeren Text liefert, ohne Tesseract anzustoßen; hineingereicht, die sofort leeren Text liefert, ohne Tesseract anzustoßen;
„Text erkennen" bekommt eine Barcode-Dekodierung hineingereicht, die sofort „Text erkennen" bekommt eine Barcode-Dekodierung hineingereicht, die sofort
eine leere Liste liefert (`buildRecognitionAdapters` in eine leere Liste liefert (`buildRecognitionAdapters` in
@@ -97,7 +96,7 @@ keine Daten verlassen das Gerät.
Punkte 14 unten) bleibt dabei unverändert und kennt keine Funktionen — die Punkte 14 unten) bleibt dabei unverändert und kennt keine Funktionen — die
drei Funktionen unterscheiden sich ausschließlich darin, welche Adapter ihr drei Funktionen unterscheiden sich ausschließlich darin, welche Adapter ihr
übergeben werden. übergeben werden.
1. **Barcode-Dekodierung** (nur in „Strichcode" und „2D-Code"). Die zur 1. **Barcode-Dekodierung** (nur in „Strichcode" und „QR-Code"). Die zur
Funktion gehörenden Codearten werden laufend aus dem Kamerabild dekodiert Funktion gehörenden Codearten werden laufend aus dem Kamerabild dekodiert
(`zxing-wasm`, `decodeBarcodes` in `src/barcode.js` bekommt die Codearten (`zxing-wasm`, `decodeBarcodes` in `src/barcode.js` bekommt die Codearten
der gewählten Funktion übergeben). Das ist exakt, im Gegensatz zu der gewählten Funktion übergeben). Das ist exakt, im Gegensatz zu
@@ -106,7 +105,7 @@ keine Daten verlassen das Gerät.
App rät nicht, sondern fragt nach. Das gilt nur für Barcodes mit einem App rät nicht, sondern fragt nach. Das gilt nur für Barcodes mit einem
bekannten Nummernschema; widersprechen sich mehrere Barcodes mit bekannten Nummernschema; widersprechen sich mehrere Barcodes mit
unbekanntem Nummernschema, wird keine ihrer Teilenummern übernommen. unbekanntem Nummernschema, wird keine ihrer Teilenummern übernommen.
2. **Teilenummer-Decoder** (nur relevant in „Strichcode"/„2D-Code" — „Text 2. **Teilenummer-Decoder** (nur relevant in „Strichcode"/„QR-Code" — „Text
erkennen" liest nie einen Barcode, siehe Punkt 0). Aus einer Hersteller-PN erkennen" liest nie einen Barcode, siehe Punkt 0). Aus einer Hersteller-PN
wie `M386A8K40BM1-CRC4Y` werden Kapazität, Bauform und Geschwindigkeit wie `M386A8K40BM1-CRC4Y` werden Kapazität, Bauform und Geschwindigkeit
tabellengesteuert abgeleitet. Gelingt das, entfällt OCR vollständig, das Ergebnis ist grün. tabellengesteuert abgeleitet. Gelingt das, entfällt OCR vollständig, das Ergebnis ist grün.
@@ -137,7 +136,7 @@ keine Daten verlassen das Gerät.
die aus dem erkannten Text abgeleiteten technischen Angaben (Kapazität, die aus dem erkannten Text abgeleiteten technischen Angaben (Kapazität,
Bauform, Rank, Geschwindigkeit) über die Stapelzuordnung Bauform, Rank, Geschwindigkeit) über die Stapelzuordnung
(`specsCompatible` in `src/spec.js`) — anders als in „Strichcode"/ (`specsCompatible` in `src/spec.js`) — anders als in „Strichcode"/
2D-Code", wo meist die exakte Teilenummer trägt. QR-Code", wo meist die exakte Teilenummer trägt.
4. **Stapel-Zuweisung.** Grün (Barcode) und Gelb (OCR) laufen ohne Eingabe 4. **Stapel-Zuweisung.** Grün (Barcode) und Gelb (OCR) laufen ohne Eingabe
durch; nur bei roter Konfidenz (nichts Eindeutiges erkannt, widersprüchliche durch; nur bei roter Konfidenz (nichts Eindeutiges erkannt, widersprüchliche
Barcodes oder widersprüchliche unbekannte Barcodes ohne jede OCR-Kapazität) Barcodes oder widersprüchliche unbekannte Barcodes ohne jede OCR-Kapazität)
@@ -194,9 +193,9 @@ und toleranter Vergleich, OCR-Bildaufbereitung (Otsu-Schwellwert) und
-Feldextraktion, Stapel-Zuweisung, die Erkennungs-Pipeline samt Zeitgrenzen -Feldextraktion, Stapel-Zuweisung, die Erkennungs-Pipeline samt Zeitgrenzen
und Mehrdeutigkeitsbehandlung, die Sitzungssicherung samt Prüfung eines und Mehrdeutigkeitsbehandlung, die Sitzungssicherung samt Prüfung eines
wiederhergestellten Zustands, die drei Scan-Funktionen (`scan-modes.js` wiederhergestellten Zustands, die drei Scan-Funktionen (`scan-modes.js`
Codearten je Funktion, DataMatrix/Aztec/PDF417 in „2D-Code") sowie die je Funktion Codearten je Funktion, DataMatrix/Aztec/PDF417 in „QR-Code") sowie die je Funktion
tatsächlich aufgerufenen Adapter (`scan-recognition.js` — Texterkennung läuft tatsächlich aufgerufenen Adapter (`scan-recognition.js` — Texterkennung läuft
nachweislich nie in „Strichcode"/„2D-Code", Barcode-Dekodierung nachweislich nachweislich nie in „Strichcode"/„QR-Code", Barcode-Dekodierung nachweislich
nie in „Text erkennen"). Kamera, Barcode-/OCR-Adapter selbst, die nie in „Text erkennen"). Kamera, Barcode-/OCR-Adapter selbst, die
Auswahl-Oberfläche und die Verdrahtung in `main.js` laufen nur im echten Auswahl-Oberfläche und die Verdrahtung in `main.js` laufen nur im echten
Browser und werden dort manuell geprüft (siehe „Am Gerät noch zu prüfen" Browser und werden dort manuell geprüft (siehe „Am Gerät noch zu prüfen"
@@ -265,8 +264,8 @@ worauf du bei der Veröffentlichung achten solltest.
| `src/ocr-extract.js` | OCR-Rohtext → Spec-Felder | | `src/ocr-extract.js` | OCR-Rohtext → Spec-Felder |
| `src/session.js` | Stapel halten, vorschlagen, buchen, umsortieren, zurücknehmen — inklusive der aus den Einträgen abgeleiteten, je Stapel bekannten Barcode-Inhalte (`stack.codes`), die vor dem Vergleich der technischen Angaben über die Zuordnung entscheiden, sofern diese Angaben nicht widersprechen | | `src/session.js` | Stapel halten, vorschlagen, buchen, umsortieren, zurücknehmen — inklusive der aus den Einträgen abgeleiteten, je Stapel bekannten Barcode-Inhalte (`stack.codes`), die vor dem Vergleich der technischen Angaben über die Zuordnung entscheiden, sofern diese Angaben nicht widersprechen |
| `src/pipeline.js` | Barcode → Teilenummer → OCR → Ampelfarbe, inkl. Zeitgrenzen, Mehrdeutigkeitsbehandlung und Kurzschluss über einen bereits bekannten Barcode-Inhalt (`deps.isKnownCode`) — unverändert; kennt keine Scan-Funktionen | | `src/pipeline.js` | Barcode → Teilenummer → OCR → Ampelfarbe, inkl. Zeitgrenzen, Mehrdeutigkeitsbehandlung und Kurzschluss über einen bereits bekannten Barcode-Inhalt (`deps.isKnownCode`) — unverändert; kennt keine Scan-Funktionen |
| `src/scan-modes.js` | Die drei Scan-Funktionen (Strichcode, 2D-Code, Text erkennen): Kennung, deutsche Beschriftung, gelesene Codearten, laufende Suche ja/nein, Texterkennung ja/nein — einzige Quelle, sowohl für die Auswahl-Oberfläche als auch für `main.js` | | `src/scan-modes.js` | Die drei Scan-Funktionen (Strichcode, QR-Code, Text erkennen): Kennung, deutsche Beschriftung, gelesene Codearten, laufende Suche ja/nein, Texterkennung ja/nein — einzige Quelle, sowohl für die Auswahl-Oberfläche als auch für `main.js` |
| `src/scan-recognition.js` | Baut die an `recognize()` übergebenen Adapter anhand der gewählten Funktion: in „Strichcode"/„2D-Code" liefert die Texterkennung sofort leeren Text ohne Tesseract anzustoßen, in „Text erkennen" liefert die Barcode-Dekodierung sofort eine leere Liste ohne `zxing-wasm` anzustoßen | | `src/scan-recognition.js` | Baut die an `recognize()` übergebenen Adapter anhand der gewählten Funktion: in „Strichcode"/„QR-Code" liefert die Texterkennung sofort leeren Text ohne Tesseract anzustoßen, in „Text erkennen" liefert die Barcode-Dekodierung sofort eine leere Liste ohne `zxing-wasm` anzustoßen |
| `src/storage.js` | Absturzschutz der laufenden Sitzung: sichert und lädt aus `localStorage`, verwirft beim Laden jeden in sich unstimmigen Zustand vollständig (siehe unten) | | `src/storage.js` | Absturzschutz der laufenden Sitzung: sichert und lädt aus `localStorage`, verwirft beim Laden jeden in sich unstimmigen Zustand vollständig (siehe unten) |
| `src/camera.js` | Kamerastart, Einzelbildaufnahme, Bilddatei-Ersatzweg | | `src/camera.js` | Kamerastart, Einzelbildaufnahme, Bilddatei-Ersatzweg |
| `src/barcode.js` | Adapter zu `zxing-wasm`; `decodeBarcodes(imageData, formats)` bekommt die Codearten übergeben, ohne Angabe wie bisher (Code128 + DataMatrix) | | `src/barcode.js` | Adapter zu `zxing-wasm`; `decodeBarcodes(imageData, formats)` bekommt die Codearten übergeben, ohne Angabe wie bisher (Code128 + DataMatrix) |
@@ -392,14 +391,14 @@ werden:
**Funktionswahl (neu)** **Funktionswahl (neu)**
- Erster Start ohne gesicherte Sitzung: Auswahl mit drei großen Flächen - Erster Start ohne gesicherte Sitzung: Auswahl mit drei großen Flächen
(„Strichcode", „2D-Code", „Text erkennen") erscheint, *bevor* die Kamera („Strichcode", „QR-Code", „Text erkennen") erscheint, *bevor* die Kamera
startet — kein Kamerabild sichtbar, solange keine Funktion gewählt ist. startet — kein Kamerabild sichtbar, solange keine Funktion gewählt ist.
- Erster Start *mit* gesicherter Sitzung: erst die Frage „Gesicherte Sitzung - Erster Start *mit* gesicherter Sitzung: erst die Frage „Gesicherte Sitzung
gefunden" (fortsetzen/verwerfen), erst danach die Funktionswahl. gefunden" (fortsetzen/verwerfen), erst danach die Funktionswahl.
- „Strichcode" wählen: laufende Suche erkennt Code-128/Code-39/EAN/UPC/…, - „Strichcode" wählen: laufende Suche erkennt Code-128/Code-39/EAN/UPC/…,
kein „Modul scannen"-Knopf sichtbar, Zielrahmen hebt sich bei erkanntem kein „Modul scannen"-Knopf sichtbar, Zielrahmen hebt sich bei erkanntem
Code hervor. Code hervor.
-2D-Code" wählen und ein Etikett mit dem eigenen DataMatrix-Code vor die -QR-Code" wählen und ein Etikett mit dem eigenen DataMatrix-Code vor die
Kamera halten: Rahmen hebt sich hervor, Treffer wird gebucht (DataMatrix Kamera halten: Rahmen hebt sich hervor, Treffer wird gebucht (DataMatrix
liest diese Funktion jetzt mit). Einen echten QR-Code vor dieselbe Funktion liest diese Funktion jetzt mit). Einen echten QR-Code vor dieselbe Funktion
halten: ebenfalls Treffer. halten: ebenfalls Treffer.
@@ -421,7 +420,7 @@ werden:
Etikettenfoto tatsächlich brauchbaren Text (bisher nur an synthetischen Etikettenfoto tatsächlich brauchbaren Text (bisher nur an synthetischen
Testbildern geprüft, nie an einem echten Foto). Testbildern geprüft, nie an einem echten Foto).
- Ladezeit des WASM-Barcode-Moduls (`zxing-wasm`) beim allerersten Scan einer - Ladezeit des WASM-Barcode-Moduls (`zxing-wasm`) beim allerersten Scan einer
Sitzung in Funktion „Strichcode" oder „2D-Code" beobachten — bleibt sie Sitzung in Funktion „Strichcode" oder „QR-Code" beobachten — bleibt sie
deutlich unter der 10-Sekunden-Zeitgrenze der Pipeline, und braucht ein deutlich unter der 10-Sekunden-Zeitgrenze der Pipeline, und braucht ein
zweiter, schnell nachfolgender Scan nicht erneut die volle Ladezeit (Beleg, zweiter, schnell nachfolgender Scan nicht erneut die volle Ladezeit (Beleg,
dass die Vorbereitung tatsächlich nur einmal läuft)? In Funktion „Text dass die Vorbereitung tatsächlich nur einmal läuft)? In Funktion „Text
@@ -434,7 +433,7 @@ werden:
- Ladezeit des Tesseract-Arbeiters beim ersten Antippen von „Modul scannen" - Ladezeit des Tesseract-Arbeiters beim ersten Antippen von „Modul scannen"
in Funktion „Text erkennen" beobachten — bleibt sie auf einem normalen in Funktion „Text erkennen" beobachten — bleibt sie auf einem normalen
Handy deutlich unter der 20-Sekunden-Zeitgrenze der Pipeline? In den Handy deutlich unter der 20-Sekunden-Zeitgrenze der Pipeline? In den
Funktionen „Strichcode"/„2D-Code" darf dieses Laden nie anlaufen, auch Funktionen „Strichcode"/„QR-Code" darf dieses Laden nie anlaufen, auch
nicht bei einem gänzlich unbekannten Etikett, da `runOcr` dort nie nicht bei einem gänzlich unbekannten Etikett, da `runOcr` dort nie
aufgerufen wird. aufgerufen wird.
- Verfügbarkeitsanzeige der Texterkennung: bleibt nach einem erfolgreichen - Verfügbarkeitsanzeige der Texterkennung: bleibt nach einem erfolgreichen
@@ -443,7 +442,7 @@ werden:
darauf zurück? darauf zurück?
- Stichprobe, ob die feste Zeichen-Whitelist der Texterkennung auf echten - Stichprobe, ob die feste Zeichen-Whitelist der Texterkennung auf echten
Etiketten keine tatsächlich benötigten Zeichen ausschließt. Etiketten keine tatsächlich benötigten Zeichen ausschließt.
- Funktion „Strichcode"/„2D-Code": kein passender Code im Bild führt zu - Funktion „Strichcode"/„QR-Code": kein passender Code im Bild führt zu
Rot-Dialog (statt Fehler oder Absturz) — hier ohne jeden OCR-Versuch. Rot-Dialog (statt Fehler oder Absturz) — hier ohne jeden OCR-Versuch.
Funktion „Text erkennen": kein verwertbarer OCR-Text führt ebenfalls zu Funktion „Text erkennen": kein verwertbarer OCR-Text führt ebenfalls zu
Rot, hier ohne jeden Barcode-Versuch. Rot, hier ohne jeden Barcode-Versuch.
+4 -1
View File
@@ -38,8 +38,11 @@ export const SCAN_MODES = [
// Kennung bleibt aus historischen Gruenden `qrcode`, obwohl die Funktion // Kennung bleibt aus historischen Gruenden `qrcode`, obwohl die Funktion
// inzwischen alle 2D-Codearten liest (nicht mehr nur QR) - Umbenennung // inzwischen alle 2D-Codearten liest (nicht mehr nur QR) - Umbenennung
// nicht vorgenommen, da `qrcode` an mehreren Stellen durchgereicht wird. // nicht vorgenommen, da `qrcode` an mehreren Stellen durchgereicht wird.
// Label heisst auf Wunsch des Auftraggebers "QR-Code", obwohl die Funktion
// bewusst auch DataMatrix, Aztec und PDF417 liest - die RAM-Etiketten
// tragen DataMatrix, nicht QR.
id: 'qrcode', id: 'qrcode',
label: '2D-Code', label: 'QR-Code',
// QR-Varianten plus DataMatrix, Aztec, PDF417 - siehe Kommentar am Kopf. // QR-Varianten plus DataMatrix, Aztec, PDF417 - siehe Kommentar am Kopf.
barcodeFormats: ['QRCode', 'MicroQRCode', 'RMQRCode', 'DataMatrix', 'Aztec', 'PDF417'], barcodeFormats: ['QRCode', 'MicroQRCode', 'RMQRCode', 'DataMatrix', 'Aztec', 'PDF417'],
continuousSearch: true, continuousSearch: true,
+2 -2
View File
@@ -17,9 +17,9 @@ test('Funktion 1 (Strichcode): eindimensionale Codearten, laufende Suche, keine
assert.equal(mode.useOcr, false); assert.equal(mode.useOcr, false);
}); });
test('Funktion 2 (2D-Code): QR-Varianten und DataMatrix, Aztec, PDF417', () => { test('Funktion 2 (QR-Code): QR-Varianten und DataMatrix, Aztec, PDF417', () => {
const mode = getScanMode('qrcode'); const mode = getScanMode('qrcode');
assert.equal(mode.label, '2D-Code'); assert.equal(mode.label, 'QR-Code');
assert.deepEqual(mode.barcodeFormats, [ assert.deepEqual(mode.barcodeFormats, [
'QRCode', 'MicroQRCode', 'RMQRCode', 'DataMatrix', 'Aztec', 'PDF417', 'QRCode', 'MicroQRCode', 'RMQRCode', 'DataMatrix', 'Aztec', 'PDF417',
]); ]);