27 Commits
Author SHA1 Message Date
TanerUsluandClaude Opus 5 6688efc546 README: Zählen-Abschnitte auf Aufnahme statt Dauerbetrieb aktualisiert
Beschreibt die neue Aufnahme-Schaltfläche ("Zählen"/"Nochmal zählen"), die
fünf Bilder je Aufnahme samt Median, die um die Einzelmessungen erweiterte
Diagnosezeile und das Zurücksetzen beim Verlassen der Funktion. Aufbau-
Tabelle, Testanzahl und der Prüfabschnitt "Am Gerät noch zu prüfen" folgen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 09:37:10 +02:00
TanerUsluandClaude Opus 5 4b6bb065b1 Zählen: Aufnahme statt Dauerbetrieb
Die Zaehlanzeige sprang beim Nutzer im Dauerbetrieb wild zwischen etwa 3
und 60, obwohl dasselbe Verfahren an einem Standfoto stabil 18 lieferte -
eine Schaetzung wird durch staendiges Neuanzeigen nicht praeziser, nur
unruhig. "Zählen" laeuft jetzt wie "Text erkennen" auf Knopfdruck: eine
Aufnahme nimmt binnen rund einer Sekunde fuenf Bilder aus dem Zielrahmen
auf, zaehlt jedes einzeln (count-objects.js unveraendert) und zeigt deren
Median (neues Modul count-capture.js). Das Ergebnis bleibt stehen, bis
erneut angetippt wird; die Diagnosezeile zeigt zusaetzlich die fuenf
Einzelmessungen. Der gleitende Median ueber neun Durchlaeufe der
Dauerzaehlung (count-history.js) entfaellt, da die Aufnahme dieselbe
Robustheit bereits selbst leistet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 09:36:43 +02:00
TanerUsluandClaude Opus 5 d84c15e0d0 Diagnoseanzeige fuer die Funktion "Zählen" ergaenzt
Der Nutzer meldet eine stark schwankende Zaehlanzeige im Livebetrieb
(3-60), obwohl dasselbe Verfahren an einem Standfoto stabil 18 liefert -
er kann aber keine Bilder hochladen und muss Messwerte daher vom
Bildschirm ablesen und durchgeben koennen.

- count-objects.js liefert additiv Zwischenwerte (Bildgroesse nach
  Normierung, Flaechen vor/nach Filterung, groesste Flaeche, typische
  Groesse, gewinnende Polaritaet) - auch bei count 0 sinnvoll belegt.
  Die eigentliche Zaehllogik bleibt unveraendert.
- count-history.js (neu): gleitender Median der letzten 9 Messungen,
  unterdrueckt einzelne Ausreisser ohne die Anzeige traege zu machen.
- main.js zeigt den Median als grosse Zahl, misst den Zeitbedarf des
  Zaehldurchlaufs und baut daraus die Diagnosezeile; der Verlauf wird
  bei jedem Funktionswechsel zurueckgesetzt.
- scan-view.js/styles.css: die grosse Zahl ist antippbar und blendet
  eine anfangs verborgene Diagnosezeile ein/aus, ohne selbst zu
  verrutschen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 08:56:26 +02:00
TanerUsluandClaude Opus 5 f0705a010c Doku: Zaehlfunktion und ihre Grenzen auf das neue Verfahren aktualisiert
Beschreibt oertlichen Kontrast statt Otsu (Normierung, Glaettung,
oertlicher Hintergrund, Massstab relativ zur groessten Flaeche) und die
neuen Grenzen: Untergrund muss sich abheben, gleichmaessige Ausleuchtung
hilft, auseinandergelegt zaehlt besser als aufgehaeuft, stark
unterschiedlich grosse Teile verfaelschen die Hochrechnung.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:21:35 +02:00
TanerUsluandClaude Opus 5 089d47a1ec Synthetische Zaehl-Tests an das oertlich-kontrastbasierte Verfahren angepasst
Das neue Verfahren braucht ein Umgebungsfenster (Radius max(Breite,Hoehe)/12),
das an jeder Fundstueck-Stelle noch echten Untergrund sieht - die alten
40x40-/80x80-Testbilder mit 10x10-Quadraten waren dafuer zu klein. Bildgroesse
und Quadratmasse angepasst (300x300/600x600), Kernaussagen unveraendert:
leeres Bild -> null, getrennte gleich grosse Flaechen -> ihre Anzahl, Rauschen
zaehlt nicht mit, Hochrechnung beruehrender Teile, kein Doppelzaehlen leicht
groesserer Einzelteile, beide Polaritaeten, 4er- statt 8er-Nachbarschaft
(Luecke statt gemeinsamem Eckpixel, da die Glaettung Raender aufweitet).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:21:24 +02:00
TanerUsluandClaude Opus 5 75c479860f Zaehlung auf oertlichen Kontrast umgestellt (Otsu versagte am echten Foto)
Otsu (bisheriges Verfahren) meldete am echten Foto des Auftraggebers
(~20 Schrauben auf Leder, unter 1% Flaechenanteil) 76712 statt rund
zwanzig - Otsu taugt nur bei etwa gleich grossen Objekt-/
Untergrundflaechen. countObjects() vergleicht jetzt jeden Bildpunkt mit
einem oertlichen Hintergrund (Kastenfilter ueber Summenbild, Radius
max(Breite,Hoehe)/12), was Ausleuchtungsunterschiede abfaengt und am
echten Foto 18 statt 76712 liefert (Test in
test/count-objects-photo.test.js, ~30-49ms Laufzeit).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:21:13 +02:00
TanerUsluandClaude Opus 5 ffb2409c24 Doku: vierte Funktion "Zählen" im README ergänzt
Funktionstabelle, Ablaufbeschreibung, Aufbau-Tabelle (threshold.js,
count-objects.js), Testzahl (165), neuer Grenzen-Abschnitt (beruehrende/
gestapelte Teile, ungleichmaessige Ausleuchtung, geringer Kontrast, stark
unterschiedliche Teilegroessen) sowie ein Geraete-Pruefpunkt fuer "Zählen".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 15:48:04 +02:00
TanerUsluandClaude Opus 5 8c761c6fb5 Vierte Scan-Funktion "Zählen": laufende Anzeige, keine Buchung
Neue Funktion in scan-modes.js (Merkmal continuousCount), verdrahtet in
main.js ueber denselben Zeitgeber/dieselbe Ueberlappungssperre wie die
Barcode-Dauersuche (continuousSearchLoop ruft jetzt runCountAttempt()
zusaetzlich zu runSearchAttempt(); jeder bricht selbst ab, wenn die
Funktion nicht passt) - kein zweiter, paralleler Mechanismus. Kein "Modul
scannen"-Knopf, keine Treffer-Rueckmeldung, kein roter Dialog, keine
Stapel-Zuweisung; die grosse Zaehlanzeige (scan-view.js/styles.css) ist
reine Anzeige und speichert nichts.

buildRecognitionAdapters() liefert fuer "Zählen" zusaetzlich leere Adapter
(Absicherung gegen den seltenen Datei-Ersatzweg ohne Kamera). Die drei
bestehenden Funktionen bleiben unveraendert; einzige notwendige Anpassung an
scan-modes.test.js war die Anzahl-Pruefung (3 -> 4 Funktionen).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 15:47:44 +02:00
TanerUsluandClaude Opus 5 5e64d260c5 Reine Zaehl-Berechnung fuer Fundstuecke in einem Bildausschnitt
Neues Modul src/count-objects.js: Otsu-Schwellwert (threshold.js) teilt den
Ausschnitt in zwei Klassen, die flaechenmaessig kleinere gilt als Objekt
(funktioniert fuer helle wie dunkle Teile auf beliebigem Untergrund).
Connected-Component-Labeling ueber eine eigene Arbeitsliste statt Rekursion
(vermeidet Stapelueberlauf bei ~1 Mio. Bildpunkten), Rauschflaechen werden
verworfen, beruehrende Teile anhand des Flaechen-Medians hochgerechnet.

Test-Driven: leeres Bild, einzelne/mehrere getrennte Flaechen, verworfenes
Rauschen, Hochrechnung ohne ein nur leicht groesseres Einzelteil zu
verdoppeln, helle wie dunkle Objekte, Bild ohne Bildpunkte, diagonal statt
flaechig beruehrende Teile bleiben getrennt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 15:47:33 +02:00
TanerUsluandClaude Opus 5 500f9b6c3d Otsu-Schwellwert in eigenes reines Modul ausgelagert (threshold.js)
Zieht otsuThreshold()/grayscaleHistogram() aus ocr.js in src/threshold.js,
ohne das Verhalten von preprocess() zu aendern (bestehende Tests in
ocr-preprocess.test.js bleiben unveraendert gruen). Vorbereitung fuer die
neue Zaehl-Funktion, die dieselbe Schwellwertbestimmung braucht, aber nichts
mit tesseract.js (ocr.js) zu tun haben soll.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 15:47:22 +02:00
TanerUslu 87ba439287 Doku: voller OCR-Rohtext in "Text erkennen" (Rahmen, Whitelist, Anzeige)
README auf den aktuellen Stand gebracht: Zielrahmen ist jetzt auch in "Text
erkennen" wirksam (grabFrameRegion statt grabFrame), breitere Zeichen-
Whitelist samt Abwägung, additiver OCR-Rohtext (rawText) in Pipeline,
Speicherung und Anzeige, wartende statt automatisch ausblendende
Rückmeldung in "Text erkennen". Datei-Tabelle, Abschnitt
"Sitzungssicherung im Detail", "Grenzen" und die manuelle Geräte-Prüfliste
entsprechend ergänzt; Testanzahl 144 → 154.
2026-07-29 15:19:34 +02:00
TanerUslu b903b1c7aa OCR-Rohtext additiv zurückgeben, je Eintrag speichern und anzeigen
recognize() (pipeline.js) liefert zusätzlich den ungefilterten OCR-Rohtext
(rawText) zurück - leer, wenn keine Texterkennung lief. Rein additiv: die
Stapelzuordnung (session.js/spec.js, unangetastet) stützt sich weiterhin
ausschließlich auf die daraus abgeleiteten, verstandenen Spec-Felder.

main.js hängt den Rohtext nach dem Buchen als zusätzliche Eigenschaft an den
Eintrag (analog zu den bereits vorhandenen Barcode-Inhalten je Eintrag).
storage.js sichert/prüft/stellt entry.rawText nach demselben optionalen
Muster wie entry.codes wieder her - ein gesicherter Stand ohne dieses Feld
wird nicht verworfen.

In Funktion "Text erkennen" bleibt die Treffer-Rückmeldung jetzt stehen, bis
der Nutzer sie wegtippt, und zeigt den vollen erkannten Text (lesbar über
dasselbe Scroll-Muster wie die übrigen Vollbild-Overlays); in den beiden
Barcode-Funktionen bleibt es beim automatischen Ausblenden. Das
zurückgegebene Versprechen von showResult löst in jedem Fall - Zeitgeber,
Wegtippen, verdrängende neue Rückmeldung - genau einmal ein, damit die
Bedienung nie dauerhaft gesperrt bleibt. Die Sitzungsliste zeigt den Rohtext
zusätzlich je Eintrag zum Nachlesen.

Tests (pipeline.test.js, storage.test.js): rawText nur bei tatsächlich
gelaufener Texterkennung, unterschiedlicher Rohtext beeinflusst die
Stapelzuordnung nachweislich nicht, Rohtext übersteht Sichern/Laden inkl.
Abwärtskompatibilität zu einem Stand ohne dieses Feld.
2026-07-29 15:19:13 +02:00
TanerUslu 1c10c68053 Zeichen-Whitelist der Texterkennung um Kleinbuchstaben erweitert
tessedit_char_whitelist ließ bisher nur Großbuchstaben, Ziffern und wenige
Sonderzeichen zu. Der Nutzer will den vollständigen Etikettentext sehen, nicht
nur die von der App verstandenen Felder - die Whitelist deckt deshalb jetzt
Groß- und Kleinbuchstaben, Ziffern sowie die auf Etiketten üblichen Satz- und
Sonderzeichen ab. Das kann die Genauigkeit bei den Codeteilen (Kapazität,
Rank, Geschwindigkeit, Teilenummer) etwas verringern - eine bewusst in Kauf
genommene Abwägung, siehe Kommentar an Ort und Stelle.
2026-07-29 15:18:56 +02:00
TanerUslu 54b1447f21 Text erkennen liest den Zielrahmen in voller Auflösung, nicht das Vollbild
grabFrameRegion() statt grabFrame(): "Modul scannen" bekam bisher das ganze
Kamerabild, auf 1280 Pixel herunterskaliert - der Zielrahmen war dabei rein
kosmetisch, obwohl er dem Nutzer einen wirksamen Ausschnitt suggeriert. Jetzt
liest die Texterkennung genau den Rahmenausschnitt, in nativer Auflösung -
denselben, den auch die laufende Barcode-Suche längst benutzt. Die
Dateiauswahl (onPickFile) bleibt unverändert beim Vollbild, da sie keinen
Zielrahmen kennt.
2026-07-29 15:18:48 +02:00
TanerUsluandClaude Opus 5 3907204209 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>
2026-07-29 14:50:24 +02:00
TanerUsluandClaude Opus 5 2d7778cea8 Funktion 2 liest 2D-Codes statt nur QR (Auftraggeber-Entscheidung revidiert)
Der Auftraggeber hatte Funktion 2 ausdruecklich auf QR beschraenkt, obwohl
die 2D-Codes auf seinen RAM-Etiketten DataMatrix sind. Am Geraet zeigte sich,
dass die Funktion auf seiner Ware nichts fand - er hat die Entscheidung
revidiert. Funktion 2 liest jetzt zusaetzlich zu QRCode/MicroQRCode/RMQRCode
auch DataMatrix, Aztec und PDF417 und heisst in der Oberflaeche "2D-Code"
statt "QR-Code". Die Kennung bleibt aus historischen Gruenden `qrcode`.

Veralteten Kommentar in scan-modes.js berichtigt, Test auf die neue
Codeliste/Beschriftung umgestellt (statt geloescht) und einen Test ergaenzt,
der paarweise verschiedene Kennungen/Beschriftungen der drei Funktionen
erzwingt. README-Funktionstabelle und Geraete-Checkliste entsprechend
angepasst.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 14:32:41 +02:00
TanerUslu ebff173443 Doku: drei Scan-Funktionen statt automatischem Barcode/OCR-Ausweichen
Funktionsweise-Abschnitt, Technik- und Aufbau-Tabelle sowie die
Geraete-Checkliste auf die neue Funktionswahl gebracht. Haelt fest,
dass in "Text erkennen" mangels Barcode-Teilenummer allein die
technischen Angaben ueber die Stapelzuordnung entscheiden, und dass
"QR-Code" bewusst kein DataMatrix liest. Testanzahl auf 143 aktualisiert.
2026-07-29 13:37:18 +02:00
TanerUslu 2e619ed64d Funktionswahl vor der Kamera, Wechsel und Knopf-Sichtbarkeit je Funktion
Neuer Vollbild-Dialog (src/ui/mode-dialog.js) mit drei grossen Flaechen,
gebaut nach dem Muster der bestehenden Dialoge. Ablauf beim Start: erst
die Fortsetzen-Frage (falls eine gesicherte Sitzung vorliegt), dann die
Funktionswahl, erst danach startet die Kamera.

Die gewaehlte Funktion steht antippbar in der Scan-Ansicht und laesst
sich dort jederzeit wechseln - der Wechsel gilt sofort: laufende Suche
startet/stoppt, "Modul scannen" erscheint nur noch in Funktion "Text
erkennen", der Zielrahmen wird beim Wechsel weg von laufender Suche
zurueckgesetzt. pipeline.js bleibt unangetastet; main.js reicht je nach
Funktion nur unterschiedliche Adapter hinein (scan-recognition.js).
2026-07-29 13:37:12 +02:00
TanerUslu 2eb9d1ecf8 Barcode-Adapter nimmt Codearten entgegen, Adapter-Weiche je Funktion
decodeBarcodes(imageData, formats) bekommt die zu suchenden Codearten
uebergeben; ohne Angabe unveraendertes Verhalten (Code128 + DataMatrix).

buildRecognitionAdapters() baut daraus und aus dem echten OCR-Adapter
die an recognize() (pipeline.js, unveraendert) uebergebenen Adapter:
in Strichcode/QR-Code liefert die Texterkennung sofort leeren Text ohne
Tesseract anzustossen, in Text-erkennen liefert die Barcode-Dekodierung
sofort eine leere Liste ohne zxing-wasm anzustossen.
2026-07-29 13:37:05 +02:00
TanerUslu 9ef038ca98 Reines Funktionen-Modul fuer die drei Scan-Funktionen
Kennung, deutsche Beschriftung, Codearten, laufende Suche und
Texterkennung je Funktion an einer einzigen Stelle (src/scan-modes.js),
ohne Browser-Zugriff und damit unter Node pruefbar. Funktion "QR-Code"
enthaelt bewusst kein DataMatrix.
2026-07-29 13:36:58 +02:00
TanerUslu 5a055923fe Trenne Dialogtexte fuer echte Mehrdeutigkeit und nichts erkannt
Der rote Dialog zeigte bisher immer "Nicht eindeutig", auch wenn die
Erkennung schlicht nichts Verwertbares geliefert hat (kein Barcode, kein
brauchbarer Klartext). Das verwirrt: es klingt nach mehreren Kandidaten,
obwohl gar keine Erkennung stattfand.

askForStack() bekommt einen expliziten Parameter nothingRecognized, da
sich die beiden Lagen nicht zweifelsfrei aus spec/candidates ableiten
lassen (main.js reicht bei "nichts erkannt" als Rueckfall alle
vorhandenen Stapel als candidates durch). main.js setzt ihn anhand von
plan.kind === 'ambiguous' (echte Mehrdeutigkeit) vs. allem anderen
(nur wegen roter Konfidenz im Dialog).

Signatur, Rueckgabeform, Schaltflaechen, Klassennamen, die
Mehrfachausloese-Sperre und die inert-Handhabung bleiben unveraendert.
2026-07-29 13:05:37 +02:00
TanerUsluandClaude Opus 5 b94639ccd1 Laufende Barcode-Suche statt Einzelbild beim Knopfdruck
Solange Kamera laeuft und keine Erkennung/kein Dialog/keine
Sitzungsliste im Weg steht, sucht die App ~5x/s im Zielrahmen nach
Barcodes. Ein gefundener Code durchlaeuft denselben Weg wie der
Knopfdruck (processCapture). Sperrzeit von 2s plus Codevergleich
verhindert, dass ein laenger vor die Kamera gehaltenes Modul mehrfach
gebucht wird, ohne einen zuegigen Modulwechsel auszubremsen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 12:59:23 +02:00
TanerUsluandClaude Opus 5 abb70e8b23 Zielrahmen aus FRAME_INSET setzen, Erkennungs-Hervorhebung ergaenzen
scan-view.js setzt die Rahmenlage jetzt aus camera.js' FRAME_INSET
statt aus einem im Stilblatt duplizierten Wert. Neue Methode
setFrameDetected() faerbt den Rahmen gruen, sobald die Dauersuche
einen Barcode im Ausschnitt findet - schlichte Farbaenderung, keine
Animation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 12:59:14 +02:00
TanerUsluandClaude Opus 5 44526e7d3b Ausschnitt in nativer Aufloesung fuer Barcode-Erkennung
FRAME_INSET und frameRect() legen die Rahmenmasse einmalig fest, statt
sie nur im Stilblatt zu duplizieren. grabFrameRegion() liefert den
Zielrahmen unskaliert aus dem Kamerabild - grabFrame() (fuer OCR)
bleibt unveraendert. Ein Code-128 auf kleinem Etikett braucht die
volle Aufloesung, sonst verschmieren die Striche unlesbar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 12:59:08 +02:00
TanerUslu 69dbeeb062 fix: dist-Pfad im Server absolut aufloesen, unabhaengig vom Startverzeichnis 2026-07-29 10:39:30 +02:00
TanerUslu 8858ab2f88 feat: Passwortschutz im Server statt im Browser
Ohne gueltiges Passwort gibt der Server weder Seite noch Skript heraus.
Das Passwort kommt aus APP_PASSWORD; fehlt die Variable, startet der Server
absichtlich nicht. /healthz bleibt passwortfrei, damit die Ueberwachung den
geschuetzten Dienst nicht faelschlich fuer ausgefallen haelt.
2026-07-29 10:32:41 +02:00
TanerUslu d3be44e5d3 chore: VCH-Deploykonfiguration fuer statische Auslieferung 2026-07-29 10:08:40 +02:00