KI-GESTÜTZTE DOKUMENTATION
Was möchten Sie wissen?
Verbindung mit Tulip
Tulip ist eine No-Code-Plattform für MES und Connected-Frontline-Operations. Die OV80i-Kamera stellt die Verbindung zu Tulip über Node-RED her, das auf der Kamera läuft — derselbe Flow-Editor, den Sie auch für PLC-, MQTT- und andere I/O-Integrationen verwenden. Tulip kann:
- Eine Inspektion über eine Bedienertaste oder ein App-Ereignis auslösen.
- Die ROI-spezifischen und globalen Pass/Fail-Ergebnisse sowie Aufnahme-Metadaten empfangen.
- Das aktive Rezept umschalten, wenn der Bediener einen Teile-Barcode scannt oder ein anderes Produkt auswählt.
- Das Live-Bild anzeigen (mit Bounding-Box-Overlays) innerhalb einer Tulip-App, damit der Bediener sieht, was die KI gesehen hat.
Diese Anleitung führt Sie durchgängig durch jeden dieser vier Integrationspunkte.
Architektur
┌────────────────────────────┐ ┌──────────────────────────────┐
│ TULIP │ │ OV80i │
│ │ │ │
│ ┌──────────────────┐ │ HTTP/MQTT │ ┌──────────────────────┐ │
│ │ Operator Button │──────┼───trigger─────┼──▶│ Node-RED HTTP IN │──▶│
│ │ in Tulip App │ │ │ │ /trigger │ │
│ └──────────────────┘ │ │ └──────────────────────┘ │
│ │ │ │ │
│ ┌──────────────────┐ │ │ ▼ │
│ │ Tulip Connector │◀─────┼─── results ───┼─── All Block Outputs │
│ │ Function (HTTP) │ │ │ (image_url, pass/fail, │
│ └──────────────────┘ │ │ per-ROI classes) │
│ │ │ │ │
│ ┌──────────────────┐ │ │ ▼ │
│ │ Image Widget │◀─────┼── live-feed ──┼─── http://CAMERA_IP/live-feed│
│ │ (iframe URL) │ │ (HMI w/ ROI │ (shows bounding boxes │
│ └──────────────────┘ │ overlays) │ on the captured image) │
│ │ │ │
│ ┌──────────────────┐ │ │ ┌──────────────────────┐ │
│ │ Recipe Selector │──────┼─── HTTP ──────┼──▶│ /pipeline/activate │ │
│ │ (barcode / btn) │ │ │ │ {id: <recipe_id>} │ │
│ └──────────────────┘ │ │ └──────────────────────┘ │
└────────────────────────────┘ └──────────────────────────────┘
Die Brücke in der Mitte ist immer Node-RED, das im IO Block der Kamera läuft — dort bauen Sie alle vier Integrationen auf.

Das Hardcoding Ihrer Tulip-Connector-URL in den Node-RED-Flow bindet den Flow an eine einzelne Bereitstellung. Definieren Sie eine TULIP_ENDPOINT-Umgebungsvariable unter System Settings → Environment Variables und lesen Sie diese in Ihren HTTP-Request-Nodes mit ${TULIP_ENDPOINT} aus. So können Sie denselben Flow exportieren und auf jeder Kamera der Linie wieder importieren. Das vollständige Vorgehen finden Sie unter Environment Variables.
Wählen Sie Ihren Transport: HTTP oder MQTT
| Option | Verwendung | Hinweise |
|---|---|---|
| HTTP (empfohlen für die meisten Tulip-Bereitstellungen) | Tulip Connector Functions rufen HTTP-Endpunkte nativ auf. Der einfachste Weg, um über eine Tulip-Widget-Schaltfläche auszulösen. | Funktioniert ohne zusätzliche Infrastruktur. Tulip → Kamera und Kamera → Tulip verwenden beide einfaches POST. |
| MQTT | In Ihrer Anlage läuft bereits ein MQTT-Broker (Sparkplug B, IT/OT-Broker usw.) und der Tulip Edge Connector ist für die Kommunikation damit konfiguriert. | Geringere Latenz bei hohem Signalisierungsaufkommen. Erfordert einen Broker. |
| OPC UA | Sie betreiben eine Tulip Edge MC-Instanz mit dem OPC UA Connector. | Der OV80i wird mit vorinstallierten OPC UA Node-RED-Blöcken ausgeliefert. |
Der Rest dieses Leitfadens verwendet HTTP in den Beispielen – das ist die Standardoption für die meisten Tulip-Bereitstellungen. Die gleichen Muster gelten für MQTT (ersetzen Sie HTTP IN / HTTP Request Nodes durch MQTT in / MQTT out Nodes).
1. Kamera aus einer Tulip-App auslösen
Ein Tulip-Bediener drückt eine Schaltfläche → Die Connector Function von Tulip ruft einen HTTP-Endpunkt auf, an dem das Node-RED der Kamera lauscht → Node-RED löst eine Aufnahme aus.
Node-RED-Seite: Trigger empfangen
Bauen Sie im IO Block der Kamera (Advanced Mode → Node-RED) Folgendes auf:
[ HTTP IN: POST /trigger ]──▶[ Trigger node ]──▶[ HTTP Response: 200 ok ]
- Ziehen Sie einen http in-Node aus der Kategorie network hinein.
- Method:
POST - URL:
/trigger
- Method:
- Verbinden Sie ihn mit dem OV-spezifischen Trigger-Node (unter block logic in der OV-Palette). Der Trigger-Node startet die Aufnahme-Pipeline der Kamera.
- Fügen Sie einen http response-Node hinzu, damit der Tulip Connector sofort ein
200 OKzurückbekommt (lassen Sie Tulip nicht auf die KI-Inferenz warten – das Ergebnis fließt asynchron zurück, siehe Abschnitt 2). - Klicken Sie auf Deploy.
Der Endpunkt ist nun unter http://<CAMERA_IP>/node-red/trigger erreichbar (der HTTP-Root von Node-RED ist unter /node-red/ eingebunden).
Tulip-Seite: Trigger über eine Schaltfläche aufrufen
In Ihrem Tulip-Konto:
- Gehen Sie zu Apps → Connectors und erstellen Sie einen neuen HTTP Connector, falls noch keiner vorhanden ist.
- Setzen Sie den Host auf die IP-Adresse Ihrer Kamera und den Port auf
80(oder443, falls Sie HTTPS aktiviert haben). - Erstellen Sie eine neue Connector Function namens
Trigger Camera:- Method:
POST - Endpoint:
/node-red/trigger - Für einen einfachen Trigger werden keine Body- oder Eingabeparameter benötigt – die Kamera verwendet das aktive Rezept.
- Method:
- Speichern und testen Sie die Connector Function. Sie sollten eine 200-Antwort sehen und die Kamera sollte ein Bild aufnehmen.
- Fügen Sie in Ihrer Tulip-App ein Button-Widget hinzu. Wählen Sie in dessen Aktion Run Connector Function → Trigger Camera.
Wenn der Bediener die Schaltfläche antippt, löst die Kamera aus.
Wenn Sie mit jedem Trigger eine Seriennummer oder Teile-ID senden möchten, ändern Sie die Tulip Connector Function so, dass sie Eingaben akzeptiert (z. B. serial_number), und fügen Sie diese in den Request-Body ein. Auf der Kameraseite empfängt Ihr HTTP IN-Node diese als msg.payload, und Sie können sie in einer Flow-Variable ablegen, damit der Flow zum Senden der Ergebnisse (Abschnitt 2) sie an den Prüfbericht anhängen kann.
2. Ergebnisse zurück an Tulip senden
Nach der Kameraaufnahme wird der All Block Outputs-Node mit dem vollständigen Inspektionsergebnis ausgelöst. Das Muster:
[ All Block Outputs ]──▶[ Function: format for Tulip ]──▶[ HTTP Request: POST to Tulip ]
Flow aufbauen
- Verbinden Sie einen function-Node nachgeschaltet zum All Block Outputs-Node.
- Die Funktion konsolidiert die ROI-Ergebnisse zu einem einzigen globalen Pass/Fail und reduziert die Nutzlast auf das, was Tulip tatsächlich benötigt:
// Read the camera's full inspection payload
const p = msg.payload || {};
// Consolidate per-ROI classifier predictions into a global pass/fail
const preds = p.classification?.predictions || [];
const allPass = preds.length > 0 && preds.every(r => r.predicted_class === 'pass');
// Optional: count segmentation defects (e.g., for thresholded fail)
const defectPixels = (p.segmentation?.blobs || [])
.reduce((s, b) => s + (b.pixel_count || 0), 0);
// Build a flat object for Tulip (Tulip Connector Functions like flat fields)
msg.payload = {
result: allPass ? "pass" : "fail",
inspection_id: p.inspection_id || null,
timestamp: new Date().toISOString(),
image_url: p.image_url || null, // see Section 4 for displaying this in Tulip
defect_pixel_count: defectPixels,
per_roi: preds.map(r => ({
roi: r.roi_name,
class: r.predicted_class,
confidence: r.confidence,
})),
// If you stashed a serial number from the trigger (see Section 1), add it:
// serial_number: flow.get('lastSerial') || null,
};
// Set headers for the outbound HTTP request
msg.headers = { 'Content-Type': 'application/json' };
msg.method = 'POST';
return msg;
- Verbinden Sie diese mit einem http request-Node:
- Method:
POST(oder verwenden Siemsg.methodaus der obigen Funktion) - URL:
${TULIP_ENDPOINT}(aus der Umgebungsvariable lesen) oder hartcodierte Tulip Connector URL - Return:
a UTF-8 string(oder JSON, falls Ihr Tulip-Endpunkt JSON zurückgibt)
- Method:
- Verbinden Sie einen debug-Node nach dem HTTP-Request, um die Antwort von Tulip während des Tests prüfen zu können.
- Klicken Sie auf Deploy.
Tulip-Seite: Ergebnisse empfangen
In Tulip:
- Erstellen Sie eine HTTP Connector Function in Empfangsrichtung – einen Webhook-Endpunkt – oder verwenden Sie die Tables API von Tulip, um Ergebnisse in eine Tulip Table zu schreiben.
- Konfigurieren Sie die Logik Ihrer Tulip-App so, dass sie auf die eingehende Nutzlast reagiert (z. B. einen Statusindikator aktualisieren, in eine Table protokollieren, einen Zähler erhöhen).
Speziell für Tulip Tables gilt das Muster: POST an https://<your-tulip-instance>.tulip.co/api/v3/tables/<table_id>/records mit den Feldern result, serial_number, timestamp. Verwenden Sie ein Tulip-API-Token im Authorization-Header – speichern Sie das Token als Credential am HTTP Connector, nicht im Node-RED-Flow.
3. Rezepte von Tulip aus wechseln
Bediener müssen häufig zu einem anderen Rezept wechseln, wenn sich der Produkttyp ändert (Barcode-Scan, Dropdown, Dispatch). Die Kamera stellt einen integrierten HTTP-Endpunkt bereit, der ein Rezept anhand seiner ID aktiviert.
Rezept-ID finden
- Öffnen Sie das Rezept im Recipe Editor.
- Schauen Sie in die Adressleiste Ihres Browsers:
/recipes/15/editor→ die ID lautet15.
Aufbau des Recipe-Switch-Flows
[ HTTP IN: POST /change-recipe ]──▶[ Function: format request ]──▶[ HTTP Request: POST localhost:5001/pipeline/activate ]──▶[ HTTP Response ]
- HTTP IN-Node:
POST /change-recipe. Tulip ruft diesen mit einem Body wie{ "id": 15 }auf. - Function-Node — die Recipe-ID an die interne API der Kamera weiterleiten:
const recipeId = msg.payload?.id;
if (!recipeId) {
msg.statusCode = 400;
msg.payload = { error: "missing 'id' field" };
return msg;
}
msg.headers = { 'Content-Type': 'application/json' };
msg.payload = JSON.stringify({ id: recipeId });
msg.method = 'POST';
return msg;
- HTTP Request-Node:
- Method:
POST - URL:
localhost:5001/pipeline/activate - Return:
a parsed JSON object
- Method:
- HTTP Response-Node, damit die Connector Function von Tulip einen Statuscode zurückerhält.
Innerhalb von Node-RED auf der Kamera lautet der Endpunkt für den Recipe-Switch localhost:5001/pipeline/activate — das ist die kamera-interne Admin-API. Sie leiten die Anfrage von Tulip über Node-RED an die lokale API weiter. Versuchen Sie nicht, Port 5001 direkt von außerhalb der Kamera anzusprechen; er ist nur für kamera-interne Flows freigegeben.
Für ältere Firmware (vor v18.92) lautete die URL http://[CAMERA_IP]/edge/pipeline/activate. Falls Sie eine ältere Firmware verwenden und localhost:5001 nicht antwortet, greifen Sie auf die v17/v18-URL zurück. Aktualisieren Sie die Kamera-Firmware auf v18.92+, um den modernen Pfad zu nutzen.
Tulip-Seite: Recipe-Switch aufrufen
- Fügen Sie eine Connector Function
Switch Recipeauf demselben HTTP Connector hinzu. - Method:
POST, Endpoint:/node-red/change-recipe. - Fügen Sie einen Eingabeparameter
recipe_id(Number) hinzu. - Setzen Sie den Request-Body auf
{ "id": $recipe_id }. - Verknüpfen Sie in Ihrer Tulip-App einen Barcode Scanner-Trigger oder ein Dropdown-Widget, um diese Funktion mit der passenden Recipe-ID aufzurufen.
Operator scannt einen Barcode → Tulip ermittelt die Recipe-ID für dieses Teil → Connector Function ruft die Kamera auf → Kamera wechselt das Recipe in unter einer Sekunde.
4. Live-Bild (mit Bounding Boxes) in Tulip anzeigen
Das Image Widget von Tulip kann jede URL anzeigen, die ein Bild zurückgibt. Die OV80i verfügt über eine integrierte HMI-URL, die die letzte Aufnahme zurückgibt — mit darüber gezeichneten Bounding-Box- und ROI-Overlays:
http://<CAMERA_IP>/live-feed

So binden Sie es in eine Tulip-App ein:
- Fügen Sie ein Image Widget zu Ihrem Tulip-Step hinzu.
- Setzen Sie die Image URL auf eine Tulip-Variable, die Sie aus dem Inspektionsergebnis befüllen, oder auf eine statische URL, wenn jede Kamera ihren eigenen Dashboard-Step hat.
- Das einfachste Muster:
http://<CAMERA_IP>/live-feedfest hinterlegen und bei jeder Aufnahme automatisch aktualisieren lassen (das Image Widget von Tulip aktualisiert sich, wenn sich seine URL oder ein Query-Parameter ändert — hängen Sie?t={{timestamp}}an, um eine Aktualisierung zu erzwingen).
Wenn Sie die Roh-Aufnahme (ohne Bounding Boxes) wünschen, verwenden Sie stattdessen image_url aus dem msg.payload — das ist eine URL pro Aufnahme, die auf das gespeicherte Bild in der Bibliothek der Kamera verweist.
Wenn Sie mehrere Kameras an derselben Linie haben, jede mit eigener IP, speichern Sie die Kamera-URL in einer Tulip-Variable pro App-Step und lassen Sie den Operator auswählen, welche Station angezeigt werden soll. Das Image Widget wechselt sofort, sobald sich die Variable ändert.
Referenz-Flow (importierbares Node-RED JSON)
Der nachfolgende Flow kombiniert alle vier Integrationen: Trigger HTTP IN, ergebnissendender HTTP Request, Rezept-Umschalter und einen Debug-Node. Kopieren Sie das JSON, öffnen Sie Node-RED → Hamburger-Menü → Import, und fügen Sie es ein.
[
{
"id": "tulip_trigger_in",
"type": "http in",
"name": "POST /trigger",
"url": "/trigger",
"method": "post",
"x": 160, "y": 100, "wires": [["tulip_trigger_fire"]]
},
{
"id": "tulip_trigger_fire",
"type": "trigger-camera",
"name": "Trigger camera",
"x": 380, "y": 100, "wires": [["tulip_trigger_resp"]]
},
{
"id": "tulip_trigger_resp",
"type": "http response",
"name": "200 ok",
"statusCode": "200",
"x": 580, "y": 100, "wires": []
},
{
"id": "tulip_results_format",
"type": "function",
"name": "Format for Tulip",
"func": "const p = msg.payload || {};\nconst preds = p.classification?.predictions || [];\nconst allPass = preds.length > 0 && preds.every(r => r.predicted_class === 'pass');\nmsg.payload = {\n result: allPass ? 'pass' : 'fail',\n timestamp: new Date().toISOString(),\n image_url: p.image_url || null,\n per_roi: preds.map(r => ({roi: r.roi_name, class: r.predicted_class, confidence: r.confidence}))\n};\nmsg.headers = {'Content-Type':'application/json'};\nmsg.method = 'POST';\nreturn msg;",
"x": 380, "y": 200, "wires": [["tulip_results_send"]]
},
{
"id": "tulip_results_send",
"type": "http request",
"name": "POST to Tulip",
"method": "POST",
"url": "${TULIP_ENDPOINT}",
"ret": "obj",
"x": 600, "y": 200, "wires": [["tulip_results_debug"]]
},
{
"id": "tulip_results_debug",
"type": "debug",
"name": "Tulip response",
"x": 800, "y": 200, "wires": []
},
{
"id": "tulip_recipe_in",
"type": "http in",
"name": "POST /change-recipe",
"url": "/change-recipe",
"method": "post",
"x": 160, "y": 300, "wires": [["tulip_recipe_format"]]
},
{
"id": "tulip_recipe_format",
"type": "function",
"name": "Format request",
"func": "const id = msg.payload?.id;\nif (!id) { msg.statusCode = 400; msg.payload = {error:'missing id'}; return msg; }\nmsg.headers = {'Content-Type':'application/json'};\nmsg.payload = JSON.stringify({id});\nmsg.method = 'POST';\nreturn msg;",
"x": 380, "y": 300, "wires": [["tulip_recipe_call"]]
},
{
"id": "tulip_recipe_call",
"type": "http request",
"name": "/pipeline/activate",
"method": "POST",
"url": "localhost:5001/pipeline/activate",
"ret": "obj",
"x": 600, "y": 300, "wires": [["tulip_recipe_resp"]]
},
{
"id": "tulip_recipe_resp",
"type": "http response",
"name": "to Tulip",
"x": 800, "y": 300, "wires": []
}
]
Sie müssen weiterhin den All Block Outputs-Node mit tulip_results_format verbinden (er ist im obigen JSON nicht enthalten, da dieser Node OV-spezifisch ist und bereits in jedem Flow vorhanden ist).
Fehlerbehebung
| Symptom | Ursache / Lösung |
|---|---|
Tulip Connector liefert connection refused | Kamera und Tulip Edge Device befinden sich nicht im selben Netzwerk, oder die Kamera-Firewall blockiert Port 80. Beide müssen gegenseitig erreichbar sein; pingen Sie die Kamera zuerst vom Tulip Edge Device aus an. |
| Trigger HTTP IN wird nie ausgelöst | Nach dem Hinzufügen des Nodes wurde vergessen, in Node-RED auf Deploy zu klicken, oder die URL enthält einen Tippfehler (muss mit / beginnen, nicht mit /node-red/). |
| Rezept-Umschaltung liefert 404 | Falscher Endpunkt für Ihre Firmware. Vor v18.92 wird /edge/pipeline/activate von der Kamera-IP verwendet; ab v18.92 wird localhost:5001/pipeline/activate aus Node-RED heraus verwendet. |
/live-feed zeigt in Tulip ein schwarzes Bild | Die Kamera hat noch keine Aufnahme gemacht, oder das Bild wurde nicht aktualisiert. Hängen Sie ?t={{Date.now()}} an, um das Image Widget zum erneuten Abrufen zu zwingen. |
| Tulip erhält ein 200, aber keinen Ergebnis-Body | Die Kamera löst den Trigger aus und gibt sofort 200 zurück — das Ergebnis wird asynchron über den ergebnissendenden Flow zurückgeliefert (Abschnitt 2). Stellen Sie sicher, dass dieser Flow verdrahtet und deployed ist. |
| Per-ROI-Ergebnisse sind verrauscht / Tulip benötigt nur pass/fail | Genau aus diesem Grund konsolidiert der Function-Node alles vor dem Senden in ein einzelnes `result: "pass" |
Nächste Schritte
- Umgebungsvariablen —
TULIP_ENDPOINTund andere bereitstellungsspezifische Konfigurationen aus dem Flow heraushalten. - Verbindung zur PLC (EtherNet/IP & PROFINET) — für die parallele PLC-Integration neben Tulip.
- Overview Node-RED Custom Blocks — Referenz für die OV-spezifischen Palette-Nodes (Trigger, All Block Outputs usw.).
- Ausgänge einrichten (Schritt 5) — wo Node-RED in den übergeordneten Pass/Fail-Flow passt.