DUST Go integrieren
DUST Go ist ein eingebetteter mobiler Browser: Er lädt Ihre Web-App in einer WebView und stellt der Seite die DUST-Scanhardware des Geräts über eine kleine JavaScript-Bridge zur Verfügung, @dustid/dust-go-connect. Sie entwickeln und hosten eine gewöhnliche Web-App; DUST Go stellt Kamera, optisches Zubehör und die Aufnahmepipeline bereit – eine native Toolchain ist nicht erforderlich.
Diese Seite führt Sie zu einem aufgelösten Scan. Alles Weitere – Anmeldung, Geolokalisierung, Kompatibilität, Desktop-Hardware – finden Sie weiter unten unter Über den ersten Scan hinaus.
Bevor Sie beginnen
- Rolle
- Anmeldedaten eines Dienstkontos, die von Ihrem Backend verwahrt werden
- Gerät
- Ein iPhone mit DUST Go und einem unterstützten Loupe-Zubehör für DUST-Aufnahmen
Zusammenspiel der Komponenten
Abschnitt betitelt „Zusammenspiel der Komponenten“- Ein Benutzer öffnet Ihre Web-App innerhalb von DUST Go (über einen App-Link).
- Ihre Seite importiert
@dustid/dust-go-connect; die Bibliothek erkennt die DUST-Go-Bridge und stellt einenconnectorbereit. - Ihre Seite ruft
scanAsync()auf. DUST Go öffnet den nativen Scanner über Ihrer Seite. - Bei der Aufnahme sendet DUST Go ein Scanereignis an Ihre Seite zurück: Die Nutzdaten enthalten die Aufnahmedaten und Metadaten.
- Ihre Seite sendet die Aufnahme an Ihr Backend, das APID (
/api/v1/tags/identify,/bindoder/verify) aufruft, um sie aufzulösen.
Ein DUST-Scan übergibt Ihrer Seite eine Rohaufnahme (ein Base64-codiertes JPEG) sowie Aufnahmemetadaten – keine aufgelöste Kennung. Identifizierung, Verifizierung und Verknüpfung erfolgen vollständig serverseitig.
Installation
Abschnitt betitelt „Installation“npm install @dustid/dust-go-connectDas Paket besitzt keine Abhängigkeiten, steht unter der MIT-Lizenz und enthält TypeScript-Typen.
DUST Go erkennen
Abschnitt betitelt „DUST Go erkennen“Der Export connector ist undefined, wenn Ihre Seite nicht innerhalb von DUST Go ausgeführt wird. Dadurch kann derselbe Build Ihrer App sowohl reguläre Browser als auch DUST Go bedienen:
import { connector } from "@dustid/dust-go-connect";
export const insideDustGo = Boolean(connector);Zwei wichtige Punkte:
- Importzeitpunkt. Die Erkennung erfolgt beim Modulimport im Browser. Wenn Sie serverseitig rendern, dürfen Sie den Connector erst nach der Hydratation verwenden.
- Serverseitige Erkennung. Neuere DUST-Go-Builds kennzeichnen außerdem den User-Agent der WebView mit
DustGo/<version> (<app id>), sodass Ihr Server die App erkennen kann, bevor JavaScript ausgeführt wird. Behandeln Sie dies als Hinweis, nicht als Sicherheitsgrenze – jeder kann einen User-Agent fälschen.
Einen Scan aufnehmen
Abschnitt betitelt „Einen Scan aufnehmen“Der einfachste Weg ist die Promise-API: Zeigen Sie den Scanner an und warten Sie auf eine Aufnahme:
import { scanAsync } from "@dustid/dust-go-connect";
const payload = await scanAsync();// payload: { type: 'DUST' | 'QR' | 'BARCODE' | 'DATA_MATRIX' | 'NFC',// data: string, metadata?: ScanMetadata }scanAsync() gibt ein Promise<ScanPayload> zurück. Das Promise wird abgelehnt, wenn der Benutzer den Scanner schließt, ohne eine Aufnahme zu erstellen, und ebenso unmittelbar, wenn die Funktion außerhalb von DUST Go aufgerufen wird (kein Connector vorhanden). Prüfen Sie daher zuerst connector, wenn derselbe Codepfad auch in regulären Browsern ausgeführt wird.
Inhalt der Nutzdaten
Abschnitt betitelt „Inhalt der Nutzdaten“payload.type | payload.data | Hinweise |
|---|---|---|
DUST | Base64-codiertes JPEG der DUST-Aufnahme | Groß; serverseitig über APID auflösen |
QR, BARCODE, DATA_MATRIX | Der decodierte Inhalt des Symbols | |
NFC | Die vom NFC-Chip gelesene Hex-ID |
payload.metadata (typisiert als ScanMetadata) beschreibt die Aufnahme: Gerätekennungen (deviceId, modelName, osName, osVersion, appVersion), Objektiv-/Kameraauswahl sowie optional Felder zur Optik (Zoom, Fokus, Belichtung, ISO), Geolokalisierung (latitude/longitude/accuracy) und Angaben zur Aufnahmequelle für externes Scanzubehör (captureSource, usbVendorId, usbProductId, dragonBackend). Leiten Sie diese Daten bei der Verknüpfung unverändert weiter – APID speichert sie zusammen mit der Kennung.
Speicherort der Anmeldedaten
Abschnitt betitelt „Speicherort der Anmeldedaten“Lesen Sie diesen Abschnitt vor dem Auflösungsschritt: Er bestimmt die Struktur Ihrer gesamten Integration.
Der Auflösungsschritt besteht somit aus zwei Dateien an zwei Orten:
| Datei | Ausführungsort | Enthält die DUST-Anmeldedaten? |
|---|---|---|
| Ihre Scanseite | Browser innerhalb von DUST Go | Nein |
Ihr /api/dust-scan-Handler | Ihr Server | Ja |
Den Scan mit APID abgleichen
Abschnitt betitelt „Den Scan mit APID abgleichen“Die DUST-Aufnahme ist erst nutzbar, nachdem APID sie zugeordnet hat. Die Seite decodiert die Base64-Aufnahme in Binärdaten und sendet sie an Ihren eigenen Endpunkt:
// No DUST credential in this file.async function identifyDustScan(base64Jpeg: string) { // The scan arrives base64-encoded; APID expects binary multipart data. const bytes = Uint8Array.from(atob(base64Jpeg), (c) => c.charCodeAt(0)); const form = new FormData(); form.set("operation", "identify"); form.set("tagType", "DUST"); form.set("data", new Blob([bytes], { type: "image/jpeg" }));
const response = await fetch("/api/dust-scan", { method: "POST", body: form, credentials: "same-origin", }); return { status: response.status, body: await response.json() };}Ihr Backend ergänzt die Anmeldedaten und den Kontext und legt den Suchumfang selbst fest:
export async function handleIdentify(form: FormData, session: Session) { // `searchTeamIds` is a JSON array of Team UUIDs. Set it on the server — a // browser-supplied scope is a request, never an authorization. form.set("searchTeamIds", JSON.stringify(session.allowedTeamIds));
const response = await fetch("https://apid.dustid.io/api/v1/tags/identify", { method: "POST", headers: { Authorization: `Bearer ${await getDustToken()}`, "Dust-Ctx-Org-Id": session.organizationId, }, body: form, });
// Pass the status and body through unchanged: the page needs to tell // "nothing matched" (404 IDENTIFIER_NOT_FOUND) from "try again" // (503 SCAN_SEARCH_INCOMPLETE). return new Response(await response.text(), { status: response.status, headers: { "Content-Type": "application/json" }, });}Das Feld heißt searchTeamIds. Nutzdaten zur Identifizierung lehnen Eigenschaften ab, die sie nicht deklarieren. Daher führt die veraltete Schreibweise searchGroupIds dazu, dass die gesamte Anfrage mit 400 INVALID_REQUEST fehlschlägt, statt ignoriert zu werden. Der einzige weiterhin bestehende ältere Name group ist der Header Dust-Ctx-Grp-Id, der nach wie vor als Alias für Dust-Ctx-Team-Id akzeptiert wird.
Dieselbe Multipart-Struktur wird für die beiden anderen Vorgänge verwendet:
/api/v1/tags/bind– fügen SiethreadIdhinzu.options.enrollmentSessionIdist optional: Geben Sie eine vom Client erzeugte UUID an, die während eines Laufs wiederverwendet wird, wenn mehrere Aufnahmen zusammengehören (beispielsweise wenn eine Registrierungsstation einen Stapel verarbeitet); lassen Sie sie bei einer einmaligen Verknüpfung weg./api/v1/tags/verify– fügen SiethreadIdundtagshinzu.tagsist ein Array aus Objekten ([{ "tagId": "…", "tagType": "DUST" }], in Multipart als JSON codiert), nicht aus ID-Zeichenfolgen.tagsist erforderlich.
Die vollständigen Anfrage-/Antwortverträge finden Sie unter Kennungen. Der React Scanner enthält eine direkt verwendbare Komponente, die alle drei Vorgänge mit einem Backend-Handler wie dem oben gezeigten implementiert.
Integration testen
Abschnitt betitelt „Integration testen“- Installieren Sie DUST Go aus dem App Store oder von Google Play (die Hardwareanforderungen finden Sie unter Unterstützte Geräte – für DUST-Aufnahmen ist unterstütztes optisches Zubehör erforderlich).
- Stellen Sie Ihre App per HTTPS unter einer URL bereit, die das Gerät erreichen kann (für die Entwicklung genügt eine LAN-Adresse).
- Fügen Sie Ihre URL in DUST Go als benutzerdefinierten App-Link hinzu und öffnen Sie ihn.
- Prüfen Sie, ob der Connector erkannt wird, und führen Sie anschließend einen Scan aus.
- Vergewissern Sie sich, dass die Aufnahme Ihr Backend erreicht und der DUST-Aufruf Ihres Backends ein darstellbares Ergebnis zurückgibt – einschließlich des Falls „Keine Übereinstimmung“.
Eine minimale Diagnoseseite, die die gesamte Bridge testet (Erkennung, scanAsync, Ereignisprotokoll), ist im Paket-Repository verfügbar.
Über den ersten Scan hinaus
Abschnitt betitelt „Über den ersten Scan hinaus“Alles Folgende ist optional. Kehren Sie hierher zurück, sobald ein einzelner Scan durchgängig aufgelöst wird.
Workflows mit mehreren Scans
Abschnitt betitelt „Workflows mit mehreren Scans“Verwenden Sie für Abläufe, bei denen mehrere Scans vor dem Absenden aufgenommen werden, die Listener-API – der Scanner bleibt zwischen den Aufnahmen geöffnet:
import { connector } from "@dustid/dust-go-connect";
connector?.add("my-listener", (event) => { switch (event.type) { case "scan": handleScan(event.payload); break; case "hide": // scanner closed case "show": // scanner opened break; default: // Ignore unknown event types — the protocol may grow. break; }});
connector?.showScanner();// later: connector?.hideScanner(); connector?.remove("my-listener");addScanListener bewirkt dasselbe, ohne dass Sie den Listener selbst verwalten müssen – die Funktion empfängt jeden Scan und gibt eine eigene Funktion zum Abbestellen zurück:
import { addScanListener } from "@dustid/dust-go-connect";
const stop = addScanListener((payload) => handleScan(payload));// later: stop();Eine Scannersitzung kann eine Reihe von Aufnahmen liefern. Senden Sie diese daher einzeln nacheinander. DUST-Nutzdaten sind große Base64-JPEGs; wenn Sie mehrere gleichzeitig hochladen, wird die Verbindung ausgelastet und die Bedienperson erhält keine brauchbare Fortschrittsanzeige. Stellen Sie die Nutzdaten in eine Warteschlange und warten Sie jeweils den Abschluss einer Übertragung ab, bevor Sie die nächste starten.
Funktionen des Scanners
Abschnitt betitelt „Funktionen des Scanners“Hosts unterscheiden sich: Ein Mobiltelefon kann Zoom und Belichtung einstellen, ein USB-Mikroskop-Zubehör stellt andere Optionen bereit und ein älterer Build stellt möglicherweise gar keine bereit. Fragen Sie die Funktionen ab, statt sie aus dem User-Agent abzuleiten:
const capabilities = connector?.getCapabilities?.();Behandeln Sie eine fehlende oder leere Bekanntgabe als nur einzelne Aufnahmen, keine Einstellungen möglich. Interpretieren Sie fehlende Angaben niemals als vorhandene Funktion.
Geolokalisierung
Abschnitt betitelt „Geolokalisierung“Standardaufrufe von navigator.geolocation funktionieren innerhalb von DUST Go – die App leitet sie transparent über die native Berechtigungsabfrage des Betriebssystems weiter. Connector-Code ist nicht erforderlich.
Anmeldeabläufe innerhalb von DUST Go
Abschnitt betitelt „Anmeldeabläufe innerhalb von DUST Go“Wenn Ihre App OAuth/OIDC verwendet, beachten Sie, dass DUST Go Navigationen zu externen Identitätsanbietern an den Systembrowser übergibt und der Callback über ein benutzerdefiniertes URL-Schema zu Ihrer Seite zurückkehrt.
Wenn Sie auf der Seite einen OAuth-redirect_uri erstellen, kapseln Sie ihn immer:
import { connector } from "@dustid/dust-go-connect";
const origin = window.location.origin;const redirectUri = ( connector?.rewriteRedirect(new URL(`${origin}/auth/callback`)) ?? new URL(`${origin}/auth/callback`)).href;Außerhalb von DUST Go (und auf Hosts, auf denen keine Umschreibung erforderlich ist) hat dies keine Wirkung. Innerhalb von DUST Go wird das Protokoll der URL durch das benutzerdefinierte Schema der App ersetzt. Dadurch entsteht eine URI wie com.dustidentity.dustgo://your-host/auth/callback (das genaue Schema stammt aus dem DUST-Go-Build; dustgo ist die Ausweichlösung), die bei Ihrem Identitätsanbieter als zulässige Weiterleitungs-URI registriert sein muss.
Versionierung und Kompatibilität
Abschnitt betitelt „Versionierung und Kompatibilität“Die Bridge verwendet ein nummeriertes Protokoll. Die Seite gibt bei einem automatischen hello-Handshake zum Importzeitpunkt bekannt, welche Ereignisse sie versteht, und der Host übermittelt nur Ereignisse, die von der Seite angekündigt wurden. So können ein älterer Host und eine neuere Seite mit eingeschränktem Funktionsumfang zusammenarbeiten, statt vollständig auszufallen.
Lesen Sie die Nummer aus dem installierten Paket ab, nicht von dieser Seite: Das SDK exportiert sie.
import { CONNECT_PROTOCOL_VERSION } from "@dustid/dust-go-connect";| Protokoll | Hinzugefügt |
|---|---|
| 1 | Der implizite ältere Vertrag: scan / hide / show, ohne Handshake. |
| 2 | Der hello-Handshake und das Ereignis calibrationResult. |
| 3 | Die Host→Seite-Bekanntgabe capabilities, der Seite→Host-Befehl runCapture und das darauf antwortende Ereignis captureStatus. |
| 4 | CaptureRequirements.app (eine vom Host durchgesetzte App-Richtlinie für die Version) und CaptureCapabilities.enforcedRequirements, damit eine Seite einen Host, der eine Anforderung prüft, von einem Host unterscheiden kann, der sie ignorieren würde. |
| 5 | ScanPayload.exif – die fotografischen EXIF-Daten der Aufnahme samt Herkunft. Rein additiv. |
| 6 | Der Seite→Host-Befehl capturePhoto und das darauf antwortende Ereignis photo: ein normales Foto (beispielsweise ein Anhang zu einem Datensatz), bewusst kein Scan. |
Das SDK im Quellbaum dieser Dokumentation ist @dustid/dust-go-connect 0.2.0 und verwendet Protokoll 6. Welche Version derzeit in der öffentlichen npm-Registry angeboten wird, wird hier nicht angegeben – prüfen Sie CONNECT_PROTOCOL_VERSION und das Feld version des tatsächlich installierten Pakets und wenden Sie sich an DUST Identity, wenn Sie eine bestimmte Version benötigen.
Regeln, die unabhängig von jeder Versionsnummer gelten:
- Die Erkennung von Funktionen zur Laufzeit ist maßgeblich. Eine Protokollnummer gibt an, was das SDK der Seite ausdrücken kann. Sie sagt nichts über den Host auf der anderen Seite oder die angeschlossene Hardware aus. Fragen Sie die Funktionen mit
getCapabilities()ab und behandeln Sie eine fehlende Bekanntgabe als „nur einzelne Aufnahmen, keine Einstellungen möglich“. - Verzweigen Sie anhand von
event.typeund ignorieren Sie unbekannte Werte. Neue Ereignistypen werden hinzugefügt. Eine Seite, die bei einem unbekannten Typ einen Fehler auslöst, funktioniert nach einem Host-Upgrade nicht mehr, obwohl sie den neuen Typ gar nicht berücksichtigen müsste. - Ein manuelles Bedienelement in der Oberfläche eines Hosts ist keine Protokollfunktion, und ein erfolgreich ausgeführter Hardwarebefehl beweist nicht, dass der Wert zum Aufnahmezeitpunkt angewendet wurde.
- Ereignisse vom Typ
calibrationResultundackCalibrationResults()sind interne Verbindungsmechanismen für DUST-eigene Kalibrierungs-Workflows – Drittanbieterintegrationen können sie ignorieren.
Desktop-Steuerung für Dragon
Abschnitt betitelt „Desktop-Steuerung für Dragon“In diesem Abschnitt geht es um einen Dragon, der an einen Desktop-Computer angeschlossen ist und über die Begleit-App aus einem regulären Browser gesteuert wird. Dies ist nicht der Android-Pfad: Innerhalb von DUST Go unter Android steuert die App den angeschlossenen Dragon selbst, und seine Aufnahmen treffen über den oben beschriebenen regulären runCapture-Ablauf ein – createDragonClient() ist nicht beteiligt, und auf dem Mobiltelefon wird keine Begleit-App installiert. Siehe Unterstützte Geräte.
Ihre Website kann die Dragon-Vorschau und deren Fokussteuerung übernehmen. Die installierte Begleit-App verarbeitet die USB-Befehle im Hintergrund. Bei der ersten Verwendung genehmigen Benutzer Ihre Website in DUST Camera Controls und gewähren auf Aufforderung Zugriff auf die Browserkamera und lokale Geräte. Die Genehmigung wird für diese Website und diesen Browser gespeichert. Die Website muss HTTPS verwenden. Camera Controls kann bei geschlossenem Fenster in der Menüleiste aktiv bleiben; ein Verbindungs-Pop-up ist nicht erforderlich. Es wird keine von DUST gehostete Website benötigt.
Installieren Sie DUST Camera Controls im Ordner „Programme“ und öffnen Sie die App einmal. Die App zeigt an, ob der Dragon verbunden ist, und bleibt in der Menüleiste verfügbar. Der Start bei der Anmeldung ist standardmäßig aktiviert; Sie können ihn in der App deaktivieren.
Installationsprogramme für die einzelnen Plattformen finden Sie auf der Seite Downloads. Distributionen mit Aktualisierungsfunktion suchen automatisch nach Aktualisierungen und bieten in der Menüleiste Nach Updates suchen … an. Sie entscheiden, wann eine Aktualisierung installiert wird; speichern Sie Ihre Arbeit und schließen Sie den Scanvorgang ab, bevor Sie die App neu starten. Evaluierungs-Builds ohne Aktualisierungsfeed benötigen ein Ersatzinstallationsprogramm von DUST.
Öffnen Sie in DICE die Option Scan, wählen Sie DUST, aktivieren Sie unter dem Scanner die Dragon-Fokussteuerung und wählen Sie bei der ersten Verwendung Verbinden. Nach der Genehmigung bietet der Bildausschnitt Autofokus, Fokuseinstellungen und Scan über den ausgewählten Vorgang. Wenn Sie bei aktiviertem Modus zu Scan zurückkehren, stellt DICE die Verbindung automatisch wieder her, sofern Camera Controls ausgeführt wird und der Zugriff auf die Browserkamera weiterhin gewährt ist. Wenn Browserberechtigungen Ihre Aufmerksamkeit erfordern, wählen Sie Verbinden oder Kamera starten, um die Verbindung abzuschließen.
import { createDragonClient } from "@dustid/dust-go-connect";
const dragon = createDragonClient();const video = document.querySelector("video")!;
// First use: request native approval and browser permissions from a user action.connectButton.onclick = async () => { try { await dragon.connect(); await dragon.openVideo(video); const controls = await dragon.getControls(); const focus = controls.find((control) => control.name === "focus"); // Use focus.min / focus.max for your manual slider when focus is available. } catch (error) { showConnectionError(error); }};
// On a later visit, reuse approval without creating a native approval prompt.// If this rejects, present Connect Dragon; do not repeatedly request approval.// await dragon.connect({ interactive: false });// Reopen video only after browser camera permission has already been granted.
manualSlider.onchange = async () => { await dragon.setControl("focus", Number(manualSlider.value));};
autofocusButton.onclick = async () => { try { const result = await dragon.autofocus(video, { radius: Number(autofocusRangeSlider.value), onProgress: ({ position, sampled }) => showProgress(position, sampled), }); manualSlider.value = String(result.position); // "low-contrast" means autofocus retained the starting focus. showFocusResult(result.outcome); } catch (error) { showFocusError(error); }};cancelButton.onclick = () => dragon.cancelAutofocus();
captureButton.onclick = async () => { const payload = await dragon.capture(video); // Send the raw DUST JPEG to your server, which calls the Identifier API. await sendToYourServer(payload);};
const unsubscribe = dragon.onState(({ connected, controls }) => { updateDeviceUI(connected, controls);});// On page/component teardown: unsubscribe(); dragon.dispose();Nur jeweils eine Website-Sitzung kann den Dragon steuern. Der Benutzer kann den Zugriff über Website-Zugriff verwalten … in Camera Controls widerrufen. Wenn das native Fenster geschlossen wird, bleibt die Verbindung verfügbar; beim Beenden der App wird sie getrennt. Eine genehmigte Sitzung erhält Aktualisierungen zum Gerätestatus, wenn der Dragon getrennt oder erneut verbunden wird. Öffnen Sie nach einer erneuten Verbindung die Videoansicht erneut. Durch das Anschließen der Hardware erhalten Websites nicht stillschweigend Zugriff darauf.
Der Autofokus sucht ausgehend vom letzten Fokusbefehl innerhalb des kalibrierten Bereichs des Geräts. Der Bereichsregler gibt die Entfernung auf jeder Seite dieser Ausgangsposition an. Lassen Sie die Seite sichtbar und halten Sie das Prüfobjekt ruhig, wobei das gewünschte Detail in der Bildmitte liegen sollte. Ein strukturloses oder schlecht beleuchtetes Prüfobjekt bietet möglicherweise nicht genügend Kontrast, um einen Fokus auszuwählen. Prüfen Sie das resultierende Bild vor der Aufnahme.
Fokuswerte sind Befehle, keine gemessenen Objektivpositionen. Diese Methoden zur manuellen Steuerung garantieren weder bestimmte Einstellungen zum Zeitpunkt der Auslösung noch ermöglichen sie vorgeschriebene oder zusammengesetzte Aufnahmen. Der mobile Scanner und sein bestehender scanAsync()-Vertrag bleiben unabhängig davon verfügbar.
Verwandte Themen
Abschnitt betitelt „Verwandte Themen“- Kennungen – die API, mit der diese Integration Aufnahmen abgleicht.
- Fehler und Scanergebnisse – die Ergebnistabellen, anhand derer Ihre Scanoberfläche verzweigen muss.
- Unterstützte Geräte – die für DUST-Aufnahmen erforderliche Hardware.
- React Scanner – derselbe Ablauf ohne DUST Go unter Verwendung der Gerätekamera.
- Entwicklung mit KI-Agenten – eine Agenten-Skill zu dieser Integration für Coding-Agenten.