Zum Hauptinhalt springen

Flow

Inhaltsverzeichnis

Erste Schritte

Bildschirmweise Anleitung

Nachrichten-/Node-Referenz

Beispiele·Muster

Betrieb

Produktionsbetrieb

Fehlerbehebung

Sonstiges


Überblick

Flow ist ein Automatisierungsmenü, mit dem Sie die Datenanbindung an externe Systeme (MES/ERP/SCADA usw.) sowie die automatische Erstellung/Aktualisierung von Domänenobjekten (Tag, Anlage, Arbeitsauftrag, Mitarbeiter usw.) als visuellen Graphen definieren. Ohne Programmierkenntnisse können Operatoren Automatisierungsszenarien selbst entwerfen, bereitstellen und betreiben.

Über 100 Node-Typen werden per Drag & Drop auf der Canvas platziert und über Wires verbunden, um Datenverarbeitungspipelines aufzubauen.

Pfad: Linkes Menü > Automation > Flow


Lernpfad — Empfohlene Einstiegsreihenfolge nach Rolle

Dieses Handbuch ist ein umfassender Leitfaden mit über 4.000 Zeilen. Es ist effizienter, mit dem Abschnitt zu beginnen, der zu Ihrer Rolle und Ihrem Ziel passt.

👶 Einsteiger (ersten Flow in 1 Stunde erstellen)

  1. Kernkonzepte — 5 Minuten
  2. Erste Schritte — 5 Minuten
  3. End-to-End-Tutorial — 30 Minuten (Schritte 1–10 durcharbeiten)
  4. Bildschirmaufbau + Bearbeitungsansicht — 10 Minuten
  5. Beispiel-Flows 1·2·3 nachbauen — 10 Minuten

→ Erster Flow bereitgestellt. Danach benötigte Nodes im Node-Katalog suchen.

🧑‍🏭 Vor-Ort-Operator (Automatisierungsszenarien erstellen)

  1. Payload-Beispiele nach Trigger — reale Datenstrukturen verstehen
  2. Detaillierte Node-Optionsreferenz — häufig genutzte Node-Optionen kennenlernen
  3. Cookbook für Datentransformation — gängige Transformationsmuster kopieren
  4. Katalog der Graph-Muster — Verdrahtungsmuster auswählen
  5. Beispiel-Flows (17 Arten) — fertige Beispiele je Szenario ansehen

🛠 Systemadministrator (Betrieb·Tuning·Störungsbehebung)

  1. Flow-Metriken und Alarme — welche Kennzahlen zu beachten sind
  2. Was man in der Ausführungshistorie sieht — Diagnoseprotokolle interpretieren
  3. Cluster·HA-Verhalten — Multi-Node-Umgebung verstehen
  4. End-to-End-Trace — problematische Nachrichten verfolgen
  5. Performance-Grenzen und Tuning + Notfallmaßnahmen

🔌 Entwickler·Integrationsingenieur (Anbindung externer Systeme)

  1. Cookbook für externe Systemintegration — Slack/Teams/Jira/SAP-Beispiele
  2. Flow-REST-API — Flows programmgesteuert steuern
  3. Webhook-Trigger — Flow von außen auslösen
  4. OPC/PLC-Industrieintegrationsmuster — industrielle Vor-Ort-Szenarien
  5. JS-Laufzeitumgebungsspezifikation + Sammlung wiederverwendbarer Skripte

🔐 Sicherheitsverantwortlicher (Audit·Authentifizierung)

  1. Sicherheit·Umgang mit sensiblen Daten — Aufbewahrung von Zugangsdaten
  2. Automatische Erneuerung externer Auth-Token — Betrieb von OAuth2-Token
  3. Berechtigungen — rollenspezifisch mögliche Aktionen
  4. Audit·Verlaufsverfolgung — Aufbewahrung von Änderungs-/Ausführungshistorie

📚 Schnellreferenz (bereits vertraute Nutzer)

Gesuchte InformationAbschnitt
Node-ID und EinzeilenbeschreibungNode-Katalog
Standardwerte der Node-OptionenDetaillierte Node-Optionsreferenz
JSON-Beispiel der NachrichtPayload-Beispiele nach Trigger
Direkt einsetzbares SkriptSammlung wiederverwendbarer Skripte · Cookbook für Datentransformation
API-Aufruf curlFlow-REST-API
Interpretation der AusführungshistorieWas man in der Ausführungshistorie sieht
Leitfaden zur FehlerbehebungSchrittweiser Debugging-Leitfaden · Häufige Probleme
Schnellübersicht der OptionenNode-Schnellkonfigurationsreferenz

Alle Abschnittslinks sind Anker innerhalb desselben Dokuments. Auch die Stichwortsuche mit Ctrl+F ist effektiv.


Kernkonzepte

BegriffBeschreibung
FlowEin Automatisierungs-Workflow, bestehend aus einer Menge von Nodes und Wires (Beziehungen). Es handelt sich um einen gerichteten Graphen mit Einstiegspunkt, dessen Aktivierung über den Bereitstellen/Aufheben-Schalter gesteuert wird
NodeEine Einheit, die eine Nachricht empfängt, verarbeitet und an den nächsten Node weiterleitet. Unterteilt in 7 Kategorien (Trigger·Filter·Transformation·Aktion·Externe Anbindung·Ablaufsteuerung·Edge)
Beziehung (Relation)Das Label eines Wires von einem Node-Ausgang zum nächsten Node. Der Node bestimmt selbst Labels wie SUCCESS/FAILURE/TRUE/FALSE/MATCH/NO_MATCH/DEFAULT/THROTTLED/EXHAUSTED zur Verzweigung. Alle Labels sind auf Großbuchstaben standardisiert
Nachricht (Message)Die Payload, die innerhalb des Flows fließt. Enthält type (Klassifizierung), originator (Subjekt-Entität), data (Inhalt), metadata (Kontext)
TriggerDer Node, der den Startpunkt eines Flows bildet. Es gibt drei Arten: Domänenereignis (Tag-Point, Alarm, Anlagenereignis usw.), externer Eintritt (Webhook, MQTT, externe DB) und zeitbasiert (Zeitplan)

Erste Schritte

Mit den folgenden 4 Schritten machen Sie sich am schnellsten mit Flow vertraut.

  1. Erstellen Sie in der Listenansicht über die Schaltfläche 새 플로우 einen leeren Flow (nur Name und Beschreibung eingeben).
  2. Ziehen Sie in der Bearbeitungsansicht aus der linken Palette nacheinander einen Trigger-Node (z. B. flow_on_tag_alarm) → Filter → Aktion (z. B. flow_send_email), platzieren Sie diese und verbinden Sie die Nodes mit Wires.
  3. Klicken Sie auf jeden Node, geben Sie im rechten Inspector die Optionen ein und überprüfen Sie das Verhalten anschließend mit SpeichernTestlauf oben rechts.
  4. Aktivieren Sie oben den Bereitstellen-Schalter — der Flow wird bei jedem eintreffenden Triggerereignis automatisch ausgeführt, und Sie können die Ergebnisse im Live-Debug-Panel und in der Ausführungshistorie einsehen.

Für Verdrahtungsmuster von Automatisierungsszenarien lesen Sie bitte Beispiel-Flows und Anwendungsbeispiele in diesem Dokument. Ein schrittweises Tutorial zum vollständigen Erstellen eines Flows von Anfang bis Ende finden Sie im End-to-End-Tutorial.


End-to-End-Tutorial

Ein schrittweises Tutorial, in dem ein tatsächlich in der Produktion einsetzbarer Automatisierungs-Flow von Anfang bis Ende erstellt wird. Szenario: Wenn die Temperatur eines Motors 80 °C überschreitet, wird automatisch ein dringender Instandhaltungsauftrag erstellt und der zuständige Mitarbeiter per E-Mail benachrichtigt.

Schritt 1 — Neuen Flow erstellen

  1. Im linken Menü Automation > Flow klicken → Listenansicht öffnen
  2. Oben rechts auf Neuer Flow klicken
  3. Folgende Angaben eingeben und mit Bestätigen abschließen
FeldEingabewert
Name모터 과열 자동 정비 발행
Beschreibung[자동화] 모터 자산의 온도 80°C 초과 시 긴급 정비 작업지시 + 이메일. 담당: ops@example.com

Nach Erstellung des Flows öffnet sich automatisch die Bearbeitungsansicht mit einer leeren Canvas.

Schritt 2 — Trigger-Node platzieren

Motortemperaturdaten werden aus dem Telemetrie-Ereignis der Anlage empfangen.

  1. Kategorie Trigger in der linken Palette aufklappen
  2. Node flow_on_tag_point auf die Canvas ziehen
  3. Node anklicken → im rechten Inspector folgende Optionen eingeben
OptionWert
Anzeigename태그 포인트 인입
tag_id_patternMOTOR-*.TEMP

Wenn Sie mit tag_id_pattern nur das Motortemperatur-Tag durchlassen, verringert sich das nachgelagerte Verarbeitungsvolumen erheblich. Andere Tags werden als SKIPPED behandelt und nicht mitgezählt.

Schritt 3 — Schwellenwertfilter

Fügen Sie einen Skriptfilter hinzu, der nur Nachrichten mit über 80 °C durchlässt.

  1. flow_script_filter aus der Kategorie Filter ziehen
  2. Wire vom Ausgangsport des Trigger-Nodes zum Eingangsport des neuen Filter-Nodes verbinden
  3. Im Inspector folgendes eingeben
OptionWert
Anzeigename임계값 필터 (80°C 초과)
languageJS
scriptdata.value > 80

Schritt 4 — Domänenwechsel (Tag → Anlage)

Da Alarme·Arbeitsaufträge natürlicherweise auf Anlagenebene ausgelöst werden, wird der originator der Nachricht vom Tag auf die übergeordnete Anlage transformiert.

  1. flow_change_originator aus der Kategorie Transformation ziehen
  2. Vom TRUE-Ausgang des Filter-Nodes einen Wire verbinden
  3. Inspector:
OptionWert
AnzeigenameTag → Asset 변경
entity_typeAsset
id_fieldmetadata.asset_id

metadata.asset_id wird beim Eintreffen eines Tag-Points automatisch befüllt. Falls in der Nachricht nicht vorhanden, können Sie den Präfixteil der Tag-ID (z. B. MOTOR-001.TEMPMOTOR-001) auch per Skript extrahieren.

Schritt 5 — Arbeitsauftrag erstellen

Ein dringender Instandhaltungsauftrag wird automatisch erstellt.

  1. flow_create_work_order aus der Kategorie Aktion (Action) — Domänen-CRUD ziehen
  2. Vom SUCCESS-Ausgang des Transformations-Nodes einen Wire verbinden
  3. Inspector:
OptionWert
Anzeigename긴급 정비 작업지시 생성
asset_id_fieldoriginator.id
title_field(statischer Wert) 긴급 점검 — 모터 과열
master_id_field(optional) data.master_id (wird sonst automatisch erzeugt)
description_field(statischer Wert) 자동 발행: 임계 온도 초과로 긴급 점검 필요
default_priorityHIGH

Schritt 6 — E-Mail-Benachrichtigung (Erfolgszweig)

Bei erfolgreicher Erstellung des Arbeitsauftrags wird der zuständige Mitarbeiter benachrichtigt.

  1. flow_send_email aus der Kategorie Externe Anbindung (External) ziehen
  2. Vom SUCCESS-Ausgang des Arbeitsauftrags-Nodes einen Wire verbinden
  3. Inspector:
OptionWert
Anzeigename정비 담당자 이메일
toops@example.com
subject_template[과열 정비] ${originator.id} 작업지시 ${data.work_order_id}
body_template자산 ${originator.id} 의 온도가 ${data.value}°C 로 상승하여 자동으로 긴급 정비가 발행되었습니다.\n작업지시 ID: ${data.work_order_id}

Schritt 7 — Behandlung des Fehlerzweigs

Die Erstellung des Arbeitsauftrags selbst kann fehlschlagen (z. B. Anlage nicht mehr vorhanden oder Berechtigungsproblem). Der Operator wird sofort per Push-Benachrichtigung informiert.

  1. flow_send_push aus Externe Anbindung ziehen
  2. Vom FAILURE-Ausgang des Arbeitsauftrags-Nodes einen Wire verbinden
  3. Inspector:
OptionWert
title자동화 실패
body_template${originator.id} 정비 자동 발행 실패: ${data.error}

Schritt 8 — Speichern und Testlauf

  1. Oben rechts auf Speichern klicken. Ein automatischer Snapshot wird abgelegt, sodass später ein Rollback möglich ist.
  2. Oben rechts auf Testlauf klicken → folgendes im JSON-Editor eingeben → Veröffentlichen
{
"type": "POST_TELEMETRY",
"originator": { "entity_type": "Tag", "id": "MOTOR-001.TEMP" },
"data": { "value": 92.5 },
"metadata": { "ts": 1746247200000, "tag_id": "MOTOR-001.TEMP", "asset_id": "MOTOR-001" }
}

Unten im Dialog wird ✓ JSON OK (type=POST_TELEMETRY) angezeigt → auf Veröffentlichen klicken.

  1. Im Live-Debug-Panel Folgendes prüfen:
    • Trigger-Node leuchtet grün → Nachricht durchgelaufen
    • Filter-Node: da 92.5 > 80, Verzweigung TRUE
    • Transformations-Node: originator geändert zu Asset/MOTOR-001
    • Arbeitsauftrags-Node: SUCCESS, data.work_order_id automatisch vergeben
    • E-Mail-Node: Versand versucht

Schritt 9 — Validierung und Bereitstellung

  1. Im Arbeitsauftragsbildschirm prüfen, ob der neue Arbeitsauftrag registriert wurde
  2. Prüfen, ob die E-Mail ordnungsgemäß angekommen ist (Postfach der Testumgebung)
  3. Noch einmal mit einer Nachricht unter 80 °C testen (sollte am Filter blockiert werden):
{ "type": "POST_TELEMETRY", "originator": {"entity_type":"Tag","id":"MOTOR-001.TEMP"},
"data": {"value": 70}, "metadata": {"asset_id":"MOTOR-001"} }

Die Verzweigung des Filter-Nodes ist FALSE, nachfolgende Nodes grau — normal.

  1. Nach Validierung aller Zweige die Statistiken mit Alle Zähler zurücksetzen neu starten
  2. Oben den Schalter Bereitstellen aktivieren (ON)

Ab jetzt wird in der tatsächlichen Produktionsumgebung sofort bei Überschreiten von 80 °C an einem Motor automatisch ein Instandhaltungsauftrag erstellt und der zuständige Mitarbeiter per E-Mail informiert.

Schritt 10 — Betriebsüberwachung

Es empfiehlt sich, unmittelbar nach der Bereitstellung 5–10 Minuten lang Folgendes zu prüfen.

OrtPrüfpunkt
ListenansichtOb die Anzahl der Ausführungen der betreffenden Flow-Zeile im normalen Bereich steigt (kein Ausufern)
Live-Debug-PanelOb keine Node-Fehler auftreten
AusführungshistorieBei fehlgeschlagenen Nachrichten die Ursache über NODE_ERROR prüfen
Empfangene E-MailsOb keine unbeabsichtigt häufigen Benachrichtigungen versendet werden

Nächste Schritte

Um diesen Flow weiterzuentwickeln, können Sie:

  • Retry-Verdrahtung hinzufügen — Backoff-Wiederholung bei fehlgeschlagenem E-Mail-/Push-Versand (siehe Beispiel 8)
  • Automatische Bandanpassung — Schwellenwerte automatisch anhand des 6-Stunden-Durchschnitts ± 3σ korrigieren (Beispiel 6)
  • Ausfallzeit-Kumulierung — Überhitzungshistorie in Anlagen-Attributen kumulieren (Beispiel 14)
  • Qualitätslinien-Isolation — Linie bei wiederholter Überhitzung automatisch stoppen (Beispiel 15)

Bildschirmaufbau

Flow besteht aus den folgenden drei Bildschirmen.

BildschirmZweck
ListeÜbersicht·Suche·Massenbereitstellung·Import der registrierten Flows
BearbeitungNodes über visuelle Canvas platzieren·verbinden·konfigurieren
AusführungshistorieNode-bezogene Ausführungsprotokolle·Zeitachsenabfrage

Listenansicht

Besteht aus dem oberen Such-/Erstellungsbereich und der Flow-Übersichtstabelle.

Werkzeuge oben

ElementBeschreibung
Statusfilter전체 / 배포 / 해제
Name·Beschreibung durchsuchenFlows nach Schlüsselwort filtern
Neuer FlowErstellt einen leeren Flow (Name·Beschreibung eingeben)
ImportierenStellt einen Flow durch Hochladen einer per Export erhaltenen JSON-Datei wieder her
Alle neu bereitstellenLädt alle aktivierten Flows auf einmal neu
AktualisierenLädt die Liste erneut

Übersichtstabelle

Die Listentabelle ist auf 25 Zeilen pro Seite paginiert, und jede Zeile zeigt zusätzlich eine Verlaufs-Sparkline sowie ein Fehlerraten-Donut-Diagramm. Der Diagrammstatus bleibt auch beim Seitenwechsel erhalten.

SpalteBeschreibung
AuswahlCheckbox für Massenbereitstellung·-aufhebung
StatusBadge 배포 / 해제
Flow-IDSequenz-ID im Format FLOW_NNNNN
Name | BeschreibungVom Operator festgelegte Metainformationen
NodesAnzahl enthaltener Nodes
TriggerAnzahl der Trigger-Nodes
AusführungenKumulierte Anzahl verarbeiteter Nachrichten
VerarbeitungszeitDurchschnittliche/letzte Verarbeitungszeit der Nodes
FehlerKumulierte Fehleranzahl
Letzte ÄnderungZeitpunkt der letzten Speicherung des Graphen
AktionSchaltflächen 편집 / 삭제

Massenbereitstellung·-aufhebung

Die ausgewählten Flows werden gemeinsam bereitgestellt (aktiviert) oder aufgehoben (deaktiviert). Nur bereitgestellte Flows empfangen Triggerereignisse.

Alle neu bereitstellen

Die Schaltfläche Alle neu bereitstellen oben lädt alle aktivierten Flows neu. Verwenden Sie sie in folgenden Situationen:

  • Unmittelbar nach einem Massenimport von Graphen aus externen Quellen
  • Wenn Sie Trigger mit eigenem Scheduler (Zeitplan·externes MQTT-Abonnement·externes DB-Polling) neu registrieren möchten
  • Bei Verdacht auf Probleme mit der Cache-Konsistenz im laufenden Betrieb

Bearbeitungsansicht (visuelle Canvas)

Ziehen Sie Nodes aus der linken Palette der Canvas, um sie zu platzieren, und verbinden Sie sie durch Klicken & Ziehen des Ausgangsports mit dem nächsten Node.

Werkzeugleiste oben

SchaltflächeAktion
Name·BeschreibungBearbeitet die Metainformationen des Flows
Bereitstellen/AufhebenAktiviert/deaktiviert den aktuellen Flow sofort
ExportierenLädt den gesamten Graphen als JSON-Datei herunter
TestlaufFührt eine einmalige Ausführung mit einer beliebigen injizierten JSON-Nachricht durch und zeigt das Ergebnis (siehe Testlauf-Nutzung unten)
SpeichernSpeichert den aktuellen Graphen auf dem Server. Beim Speichern wird ein automatischer Snapshot abgelegt, sodass später ein Rollback möglich ist

Beim Versuch, einen Graphen ohne Trigger zu speichern, erscheint die Warnung „Wird nur durch manuellen Testlauf gestartet“. Sie können den Trigger absichtlich weglassen und den Flow ausschließlich für manuelle Ausführung nutzen.

Testlauf-Nutzung

Beim Klicken auf die Schaltfläche 테스트 실행 öffnet sich ein JSON-Bearbeitungsdialog. Der Operator kann direkt eine Nachricht verfassen und einmalig veröffentlichen, um das Graphenverhalten zu überprüfen, ohne auf ein Triggerereignis zu warten.

ElementBeschreibung
EditorJSON-Editor mit Zeilennummern und Syntaxhervorhebung. Der Nachrichteninhalt kann frei verfasst werden
Validierungsanzeigetype bei vorhandenen Pflichtfeldern, ✓ JSON OK (type=X); bei fehlenden Feldern ⚠ type 필수
VeröffentlichenMit der Schaltfläche 발행 wird die Nachricht in den Dispatcher injiziert. Ergebnisse im Live-Debug-Panel und in der Ausführungshistorie einsehbar

Beispiel-Standardvorlage

{
"type": "POST_TELEMETRY",
"originator": { "entity_type": "Asset", "id": "MOTOR-001" },
"data": { "speed": 1500, "temp": 75.3 },
"metadata": { "ts": 1746247200000, "site_id": "SITE-01" }
}

Wenn Sie bei nicht gespeicherten Änderungen auf Testlauf klicken, erscheint der Hinweis „Der Server führt die gespeicherte Version aus“. Speichern Sie zuerst, um Änderungen zu validieren.

Kategorien können auf- und zugeklappt werden, und über das Suchfeld ist eine sofortige Filterung möglich.

KategorieFarbeAnzahl Nodes
TriggerGrau22 Arten
FilterBlau6 Arten
TransformationGrün8 Arten
Aktion (Action) — Integration·Speicherung·Anlagenpublikation·BefehlsaufrufOrange7 Arten
Aktion (Action) — Domänen-CRUDOrange34 Arten
Externe Anbindung (External)Lila9 Arten
Ablaufsteuerung (Control)Grau7 Arten
EdgeTürkis22 Arten

Mitte — Canvas

WerkzeugTastenkombination / BedienungAktion
Vergrößern/VerkleinernCtrl/⌘ + / Ctrl/⌘ - · MausradCanvas-Zoom
100%Ctrl/⌘ 0Zoom zurücksetzen
An Bildschirm anpassenCtrl/⌘ 1Automatische Anpassung, sodass alle Nodes sichtbar sind
Ausgewählte Nodes löschenDel / BackspaceLöscht die ausgewählten Nodes/Wires
Canvas verschieben (Panning)Linksklick auf leeren Bereich und ziehenWenn Sie den leeren Hintergrund der Canvas fassen und ziehen, ohne einen Node anzuklicken, bewegt sich die gesamte Canvas mit

Unten rechts auf der Canvas wird eine Minimap angezeigt. Ein Klick auf die Minimap ermöglicht eine sofortige Navigation zur entsprechenden Position.

💡 Tipp zum Panning: Ziehen auf einem Node bewegt den Node — um die Canvas zu verschieben, müssen Sie unbedingt einen leeren Hintergrundbereich ohne Nodes/Wires fassen. Bei großen Flows ist Panning oft schneller als die Minimap.

Rechts — Node-Konfiguration

Wenn Sie auf der Canvas einen Node anklicken, wird im rechten Inspector das Konfigurationsformular für diesen Node angezeigt. Die Eingabefelder werden je nach Node-Typ automatisch generiert.

EingabemethodeBeschreibung
Statischer WertVerwendet den direkt im Formular eingegebenen Wert unverändert
*_field dynamischer WertExtrahiert den Wert aus einem Pfad der Nachrichten-Payload (z. B. data.tag_id, metadata.site_id). Fällt bei fehlendem Wert auf den statischen Wert zurück

Skript-Nodes (Filter·Transformation·Switch) können direkt im Inspector über den Code-Editor bearbeitet werden und lassen sich auch in einem separaten Dialog vergrößern, um auf einem großen Bildschirm zu arbeiten.

Die Schriftart des Code-Editors verwendet einen lesbarkeitsoptimierten Monospace-Font-Stack (Priorität: Cascadia Code · JetBrains Mono · Consolas · Menlo). Auch koreanische Kommentare werden stabil ausgerichtet dargestellt.

Zähler zurücksetzen

Oben rechts im Node-Konfigurationsbereich werden zwei Zurücksetzen-Schaltflächen als Icons angezeigt. Beim Überfahren mit der Maus erscheint zu jeder Schaltfläche ein Tooltip.

Icon-SchaltflächeAktion
🩹 (Pflaster)Fehlerzähler zurücksetzenSetzt nur den kumulierten Fehlerzähler aller Nodes in diesem Flow auf 0 zurück
🔄 (Kreisförmiger Pfeil)Alle Zähler zurücksetzenSetzt Verarbeitung·Fehler·Verarbeitungszeit sowie alle flow-weiten Statistiken auf 0 zurück. Nutzen Sie diese Funktion, wenn Sie die Betriebsvalidierung abgeschlossen haben und die Statistik neu beginnen möchten

Beide Schaltflächen wirken sofort ohne Bestätigungsdialog — es werden nur die Statistiken zurückgesetzt, das Node-Verhalten und die Nachrichtenverarbeitung sind davon nicht betroffen.

Rechts — Live-Debug

Das Live-Debug-Panel wird unterhalb des Inspectors angezeigt.

ElementBeschreibung
Aktualisierungsintervall2 Sekunden
Farbcodierung der EbeneINFO (blau)/WARN (gelb)/ERROR (rot) am linken Rand
Angezeigte InformationenNode-Anzeigename · Verarbeitungszeit (ms) · Nachrichtenvorschau
PausierenPausiert die Aktualisierung über den Schalter oben rechts im Panel
LeerenLeert die kumulierten Debug-Einträge nur auf dem Bildschirm

Oben rechts am Node auf der Canvas wird eine kleine Statusanzeige (LED) angezeigt.

FarbeBedeutung
GrauWartend — keine Nachricht empfangen
GrünNachricht wird durchgeleitet
RotFehler bei der Verarbeitung aufgetreten

Unten rechts am Node wird die Verarbeitungszeit in der Form 평균 X · 최근 Y angezeigt.


Nachrichtenstruktur

Die innerhalb des Flows fließende Nachricht besteht aus den folgenden 4 Bereichen.

{
"type": "POST_TELEMETRY",
"originator": {
"entity_type": "Asset",
"id": "MOTOR-001"
},
"data": { "speed": 1500, "temp": 75.3 },
"metadata": {
"ts": 1746247200000,
"site_id": "SITE-01",
"shift": "DAY",
"tag_id": "MOTOR-001.SPEED"
}
}
BereichBedeutung
typeNachrichtenklassifizierung. Verzweigungskriterium des Filter-Nodes
originatorSubjekt-Entität der Nachricht (auf welche Anlage/welches Tag/welche Bestellung bezogen)
dataPayload-Inhalt
metadataKontext (Zeit·Standort·Schicht·Tag-ID usw.)

Nachrichtentypen

TypAuslösender Einstiegspunkt
POST_TELEMETRY / TAG_POINTEingang eines Tag-Points
POST_ATTRIBUTESAktualisierung von Tag-/Anlagen-Metadaten
TAG_ALARMTag-bezogener Alarm
ENTITY_CREATED / UPDATED / DELETEDEntitäts-Lebenszyklusereignis
ASSET_DATA / ASSET_EVENT / ASSET_ALARM / ASSET_COMMAND / ASSET_AGGREGATION / ASSET_CONTEXTAnlagen-Domänenereignis
ASSET_HEALTH_STATUS / ASSET_CONNECTION_STATUSPeriodische Anlagenbewertung (Zustand/Verbindungsstatus)
OEE_EVENT / RAM_EVENT / EMS_EVENTISO-Analyseergebnisereignis
OPC_STATUS / EDGE_STATUSOPC-/Edge-Gerätestatus
DIAGNOSTIC / DOMAIN_CHANGEDDiagnose·Domänenänderung
ALARMAlarmauslösung
WEBHOOKHTTP-Webhook-Empfang
KAFKA_INBOUND / MQTT_INBOUNDEmpfang aus externem Topic
TIMERZeitplan-Auslösung

Payload-Beispiele nach Trigger

Beim Schreiben von Skript-Nodes müssen Sie genau wissen, auf welche Felder Sie zugreifen können. Nachfolgend finden Sie tatsächliche Nachrichten-JSON-Beispiele, die von jedem Trigger erzeugt werden. Alle Trigger-Nachrichten enthalten gemeinsam type, originator, data, metadata.

flow_on_tag_point — Eingang eines Tag-Points

Wird bei jedem eingehenden Wert eines einzelnen Tags ausgelöst. Der häufigste Trigger.

{
"type": "POST_TELEMETRY",
"originator": { "entity_type": "Tag", "id": "MOTOR-001.SPEED" },
"data": {
"value": 1500.7,
"quality": "GOOD",
"ts": 1746247200123
},
"metadata": {
"tag_id": "MOTOR-001.SPEED",
"site_id": "SITE-01",
"area_id": "AREA-A",
"line_id": "LINE-1",
"asset_id": "MOTOR-001",
"opc_id": "OPC-LINE-1",
"java_type": "Float",
"unit": "rpm",
"shift": "DAY"
}
}
FeldBedeutungSkriptzugriff
data.valueEmpfangener Wert (numerisch/Text/boolesch)msg.data.value
data.qualityOPC-Qualität (GOOD/BAD/UNCERTAIN)msg.data.quality
data.tsEmpfangszeitpunkt (Epoch ms)msg.data.ts
metadata.tag_idTag-IDmsg.metadata.tag_id

flow_on_tag_alarm — Auftreten eines Tag-Alarms

Wird ausgelöst, sobald das Alarmband (hi/lo/...) eines Tags überschritten wird.

{
"type": "TAG_ALARM",
"originator": { "entity_type": "Tag", "id": "MOTOR-001.TEMP" },
"data": {
"alarm_band": "HI_HI",
"value": 95.3,
"threshold": 90.0,
"priority": "ERROR",
"band_message": "온도 위험"
},
"metadata": {
"tag_id": "MOTOR-001.TEMP",
"asset_id": "MOTOR-001",
"site_id": "SITE-01",
"ts": 1746247200123
}
}
Wert von data.alarm_bandBedeutung
NORMAL / HI / LO / HI_HI / LO_LO / TRIP_HI / TRIP_LONumerische Alarmstufe
BOOL_TRUE / BOOL_FALSEBoolescher Alarm

flow_on_asset_data / flow_on_asset_event — Anlagenereignis

Wird ausgelöst, wenn ein auf Anlagenebene aggregiertes Ereignis (CEP-Verarbeitungsergebnis·Plugin-Bewertungsergebnis usw.) auftritt.

{
"type": "ASSET_EVENT",
"originator": { "entity_type": "Asset", "id": "MOTOR-001" },
"data": {
"event_type": "STARTUP",
"details": { "rpm_target": 1500 }
},
"metadata": {
"asset_id": "MOTOR-001",
"site_id": "SITE-01",
"ts": 1746247200123
}
}

flow_on_asset_data überträgt zeitreihenbasierte Daten auf Anlagenebene (data.values als Key-Value-Map), flow_on_asset_aggregation überträgt Minuten-/Stundenaggregate.

flow_on_asset_health_status / flow_on_asset_connection_status — Periodische Bewertung

Die Plattform bewertet im 1-Minuten-Intervall den Zustand/Verbindungsstatus auf Anlagenebene.

{
"type": "ASSET_HEALTH_STATUS",
"originator": { "entity_type": "Asset", "id": "MOTOR-001" },
"data": {
"status": "WARN",
"info_count": 12,
"warn_count": 3,
"error_count": 0,
"prev_status": "OK"
},
"metadata": { "asset_id": "MOTOR-001", "ts": 1746247200123 }
}
Wert von data.statusBedeutung
OK / WARN / ERROR / UNKNOWNZustandsstufe
CONNECTED / LATENT / ERROR / DISCONNECTED / UNKNOWNVerbindungsstufe (connection_status)

Es wird häufig das Muster verwendet, im Vergleich mit prev_status nachfolgende Aktionen nur zum Zeitpunkt des Statusübergangs auszulösen.

flow_on_oee_event / flow_on_ram_event / flow_on_ems_event — Plugin-Ereignis

Wird ausgelöst, wenn ein OEE/RAM/EMS-Bewertungsergebnis auf Arbeitsauftragsebene aktualisiert wird.

{
"type": "OEE_EVENT",
"originator": { "entity_type": "WorkOrder", "id": "WO-20260512-001" },
"data": {
"oee": 0.78,
"availability": 0.95,
"performance": 0.85,
"quality": 0.97,
"good_count": 1560,
"bad_count": 42,
"target_count": 2000
},
"metadata": {
"order_id": "WO-20260512-001",
"asset_id": "LINE-1.PRESS",
"shift_id": "DAY-A",
"ts": 1746247200123
}
}

flow_on_opc_status / flow_on_edge_status — OPC-/Edge-Status

{
"type": "OPC_STATUS",
"originator": { "entity_type": "OPC", "id": "OPC-LINE-1" },
"data": {
"connection_status": "CONNECTED",
"scan_status": "START",
"prev_status": "DISCONNECTED"
},
"metadata": { "opc_id": "OPC-LINE-1", "edge_id": "EDGE-A", "ts": 1746247200123 }
}

flow_on_diagnostic — System-Diagnosemeldung

Wird ausgelöst, wenn eine Diagnosemeldung aus einem Servermodul eingeht.

{
"type": "DIAGNOSTIC",
"originator": { "entity_type": "Module", "id": "cep-engine" },
"data": {
"level": "WARN",
"code": "PATTERN_LAG",
"summary": "EQL 패턴 평가 지연 1.2s",
"module": "cep-engine"
},
"metadata": { "ts": 1746247200123 }
}
data.levelBedeutung
INFO / WARN / ERRORDiagnoseschweregrad

flow_on_domain_changed — Domänenänderungsereignis

Wird ausgelöst, wenn Domänenentitäten wie Anlage·Tag·Standort·Arbeitsauftrag usw. per CRUD verändert werden.

{
"type": "DOMAIN_CHANGED",
"originator": { "entity_type": "Asset", "id": "MOTOR-001" },
"data": {
"action": "UPDATED",
"before": { "asset_name": "Motor1" },
"after": { "asset_name": "Motor 01 - Renamed" },
"changed_by": "admin"
},
"metadata": { "ts": 1746247200123 }
}

flow_on_entity_event — Entitäts-Lebenszyklus

Integriert für die drei Typen ENTITY_CREATED / ENTITY_UPDATED / ENTITY_DELETED ausgelöst. Ein einzelner Node empfängt alle drei Lebenszyklen.

{
"type": "ENTITY_CREATED",
"originator": { "entity_type": "Customer", "id": "CUST-9001" },
"data": { "customer_name": "신규 고객", "external_id": "ERP-CUST-9001" },
"metadata": { "ts": 1746247200123 }
}

flow_on_webhook — Externer HTTP-Push

Die von einem externen System an POST /api/v4/flow/webhook/{flow_id} gesendete Payload wird unverändert in eine Nachricht umgewandelt. Authentifizierung über {flow_id} im URL-Pfad und Header X-API-Key.

{
"type": "WEBHOOK",
"originator": { "entity_type": "External", "id": "ERP" },
"data": {
"order_no": "PO-20260512-001",
"customer": "ACME",
"quantity": 1000
},
"metadata": {
"http_method": "POST",
"remote_addr": "10.20.0.55",
"request_id": "req-7c0a...",
"ts": 1746247200123
}
}

Der gesamte vom externen System gesendete JSON-Body wird unverändert in data eingefügt. HTTP-Header werden teilweise (remote_addr/method/request_id) in metadata angezeigt.

flow_on_mqtt_subscribe — MQTT-Topic-Abonnement

{
"type": "MQTT_INBOUND",
"originator": { "entity_type": "Topic", "id": "factory/line1/events" },
"data": { "event": "STARTUP", "rpm": 1500 },
"metadata": {
"topic": "factory/line1/events",
"qos": 1,
"broker": "tcp://mqtt.example.com:1883",
"ts": 1746247200123
}
}

flow_jdbc_poll — Periodisches externes DB-Polling

Führt eine konfigurierte SELECT-Abfrage periodisch aus und löst für jede Zeile eine Nachricht aus.

{
"type": "KAFKA_INBOUND",
"originator": { "entity_type": "DB", "id": "mes_db" },
"data": {
"PO_NO": "PO-20260512-001",
"CUSTOMER": "ACME",
"QTY": 1000,
"DUE_DATE": "2026-05-20"
},
"metadata": {
"datasource": "mes_db",
"query": "SELECT * FROM po WHERE status='NEW'",
"row_index": 0,
"ts": 1746247200123
}
}

Bei 100 Zeilen werden 100 Nachrichten nacheinander ausgelöst. Um zu vermeiden, dass dieselbe Zeile wiederholt verarbeitet wird, aktualisieren Sie innerhalb der SELECT-Abfrage entsprechend ein Verarbeitungsflag oder fügen Sie eine Vergleichsbedingung für die Spalte processed_at hinzu.

flow_schedule — Zeitbasierte Auslösung

Wird über einen Cron-Ausdruck oder ein festes Intervall ausgelöst. Die Payload ist leer, nur metadata.ts wird befüllt.

{
"type": "TIMER",
"originator": { "entity_type": "Schedule", "id": "daily-report" },
"data": {},
"metadata": {
"cron": "0 0 8 * * ?",
"fired_at": 1746247200000,
"ts": 1746247200000
}
}

Hinweise bei der Payload-Transformation

  • originator.id ist die Domänen-ID — wenn Sie sie mit dem flow_change_originator-Node ändern, arbeiten nachfolgende Aktions-Nodes wie flow_save_attributes·flow_publish_asset_* mit dem neuen originator.
  • Beim Austauschen von data/metadata per Skript wird eine direkte Zuweisung anstelle einer flachen Kopie (Object.assign) empfohlen — eine Änderung am Original kann andere Flows beeinflussen, die denselben Trigger abonnieren.
  • Alle Epoch-Zeitfelder sind in Millisekunden (ms). Falls Sekunden benötigt werden, Math.floor(msg.metadata.ts / 1000).

Node-Katalog

Detaillierte Node-IDs und Optionen können Sie im Inspector der Bearbeitungsansicht einsehen.

Trigger (22 Arten)

Der Startpunkt jedes Flows ist ein Trigger-Node. Es gibt keine separaten Einstiegs-/Endpunkt-Nodes.

Automatischer Domänenempfang — Interne Systemereignisse werden automatisch dispatcht.

KategorieTrigger-Node
Tagflow_on_tag_point (Telemetrie), flow_on_tag_alarm
Anlageflow_on_asset_data, flow_on_asset_event, flow_on_asset_alarm, flow_on_asset_command, flow_on_asset_aggregation, flow_on_asset_context, flow_on_asset_health_status, flow_on_asset_connection_status
Pluginflow_on_oee_event, flow_on_ram_event, flow_on_ems_event
OPC/Edgeflow_on_opc_status, flow_on_edge_status
Diagnose·Domäneflow_on_diagnostic, flow_on_domain_changed
Entitätflow_on_entity_event
Einen Node namens flow_on_alarm gibt es nicht

Alarm-Trigger sind je nach Ziel in zwei getrennt — Tag-Alarm ist flow_on_tag_alarm, Anlagen-Alarm ist flow_on_asset_alarm. Ein Beispiel aus einem älteren Dokument verwendete flow_on_alarm, ein Name, der nicht in der Palette vorhanden ist — wenn Sie es genauso nachahmen, ist der Node nicht auffindbar.

Alle Trigger-Nodes ermöglichen mit der Option *_pattern (Glob: *, ?) eine nachrichtenweise Vorabfilterung. Nicht dem Muster entsprechende Nachrichten werden nicht an nachfolgende Nodes weitergegeben, und auch der Ausführungszähler erhöht sich nicht (SKIPPED-Behandlung). Es wird empfohlen, bereits in der Triggerstufe zu filtern, um die Betriebslast zu minimieren.

Externer Eintritt

NodeAktion
flow_on_webhookEmpfängt eine von einem externen System per HTTP gepushte Payload
flow_on_mqtt_subscribeAbonniert ein Topic eines externen MQTT-Brokers
flow_jdbc_pollLiest periodisch das SELECT-Ergebnis einer externen Datenbank und löst pro Zeile aus

Zeitbasiert

NodeAktion
flow_scheduleCron-/Zeitplan — löst die Nachricht TIMER aus

Filter (6 Arten)

NodeBeschreibung
flow_msg_type_filterWenn type in der angegebenen Liste enthalten ist, TRUE
flow_originator_type_filterWenn originator.entity_type in der angegebenen Liste enthalten ist, TRUE
flow_script_filterBoolesche Auswertung per Skript
flow_check_existence_fieldPrüft, ob ein bestimmtes Feld data/metadata existiert
flow_switchVerzweigung mit mehreren Cases (jeder Case eine eigene Relation)
flow_check_relationVerzweigung basierend auf der Relation der vorherigen Stufe

Transformation (8 Arten)

NodeAnzeigenameBeschreibung
flow_script_transformSkript-TransformationTransformiert data/metadata per Skript
flow_change_originatorAbsender ändernÄndert originator zu einer anderen Entität
flow_rename_keysSchlüsselnamen ändernÄndert Feldnamen von data in großer Menge
flow_templateVorlageErzeugt Ersatztext auf Basis von ${path}
flow_splitTeilenWenn data ein Array ist, wird pro Element eine Nachricht erzeugt
flow_mergeZusammenführenFührt mehrere Nachrichten innerhalb eines Zeitfensters zusammen — Gegenteil von flow_split
flow_flattenAbflachenHebt untergeordnete Schlüssel eines verschachtelten Objekts auf die oberste Ebene (data.data_map.xdata.x)
flow_to_emailE-Mail-TransformationWandelt die Nachricht in ein E-Mail-Format um

flow_flatten wird verwendet, wenn Sie bei Nachrichten wie Tag-Points, bei denen der Wert eine Ebene tiefer in data_map liegt, im nachfolgenden Node direkt über ${data.x} darauf verweisen möchten.

Aktion — Integration·Speicherung (2 Arten)

NodeBeschreibung
flow_save_tag_pointLädt Tag-Points (identischer Pfad wie beim normalen Ingest)
flow_save_attributesTeilweise Aktualisierung von Tag-/Anlagen-Metadaten

Wenn Sie flow_dds_publish suchen (freie Publikation auf den internen Nachrichtenkanal), finden Sie es nicht hier, sondern in der Palettengruppe Externe Anbindung.

Aktion — Anlagenereignis-Publikation (4 Arten)

Publiziert Anlagenereignisse über denselben Verarbeitungspfad wie CEP (EQL) (konsistente Verarbeitung von persistenter Speicherung + Cache + Timeline + Plugin + Nachrichtenkanal).

NodeKanal
flow_publish_asset_eventAnlagenereignis
flow_publish_asset_contextAnlagenkontext
flow_publish_asset_aggregationAnlagenaggregation
flow_publish_asset_commandAnlagenbefehl

flow_asset_command_invoke — Ausführung statt Publikation

NodeAnzeigenameAufgabe
flow_asset_command_invokeAnlagenbefehlsaufrufFührt einen an der Anlage definierten Befehl synchron aus und wartet auf das Ergebnis
Leicht mit flow_publish_asset_command zu verwechseln
  • flow_publish_asset_commandPubliziert nur ein Anlagen-Befehlsereignis auf den Kanal. Damit ist es beendet.
  • flow_asset_command_invoke — Führt einen an der Anlage definierten Befehl tatsächlich aus und wartet, bis das Ergebnis vorliegt.

Wenn Sie eigentlich wollten, dass der Befehl ausgeführt wird, aber den Publikations-Node verwenden, sieht es so aus, als würde nichts passieren.

Aktion — Domänen-CRUD (34 Arten)

Alle Domänenoperationen werden an denselben Domänenservice delegiert, wodurch Audit·Konsistenz gewahrt bleiben. Mit der dynamischen Option *_field können Werte aus der Nachrichten-Payload extrahiert werden.

DomäneCreateUpdateDelete
Anlage (Asset)flow_create_assetflow_update_assetflow_delete_asset
Tagflow_create_tagflow_update_tagflow_delete_tag
Standort/Bereich/Linieflow_create_siteflow_update_siteflow_delete_site
Arbeitsauftrag (WorkOrder)flow_create_work_orderflow_update_work_orderflow_delete_work_order
Alarmkonfiguration (EQL)flow_create_alarm_configflow_update_alarm_configflow_delete_alarm_config
Kunde (Customer)flow_create_customerflow_update_customerflow_delete_customer
Produkt (Product)flow_create_productflow_update_productflow_delete_product
Mitarbeiter (Employee)flow_create_employeeflow_update_employeeflow_delete_employee
Kalender (Schicht)flow_create_calendarflow_update_calendarflow_delete_calendar

Teilweise Aktualisierung des Tag-Alarmbands (2 Arten)

NodeBeschreibung
flow_update_tag_alarm_band_numericAktualisiert nur die eingegebenen Felder eines numerischen Alarmbands (hi/lo/hi_hi/lo_lo/trip_hi/trip_lo/band_message/use_alarm)
flow_update_tag_alarm_band_booleanAktualisiert nur die eingegebenen Felder eines booleschen Alarmbands (bool_true/bool_false/Priorität/Nachricht/use_alarm)

Statusübergänge des Arbeitsauftrags (WorkOrder) (5 Arten)

Da nicht direkt numerische Spalten aktualisiert, sondern die Statusübergangsmethoden des Domänenservices aufgerufen werden, bleibt die OEE/RAM/EMS-Sichtbarkeit erhalten.

NodeÜbergang
flow_start_work_orderWAITSTART
flow_pause_work_orderSTARTPAUSED
flow_resume_work_orderPAUSEDSTART
flow_end_work_orderSTART oder PAUSEDEND
flow_abort_work_orderSTART oder PAUSEDABORTED (Optionen abort_code, notes)

Automatische NOT-NULL-Ergänzung — Create-Nodes befüllen NOT-NULL-Spalten automatisch mit Default-Werten. Beispiel: Beim Arbeitsauftrag sind status="WAIT" / master_id die MES-Master-ID (bei Fehlen automatisch nachgefüllt), Kundenmanager-Informationen "admin"/"admin@example.com", Mitarbeiter org_id fällt auf site_id zurück, insert_user_id="flow" für alle Zeilen. Bei FK-Spalten (z. B. customer_id/product_id) wird ein leerer String in NULL umgewandelt.

Update-Node — Teilaktualisierung — Die Update-Nodes für Customer/Product/Employee/Calendar und Alarmband fragen zunächst den bestehenden Datensatz ab und speichern dann nur die eingegebenen Felder zusammengeführt. Leere Strings·null-Werte werden ignoriert, sodass der bestehende Wert erhalten bleibt. Für eine vollständige Überschreibung verwenden Sie die Kombination Delete + Create.

Direkter Alarm-Trigger-Node ist bewusst ausgeschlossen. Alarme dürfen nur über den flow_create_alarm_config-Pfad entstehen, damit die Konsistenz der Alarmhistorie gewahrt bleibt.

Edge (22 Arten)

Automatisiert die Registrierung von OPC-Servern, Tag-CRUD, Lesen/Schreiben von Tag-Werten, Abfragen und die Steuerung von Docker-Apps durch Aufruf der REST-API des Edge-Geräts (OPC Agent). Alle Nodes teilen sich semantisch dieselbe Aktion, unterscheiden sich nur in der zugrunde liegenden HTTP-Methode (GET/POST/PUT/DELETE).

GruppeNode
OPC-Server-Verwaltungflow_edge_opc_create, flow_edge_opc_update, flow_edge_opc_delete, flow_edge_opc_start, flow_edge_opc_stop, flow_edge_opc_list
Tag-Verwaltungflow_edge_tag_create, flow_edge_tag_update, flow_edge_tag_delete, flow_edge_tag_read, flow_edge_tag_write, flow_edge_tag_list
Abfrageflow_edge_monitoring, flow_edge_info, flow_edge_transfer
Docker-App-Steuerungflow_edge_app_list, flow_edge_app_inspect, flow_edge_app_start, flow_edge_app_stop, flow_edge_app_restart, flow_edge_app_logs, flow_edge_app_stats

3 Abfrage-Arten

NodeAnzeigenameAufgabe
flow_edge_monitoringMonitoringFragt Edge-Monitoring-Kennzahlen ab
flow_edge_infoEdge-InfoFragt Edge-ID · Version · Uptime ab
flow_edge_transferÜbertragungsstatusStatus der MQTT/Sparkplug-Übertragung
NodeAnzeigenameAufgabe
flow_edge_opc_listOPC-ListeFragt die Liste der OPC-Server des Edge ab
flow_edge_tag_listTag-ListeFragt die Tag-Liste des OPC ab

7 Arten der Docker-App-Steuerung

Automatisiert per Flow, was zuvor manuell im Docker-Panel der Edge-Detailansicht erledigt wurde.

NodeAnzeigenameAufgabe
flow_edge_app_listApp-ListeListe der Edge-Docker-Container
flow_edge_app_inspectApp-DetailsContainer-Details (inspect)
flow_edge_app_startApp startenContainer starten
flow_edge_app_stopApp stoppenContainer stoppen
flow_edge_app_restartApp neu startenContainer neu starten
flow_edge_app_logsApp-LogContainer-Log (line=N)
flow_edge_app_statsApp-StatistikContainer CPU / Speicher / I/O
App-Steuerungs-Nodes greifen real auf Vor-Ort-Geräte zu

app_stop · app_restart stoppen und starten tatsächlich Container, die auf dem Edge vor Ort laufen. Wenn Sie dies durch Anhängen an einen Trigger automatisch ausführen lassen, grenzen Sie die Bedingung eng ein — wenn Sie app_restart an einen flatternden Alarm hängen, startet der Container immer wieder neu.

Gemeinsame Konfiguration

OptionBeschreibung
urlEdge-REST-Endpunkt. Unterstützt ${data.x}/${metadata.y}-Vorlagenersetzung
methodHTTP-Methode (falls nicht gesetzt, Node-spezifischer Standardwert — z. B. create=POST, update=PUT, delete=DELETE, read/monitoring=GET)
headersJSON-Header (z. B. {"Authorization":"Bearer ${TOKEN}"})
body_templateRequest-Body (falls nicht gesetzt, wird data unverändert gesendet, bei GET/DELETE kein Body gesendet)
timeout_msTimeout (Standard 5000)

Antwort·Verzweigung

  • data.response_status — HTTP-Statuscode
  • data.response — Antwortkörper (String)
  • data.error — Fehlermeldung (bei Fehlschlag)
  • SUCCESS (200–399) / FAILURE (sonst oder bei Exception)

Externe Anbindung (9 Arten)

Alle External-Nodes unterstützen die dynamische Option *_field.

NodeDynamische Option
flow_dds_publishFreie Publikation auf den internen Nachrichtenkanal (kein externer Aufruf, aber in dieser Gruppe)
flow_http_requesturl_field / method_field / body_field
flow_kafka_publishtopic_field / key_field
flow_mqtt_publishtopic_field
flow_webhook_callbackurl_field
flow_send_emailto_field / cc_field / subject_field / body_field
flow_send_smsto_field / text_field
flow_send_pushtitle_field / body_field
flow_jdbc_querySQL statisch (SELECT/INSERT/UPDATE/DELETE)

Ablaufsteuerung (7 Arten)

NodeBeschreibung
flow_logDebug-Log (level / prefix)
flow_noopDurchgang
flow_delayNach delay_ms Weiterleitung an den nächsten Node
flow_throttleBegrenzung max_msgs / window_ms (bei Überschreitung Relation THROTTLED)
flow_debounceLöst nach Stabilisierung von window_ms nur die letzte Nachricht aus
flow_mergeKumuliert Eingaben während window_ms und emittiert einmalig als data.merged-Array
flow_subflowtarget_flow_id — Aufruf eines anderen Flows
flow_retrymax_attempts (Standard 3) / backoff_ms (Standard 1000) / backoff_multiplier (Standard 2.0). Nach Backoff-Wartezeit wird die Nachricht in den SUCCESS-Zweig weitergeleitet, bei Erreichen der maximalen Versuche in den EXHAUSTED-Zweig. metadata.retry_count / metadata.retry_exhausted automatisch aktualisiert

Empfohlenes Verdrahtungsmuster für Retry

[risky_node] ─[FAILURE]─▶ [flow_retry] ─[SUCCESS]─▶ (다시 risky_node 로 루프 연결)
└[EXHAUSTED]─▶ [에러 핸들러 / 알림]

Detaillierte Node-Optionsreferenz

Beschreibt die Optionen komplexer Nodes ausführlich mit Standardwerten·Beispielen·Fehlerbehandlung je Option, nicht nur in einer einzeiligen Tabelle.

flow_script_filter — Skriptfilter

OptionTypStandardBeschreibung
scripttext(erforderlich)Auswertungsausdruck — gibt boolean zurück. true → Verzweigung TRUE / false → Verzweigung FALSE
script_typeenumjavascriptjavascript / eql
on_errorenumFALSEBei Skript-Exception — ob in Verzweigung TRUE / FALSE / FAILURE gesendet wird

Skriptkontext

VariableBedeutung
msg.typeNachrichtentyp (z. B. POST_TELEMETRY)
msg.dataPayload (veränderbar, hat aber im Filter keine Bedeutung)
msg.metadataKontext
msg.originatororiginator-Objekt

Beispiel

// 온도가 임계 초과 + 야간 시프트만
msg.data.value > 80 && msg.metadata.shift === 'NIGHT'
// 사이트별 임계 분기
var th = {'SITE-A': 80, 'SITE-B': 90, 'SITE-C': 75};
msg.data.value > (th[msg.metadata.site_id] || 100);

flow_script_transform — Skript-Transformation

OptionTypStandardBeschreibung
scripttext(erforderlich)Transformationsausdruck — ändert das msg-Objekt oder gibt ein neues zurück
script_typeenumjavascriptjavascript / eql
modeenummutatemutate (in-place) / return (verwendet Rückgabewert)

Beispiel

// data 에 계산 필드 추가
msg.data.fahrenheit = msg.data.value * 9/5 + 32;
msg.metadata.processed_at = Date.now();
// 페이로드 통째로 교체 (mode=return)
return {
type: 'WEBHOOK',
originator: msg.originator,
data: { temp: msg.data.value, level: msg.data.value > 80 ? 'HIGH' : 'OK' },
metadata: msg.metadata
};

Im Modus mutate werden return-Anweisungen ignoriert, selbst wenn vorhanden. Um durch ein neues Objekt zu ersetzen, muss mode=return eingestellt werden.

flow_switch — Mehrfachverzweigung

OptionTypStandardBeschreibung
casesarray(erforderlich)[{expression, relation}]-Array — Auswertung von oben nach unten, erster Treffer wird verwendet
default_relationstringDEFAULTFalls kein Case zutrifft
script_typeenumjavascript

Beispiel

// cases 설정
[
{ "expression": "msg.data.value > 90", "relation": "CRITICAL" },
{ "expression": "msg.data.value > 80", "relation": "WARN" },
{ "expression": "msg.data.value > 70", "relation": "INFO" }
]
// default_relation: "NORMAL"

Im nachfolgenden Node ist mit 4 Verzweigungslabels (CRITICAL/WARN/INFO/NORMAL) jeweils eine unterschiedliche Verarbeitung möglich.

flow_retry — Automatischer Wiederholungsversuch

Erholt sich automatisch von vorübergehenden Fehlern externer IO-Nodes.

OptionTypStandardBeschreibung
max_attemptsint3Maximale Versuchsanzahl (bei Überschreiten dieses Werts EXHAUSTED)
backoff_mslong1000Erste Wartezeit (ms)
backoff_multiplierdouble2.0Exponentieller Backoff-Multiplikator — 1. Versuch 1 s → 2. Versuch 2 s → 3. Versuch 4 s
max_backoff_mslong30000Obergrenze der einzelnen Wartezeit
jitter_pctint0Zufälliges Jitter von ±N% beim Backoff (zur Vermeidung von Thundering Herd)

Automatische Ergänzung von metadata

FeldBedeutung
metadata.retry_countBisherige Anzahl der Versuche
metadata.retry_exhaustedBei true erfolgt der Eintritt in den EXHAUSTED-Zweig
metadata.retry_last_errorGrund des letzten Fehlschlags

Wenn die Summe der Backoff-Zeiten 60 Sekunden übersteigt, kann die Trigger-Verarbeitungswarteschlange blockiert werden. Wenn die Antwort des externen Systems durchgängig langsam ist, begrenzen Sie zunächst mit flow_throttle die Eintrittsgeschwindigkeit.

flow_on_webhook — HTTP-Trigger

OptionTypStandardBeschreibung
auth_requiredbooleantrueOb der Header X-API-Key erforderlich ist — bei Deaktivierung kann jeder aufrufen
allowed_originscsv*Whitelist der CORS-Origins
max_body_kbint256Obergrenze der Body-Größe (bei Überschreitung Antwort 413)
payload_patternglob*Glob zur Vorabfilterung von Nachrichten

Aufrufmethode

curl -X POST \
https://platform.example.com/api/v4/flow/webhook/{flow_id} \
-H "X-API-Key: {edge_or_token_key}" \
-H "Content-Type: application/json" \
-d '{"order_no":"PO-001","customer":"ACME","quantity":1000}'
  • {flow_id} im Pfad kann in der Listenansicht kopiert werden
  • X-API-Key ist ein Token, das im Bildschirm API Key oder API-Authentifizierungstoken des Edge ausgestellt wurde
  • Antworten: 200 OK (in die Nachrichtenwarteschlange eingereiht) / 401 (Authentifizierungsfehler) / 404 (Flow nicht vorhanden oder nicht bereitgestellt) / 413 (Body überschritten)

flow_http_request — Externer HTTP-Aufruf

OptionTypStandardBeschreibung
urlstring(erforderlich)Aufzurufende URL. ${data.x}-Vorlagenersetzung
url_fieldstringWenn die URL dynamisch aus der Payload bezogen werden soll — z. B. data.endpoint
methodenumGETGET / POST / PUT / DELETE / PATCH
method_fieldstringMethode dynamisch aus der Payload
headersjson{}Format {"Authorization": "Bearer ${TOKEN}"}
bodytextStatischer Body (unterstützt Vorlagenersetzung)
body_fieldstringWenn der Body aus der Payload bezogen werden soll — üblicherweise data
timeout_msint5000Obergrenze der Antwortwartezeit
follow_redirectbooleantrueAutomatisches Folgen von 3xx-Redirects
verify_sslbooleantrueTLS-Zertifikatsprüfung (nur zu Testzwecken deaktivieren)

Ergänzung der Antwort-Payload

FeldBedeutung
data.response_statusHTTP-Statuscode (200 / 404 / 500 ...)
data.response_bodyAntwortkörper (bei JSON automatisch geparst)
data.response_headersAntwort-Header-Objekt

Verzweigung

  • SUCCESS — 2xx/3xx
  • FAILURE — 4xx/5xx oder Exception/Timeout

flow_send_email — E-Mail-Versand

OptionTypStandardBeschreibung
tostringStatischer Empfänger (kommagetrennt)
to_fieldstringEmpfänger aus der Payload extrahieren — z. B. data.recipient
cc / cc_fieldstringCC
bcc / bcc_fieldstringBCC
subject / subject_fieldstring(mind. 1 erforderlich)Betreff — Vorlagenersetzung
body / body_fieldtext(mind. 1 erforderlich)Text (HTML erlaubt)
is_htmlbooleantrueBei reiner Textmail deaktivieren
attachmentsjson[][{"url":"...","filename":"..."}]

Die SMTP-Konfiguration wird im Voraus vom Operator unter System → Einstellungen in den E-Mail-Einstellungen registriert. Vor der Registrierung fallen alle E-Mail-Nodes in den Zweig FAILURE.

flow_jdbc_poll — Externes DB-Polling

OptionTypStandardBeschreibung
datasource_idstring(erforderlich)Externe DB-Kennung, registriert unter System → Einstellungen
querysql(erforderlich)SELECT-Abfrage — liefert maximal 1.000 Zeilen pro Aufruf
poll_interval_msint60000Polling-Intervall (Standard 1 Minute)
marker_columnstringSpalte „Letzter Verarbeitungszeitpunkt" — SELECTiert nur Zeilen nach dem Marker
marker_initialstring1970-01-01 00:00:00Ausgangswert des Markers beim ersten Polling
row_limitint1000Maximale Zeilenanzahl pro Polling (sicher auch bei Überschreitung)
on_error_continuebooleantrueBei DB-Fehler nur Diagnose protokollieren und mit dem nächsten Polling fortfahren

Anwendungsbeispiel für marker_column

SELECT po_no, customer, qty, created_at
FROM po
WHERE created_at > :marker
ORDER BY created_at

→ An der Stelle von :marker wird automatisch der maximale created_at-Wert aus dem letzten Polling eingesetzt.

flow_kafka_publish / flow_mqtt_publish — Externe Publikation

OptionTypStandardBeschreibung
brokerstring(erforderlich)kafka:9092 oder tcp://mqtt:1883
topicstringStatisches Topic — ${data.x}-Ersetzung möglich
topic_fieldstringTopic aus der Payload extrahieren (z. B. data.target_topic)
key / key_fieldstring(nur Kafka) Nachrichtenschlüssel
body / body_fieldjson/text(mind. 1 erforderlich)Zu publizierender Inhalt — falls nicht gesetzt, data unverändert
qosint1(nur MQTT) 0/1/2
retainbooleanfalse(nur MQTT) Retained-Flag

flow_publish_asset_* — Anlagenereignis publizieren

Anlagenereignisse (Ereignis/Kontext/Aggregation/Befehl) werden über einen einheitlichen Kanal publiziert, der gleichzeitig von CEP/Plugin/Timeline erkannt wird. Gemeinsame Optionen der 4 Nodes:

OptionTypStandardBeschreibung
asset_idstringStatische Anlagen-ID
asset_id_fieldstringAnlagen-ID aus der Payload extrahieren (üblicherweise metadata.asset_id)
event_typestringKlassifizierung des Anlagenereignisses (z. B. STARTUP, SHUTDOWN, MAINTENANCE)
event_type_fieldstringKlassifizierung aus der Payload extrahieren
payloadjson${data}Zu publizierender Inhalt — falls nicht gesetzt, data unverändert

Bei flow_publish_asset_command wird die Nachricht sofort über das Befehlsempfangs-Topic der Anlage (asset_id/cmd/{event_type}) an das Edge zugestellt.

flow_create_* / flow_update_* — Domänen-CRUD

Alle Create/Update-Nodes teilen sich folgendes Optionsmuster.

OptionTypBeschreibung
{컬럼명}stringStatischer Wert (falls nicht eingegeben, NULL/Default)
{컬럼명}_fieldstringWert aus der Payload extrahieren (data.foo / metadata.bar)
id_strategyenumauto (systemvergeben) / field (aus {도메인}_id_field extrahiert)
on_duplicateenumerror (Standard) / skip / update — nur bei Create-Nodes

Automatische NOT-NULL-Ergänzung

Create-Nodes befüllen NOT-NULL-Spalten automatisch mit Default-Werten.

DomäneAutomatisch befüllte Spalte
Arbeitsauftragstatus="WAIT" / master_id (bei Fehlen automatisch nachgefüllt) / insert_user_id="flow"
KundeManagerinfo "admin" / "admin@example.com" (falls nicht registriert)
Mitarbeiterorg_id=site_id (Fallback)
Gemeinsaminsert_date=now() / insert_user_id="flow"

Behandlung leerer Strings bei FK

Wenn bei einer FK-Spalte (z. B. customer_id/product_id) ein leerer String "" eingeht, wird er automatisch in NULL umgewandelt. In JS ist msg.data.customer_id = '' sicherer als delete msg.data.customer_id.

flow_edge_* — Edge-REST-Aufruf

Die 22 Nodes, die den REST-Endpunkt eines Edge-Geräts aufrufen, teilen sich gemeinsame Optionen.

OptionTypStandardBeschreibung
edge_idstringStatische Edge-ID
edge_id_fieldstringEdge-ID aus der Payload extrahieren
pathstring(Node-spezifischer Standard)Edge-REST-Pfad (z. B. /api/v1/opc, /api/v1/app/grafana/start)
body_templatetextRequest-Body — falls nicht gesetzt, data unverändert
timeout_msint5000

Automatische Authentifizierung

Der Edge-Node führt beim Aufruf automatisch ein Lookup von api_key für dieses Edge in der Mastertabelle mm_edge durch und hängt es als X-API-Key-Header an. Der Operator muss keine separate Konfiguration vornehmen.

Antwort-Payload

FeldBedeutung
data.edge_response_statusEdge-Antwortcode
data.edge_responseAntwortkörper
data.edge_idZiel-Edge-ID des Aufrufs (zur Bestätigung)

Die Verzweigung ist identisch mit flow_http_request (SUCCESS / FAILURE).


Skript-Nodes schreiben

Die Nodes flow_script_filter / flow_script_transform / flow_switch unterstützen zwei Ausdruckstypen.

JavaScript (Standard, empfohlen)

Standard-ECMAScript-Syntax. Mehrzeiligkeit·var/let/const·Funktionen·Objektliterale werden alle unterstützt.

Bindings

VariableBeschreibung
msgGesamte Nachricht. Direkter Zugriff auf msg.data.x, msg.metadata.topic, msg.type, msg.originator.id
dataKurzalias für msg.data
metadataKurzalias für msg.metadata

Filterbeispiel

data.temp > 80

Transformationsbeispiel

data.temp_f = data.temp * 1.8 + 32;
data.alert = data.temp > 80 ? 'HIGH' : 'OK';
msg

Switch-Beispiel (boolean je Case)

data.t > 100 // case "Critical"

Häufig verwendete Transformationsmuster

// 1) 단위 변환 (섭씨 → 화씨) + 라벨링
data.temp_f = data.temp * 1.8 + 32;
data.alert = data.temp > 80 ? 'HIGH' : 'OK';
msg

// 2) 메타데이터 보강 — 시간대·시프트 자동 부여
const h = new Date(metadata.ts).getHours();
metadata.shift = (h >= 6 && h < 18) ? 'DAY' : 'NIGHT';
msg

// 3) 외부 페이로드를 도메인 모델로 매핑 (MES PO → WorkOrder)
const po = data;
data = {
master_id: 'WO-MES-' + po.po_no,
asset_id: po.line_id || 'UNASSIGNED',
title: po.product_name + ' (' + po.qty + ')',
due_date: po.delivery_date,
qty: po.qty
};
msg

// 4) 실패 분기로 명시적 라우팅 (필수 필드 누락 시)
if (!data.tag_id || data.value == null) throw new Error('필수 필드 누락');
msg

// 5) 배열 분할 후 데이터 정제 — split 노드 후에 사용
data.value = parseFloat(data.raw);
data.threshold = data.value > 100;
msg

Häufig verwendete Filtermuster

// 우선순위 화이트리스트
['ERROR', 'CRITICAL'].includes(data.priority)

// 시간대 기반 필터 (주간만 허용)
new Date(metadata.ts).getHours() >= 8 && new Date(metadata.ts).getHours() < 20

// 자산 ID 패턴 매칭
/^MOTOR-.*$/.test(originator.id)

// 임계값 + 안정성 (값이 5번 이상 누적된 경우)
data.value > data.threshold && data.consecutive_count >= 5

Benutzerskripte laufen in einer sicheren Sandbox, in der Datei-, Netzwerk-, Thread- und beliebiger Klassenzugriff blockiert ist. Wenn ein externer Systemaufruf benötigt wird, verdrahten Sie separat einen externen Anbindungs-Node wie flow_http_request.

EQL-Ausdruck

Für Kompatibilität mit bestehenden EQL-Nutzern. Unterstützt nur einen einzelnen Ausdruck (keine Mehrzeiligkeit·keine semikolongetrennte Trennung), nur Muster mit Seiteneffekten sind nutzbar.

#msg.getData().getInt('temp') > 80

Wenn mehrere Aktionen benötigt werden, verwenden Sie bitte JavaScript.

Spezifikation der JavaScript-Laufzeitumgebung

Skripte werden in einer isolierten Sandbox ausgeführt. Sie sollten genau wissen, welche Funktionen möglich/nicht möglich sind, um stabile Skripte schreiben zu können.

Verfügbar (✅)

FunktionAnmerkung
Standard-ECMAScriptvar/let/const·Funktionen·Klassen·Destrukturierung·Spread·?.·?? usw.
Objektliterale{ key: value, ... }
Array-Methodenmap / filter / reduce / forEach / find / some / every / flat / slice
String-Methodensplit / replace / includes / match / padStart / repeat
Mathematische FunktionenGesamter Math.*
JSONJSON.parse / JSON.stringify (falls data bereits ein Objekt ist, ist erneutes stringify nicht nötig)
Datenew Date() / Date.now() / getHours() / toISOString() usw.
Reguläre Ausdrücke/pattern/-Literal + RegExp-Konstruktor
Error throwthrow new Error('...') — automatische Verzweigung in FAILURE
try/catch/finallyFehlerbehandlung

Nicht verfügbar (❌)

FunktionGrund / Alternative
Netzwerkaufrufe (fetch / XMLHttpRequest)Sandbox-Blockade — separat den Node flow_http_request verdrahten
Dateisystem (require('fs'))Sandbox-Blockade
Threads (setTimeout / setInterval / Worker)Nur synchrone Ausführung erlaubt — bei benötigter Verzögerung den Node flow_delay verwenden
require / importKein Laden externer Module möglich — benötigte Funktionen müssen im selben Skript definiert werden
eval / new Function(string)Aus Sicherheitsgründen blockiert
Beliebige Java-KlassenAuch im EQL-Kompatibilitätsmodus dem Benutzercode nicht zugänglich
process / global / windowNicht definiert
WebSocket / EventSourceBlockiert — Nachrichtenempfang erfolgt über Trigger-Nodes

Ausführungsgrenzen — es gibt keine

Für Skripte sind keine Zeit-/Speicherlimits gesetzt

Ein älteres Dokument enthielt eine Tabelle mit 500 ms Ausführungszeit · 16 MB Speicher · 1024 Stack · 2 MB Ausgabe, aber keiner dieser vier Werte wird angewendet.

  • Es sieht so aus, als könnte man in der Node-Konfiguration timeout_ms verwenden, aber Skript-Nodes lesen diesen Wert nicht. (ScriptTransformNode · ScriptFilterNode lesen nur script und language.)
  • Auch im JS-Ausführungskontext sind keine Grenzen für Zeit·Anweisungsanzahl·Speicher gesetzt.

Deshalb blockiert ein Skript wie while (true) {} ununterbrochen einen Worker-Thread. Das flow-weite Limit von 30 Sekunden (flow_timeout_ms) wird geprüft, wenn die Ausführungsschleife die nächste Aufgabe entnimmt — eine Endlosschleife innerhalb des Skripts erreicht diese Prüfung nie.

Verwenden Sie nur Skripte, die von selbst enden. Vermeiden Sie Endlosschleifen·massive Wiederholungen·das Anhäufen großer Strings, und setzen Sie in Schleifen unbedingt eine Obergrenze.

Was tatsächlich blockiert ist — Sicherheits-Sandbox

Statt Zeit·Speicher sind Aktionen, die nach außen greifen, sicher blockiert.

ElementStatus
Zugriff auf Java-Klassen (z. B. Java.type)Blockiert
Datei-·Netzwerk-IOBlockiert
Thread-ErstellungBlockiert
Nativer ZugriffBlockiert
Experimentelle OptionenBlockiert
Zugriff auf Host-ObjekteNur auf der Whitelist stehende

Wenn ein externer Aufruf nötig ist, tun Sie dies nicht im Skript, sondern trennen Sie es in einen speziellen Node wie flow_http_request — im Skript funktioniert es ohnehin nicht, und bei speziellen Nodes greift timeout_ms tatsächlich.

Bündeln Sie schwere Verarbeitung nicht in einem einzigen Skript, sondern verteilen Sie sie auf mehrere Nodes.

Rückgaberegel für msg

// flow_script_transform 의 두 가지 모드
// 1) mutate 모드 (기본) — msg 객체를 직접 수정, 마지막에 msg 또는 아무 값 반환
data.foo = 'bar';
msg

// 2) return 모드 — 완전히 새 객체로 교체
return {
type: msg.type,
originator: msg.originator,
data: { ...data, foo: 'bar' },
metadata: msg.metadata
};

Standardzeit·Locale

ElementVerhalten
Zeitzone des Server-SystemsUTC (direkte Verwendung von Epoch ms empfohlen)
Anzeige koreanischer ZeittoLocaleString('ko-KR', { timeZone: 'Asia/Seoul' })
Zeitberechnung koreanischer Zeitnew Date(ts + 9*3600000).getUTCHours() oder obige Locale
Sekundengenauer TimestampMath.floor(Date.now() / 1000) * 1000

Speichersichere Schreibmuster

Skript-Nodes haben ein Speicherlimit von 16 MB, aber bei häufig aufgerufenen Nodes summiert sich ein kleines Speicherleck zu einer großen GC-Belastung des Engines. Vermeiden Sie folgende Muster.

Antipattern 1 — Closure hält große Daten fest

// ❌ 나쁜 예 — 큰 배열을 변환 함수에 캡쳐
const heavy = data.records || []; // 1만 건
const summarize = (item) => heavy.find(r => r.id === item.id);
data.matched = data.targets.map(summarize);
msg
// ✅ 좋은 예 — 인덱스 미리 만들고 함수 안에서만 사용
const index = {};
(data.records || []).forEach(r => { index[r.id] = r; });
data.matched = data.targets.map(t => index[t.id]);
data.records = undefined; // 변환 후 큰 원본 제거
msg

Antipattern 2 — Übertragung großer Arrays unverändert

// ❌ data.records 가 10,000 건이면 모든 후속 노드에서 메모리 차지
msg
// ✅ 필요한 통계만 남기고 원본 제거
data.summary = {
count: (data.records || []).length,
total: (data.records || []).reduce((s, r) => s + r.value, 0)
};
delete data.records;
msg

Antipattern 3 — Tiefe Objektkopie

// ❌ JSON.parse(JSON.stringify(obj)) 는 큰 객체에서 매우 느림
data.copy = JSON.parse(JSON.stringify(data.original));
// ✅ 얕은 복사 또는 필요한 필드만 직접 선택
data.summary = { id: data.original.id, name: data.original.name };

Antipattern 4 — Explosion regulärer Ausdrücke (Catastrophic Backtracking)

// ❌ (a+)+b 형태의 중첩 그룹은 입력에 따라 지수 시간
const re = /^(a+)+b$/;
if (re.test(data.text)) ...
// ✅ 비포획 그룹 + atomic 그룹 패턴 또는 단순 매칭
const re = /^a+b$/;
if (re.test(data.text)) ...

Antipattern 5 — Kumulative Variable let außerhalb der Funktion

// ❌ 함수 밖 let 은 매 노드 호출마다 0으로 리셋되지만, 의도와 다르게 동작 가능
let counter = 0;
data.items.forEach(() => counter++);
data.counter = counter;
// ✅ 명시적으로 함수 안에서 선언
data.counter = data.items.length; // 같은 결과, 더 명확

Antipattern 6 — Verschachteltes try/catch mit endlosen Versuchen

// ❌ 실패해도 다시 던지지 않으면 그래프가 잘못된 분기로 이동
try {
riskyCall();
} catch (e) { /* 무시 */ }
msg
// ✅ 실패 의도면 throw, 정상 의도면 명시적으로 기록
try {
riskyCall();
data.status = 'OK';
} catch (e) {
data.status = 'ERROR';
data.error_msg = e.message;
}
msg

Eine im Skript per throw ausgelöste Exception wird in den FAILURE-Zweig geleitet, wobei die Nachricht erhalten bleibt. Externe IO-Nodes haben eine eigene Verzweigung — umschließen Sie sie nicht mit try/catch.

Diagnose bei Speicherdruck

Es gibt keinen Code wie NODE_SCRIPT_OOM

Ein älteres Dokument beschrieb NODE_SCRIPT_OOM · FLOW_MSG_TRIMMED · ENGINE_GC_PRESSURE als Signal für Speicherdruck, aber das Produkt erzeugt keinen solchen Code. Es gibt weder eine Speicherobergrenze für Skripte noch eine automatische Payload-Kürzung.

Beurteilen Sie Speicherdruck nicht anhand von Code, sondern anhand von Kennzahlen und Symptomen.

Worauf achtenDruckhinweis
FLOW_EXECUTOR_DROPPED_COUNTBeginnt bei 0 anzusteigen — der Verarbeitungspool ist gesättigt und verwirft Nachrichten
FLOW_EXECUTOR_QUEUE_SIZESteigt kontinuierlich ohne Rückgang
FLOW_EXECUTION_TIMEMaximalwert steigt auf ein Vielfaches des Normalwerts
ServerlogWarnung work_queue full ... task dropped, Warnung FlowExecutor timeout
JVMZunehmende GC-Zeit · steigende Heap-Auslastung

Wenn Sie diese Signale bemerken, prüfen Sie zuerst Flows, die große Payloads verarbeiten, und stellen Sie fest, ob im Skript große Strings· Arrays angehäuft werden.


Mobile-Push-Benachrichtigungskanal

Mit dem Node flow_send_push senden Sie Push-Benachrichtigungen an die mobile App des Operators.

Node-Optionen

OptionTypStandardBeschreibung
to / to_fieldstring(mind. 1 erforderlich)Empfänger-Benutzer-ID (kommagetrennt) oder Payload-Pfad
title / title_fieldstring(mind. 1 erforderlich)Titel der Benachrichtigung (max. 50 Zeichen empfohlen)
body / body_fieldtext(mind. 1 erforderlich)Text (max. 120 Zeichen empfohlen)
priorityenumNORMALNORMAL / HIGH — HIGH wird auch auf dem Sperrbildschirm angezeigt
soundenumdefaultdefault / silent / benutzerdefinierter Ton
datajson{}Zusatzdaten, die von der App verarbeitet werden (Payload-Limit 4 KB)
deep_linkstringBildschirm, der beim Tippen auf die Benachrichtigung geöffnet wird (z. B. pp://asset/MOTOR-001)
ttl_secint86400Aufbewahrungszeit bei Nichtempfang (Sekunden) — automatisches Löschen nach Ablauf

Automatisches Token-Routing pro Benutzer

Wenn sich ein Operator zum ersten Mal in der mobilen App anmeldet, wird das Gerätetoken automatisch unter Sicherheit → API-Authentifizierungstoken registriert. Im Flow müssen Sie das Token nicht direkt handhaben, sondern nur die Benutzer-ID angeben.

  • Wenn sowohl iOS- als auch Android-Token registriert sind, erfolgt der Versand an beide Geräte
  • Ist ein Token ungültig (App deinstalliert usw.), wird die Registrierung automatisch aufgehoben

Einfaches Versandbeispiel

[flow_on_asset_alarm]
↓ where priority='ERROR'
[flow_send_push]
to_field: "metadata.responsible_user"
title: "🚨 ${metadata.asset_id} 알람"
body_field: "data.band_message"
priority: HIGH
deep_link: "pp://alarm/view/${data.alarm_id}"

Mehrsprachiger Push

// flow_script_transform — 사용자 로케일에 따라 본문 분기
const locale = metadata.user_locale || 'ko-KR';
const templates = {
'ko-KR': { title: '🚨 ${asset} 위험 알람', body: '값 ${value}, 즉시 점검 바랍니다.' },
'en-US': { title: '🚨 ${asset} Critical Alarm', body: 'Value ${value}, please inspect immediately.' },
'ja-JP': { title: '🚨 ${asset} 危険警報', body: '値 ${value}, 即時点検が必要です。' }
};
const tpl = templates[locale] || templates['ko-KR'];
data.push_title = tpl.title.replace('${asset}', metadata.asset_id).replace('${value}', data.value);
data.push_body = tpl.body.replace('${value}', data.value);
msg

Danach Verwendung als title_field=data.push_title / body_field=data.push_body von flow_send_push.

Gruppierte Benachrichtigungsbündelung (Inbox-Stil)

Mehrere Alarme auf einmal zu einer Benachrichtigung bündeln (im 5-Minuten-Takt):

[flow_on_asset_alarm]

[flow_merge window=300s]
↓ (data.merged 배열)
[flow_script_transform — 요약 만들기]
↓ data.push_body="알람 N건: A자산, B자산, ..."
[flow_send_push]

Automatische Eskalation bei Abwesenheit des Benutzers

Automatische Eskalation per SMS oder E-Mail 30 Minuten nach unbestätigtem Push.

[flow_on_asset_alarm priority=ERROR]

[flow_send_push]
↓ SUCCESS
↓ data.alert_id = response_id
[flow_delay 1800s (30분)]

[flow_http_request GET /api/alert/${alert_id}/status]
↓ (response_body.read=false 면)
[flow_script_filter (data.response_body.read === false)]
↓ TRUE
[flow_send_sms]
to_field: "metadata.responsible_phone"
text: "푸시 미확인 30분 경과: ${data.title}"

Empfehlung zur Begrenzung der Versandhäufigkeit

PrioritätEmpfohlene Häufigkeit
HIGH (Anzeige auf Sperrbildschirm)Max. 5 pro Stunde und Benutzer — zur Vermeidung von Alarmmüdigkeit
NORMALMax. 20 pro Stunde und Benutzer

Verdrahten Sie den Node flow_throttle vor dem Versand, oder senden Sie Alarme derselben Anlage erst nach Stabilisierung mit flow_debounce.


Automatische Erneuerung externer Auth-Token

Muster zur automatischen Erneuerung ablaufender Tokens wie OAuth2 beim Aufruf externer Systeme.

Einfache Erneuerung — zeitbasiert (Cron)

[flow_schedule cron='0 */50 * * * ?'] ← 50분마다 (만료 1시간 전)

[flow_http_request]
url: "https://auth.example.com/oauth2/token"
method: POST
body: "grant_type=client_credentials&client_id=${creds.client_id}&client_secret=${creds.client_secret}"

[flow_script_transform]
↓ data.access_token = data.response_body.access_token
[flow_save_attributes] ← 자격 증명 저장소에 저장
target_id: "creds:erp_api"
attributes: {"access_token": "${data.access_token}", "expires_at": ${data.response_body.expires_in * 1000 + ts}}

Danach in flow_http_request eines anderen Flows:

Headers: Authorization: Bearer ${creds:erp_api.access_token}

Proaktive Erneuerung — bei Erhalt von 401

[main flow]

[flow_http_request]
↓ SUCCESS → 정상 처리
↓ FAILURE
[flow_script_filter (response_status === 401)]
↓ TRUE
[flow_subflow target_flow_id="refresh-token"] ← 토큰 갱신

[원래 노드로 루프] ← 갱신된 토큰으로 재시도

Verwendung des Refresh Tokens

[flow_http_request]
url: "https://auth.example.com/oauth2/token"
method: POST
body: "grant_type=refresh_token&refresh_token=${creds.refresh_token}"

[flow_script_transform]
// 새 access_token + 새 refresh_token (rotation)
data.access_token = data.response_body.access_token;
data.refresh_token = data.response_body.refresh_token;
data.expires_at = Date.now() + data.response_body.expires_in * 1000;
msg

[flow_save_attributes]

Automatischer Alarm bei Ablauf-Schwelle des Tokens

[flow_schedule cron='0 0 * * * ?'] ← 매시

[flow_jdbc_query]
sql: "SELECT id, expires_at FROM credentials WHERE expires_at < NOW() + INTERVAL '1 day'"

[flow_split]

[flow_send_email]
subject: "API 토큰 만료 임박: ${data.id}"
body: "${data.id} 토큰이 ${data.expires_at} 만료 예정입니다."

Empfohlener Speicherort für Zugangsdaten

ArtEmpfohlener Speicherort
Statisch (kaum Änderungen)Zugangsdatenspeicher unter System → Einstellungen
Dynamisch (automatische Erneuerung)Mit obigem Muster über flow_save_attributes in Anlagen-Metadaten speichern
Benutzerspezifisches OAuthBildschirm Sicherheit → API-Authentifizierungstoken

Belassen Sie Zugangsdaten nicht im Klartext innerhalb des Graphen, sondern schreiben Sie sie unbedingt in Form eines Verweises auf einen externen Speicher (${creds.x}). Auch bei Export/Import werden Klartext-Token nicht in die JSON aufgenommen.


Mit der Option language wird ausgewählt, welche Sprache verwendet wird (JS oder EQL).


Ausführungshistorie

Sie können nodebezogene Ausführungsereignisse chronologisch abfragen.

Suchbedingungen

ElementBeschreibung
ZeitGibt den abzufragenden Zeitraum an
Ebene전체 / INFO / WARN / ERROR
Flow-IDFiltert nur einen bestimmten Flow
Nachrichten-IDZur Verfolgung einer einzelnen Nachricht
AnzahlLetzte 200/500/1.000 Einträge

Schneller Zeitbereich

Über die Schaltflächen oben im Zeitachsenpanel sofort navigieren: 10분전 / 30분전 / 1시간전 / 6시간전 / 12시간전 / 전체기간.

Ergebnisspalten

SpalteBeschreibung
EbeneINFO / WARN / ERROR
ZeitZeitpunkt des Ereignisses
EreignisFLOW_START / NODE_IN / NODE_OUT / NODE_ERROR / FLOW_END
Flow-IDWelcher Flow
NodeAnzeigename des Nodes
Node-Typz. B. flow_script_transform
RelationSUCCESS / FAILURE / TRUE / FALSE / MATCH / NO_MATCH / DEFAULT / THROTTLED / EXHAUSTED (alle in Großbuchstaben)
NachrichtZusammenfassung von Nachrichtentyp · Subjekt · Relation · Verarbeitungszeit · Datenvorschau

Mit der Schaltfläche CSV herunterladen können Sie das aktuelle Abfrageergebnis exportieren.

Die Aufbewahrungsdauer der Ausführungshistorie beträgt 7 Tage. Für eine langfristige Aufbewahrung laden Sie die Daten bitte in ein externes Log-System.


Allgemeiner Workflow

  1. Neuen Flow erstellen — Schaltfläche 새 플로우 in der Listenansicht → Name·Beschreibung eingeben
  2. Bearbeitungsansicht öffnen — automatisch öffnet sich eine leere Canvas
  3. Trigger-Node platzieren — Trigger-Node aus der linken Palette ziehen
  4. Verarbeitungs-Nodes hinzufügen — in der Reihenfolge Filter → Transformation → Aktion platzieren und mit Wires verbinden
  5. Node konfigurieren — jeden Node anklicken und Optionen im rechten Inspector eingeben
  6. Speichern — Schaltfläche 저장 oben rechts (automatischer Snapshot wird abgelegt)
  7. Testlauf — eine beliebige Nachricht injizieren und das Ergebnis prüfen
  8. Bereitstellen — mit dem 배포-Schalter aktivieren → automatische Ausführung bei eintreffendem Triggerereignis
  9. Überwachung — Prüfung über Live-Debug-Panel und Ausführungshistorie

Beispiel-Flows

Jedes Beispiel besteht aus einem Node-Verdrahtungsdiagramm + zentraler Node-Konfiguration + Verhaltensbeschreibung. Die Node-Konfiguration in JSON-Form entspricht 1:1 den Werten, die Sie im rechten Inspector eingeben.

Beispiel 1: Automatische Erstellung eines MES-Arbeitsauftrags

Fragt neue POs vom MES jede Minute ab und wandelt sie in Arbeitsaufträge um.

[flow_schedule: 매분]

▼ TIMER
[flow_http_request: MES /api/po/list?status=NEW]

▼ SUCCESS
[flow_split: data → 각 PO별 메시지]


[flow_script_transform: PO → WorkOrder 매핑]


[flow_create_work_order]

├── SUCCESS → [flow_log: 워크오더 생성됨]
└── FAILURE → [flow_send_email: 실패 알림]

Node-Konfiguration

NodeZentrale Konfiguration
flow_schedulecron: 0 * * * * ? (jede Minute bei 0 Sekunden)
flow_http_requestmethod: GET, url: https://mes.example.com/api/po/list?status=NEW, headers: {"Authorization":"Bearer ${MES_TOKEN}"}
flow_splitpath: data (in Array aufteilen)
flow_script_transformlanguage: JS, siehe Skript unten
flow_create_work_ordermaster_id_field: data.master_id, asset_id_field: data.asset_id, title_field: data.title
flow_send_emailto_field: metadata.alert_to, subject: [MES 동기화 실패] ${data.po}

Beispiel Script Transform

data.master_id = 'WO-MES-' + data.po;
data.title = data.product_name + ' (' + data.qty + ')';
data.asset_id = data.line_id || 'UNASSIGNED';
data.due_date = data.delivery_date;
metadata.alert_to = 'ops@example.com';
msg

Beispiel 2: Anlagenbefehl über externen Webhook auslösen

Validiert die von einem externen System gesendete HTTP-Payload und wandelt sie in einen internen Anlagenbefehl um.

[flow_on_webhook]

▼ WEBHOOK
[flow_script_filter: payload 검증]

├── TRUE

[flow_publish_asset_command]

├── SUCCESS → [flow_log]
└── FAILURE → [flow_webhook_callback: 외부에 실패 통보]

Aufrufmethode: Bei einem POST /flow/webhook/{flow_id} mit übertragenem JSON-Body wird der Trigger mit dem Body unverändert im Bereich data ausgelöst.

Beispiel Script Filter

// 인증 토큰 일치 + 필수 필드 존재 검사
if (data.token !== 'EXPECTED_TOKEN') return false;
if (!data.asset_id || !data.cmd_key) return false;
true

Beispiel 3: Alarm → automatische Erstellung eines dringenden Arbeitsauftrags

Bei Empfang eines Alarms mit Schweregrad ERROR oder höher wird für die übergeordnete Anlage ein dringender Instandhaltungsauftrag erstellt.

[flow_on_tag_alarm]

▼ ALARM
[flow_script_filter: priority = ERROR/CRITICAL]

├── TRUE

[flow_change_originator: Tag → 상위 Asset]


[flow_create_work_order: 긴급 정비]

└── SUCCESS → [flow_send_email: 정비 담당자]

Beispiel Script Filter

['ERROR', 'CRITICAL'].includes(data.priority)

Beispiel 4: Externe DB-Synchronisation — Anlagen-Massenregistrierung

Fragt neue Anlagenzeilen aus einer Legacy-DB ab und registriert sie automatisch als Anlagen.

[flow_jdbc_poll: SELECT * FROM legacy_assets WHERE sync_status='NEW']


[flow_script_transform: 컬럼 매핑]


[flow_create_asset]

├── SUCCESS → [flow_jdbc_query: UPDATE legacy_assets SET sync_status='OK' WHERE id=?]
└── FAILURE → [flow_log: ERROR + flow_send_push]

Node-Konfiguration

NodeZentrale Konfiguration
flow_jdbc_polldsn: externe DB-Verbindung, sql: SELECT * FROM legacy_assets WHERE sync_status='NEW' LIMIT 100, interval_ms: 60000
flow_create_assetasset_id_field: data.legacy_id, asset_name_field: data.name, site_id_field: data.plant_code
flow_jdbc_querysql: UPDATE legacy_assets SET sync_status='OK' WHERE id=?, params_field: data.legacy_id

Beispiel 5: Automatischer Statusübergang des Arbeitsauftrags

Führt anhand von Start-/Stopp-Ereignissen der Anlage einen automatischen Statusübergang des Arbeitsauftrags durch.

[flow_on_asset_event]

▼ ASSET_EVENT
[flow_switch: data.event_type 기준]

├── case "RUN" ─▶ [flow_start_work_order] ─▶ [flow_log]
├── case "STOP" ─▶ [flow_pause_work_order] ─▶ [flow_log]
├── case "DONE" ─▶ [flow_end_work_order] ─▶ [flow_log]
└── DEFAULT ─▶ [flow_noop]

Beispiel für Switch-Node-Cases

  • RUN: data.event_type === 'RUN'
  • STOP: data.event_type === 'STOP'
  • DONE: data.event_type === 'DONE' && data.qty_done >= data.qty_planned

Wenn der Statusübergang fehlschlägt (ungültiger aktueller Status), erfolgt automatisch eine Weiterleitung nach FAILURE, sodass Sie auch ohne separaten Filter sicher verdrahten können.

Beispiel 6: Automatische Anpassung des Alarmbands

Passt anhand einer Anlagenaggregation (z. B. 6-Stunden-Durchschnitt) das obere/untere Alarmband des Tags dynamisch an.

[flow_on_asset_aggregation]

▼ ASSET_AGGREGATION
[flow_script_transform: 통계 → 임계값 산출]


[flow_update_tag_alarm_band_numeric]

├── SUCCESS → [flow_log]
└── FAILURE → [flow_send_email: 운영자 알림]

Beispiel Script Transform

// 6h 평균 ± 3σ 를 임계값으로 사용
const mean = data.mean;
const stddev = data.stddev || 1;
data.tag_id = originator.id + '.TEMP';
data.hi = mean + 3 * stddev;
data.lo = mean - 3 * stddev;
data.hi_hi = mean + 4 * stddev;
data.lo_lo = mean - 4 * stddev;
data.use_alarm = true;
msg

Beispiel 7: Automatische Registrierung eines Edge-Geräts

Registriert bei Empfang neuer OPC-Serverinformationen diese in großer Menge im Edge-Gerät.

[flow_on_webhook] (POST 본문에 OPC + 태그 목록)


[flow_edge_opc_create]

▼ SUCCESS
[flow_split: data.tags 배열]


[flow_edge_tag_create]

▼ SUCCESS (모든 태그 등록 완료 후)
[flow_edge_opc_start]

└── SUCCESS → [flow_log: 엣지 디바이스 가동]

Beispiel für Aufrufkörper

{
"type": "WEBHOOK",
"data": {
"opc_id": "OPC-LINE-A",
"endpoint": "opc.tcp://line-a.local:4840",
"tags": [
{ "tag_id": "MOTOR-001.SPEED", "address": "ns=2;s=Motor1.Speed" },
{ "tag_id": "MOTOR-001.TEMP", "address": "ns=2;s=Motor1.Temp" }
]
}
}

Beispiel 8: Zuverlässigkeitssteigerung bei externer API (Retry)

Wendet Backoff-Wiederholung auf intermittierend fehlschlagende externe API-Aufrufe an und benachrichtigt den Operator, wenn die maximale Versuchszahl überschritten wird.

[flow_on_asset_event]


[flow_http_request: 외부 ERP API]

├── SUCCESS → [flow_log]
└── FAILURE ─▶ [flow_retry]

├── SUCCESS ─▶ (다시 flow_http_request 로 루프 결선)
└── EXHAUSTED ─▶ [flow_send_email: 'ERP 동기화 N회 실패']

Retry-Node-Konfiguration

  • max_attempts: 5
  • backoff_ms: 2000
  • backoff_multiplier: 2.0 → Intervalle von 2, 4, 8, 16, 32 Sekunden

Beispiel 9: Weiterleitung von Plugin-Ereignissen (Benachrichtigung bei niedrigem OEE)

Sendet eine Push-Benachrichtigung an den Linienmanager, wenn der OEE-Wert unter den Schwellenwert fällt.

[flow_on_oee_event]


[flow_script_filter: data.availability * data.performance * data.quality < 0.6]

├── TRUE

[flow_template: '라인 ${originator.id} OEE ${data.oee_pct}%']


[flow_send_push: 라인 매니저]

Beispiel Template

  • body: 라인 ${originator.id} OEE ${data.oee_pct}% (목표 60% 미달, 주요 손실: ${data.top_loss})

Beispiel 10: Pipeline zur Nachrichtenbereinigung (Throttle + Debounce)

Begrenzt häufige Tag-Änderungen auf 1 pro Minute und löst zusätzlich nur dann den nachfolgenden Node aus, wenn 5 Sekunden lang keine Änderung erfolgt.

[flow_on_tag_point]


[flow_throttle: max_msgs=1, window_ms=60000]

├── SUCCESS → [flow_debounce: window_ms=5000]
│ │
│ ▼
│ [flow_save_attributes]
└── THROTTLED → [flow_log: 차단됨]

Beispiel 11: Aggregation mehrerer Trigger (Merge)

Bündelt 3 Ereignistypen (OEE/RAM/EMS) in einem 30-Sekunden-Intervall zu einer einzigen Berichtsnachricht.

[flow_on_oee_event] ─┐
[flow_on_ram_event] ─┼─▶ [flow_merge: window_ms=30000]
[flow_on_ems_event] ─┘ │

[flow_script_transform: 요약 메시지 생성]


[flow_send_email: 일일 요약]

Wenn Sie mehrere Trigger-Nodes im selben Flow platzieren, werden sie alle zu Einstiegspunkten. Im data.merged-Array von flow_merge werden alle während des Fensters eingegangenen Nachrichten kumuliert.

Beispiel 12: Gemeinsame Verarbeitung als Subflow bündeln

Trennt gemeinsame Nachrichtenbereinigungslogik (Duplikatprüfung + Einheitenumrechnung + Speicherung) in einen separaten Flow und ruft ihn von mehreren Triggern auf.

Hauptflow (jeweils unabhängig)

[flow_on_tag_point] ─▶ [flow_subflow: target_flow_id=FLOW_00099]
[flow_on_asset_data] ─▶ [flow_subflow: target_flow_id=FLOW_00099]

Subflow FLOW_00099

(트리거 없음 — 호출 전용)
[flow_log: 'subflow in']


[flow_check_existence_field: data.value 존재]

├── TRUE

[flow_script_transform: 단위 변환]


[flow_save_tag_point]

Ein Subflow kann auch ohne Trigger gespeichert werden und ausschließlich für externe Aufrufe verwendet werden (beim Speichern erscheint eine Warnung).

Beispiel 13: Automatischer Versand eines Tagesberichts bei Schichtwechsel

Sendet täglich zum Ende der Nachtschicht (z. B. 06:00 Uhr) eine E-Mail mit einer Zusammenfassung von Produktion·Qualität·Ausfallzeit über den Zeitraum von gestern bis heute.

[flow_schedule: 0 0 6 * * ?] (매일 06:00)

▼ TIMER
[flow_http_request: 내부 통계 API /api/report/daily]

▼ SUCCESS
[flow_script_transform: 본문 마크다운 생성]


[flow_send_email]

Beispiel Script Transform

const r = data.report;
data.subject = `[${r.site_id}] ${r.date} 일일 운영 요약`;
data.body =
`■ 생산: ${r.qty_done}/${r.qty_planned} (${(100*r.qty_done/r.qty_planned).toFixed(1)}%)\n` +
`■ 가동률: ${r.availability}%\n` +
`■ 품질률: ${r.quality}%\n` +
`■ 다운타임 Top3:\n` +
r.downtimes.slice(0,3).map(d => ` - ${d.code} ${d.minutes}`).join('\n');
msg

Beispiel 14: Automatische Ausfallzeitaggregation

Aktualisiert bei Eingang eines STOP-Ereignisses der Anlage die kumulierte Ausfallzeit je Schicht und sendet bei Schwellenüberschreitung eine Benachrichtigung.

[flow_on_asset_event]


[flow_msg_type_filter: type in [ASSET_EVENT]]

▼ TRUE
[flow_script_filter: data.event_type === 'STOP']

▼ TRUE
[flow_script_transform: 다운타임 분 단위 계산]


[flow_save_attributes: 자산 누적 다운타임 갱신]

▼ SUCCESS
[flow_script_filter: data.shift_downtime_min > 30]

▼ TRUE
[flow_send_push: '시프트 다운타임 30분 초과']

Beispiel 15: Automatische Isolation einer Qualitätsfehlerlinie

Bei 5 oder mehr aufeinanderfolgend gemeldeten Fehlern in der Qualitätsprüfung wird der Anlagenlinie ein Stoppbefehl erteilt und der Arbeitsauftrag abgebrochen.

[flow_on_asset_event] (event_type=QUALITY_FAIL)


[flow_script_transform: data.consecutive_fail = (... + 1)]


[flow_save_attributes]

▼ SUCCESS
[flow_script_filter: data.consecutive_fail >= 5]

▼ TRUE
[flow_publish_asset_command: cmd_key='STOP']


[flow_abort_work_order: abort_code='QUALITY']

└── SUCCESS → [flow_send_email: 품질 매니저 + 라인 매니저]

Beispiel 16: Überschreitung des Energieschwellenwerts — Empfehlung zur vorübergehenden Linienstilllegung

Sendet dem Operator eine SMS mit Handlungsempfehlung, wenn der Stundenenergieverbrauch der Linie das Budget übersteigt.

[flow_on_ems_event]


[flow_script_filter: data.power_kwh > data.budget_kwh * 1.2]

▼ TRUE
[flow_template: '${originator.id} 시간당 ${data.power_kwh}kWh (예산 ${data.budget_kwh}kWh 초과)']


[flow_send_sms]

└── SUCCESS → [flow_save_attributes: 자산에 마지막 경고 시각 기록]

Beispiel 17: Bidirektionale Synchronisation mit externem System — Spiegelung des Arbeitsauftragsstatus

Synchronisiert den vom externen ERP eingehenden Status bidirektional mit dem internen Arbeitsauftragsstatus.

Abwärts (ERP → intern)

[flow_on_mqtt_subscribe: erp/work-order/status]


[flow_script_transform: 메시지 → 도메인 매핑]


[flow_switch: data.status]

├── case "STARTED" ─▶ [flow_start_work_order]
├── case "PAUSED" ─▶ [flow_pause_work_order]
├── case "DONE" ─▶ [flow_end_work_order]
└── DEFAULT ─▶ [flow_log: WARN]

Aufwärts (intern → ERP)

[flow_on_entity_event] (originator.entity_type=Order)


[flow_msg_type_filter: type in [ENTITY_UPDATED]]

▼ TRUE
[flow_template: ERP 형식으로 변환]


[flow_mqtt_publish: erp/work-order/status]

Um bei bidirektionaler Synchronisation Endlosschleifen zu vermeiden, kennzeichnen Sie die Nachrichtenherkunft mit einem Schlüssel wie metadata.source und filtern Sie in der Triggerstufe eigene, selbst publizierte Nachrichten heraus.


Import/Export

Flow-Definitionen können als JSON serialisiert werden, um sie in andere Umgebungen zu portieren oder zu sichern.

AktionOrtBeschreibung
ExportierenSchaltfläche 내보내기 oben in der BearbeitungsansichtLädt Graph + Nodes + Wires + Node-Konfiguration vollständig als JSON herunter
ImportierenSchaltfläche 가져오기 oben in der ListenansichtJSON-Text einfügen oder hochladen
Automatischer SnapshotAutomatisch beim SpeichernWird beim Speichern des Graphen versionsweise abgelegt (für Rollback)

Verhalten beim Importieren

  • Es wird immer eine neue Flow-ID vergeben (zum Schutz vor Überschreiben der bestehenden ID)
  • Auch Node-IDs werden neu vergeben, die Wire-Verknüpfungen werden automatisch neu abgebildet
  • Ein soeben importierter Flow wird im aufgehobenen Zustand abgelegt; der Operator muss ihn nach Prüfung selbst bereitstellen

Fehlerbehandlung

Auf Node-Ebene

  • Tritt während der Node-Verarbeitung eine Exception auf, erfolgt automatisch eine Weiterleitung über die FAILURE-Relation.
  • Ist am FAILURE-Ausgang kein Node angeschlossen, wird die Nachricht verworfen (drop) und nur ein Fehlerlog verbleibt.
  • Nachrichten, die dem *_pattern des Trigger-Nodes nicht entsprechen, werden als SKIPPED behandelt und nicht an nachfolgende Nodes weitergegeben; sie werden auch nicht im Verarbeitungs-/Fehlerzähler mitgezählt.
  • Alle Fehler werden im Live-Debug-Panel und in der Ausführungshistorie angezeigt.

Auf Flow-Ebene

ElementStandardBeschreibung
max_depth100Begrenzt die kumulierte Anzahl der Node-Besuche während der Verarbeitung einer Nachricht
max_revisit3Begrenzt die Anzahl der Wiederbesuche desselben Nodes (verhindert Endlosschleifen bei Zyklen)
flow_timeout_ms30.000Erzwungener Abbruch bei Überschreitung der Verarbeitungszeit

Wiederholung bei externen IO-Nodes

HTTP·Kafka·externe DB usw. externe IO-Nodes können mit den Optionen retry_count / retry_delay_ms eine sofortige interne Wiederholung durchführen; bei Fehlschlag aller Wiederholungen erfolgt eine Weiterleitung über die FAILURE-Relation. Falls ein feiner abgestimmter Backoff oder eine EXHAUSTED-Zweigbehandlung benötigt wird, verwenden Sie separat den flow_retry-Node.


Betriebsdiagnose

Administratoren können im Systemmenü den Status der Dispatch-Warteschlange der Flow-Engine einsehen (Worker-Betrieb, Warteschlangengröße, kumulierte Verarbeitungs-/Fehler-/Drop-Anzahl, letzter Fehler).

Der Server prüft im Hintergrund periodisch die Last des Flow-Worker-Pools; bleibt die Last über einen bestimmten Zeitraum bestehen, wird im Betriebsprotokoll eine Statusänderung (HEALTHYDEGRADEDCRITICAL) in einer Zeile protokolliert. Bei Wiederherstellung des Normalzustands wird zusätzlich ein Wiederherstellungslog protokolliert.


Berechtigungen

Flow führt kein eigenes Berechtigungsmodell ein, sondern nutzt unverändert die bestehende Systemauthentifizierung/-berechtigung.

FunktionErforderliche Berechtigung
Listenabfrage / Ausführungshistorie abfragenAlle authentifizierten Benutzer
Flow erstellen·bearbeiten·bereitstellen·löschenADMIN
Import/Export / Alle neu bereitstellenADMIN

Betriebsmuster (Recipes)

Eine Bibliothek häufig verwendeter Verdrahtungsformen. Jedes Muster können Sie unverändert kopieren und als Ausgangspunkt eines neuen Flows verwenden.

Muster 1 — Verarbeitung + Benachrichtigungsverzweigung

Doppelte Verzweigung: bei Erfolg Speicherung, bei Fehlschlag Benachrichtigung.

[Action Node]
├── SUCCESS → [flow_log] / [flow_save_attributes] / ...
└── FAILURE → [flow_send_email] / [flow_send_push]

Muster 2 — Sicherer Wiederholungsversuch

Konfiguriert Backoff + EXHAUSTED-Handler, damit externe IO robust gegen vorübergehende Fehler ist.

[risky_node] ─[FAILURE]→ [flow_retry] ─[SUCCESS]→ (risky_node 로 루프)
└[EXHAUSTED]→ [에러 핸들러]

Muster 3 — Lastblockierung durch Vorabfilter

Reduziert nachfolgendes Verarbeitungsvolumen durch Vorfilterung der Nachrichten in der Triggerstufe mit *_pattern. Nicht dem Muster entsprechende Nachrichten werden als SKIPPED behandelt und nicht im Zähler mitgezählt.

[flow_on_tag_point] (옵션 tag_id_pattern: "MOTOR-*.SPEED")


[필터/변환/액션 ...]

Muster 4 — Mehrfachverzweigung nach Case

Verzweigt je nach Status/Typ in mehrere Richtungen.

[flow_switch] (case별 boolean 표현식)
├── case A → [...]
├── case B → [...]
└── DEFAULT → [...]

Muster 5 — Fensteraggregation + einmaliges Emit

Sammelt hochfrequente Eingaben über einen bestimmten Zeitraum und wandelt sie in eine Nachricht um.

[High-rate Trigger]


[flow_merge: window_ms=10000] → data.merged 배열에 누적


[flow_script_transform: 요약]


[Action / 외부 발송]

Muster 6 — Retry + Umgehung nach Erreichen der Wiederholungsgrenze

Weicht nach Ende der Wiederholungsversuche auf einen alternativen Pfad (andere API, Benachrichtigung, DB-Speicherung) aus.

[Primary HTTP] ─[FAILURE]→ [flow_retry]
├─[SUCCESS] → (Primary HTTP)
└─[EXHAUSTED] → [Backup HTTP] ─[FAILURE]→ [flow_log/Email]

Muster 7 — Nachfolgende Aktion nach Domänenwechsel

Wandelt einen Tag-bezogenen Alarm in einen Anlagen-bezogenen um und delegiert die Verarbeitung an die jeweilige Anlage.

[flow_on_tag_alarm]


[flow_change_originator: Tag → Asset]


[자산 단위 액션 (Create Work Order / Publish Asset Event 등)]

Muster 8 — Kombination aus Throttle + Debounce

Throttle auf höchstens 1× pro Minute + Verarbeitung nur bei ausbleibender Änderung über 5 Sekunden.

[High-rate Trigger]


[flow_throttle: max_msgs=1, window_ms=60000]

▼ SUCCESS
[flow_debounce: window_ms=5000]


[Action]

Muster 9 — Modularisierung gemeinsamer Logik als Subflow

Trennung in einen Subflow, wenn mehrere Einstiegspunkte dieselbe nachfolgende Verarbeitung (Validierung·Bereinigung·Speicherung) teilen müssen.

메인1: [Trigger A] → [flow_subflow: target=FLOW_99]
메인2: [Trigger B] → [flow_subflow: target=FLOW_99]

서브 (FLOW_99): (트리거 없음)
[검증] → [정제] → [적재]

Muster 10 — Umgehung des direkten Triggers

Um das Ergebnis eines Flows als Eingabe für den nächsten Flow fließen zu lassen, mit flow_dds_publish auf den Domänenkanal publizieren; der andere Flow empfängt denselben Nachrichtentyp als Trigger.

플로우 A: [...] → [flow_dds_publish: type=ASSET_EVENT, originator=...]
플로우 B: [flow_on_asset_event] → [...]

Anwendungsbeispiele (Übersicht)

SzenarioAufbau
MES-Anbindungflow_scheduleflow_http_requestflow_script_transformflow_create_work_order
Ereignisweiterleitung nach außenflow_on_asset_eventflow_msg_type_filterflow_mqtt_publish
Datenbereinigung·-speicherungflow_on_tag_pointflow_script_transformflow_save_tag_point
Alarmautomatisierungflow_on_tag_alarmflow_script_filterflow_send_email + flow_create_work_order
Externe DB-Synchronisationflow_jdbc_pollflow_script_transformflow_create_asset
Webhook-Empfangflow_on_webhookflow_script_filterflow_publish_asset_command
Automatische Anpassung des Alarmbandsflow_on_asset_aggregationflow_script_transformflow_update_tag_alarm_band_numeric
Automatisierung des Arbeitsauftragsstatusflow_on_asset_eventflow_switchflow_start/end/pause/resume_work_order
Zuverlässigkeitssteigerung der APIflow_http_request ─FAILURE→ flow_retry ─SUCCESS→ Schleife / EXHAUSTED→ Benachrichtigung
Benachrichtigung bei niedrigem OEEflow_on_oee_eventflow_script_filterflow_templateflow_send_push
Massenregistrierung von Edgesflow_on_webhookflow_edge_opc_createflow_splitflow_edge_tag_createflow_edge_opc_start
Hochfrequenzbereinigungflow_throttleflow_debounce → Folgeschritt
Aggregation mehrerer Ereignissemehrere Trigger → flow_merge → Zusammenfassungstransformation → Versand

Schrittweiser Debugging-Leitfaden

Das Standardverfahren, dem Sie folgen sollten, wenn ein Flow nicht wie beabsichtigt funktioniert.

Schritt 1 — Auslöseprüfung

Prüfen Sie in der Listenansicht, ob die Ausführungsanzahl des betreffenden Flows steigt.

BeobachtungBedeutung·nächste Aktion
Zähler ist 0Trigger löst nicht aus. Prüfen Sie den Bereitstellen-Status des Flows + Trigger-Node-Verdrahtung + Option *_pattern
Zähler steigt, aber auch die Fehler steigen mitFehlschlag im Aktions-Node. Weiter zu Schritt 2
Zähler steigt, aber Folgeverarbeitung erfolgt nichtFehlende Verzweigungsverdrahtung. Alle Ausgänge wie FAILURE/THROTTLED/EXHAUSTED überprüfen

Schritt 2 — Nodeweisen Ablauf mit Live-Debug prüfen

Öffnen Sie die Bearbeitungsansicht und aktivieren Sie das Live-Debug-Panel (Aktualisierung alle 2 Sekunden).

BeobachtungBedeutung
LED eines bestimmten Nodes bleibt grauNachricht erreicht ihn nicht — im vorherigen Node wurde in FAILURE verzweigt oder im Filter blockiert
LED rot + ERROR-ZeileException während der Node-Verarbeitung. Feld data.error der Nachricht und NODE_ERROR-Ereignis in /flow/log prüfen
LED grün, aber nächster Node grauDiskrepanz beim Ausgangs-Relation-Label. Prüfen, ob das Wire-Label genau der Ausgangs-Relation des Nodes (SUCCESS/TRUE usw.) entspricht

Schritt 3 — Nachrichtenverfolgung über die Ausführungshistorie

Verfolgen Sie im Bildschirm /flow/log den gesamten Ablauf einer einzelnen Nachricht anhand der Nachrichten-ID.

  • Im Nachrichten-ID-Filter die aus Live-Debug gesehene msg_id eingeben
  • Chronologisch sortieren in der Reihenfolge FLOW_STARTNODE_INNODE_OUTFLOW_END
  • Wenn NODE_ERROR erscheint, ist der error_message dieses Nodes die Ursache

Schritt 4 — Node-Konfiguration prüfen

Häufige Fehler:

FehlerPrüfung
Tippfehler im *_field-PfadStimmt data.tag_id? Ist es metadata.tag_id? Tatsächlichen Schlüssel über die Nachrichtenvorschau im Live-Debug prüfen
${...}-Vorlagenvariable nicht ersetztPrüfen, ob der Variablenpfad in der Nachricht existiert, ob kein Tippfehler vorliegt
Timeout bei externem IOtimeout_ms erhöhen. Antwortzeit des externen Systems selbst
Berechtigungs-·Auth-HeaderPrüfen, ob das JSON-Format von headers korrekt ist, ob das Token gültig ist

Schritt 5 — Isolierter Test

Verschieben Sie den problematischen Node allein in einen neuen temporären Flow und lassen Sie mit Testlauf nur eine Nachricht auslösen, um das Ergebnis isoliert zu validieren. Funktioniert er dort normal, ist die Verdrahtung·Nachrichtenform der vorherigen Stufe im ursprünglichen Flow verdächtig.

Schritt 6 — Nach Zurücksetzen der Zähler reproduzieren

Nach Zurücksetzen aller Zähler nur eine Nachricht auslösen — mit sauberer Statistik reproduziert wird das Problem klarer.


Häufige Probleme

SymptomUrsache·Maßnahme
Trigger löst nicht ausPrüfen, ob der Flow bereitgestellt ist, ob *_pattern des Trigger-Nodes nicht zu eng ist. Bei Zeitplan-/externen Abo-Nodes nach Alle neu bereitstellen erneut versuchen
Live-Debug ist leerPrüfen, ob der Nachrichtenzähler nicht steigt — nicht dem Trigger-Muster entsprechende Nachrichten (SKIPPED) werden nicht im Zähler mitgezählt. Auch prüfen, ob der Pause-Schalter oben im Panel aktiviert ist
Zählerwert kumuliert sich abnormalMit der Schaltfläche Alle Zähler zurücksetzen oben rechts in der Node-Konfiguration das Statistikfenster zurücksetzen
Dieselbe Nachricht wird wiederholt verarbeitetVerdacht auf einen Zyklus. Ein Wiederbesuch desselben Nodes ist nur innerhalb der Standardgrenze von 3× (max_revisit) erlaubt. Mit flow_subflow trennen und die Eingabemenge über flow_throttle/flow_debounce anpassen
Aufruf des externen Systems schlägt intermittierend fehlBackoff-Wiederholung über die Optionen retry_count/retry_delay_ms des Nodes oder über den Node flow_retry verdrahten
Zeitplan funktioniert nach Import nichtAlle neu bereitstellen oben in der Liste ausführen
Nach Ausführung des Update-Nodes bleiben einige Felder unverändertBeabsichtigtes Verhalten. Der Update-Node aktualisiert nur die eingegebenen Felder und lässt die übrigen unverändert. Für eine vollständige Aktualisierung Delete + Create kombinieren
Create-Node schlägt mit NOT-NULL-Fehler fehlPrüfen Sie in der Node-Konfiguration, ob der dynamische Optionspfad *_field in der Nachricht tatsächlich existiert. Einige NOT-NULL-Spalten werden automatisch ergänzt, aber Kern-IDs (z. B. asset_id, tag_id) müssen Sie direkt befüllen
flow_kafka_publish / flow_mqtt_publish wird nicht publiziertVerbindungsdaten des externen Brokers (bootstrap_servers/broker_url) und Topic-Berechtigungen prüfen. flow_log daneben verdrahten, um zu prüfen, ob die Nachricht unmittelbar vor der Publikation ankommt
flow_http_request antwortet nichttimeout_ms (Standard 5000) erhöhen und den Body direkt als ${msg.data.x}-Form in body_template angeben. Die Antwort wird in data.response_status / data.response abgelegt
flow_retry wird nicht erneut versuchtFall einer fehlerhaften Verdrahtung. Der SUCCESS-Ausgang von flow_retry muss zurück zum ursprünglich fehlgeschlagenen Node verdrahtet sein, damit ein erneuter Versuch stattfindet (siehe Muster 2 unten)
Eine Zeile wie flow_jdbc_poll wird jedes Mal erneut eingelesenDie Bedingung WHERE der Polling-SQL muss eine Statusaktualisierung nach der Verarbeitung enthalten (z. B. WHERE sync_status='NEW' + am Ende desselben Flows UPDATE ... sync_status='OK' über flow_jdbc_query)
Kann keinen direkten Alarm-Trigger-Node findenBeabsichtigter Ausschluss. Alarme müssen ausschließlich über den flow_create_alarm_config-Pfad entstehen, damit die Konsistenz der Alarmhistorie gewahrt bleibt
Skript-Node schlägt mit einem Zugriffsfehler auf Java class fehlWird in der Skript-Sandbox blockiert. Für externe Aufrufe verdrahten Sie einen separaten externen Anbindungs-Node
Statusübergangs-Node des Arbeitsauftrags liefert nur FAILUREDer aktuelle Status ist kein Startstatus, der einen Übergang zulässt. Beispiel: flow_pause_work_order funktioniert nur im Status START. Status vorab mit flow_check_existence_field / flow_script_filter prüfen
Testlauf funktionierte, aber der Graph blieb im geänderten ZustandDer Testlauf löst immer die gespeicherte Version aus. Um Änderungen zu validieren, zuerst speichern → dann Testlauf
Importierter Flow ist im inaktiven ZustandBeabsichtigtes Verhalten. Nach Prüfung den Bereitstellen-Schalter selbst aktivieren

Häufig gestellte Fragen (FAQ)

Häufige Fragen, wenn Operatoren Flow zum ersten Mal nutzen.

F: Kann ich mehrere Trigger in einem Flow platzieren? A. Ja. Wenn Sie mehrere Trigger-Nodes im selben Flow platzieren, werden alle zu Einstiegspunkten und lösen jeweils unabhängig aus. In Kombination mit flow_merge können Sie mehrere Ereignistypen zu einer gemeinsamen Folgeverarbeitung zusammenführen.

F: Kann ich auch einen Flow ohne Trigger erstellen? A. Ja. Beim Speichern erscheint eine Warnung, aber der Flow wird gespeichert. Sie können ihn als „Bibliotheks"-Form nutzen, die nur über Testlauf oder den Aufruf flow_subflow eines anderen Flows ausgelöst wird.

F: Kann eine Nachricht mehrere Nodes gleichzeitig durchlaufen? A. Ja. Wenn Sie am Ausgangsport eines Nodes mehrere Wires verbinden, wird dieselbe Nachricht gleichzeitig verzweigt und an alle nachfolgenden Nodes weitergeleitet.

F: Kann der Transformations-Node die Nachricht selbst erzeugen und in eine andere Nachricht umwandeln? A. Ja. In flow_script_transform können msg.type, msg.originator, msg.data, msg.metadata alle frei geändert werden. Selbst wenn Sie die Nachricht wie einen anderen Triggertyp aussehen lassen, wird dadurch nicht automatisch ein anderer Flow aufgerufen (die ursprüngliche Trigger-Zuordnung bleibt erhalten). Um einen anderen Flow aufzurufen, verwenden Sie flow_subflow oder flow_dds_publish.

F: Wie viele automatische Snapshots werden aufbewahrt? Kann ich sie selbst wiederherstellen? A. Bei jedem Speichern des Graphen wird automatisch einer abgelegt, die Aufbewahrungsrichtlinie richtet sich nach der Betriebsumgebungskonfiguration. Eine UI zur direkten Wiederherstellung im Bildschirm wird nicht angeboten; bei Bedarf können Sie den Administrator bitten, auf eine bestimmte Version zurückzusetzen. Am sichersten ist es, vor Änderungen mit 내보내기 die JSON-Datei extern zu sichern.

F: Wie lange wird die Ausführungshistorie aufbewahrt? A. Standardmäßig 7 Tage. Für eine langfristige Aufbewahrung nutzen Sie flow_kafka_publish oder flow_jdbc_query, um die Daten in ein externes Log-System zu laden.

F: Ich möchte nur die Statistik eines Flows separat zurücksetzen. A. Verwenden Sie Fehlerzähler zurücksetzen (nur Fehler) oder Alle Zähler zurücksetzen (gesamt) oben rechts in der Node-Konfiguration der Bearbeitungsansicht. Andere Flows werden davon nicht beeinflusst.

F: Ich möchte einen Flow in eine andere Umgebung (Entwicklung/Staging/Produktion) verschieben. A. Laden Sie die JSON über 내보내기 in der Bearbeitungsansicht herunter und laden Sie sie über 가져오기 in der Listenansicht der Zielumgebung hoch. Ein importierter Flow wird immer mit einer neuen ID + im aufgehobenen Zustand abgelegt, sodass der Operator ihn nach Prüfung selbst bereitstellen kann.

F: Dieselbe Payload wird zweimal verarbeitet. Wie kann ich das verhindern? A. Grenzen Sie in der Triggerstufe mit *_pattern ein, oder begrenzen Sie die Häufigkeit mit flow_throttle/flow_debounce. Bei externen Eingaben (Webhook·MQTT) verwenden Sie auf der Sendeseite einen Idempotenzschlüssel und filtern Duplikate mit flow_check_existence_field oder einem Filter auf Basis der Nachrichten-ID.

F: Ist eine zyklische (Loop-)Verdrahtung sicher? A. Ein beabsichtigter Zyklus wie flow_retry ist sicher. Nicht beabsichtigte Zyklen werden durch max_revisit (Standard 3×) automatisch blockiert. Es empfiehlt sich jedoch, im laufenden Betrieb den Ablauf mit flow_log zu visualisieren, um unbeabsichtigte Zyklen frühzeitig zu erkennen.

F: Werden Flow-Änderungen in Echtzeit übernommen? A. Sie werden sofort beim Speichern des Graphen wirksam. Trigger mit eigenem Scheduler wie Zeitplan·externes Abonnement·externes DB-Polling müssen jedoch über Alle neu bereitstellen oder den Wechsel Aufheben→Bereitstellen erneut registriert werden.

F: Kann ich die ID eines bereits registrierten Nodes ändern? A. Die Node-ID wird vom System automatisch vergeben. Der Anzeigename kann im Konfigurationsformular des Nodes geändert werden, und dieser wird in Live-Debug·Ausführungshistorie angezeigt.

F: Können nicht berechtigte Benutzer einen Flow versehentlich ändern? A. Erstellen·Bearbeiten·Bereitstellen·Löschen eines Flows erfordert die ADMIN-Berechtigung. Normale Benutzer können nur die Listenabfrage und die Abfrage der Ausführungshistorie durchführen.


Bewährte Betriebspraktiken

Grundsätze, die Sie beim sicheren Betrieb von Flow in der Produktion beachten sollten.

Lastmanagement

  • Filtern Sie in der Triggerstufe mit *_pattern vorab, um das nachfolgende Verarbeitungsvolumen zu reduzieren. Tag-Points, die jede Minute zehntausendfach eingehen, sind der teuerste Einstiegspunkt.
  • Kombinieren Sie externe Systemaufrufe (flow_http_request/flow_jdbc_query usw.) mit flow_throttle / flow_debounce, um die externe Last zu steuern.
  • Wenn mehrere Folge-Nodes an derselben Eingabe hängen müssen, trennen Sie diese über flow_subflow, um die Gesamtzahl der Graph-Nodes zu reduzieren. Je mehr Nodes vorhanden sind, desto höher auch die Kosten des Live-Debug-Pollings.
  • Aktivieren Sie den Debug-Modus nur in der Betriebsvalidierungsphase. Je mehr Daten geladen werden, desto schneller füllt sich das 7-Tage-Fenster der Ausführungshistorie.

Sicheres Schreiben

  • Verdrahten Sie an jedem Aktions-Node unbedingt einen FAILURE-Zweig (mindestens ein flow_log). Ist FAILURE leer, wird die Nachricht stillschweigend verworfen, was die Fehlerverfolgung erschwert.
  • Kombinieren Sie externe IO-Nodes nach Möglichkeit mit flow_retry, um vorübergehende Störungen abzufangen.
  • Der Update-Node aktualisiert nur die eingegebenen Felder (Teilaktualisierung). Für eine vollständige Überschreibung nutzen Sie die Kombination Delete + Create.
  • Ein Graph ohne Trigger-Node dient ausschließlich für manuellen Testlauf. Prüfen Sie beim Speichern die Warnung, um nicht versehentlich einen Trigger zu vergessen.
  • Erstellen Sie Zyklen (Verdrahtungen, die zum selben Node zurückführen) nur in beabsichtigter Form wie flow_retry; ansonsten schützt max_revisit, aber visualisieren Sie verdächtige Graphen mit flow_log.

Änderungsverfahren (Change Management)

Empfohlene Reihenfolge bei Änderungen an einem produktiv laufenden Flow.

  1. Sicherung — Laden Sie den aktuellen Graphen mit 내보내기 in der Bearbeitungsansicht als JSON-Datei herunter und bewahren Sie ihn auf (automatische Snapshots werden ebenfalls abgelegt, aber eine externe Aufbewahrung ist sicherer).
  2. Duplizieren oder in neuem Flow arbeiten — Nehmen Sie Änderungen eher in einem neuen Flow (oder einer per Import erstellten Kopie) vor und validieren Sie diese, statt den laufenden Flow sofort zu bearbeiten.
  3. Testlauf — Injizieren Sie direkt JSON-Nachrichten, um alle Zweige (SUCCESS/FAILURE/EXHAUSTED usw.) einmal auszulösen, und prüfen Sie das Ergebnis in der Ausführungshistorie.
  4. Übernahme in den Betrieb — Übertragen Sie die validierte Graph-JSON via 내보내기 → in der Produktionsumgebung 가져오기 → nach Prüfung durch den Operator den Bereitstellen-Schalter.
  5. Rollback bei Problemen — Sofort mit dem Aufheben-Schalter deaktivieren. Da automatische Snapshots abgelegt wurden, kann ein Entwickler beauftragt werden, auf die vorherige Version zurückzusetzen.

Nutzung von Zählern·Statistiken

  • Wenn die Verlaufs-Sparkline in der Listenansicht plötzlich abflacht, prüfen Sie eine mögliche fehlende Triggerauslösung oder SKIPPED-Behandlung.
  • Bei einem abnormalen Fehlerraten-Donut-Diagramm sollten Sie den *_field-Pfad in der Node-Konfiguration überprüfen. Fehlt ein Schlüssel in der Nachrichten-Payload, kommt es häufig zu Fehlschlägen.
  • Setzen Sie nach der Betriebsvalidierung das Statistikfenster mit Alle Zähler zurücksetzen zurück, um die normale Baseline neu zu messen.

Notfallmaßnahmen

Schrittweises Verfahren, das Sie bei Problemen im laufenden Betrieb schnell anwenden sollten.

Szenario 1 — Bestimmter Flow läuft Amok (Nachrichtenflut)

Symptom: Die Ausführungsanzahl eines Flows steigt gegenüber dem Normalwert um das Zehn- bis Hundertfache, gleichzeitig steigen auch die Fehler

Maßnahme

  1. Deaktivieren Sie den betreffenden Flow sofort mit dem Aufheben-Schalter (in der Listenansicht 1 Sekunde)
  2. Prüfen Sie im Live-Debug-Panel·Ausführungshistorie, welcher Trigger die Flut verursacht hat
  3. Grenzen Sie die Option *_pattern des Trigger-Nodes ein oder verdrahten Sie unmittelbar danach flow_throttle / flow_debounce
  4. Bei Bedarf mit flow_check_existence_field oder flow_msg_type_filter auf bestimmte Nachrichtentypen begrenzen
  5. Nach der Korrektur mit Testlauf reproduzieren → nach Bestätigung des Normalzustands Bereitstellen wieder aufnehmen

Szenario 2 — Massenausfall durch Störung eines externen Systems

Symptom: Fehler an externen IO-Nodes wie HTTP/Kafka/externer DB häufen sich gleichzeitig

Maßnahme

  1. Bei größerem Auswirkungsbereich die betroffenen Flows gebündelt aufheben (in der Listenansicht mehrfach auswählen und gebündelt aufheben)
  2. Wiederherstellung des externen Systems bestätigen
  3. Bei externen IO-Nodes ohne flow_retry-Verdrahtung diese ergänzen
  4. Bei verlangsamter Antwort des externen Systems timeout_ms anpassen
  5. Je nach Betriebsumgebung Alle neu bereitstellen ausführen und danach Bereitstellen wieder aufnehmen

Szenario 3 — Endlosschleife durch Zyklus

Symptom: Eine einzelne Nachricht durchläuft kontinuierlich denselben Node, Verarbeitungszeit kumuliert sich

Maßnahme

  1. Durch den max_revisit-Schutz wird zwar automatisch nach maximal 3 Wiederbesuchen blockiert, aber prüfen Sie zur Betriebssicherheit trotzdem nach dem Aufheben
  2. Verfolgen Sie den Zyklus visuell im Graphen (Wires in der Bearbeitungsansicht nachverfolgen)
  3. Bei beabsichtigter Schleife (flow_retry) prüfen, ob max_attempts angemessen ist
  4. Bei unbeabsichtigtem Zyklus die Verdrahtung entfernen oder mit flow_check_relation eine Verzweigung hinzufügen
  5. Nach der Korrektur Alle Zähler zurücksetzen → erneut bereitstellen

Szenario 4 — Verdacht auf Datenbeschädigung (fehlerhafte automatische Aktualisierung)

Symptom: Domänendaten wurden durch Automatisierung unbeabsichtigt aktualisiert

Maßnahme

  1. Betreffenden Flow sofort aufheben
  2. Extern gesicherte vorherige Graph-JSON heranziehen oder die vorherige Version aus dem automatischen Snapshot prüfen (mit Unterstützung des Administrators)
  3. Graph analysieren: unbeabsichtigte Update-Node-Verdrahtung·fehlerhafter *_field-Pfad·Fehler in der Skript-Transformation prüfen
  4. Betroffene Domänendaten über ein separates Verfahren im Back-Office-Bildschirm korrigieren
  5. Den korrigierten Graphen mit Testlauf validieren und erneut bereitstellen

Szenario 5 — Stopp während Systeminspektion·Wartung

Symptom: Externe IO-Aufrufe sollen während der Wartungszeit eines externen Systems vorübergehend gestoppt werden

Maßnahme

  1. Betroffene Flows gebündelt aufheben (Mehrfachauswahl in der Liste)
  2. Nach Ende der Wartung Bereitstellen wieder aufnehmen
  3. Bei Triggern mit eigenem Scheduler (Zeitplan·externes MQTT-Abonnement·externes DB-Polling) einmal Alle neu bereitstellen ausführen und die ordnungsgemäße Registrierung bestätigen

Szenario 6 — Live-Debug-Warteschlange voll

Symptom: Warteschlangengröße in der Betriebsdiagnoseseite nahe der Schwelle, Drop-Anzahl steigt

Maßnahme

  1. Reduzieren Sie die Anzahl der Flows mit aktiviertem Debug-Modus und die geladene Menge (schalten Sie den Debug-Modus bei validierten Flows aus)
  2. Reduzieren Sie mit *_pattern in der Triggerstufe das nachfolgende Verarbeitungsvolumen selbst
  3. Wenn das System automatisch in den Erholungsmodus wechselt, wird im Lastwächter ein Log mit DEGRADED/CRITICAL protokolliert — teilen Sie dies dem Administrator mit

Bei allen Szenarien lautet die Priorität stets sofort aufheben → Ursache klären → korrigieren → validieren → erneut bereitstellen. Beachten Sie ergänzend auch das Änderungsverfahren.


Sicherheit·Umgang mit sensiblen Daten

Da Flow sensible Ein-/Ausgaben wie externe API-Aufrufe·E-Mail/SMS-Versand·Webhook-Empfang verarbeitet, beachten Sie bitte folgende Grundsätze.

Token·Zugangsdaten

  • Geben Sie API-Token·Passwörter nicht im Klartext direkt in der Node-Konfiguration ein. Verwenden Sie eine Umgebungsvariablen-Ersetzung in der Form ${ENV_VAR}, um sie aus dem Geheimnisspeicher der Betriebsumgebung einzuspeisen.
  • Trennen Sie die Token-Position innerhalb der headers-JSON möglichst als Umgebungsvariable ab, damit das Token in der Produktionsumgebung nicht offengelegt wird.
// 권장
{ "Authorization": "Bearer ${MES_TOKEN}" }

// 비권장
{ "Authorization": "Bearer eyJhbGciOi..." }

Schutz des Webhook-Eintrittspunkts

flow_on_webhook ist ein interner Einstiegspunkt, der von authentifizierten Benutzern aufgerufen wird; wenn Sie ihn jedoch extern zugänglich machen, verdrahten Sie unbedingt einen Filter zur Payload-Validierung.

// flow_script_filter — 토큰 + 필수 필드 검사
if (data.token !== '${WEBHOOK_TOKEN}') return false;
if (!data.asset_id || !data.cmd_key) return false;
true

Maskierung sensibler Daten

Im Live-Debug-Panel und in der Ausführungshistorie wird eine Nachrichtenvorschau angezeigt. Maskieren Sie personenbezogene Daten (Name·Kontakt·Konto) und Token unmittelbar vor der Speicherung.

// 디버그/로그 적재 직전 변환
data.email_masked = data.email
? data.email.replace(/(.{2}).+(@.+)/, '$1***$2') : null;
delete data.email;
delete data.token;
msg

Verarbeitung des Antwortkörpers bei externem IO

Bei data.response von flow_http_request wird der gesamte Antwortkörper geladen. Enthält die Antwort sensible Daten, extrahieren Sie sofort mit einem nachfolgenden Transformations-Node nur die benötigten Schlüssel und entfernen Sie das Original.

// 응답에서 필요한 필드만 보존
data = { id: data.response_obj.id, status: data.response_obj.status };
msg

Isolation der Skript-Nodes

Skript-Nodes werden in einer sicheren Sandbox ausgeführt, in der Datei-, Netzwerk- und beliebiger Klassenzugriff blockiert sind. Verdrahten Sie bei Bedarf für externe Aufrufe unbedingt einen separaten externen Anbindungs-Node.


Flow-Metriken und Alarme

Automatisch erfasste Kennzahlen im laufenden Flow-Betrieb — wo sie einzusehen sind und wie sich Alarme darauf einrichten lassen.

Flow-bezogene KPIs

In jeder Zeile der Listenansicht (/flow/index) werden folgende KPIs angezeigt.

KennzahlBedeutungAbnormales Signal
GesamtausführungsanzahlAnzahl der durch Triggerauslösung einmal durchlaufenen Graph-Durchläufe (Summe aus Erfolg/Fehler)Starker Rückgang gegenüber üblich → Trigger tot / starker Anstieg → Amoklauf
FehleranzahlAnzahl der Fälle, in denen an irgendeinem Node im Graphen in den FAILURE-Zweig gefallen wurdeBei ≥5% des Gesamtwerts überprüfen
Fehlerrate에러 / 전체 × 100Bei Überschreiten eines Schwellenwerts einen Alarm einrichten
Letzte AusführungZeitpunkt der letzten Auslösung„Keine Auslösung seit mehr als 5 Minuten" ist nur normal, wenn dies erwartet ist
Durchschnittliche VerarbeitungszeitDurchschnittliche ms, die eine Nachricht benötigt, um den gesamten Graphen zu durchlaufenGroße Änderung bei Hinzufügen/Entfernen externer IO-Nodes
Trend der letzten Verarbeitungszeit5-Minuten-Sparkline — Live-Debug-PanelBei Spikes die Antwort des externen Systems prüfen

Node-bezogene KPIs

Wenn Sie in der Bearbeitungsansicht auf einen Node klicken, wird Folgendes unten rechts am Node angezeigt.

[Node Name]
처리 999 · 에러 3 · 평균 12ms · 최근 18ms
OrtAnzeige
LED obenGrau (wartend) / Grün (in Verarbeitung) / Rot (Fehler)
Label unten처리 N · 에러 M · 평균 Xms · 최근 Yms

4 Node-Statistiken

ZählerBedeutung
VerarbeitungAnzahl der Nachrichten, die in den Node eingingen und über einen normalen Zweig verlassen wurden
FehlerAnzahl der Fälle mit FAILURE-Zweig oder Exception
Durchschnittliche VerarbeitungszeitVerarbeitungszeit des Nodes selbst in ms (inkl. externer IO)
Letzte VerarbeitungszeitVerarbeitungszeit des zuletzt verarbeiteten Falls in ms

Systemweite Metriken

Die Metriken der gesamten Flow-Engine können Sie im Bildschirm System → Monitoring einsehen.

Die Metriken werden unter der JMX-Domäne plantpulse.core.engine als folgende fünf Metriken offengelegt.

MetrikArtBedeutungAblesen
FLOW_EXECUTOR_QUEUE_SIZEGaugeWarteschlangengröße des Flow-AusführungspoolsKontinuierliches Anwachsen bedeutet, dass die Verarbeitung nicht mit dem Eingang mithält
FLOW_EXECUTOR_ACTIVE_COUNTGaugeAnzahl aktiver Threads im AusführungspoolSättigung, wenn nahe der Poolgröße
FLOW_EXECUTOR_DROPPED_COUNTGauge (kumuliert)Kumulierte Anzahl verworfener Tasks durch Pool-SättigungUngleich 0 bedeutet Nachrichtenverlust — der Wert, den Sie zuerst prüfen sollten
FLOW_DEBUG_QUEUE_SIZEGaugeWartewarteschlangengröße für die Debug-EreignisspeicherungWird groß, wenn viele Flows den Debug-Modus aktiviert haben
FLOW_EXECUTION_TIMETimerVerteilung der Verarbeitungszeit pro FlowVerfolgung von Durchschnitt·Maximum
Es gibt keine Metrik namens flow.engine.*

Ein älteres Dokument enthielt eine Tabelle mit flow.engine.queue_depth · in_flight · dispatch_lag_ms · exec_p95_ms · failed_per_min · script_timeout_per_min, aber Metriken mit diesen Namen existieren nicht. Die genannten fünf sind alle, die es gibt.

(flow.engine.enabled ist keine Metrik, sondern ein Konfigurationsschlüssel von engine.properties — das Master-Gate zum Abschalten der gesamten Flow-Engine.)

Muster für metrikbasierte Alarmeinrichtung

4 Muster zur Überwachung der eigenen Flow-Metriken über EQL-Alarm oder CEP → Trigger.

Muster A — Überschreitung des Fehlerratenschwellenwerts

context EVERY_1_MINUTES
SELECT flow_id, count(CASE WHEN status='FAILURE' THEN 1 END) * 100.0 / count(*) AS err_pct
FROM AssetEvent.win:time(5 min)
WHERE event_type = 'FLOW_EXEC'
GROUP BY flow_id
HAVING err_pct > 5

Muster B — Backpressure in der Verarbeitungswarteschlange

Alarm, wenn flow.engine.queue_depth > 500 länger als 1 Minute anhält — eine Situation, in der die Auslösegeschwindigkeit des Triggers die Verarbeitungsgeschwindigkeit übersteigt.

Muster C — Ausbleiben der Auslösung eines bestimmten Flows

SELECT * FROM pattern [
every a = AssetEvent(event_type='FLOW_EXEC', flow_id='my-flow')
-> ( timer:interval(15 min)
and not AssetEvent(event_type='FLOW_EXEC', flow_id=a.flow_id) )
]

Alarm, wenn ein Flow, der normalerweise N-mal pro Minute auslöst, 15 Minuten oder länger schweigt.

Muster D — Explosion von Timeouts bei externem IO

context EVERY_5_MINUTES
SELECT flow_id, node_id, count(*) AS timeout_count
FROM Log.win:time(5 min)
WHERE module = 'flow-engine' AND code = 'NODE_TIMEOUT'
GROUP BY flow_id, node_id
HAVING count(*) > 10

Empfehlung für Alarmausgabekanäle

AlarmtypEmpfohlener Kanal
Fehlerrate·Auslöseausfall (direkter Betrieb)E-Mail + Push-Benachrichtigung
Warteschlangen-Backpressure·Timeout-Explosion (System)Slack/Teams-Webhook
Automatische Diagnose (Referenz)Nur Diagnoselog

⚠️ Verlassen Sie sich bei einem Alarm-Flow selbst niemals auf Metriken, für die Alarme eingerichtet sind — stirbt der Alarm-Flow, kommt der Alarm selbst nicht mehr. Überwachen Sie den Alarm-Flow über einen externen Health-Check unter System → Monitoring.


Nachrichtenverarbeitungssemantik und Backpressure

Zusicherungsniveau und Backpressure-Verhalten bei der Nachrichtenverarbeitung durch die Flow-Engine.

Zustellungsgarantie — At-Least-Once

Die Flow-Engine garantiert At-Least-Once-Zustellung.

FallVerhalten
Normale VerarbeitungEinmal ausgelöst → einmal Graph durchlaufen → einmal abgeschlossen
Neustart der Engine während der VerarbeitungIn der Trigger-Warteschlange verbliebene unverarbeitete Nachrichten werden nach dem nächsten Hochfahren erneut verarbeitet
Node-bezogene ExceptionÜbergang nur in den FAILURE-Zweig. Die Nachricht geht nicht verloren
Timeout bei externem IOFAILURE-Zweig + automatische Wiederholung mit flow_retry möglich

Möglichkeit von Duplikaten — Es handelt sich nicht um Exactly-Once. Wird flow_create_* zwischendurch unterbrochen und erneut versucht, kann dieselbe ID zweimal eingehen — verwenden Sie deshalb on_duplicate=skip oder den Idempotenzschlüssel des externen Systems.

Muster für Idempotenzschlüssel

Muster zur Sicherstellung der Idempotenz beim Aufruf externer Systeme aus einem Flow.

// flow_script_transform — 멱등성 키 생성
msg.data.idempotency_key =
msg.metadata.asset_id + '|' +
msg.metadata.ts + '|' +
msg.data.event_type;

Beim anschließenden externen Aufruf im Header anhängen:

"headers": { "Idempotency-Key": "${data.idempotency_key}" }

Verarbeitungsreihenfolge — Trigger-bezogenes FIFO

Nachrichten desselben OriginatorsAndere Originators
Trigger-bezogenes FIFO (in Ankunftsreihenfolge)Parallele Verarbeitung (unabhängig von der Reihenfolge)

Selbst wenn 2 Ereignisse der Anlage A fast gleichzeitig auftreten, werden die Ereignisse von A in der Reihenfolge ihres Auftretens verarbeitet. Ereignisse der Anlage A und der Anlage B können in unterschiedlichen Workern parallel verarbeitet werden.

Backpressure

Verhalten, wenn die Verarbeitungsgeschwindigkeit nicht mit der Auslösegeschwindigkeit mithält.

SituationVerhalten
Warteschlangentiefe < 80%Normal — neuer Trigger wird sofort enqueued
Warteschlangentiefe 80%–100%Diagnose-WARN-Log tritt auf — Warteschlange nimmt weiterhin auf
Warteschlangentiefe = 100% (voll)Neuer Trigger wird verworfen + Diagnose-ERROR-Log tritt auf

Was der Operator tun sollte, wenn die Warteschlange voll ist

  1. Prüfen Sie flow.engine.queue_depth unter System → Monitoring
  2. Identifizieren Sie den Flow mit explodierter Ausführungsanzahl in der Listenansicht
  3. Grenzen Sie den Vorabfilter des Triggers (*_pattern) dieses Flows ein, um die Last zu reduzieren
  4. Oder heben Sie die Bereitstellung des betreffenden Flows vorübergehend auf, um im Notfall zu handeln

Circuit Breaker (externes IO)

Externe IO-Nodes (HTTP/Kafka/MQTT/E-Mail) werden bei Erfüllung folgender Bedingungen 30 Sekunden lang gebündelt blockiert.

BedingungSchwelle
Aufeinanderfolgende Fehlschläge in der letzten Minute≥ 10
Durchschnittliche Antwortzeit≥ 10 Sekunden

Während der Blockade werden alle an diesen Node eingehenden Nachrichten sofort in den FAILURE-Zweig verzweigt. Erholt sich das externe System, wird die Blockade automatisch aufgehoben. Dieses Verhalten dient dazu, eine externe Störung zu isolieren, damit sie die Flow-Engine selbst nicht lahmlegt.

Der Zeitpunkt, an dem der Circuit geöffnet wurde, wird im Diagnoselog als code = CIRCUIT_OPENED protokolliert. Hat sich das externe System schnell erholt, können Sie über metadata.retry_count in der Ausführungshistorie verlorene Nachrichten manuell erneut ausführen.

Vermeidung von Zyklen

Wenn im Flow ein Zyklus wie folgt entsteht, kann eine Endlosschleife auftreten.

A → B → C → A (잘못된 결선)

Die Flow-Engine blockiert Zyklen mit zwei Verteidigungslinien.

VerteidigungslinieVerhalten
max_depth=100Erzwungenes Ende nach Durchlaufen von 100 Nodes
max_revisit=3Nachricht wird beim 4. Besuch desselben Nodes verworfen + Diagnose-ERROR

Die Schleife SUCCESS-Zweig von flow_retry → ursprünglicher Node ist ein beabsichtigter Zyklus; da metadata.retry_count dabei mitsteigt, endet dieser normal, bevor max_revisit greift.


Was man in der Ausführungshistorie sieht

Der „Fehlercode-Katalog" eines älteren Dokuments existierte nicht wirklich

Codes wie NODE_SCRIPT_TIMEOUT · FLOW_TIMEOUT · FLOW_MAX_DEPTH · TRIGGER_QUEUE_FULL · WEBHOOK_AUTH_FAIL · DOMAIN_DUP_KEY waren in einer Tabelle aufgeführt, aber das Produkt erzeugt diese Zeichenketten nirgendwo. Suchen Sie im Log nach diesem Code, erhalten Sie für immer 0 Treffer.

Was die Flow-Engine tatsächlich protokolliert, sind die folgenden 5 Ereignistypen.

In der Flow-Ausführungshistorie (mm_flow_log, linkes Menü Automation > Flow-Ausführungshistorie) werden fünf Arten von Ereignissen gespeichert.

EreignistypWannSpeicherbedingung
FLOW_STARTBeim Eintritt in den FlowImmer
FLOW_ENDBeendigung der Flow-Verarbeitung (Erfolg·Timeout beide)Immer
NODE_INWenn ein Node eine Nachricht empfängtNur im Debug-Modus
NODE_OUTWenn ein Node eine Nachricht ausgibtNur im Debug-Modus
NODE_ERRORException während der Node-VerarbeitungImmer

Felder, die jede Zeile gemeinsam hat.

FeldInhalt
levelINFO / WARN / ERROR
flow_id · flow_node_id · node_name · node_typeWelcher Flow, welcher Node
msg_idZur nachrichtenbezogenen Verfolgung — um den Ablauf einer Nachricht nachzuverfolgen, gruppieren Sie nach diesem Wert
message · error_messageFür Menschen lesbare Beschreibung, Fehlermeldung
duration_nsNode-Ausführungszeit (Nanosekunden) — nur bei NODE_OUT · NODE_ERROR von Bedeutung
Normalerweise werden keine nodebezogenen Logs gespeichert

NODE_IN · NODE_OUT werden nur im Debug-Modus gespeichert. Dass in der normalen Ausführungshistorie nur FLOW_START · FLOW_END zu sehen sind, ist normal. Um Node für Node nachzuverfolgen, aktivieren Sie den Debug-Modus des betreffenden Flows — dies erhöht jedoch die Logmenge erheblich.

Suche nach Symptomen

Statt vom Code auszugehen, gehen wir vom Symptom aus.

SymptomZuerst prüfen
Trigger löst aus, aber es scheint kein Node zu laufenOb der Flow bereitgestellt (Schalter ON) ist · ob *_pattern des Triggers die Nachricht nicht herausfiltert
Verarbeitung bricht mittendrin abÜberschreitung von 30 Sekunden (flow_timeout_ms) pro Nachricht. Prüfen Sie die Warnung FlowExecutor timeout im Serverlog
Dieselbe Nachricht wird wiederholt verarbeitetZyklus. Wird durch max_revisit (3×) automatisch blockiert, prüfen Sie dennoch die Verdrahtung
Graph ist zu lang und endet nichtÜberschreitung von max_depth (100). In Subflows aufteilen
Node wirft eine ExceptionPrüfen Sie error_message der NODE_ERROR-Zeile in der Ausführungshistorie
Externer Aufruf schlägt fehlPrüfen Sie data.response_status · data.error des betreffenden Nodes im nachfolgenden Node

Die Grenzwerte (100 · 3 · 30.000 ms) sind die Standardwerte von ExecutionState.


Cluster·Hochverfügbarkeits(HA)-Verhalten

Ist die Plattform als Cluster-Umgebung installiert, verhält sich die Flow-Engine gemäß folgenden Regeln verteilt.

Trennung der Node-Rollen

RolleVerhalten
LeaderDer einzelne Node, der Änderungen am Flow-Graphen (Speichern/Bereitstellen/Aufheben) seriell verarbeitet
WorkerAllgemeine Nodes, die die Triggerauslösung·Nachrichtenverarbeitung parallel ausführen (alle Nodes fungieren gleichzeitig als Worker)
SchedulerZuständig für die flow_schedule Cron-Bewertung — derselbe Node wie der Leader

Der Leader-Node wird beim Hochfahren der Plattform automatisch gewählt; fällt der Leader aus, wird automatisch einer der übrigen Nodes zum Leader befördert. Der Operator muss dies nicht manuell festlegen.

Nachrichtenverteilung — konsistentes Routing auf Anlagenebene

VerteilungsschlüsselVerhalten
originator.id (Anlagen-/Tag-/Bestellungs-ID)Nachrichten derselben Anlage werden immer an denselben Worker geroutet — Sequenzgarantie
Externer Eintritt (flow_on_webhook usw.)Round-Robin-Verteilung

Diese Regel verhindert, dass Ereignisse der Anlage A gleichzeitig auf mehreren Workern verarbeitet werden und die Reihenfolge durcheinandergerät. Im Ergebnis gilt auf Anlagenebene die Garantie einer Verarbeitung durch einen einzigen Worker, während zwischen Anlagen gleichzeitig eine parallele Verarbeitung gilt.

Verhalten bei Leader-Ausfall — Failover

[Leader 다운 t=0]

[다른 노드가 리더 승격 시도 t=0~3s]

[새 리더 확정 t=3~5s] ← cron 스케줄·플로우 배포 변경 재개

[기존 워커들은 정상 동작 유지 — 트리거 처리 영향 없음]
PhaseAuswirkung
0–3 SekundenAuslösung von flow_schedule vorübergehend gestoppt / Triggerverarbeitung nicht betroffen
3–5 SekundenNeuer Leader bestimmt, Zeitplan wird fortgesetzt
Ab 5 SekundenNormal

Die Cron-Auslösung wird gemäß der misfire-Richtlinie sofort für eine einmal ausgefallene Auslösung nachgeholt. Im laufenden Betrieb kann bei einer Bewertungseinheit von flow_schedule unter 5 Sekunden ein kurzzeitiges Ausbleiben sichtbar werden.

Persistenz der Trigger-Warteschlange

ElementVerhalten
Position der Trigger-WarteschlangeIn-Memory-Warteschlange + permanenter Speicher (Transaktionsprotokoll)
Bei Neustart des NodesIn der Warteschlange verbliebene unverarbeitete Nachrichten werden nach dem nächsten Hochfahren erneut dispatcht
Node-Ausfall während der VerarbeitungDiese Nachricht wird erneut verarbeitet, aber mit der At-Least-Once-Garantie muss beim externen System ein Idempotenzschlüssel vorhanden sein

Checkliste für Operatoren bei Cluster-Bereitstellung

  1. Zeitsynchronisation (NTP) aller Nodes — die Auslösezeitpunkte der Trigger stimmen zwischen Nodes überein
  2. Externe Systeme (MQTT/Kafka-Broker) an einem Netzwerkstandort platzieren, den alle Nodes erreichen können
  3. Die SMTP-Konfiguration von flow_send_email nur einmal in den Systemeinstellungen registrieren — wird von allen Nodes gemeinsam genutzt
  4. Worker-Poolgröße (flow.engine.workers) an die Anzahl der CPU-Kerne pro Node anpassen

Single-Node-Modus (Entwicklung·Kleinbetrieb)

  • Leader·Worker·Scheduler laufen alle in einem Prozess
  • Kein Failover — fällt der Node aus, stoppt der Flow selbst
  • Trigger-Warteschlange wird durch In-Memory + Disk gesichert, sodass eine Wiederherstellung nach Neustart möglich ist

End-to-End-Trace

Methode zur nachträglichen Verfolgung, wie eine Nachricht den gesamten Graphen durchlaufen hat.

Automatische Vergabe einer Korrelations-ID

Die Flow-Engine vergibt automatisch eine Korrelations-ID (correlation ID) an alle durch Trigger ausgelösten Nachrichten.

{
"type": "POST_TELEMETRY",
...,
"metadata": {
"trace_id": "tr-a1b2c3d4-e5f6-7890-...",
"span_id": "sp-01",
"parent_id": null,
...
}
}
FeldBedeutung
metadata.trace_idEine einzigartige ID für eine gesamte Triggerauslösung — von allen Nodes im Graphen durchlaufende Nachrichten geteilt
metadata.span_idNodebezogene eindeutige ID — wird bei jedem Node-Durchlauf aktualisiert
metadata.parent_idspan_id des vorherigen Nodes

Suche nach trace_id in der Ausführungshistorie

Wenn Sie im Ausführungshistorie-Bildschirm die ID in das Eingabefeld trace_id einfügen, werden die chronologisch sortierten Logs aller Nodes angezeigt, die diese Nachricht durchlaufen hat.

🔍 trace_id = tr-a1b2c3d4-...

[12:34:56.123] [trg] flow_on_tag_point 태그=MOTOR.TEMP, value=87
[12:34:56.125] [filter] flow_script_filter score>80 → TRUE
[12:34:56.126] [transform] flow_change_originator Tag → Asset
[12:34:56.130] [action] flow_create_work_order WO-20260513-001 생성
[12:34:56.241] [external] flow_send_email admin@... 발송 성공

Trace-Weitergabe bei Subflow-Aufruf

Wenn Sie mit dem flow_subflow-Node einen anderen Flow aufrufen, wird dieselbe trace_id unverändert übernommen. Das heißt, alle Node-Logs des Hauptflows + des aufgerufenen Subflows lassen sich über denselben Trace durchsuchen.

Weitergabe an externe Systeme

Bei externen HTTP-Aufrufen wird automatisch der Header X-Trace-Id hinzugefügt.

GET /api/orders HTTP/1.1
Host: erp.example.com
X-Trace-Id: tr-a1b2c3d4-e5f6-...
X-Span-Id: sp-04

Wenn das externe System diesen Header empfängt und ebenfalls im Log erfasst, können die Logs beider Systeme mit derselben ID abgeglichen werden.

Anzeige von trace_id in Alarm·E-Mail

Wenn Sie ${metadata.trace_id} im Alarmtext oder E-Mail-Template einschließen, kann der Operator das Ereignis unmittelbar nach Erhalt des Alarms im Historienbildschirm sofort verfolgen.

제목: [긴급] 모터 과열 — ${metadata.asset_id}
본문:
시각: ${metadata.ts}
값: ${data.value}°C
trace: ${metadata.trace_id}
이력 보기: https://platform.example.com/flow/log?trace_id=${metadata.trace_id}

Aufbewahrungsdauer der Traces

DatenAufbewahrungsdauer
trace_id und nodebezogene Span-Logs7 Tage (identisch mit der Ausführungshistorie)
Externe Speicherung (langfristige Aufbewahrung)Externes Spiegeln von Systemen unter Audit·Verlaufsverfolgung nutzen

Falls die trace_id lang ist und die Nachrichtengröße belastet, können Sie mit flow_script_transform ein Kurzformat erstellen, das nur die letzten 4 Zeichen (wie tr-...d4) für Alarm·E-Mail verwendet. Für die Suche wird jedoch die vollständige ID benötigt.


Katalog der Graph-Muster

10 häufig verwendete Verdrahtungsmuster im Flow-Graphen.

Muster 1 — Pipeline (einfach seriell)

[trigger] → [filter] → [transform] → [action]

| Merkmal | Nachricht durchläuft die Nodes der Reihe nach | | Anwendungsbeispiel | Alarm bei Schwellenüberschreitung → E-Mail-Versand |

Muster 2 — Fan-out (1 zu N)

┌─→ [action 1]
[trigger] → [t] ─────┼─→ [action 2]
└─→ [action 3]

| Merkmal | Eine Nachricht wird von mehreren Aktionen gleichzeitig verarbeitet | | Anwendungsbeispiel | Bei Alarmauslösung → E-Mail + SMS + Slack + Arbeitsauftragserstellung |

Kopien derselben Nachricht werden auf mehrere Nodes verteilt. Jeder Zweig wird unabhängig verarbeitet, ein Fehlschlag in einem Zweig hat keinen Einfluss auf andere.

Muster 3 — Fan-in (N zu 1) — Merge

[trigger A] ──┐
[trigger B] ──┼─→ [flow_merge] → [aggregator] → [action]
[trigger C] ──┘

| Merkmal | Nachrichten mehrerer Trigger werden innerhalb eines Zeitfensters gesammelt und auf einmal verarbeitet | | Anwendungsbeispiel | Alle innerhalb von 5 Minuten aufgetretenen Alarme in einem Tagesbericht zusammenfassen |

Muster 4 — Scatter-Gather (Verteilung → Sammlung)

[trigger] → [split] ─┬─→ [process] ──┐
├─→ [process] ──┼─→ [merge] → [action]
└─→ [process] ──┘

| Merkmal | Array wird elementweise aufgeteilt verarbeitet, danach Ergebnisse wieder zusammengeführt | | Anwendungsbeispiel | 100 externe Bestellungen parallel validieren und danach das Ergebnis gebündelt melden |

Muster 5 — Switch (bedingte Verzweigung)

┌─[CRITICAL]→ [긴급 알람]
[trigger] → [flow_switch] ──┼─[WARN] → [경고 알람]
└─[NORMAL] → [통과]

| Merkmal | Eine Nachricht je nach Bedingung auf unterschiedliche Pfade leiten | | Anwendungsbeispiel | Trennung der Verarbeitungskanäle je nach Alarmpriorität |

Muster 6 — Retry with Fallback

[risky] ─[FAILURE]─→ [flow_retry] ─[SUCCESS]─→ (다시 risky)
└[EXHAUSTED]→ [fallback action]

| Merkmal | Vorübergehende Störungen automatisch wiederholen, dauerhafte Störungen alternativ behandeln | | Anwendungsbeispiel | Bei fehlgeschlagener externer API 3 automatische Wiederholungen, bei weiterem Fehlschlag Benachrichtigung an eine Person |

Muster 7 — Circuit Breaker (Nutzung des Circuits)

[trigger] → [throttle] → [external_io] ─[SUCCESS]─→ [save]
└[FAILURE]─→ [log only]

| Merkmal | Aufrufgeschwindigkeit mit flow_throttle begrenzen + gebündelte Blockade mit Circuit Breaker | | Anwendungsbeispiel | Überlastschutz eines externen Systems |

Muster 8 — Dead Letter Queue (DLQ)

[main flow] ─[FAILURE]─→ [flow_save_attributes] → 별도 자산에 적재

운영자가 주기적 점검 후 수동 재처리

| Merkmal | Dauerhaft fehlgeschlagene Nachrichten in einem separaten Speicher ablegen | | Anwendungsbeispiel | Sammlung fehlgeschlagener Synchronisationsnachrichten mit externem ERP (Ziel für manuelle Nachverarbeitung) |

Muster 9 — Sliding Window Aggregation

[trigger] → [flow_throttle 60s] → [transform: 누적] → [action]
(마지막 60건만 유지)

| Merkmal | Entscheidung anhand des Zustands innerhalb eines Fensters der letzten N Einträge | | Anwendungsbeispiel | Notfallmodus für den Standort bei mehr als 30 Alarmen in den letzten 5 Minuten |

Muster 10 — Saga (mehrstufige Transaktion)

[start] → [step1] ─OK→ [step2] ─OK→ [step3] ─OK→ [complete]
│ │ │
└─FAIL→[rollback1] │
│ │
┌─FAIL→[rollback1+2]

└─FAIL→[rollback1+2+3]

| Merkmal | Behandlung teilweiser Fehlschläge einer Aufgabe über mehrere externe Systeme hinweg durch Kompensation | | Anwendungsbeispiel | Arbeitsauftragserstellung → Anlagenreservierung → ERP-Synchronisation → Mitarbeiterbenachrichtigung (bei Fehlschlag einer Stufe werden alle vorherigen Stufen storniert) |

Leitfaden zur Musterauswahl

AnforderungEmpfohlenes Muster
Einfacher SchwellenwertalarmPipeline (1)
Ein Ereignis → mehrere KanäleFan-out (2)
Mehrere Ereignisse → eine ZusammenfassungFan-in / Merge (3)
Massenverarbeitung eines ArraysScatter-Gather (4)
ZweigverarbeitungSwitch (5)
Zuverlässigkeit einer externen APIRetry (6)
Schutz eines externen SystemsCircuit (7)
Aufbewahrung fehlgeschlagener NachrichtenDLQ (8)
Entscheidung anhand der letzten N kumulierten EinträgeSliding (9)
Konsistenz über mehrere externe SystemeSaga (10)

Bewährte Praktiken für Flow-Tests

Teststrategie für sicheres Ändern·Bereitstellen von Flows.

3-stufiger Test — Unit → Integration → Simulation

StufeWerkzeugPrüfobjekt
① UnitBearbeitungsansicht ▶ TestlaufIsoliertes Verhalten eines einzelnen Nodes (Skriptausdruck, Antwort auf externen Aufruf)
② IntegrationDerselbe Bildschirm, temporäre Payload + Live-Debug ONGesamte Sequenz·Verzweigung des Graphen
③ SimulationBereitstellen + Warten auf realen Trigger (Staging-Umgebung)Realer Nachrichtenfluss·Verbindung mit externem System

Payload-Bibliothek für Testläufe

Trigger-bezogene Payload-Beispiele, die in den Testlauf-Dialog eingefügt werden können, finden Sie im Abschnitt Payload-Beispiele nach Trigger. Erstellen Sie auch im Voraus Grenzfälle, die im Produktionsbetrieb häufig auftreten.

Beispiele für Grenzfälle

FallPayload
null-Feld{"value": null} — ob das Skript null-sicher ist
Leerer String{"value": ""} — validieren, ob ein leerer String als 0 interpretiert wird
Negative Zahl{"value": -1} — ob die Schwellenwertprüfung dem ± Vorzeichen entsprechend funktioniert
Sehr große Zahl{"value": 1e20} — Überlauf/Genauigkeit
Unicode{"name": "한글-Émoji-🚀"} — Kodierung im externen System

Sicheres Änderungsverfahren

1. 기존 플로우를 [내보내기] (JSON 파일 저장)
2. 새 플로우를 사본으로 만듦 (이름 끝에 `_v2`)
3. 사본의 트리거 패턴을 좁혀 일부 자산만 매칭 (예: TEST-* 사이트만)
4. 신구 동시 배포 — 새 버전 데이터 확인
5. 1주일 안정성 검증 후 신 버전을 전체 트리거 패턴으로 변경
6. 구 버전 해제 + 보관

Aufbewahrung von Regressionstestszenarien

Es wird empfohlen, häufig verwendete Szenarien als Textdatei aufzubewahren und nach Änderungen unbedingt erneut auszuführen.

# regression-tests/alarm-to-workorder.json
{
"case": "고온 알람 → 워크오더 자동 생성",
"input": {
"type": "TAG_ALARM",
"data": { "alarm_band": "HI_HI", "value": 95.0 }, ...
},
"expected": {
"domain_changes": ["WorkOrder.CREATED"],
"notifications": ["email:admin@example.com"]
}
}

Mock-Muster für externe Systeme

Um Antworten externer Systeme in der Staging-Umgebung zu simulieren:

MethodeBeschreibung
url von flow_http_request auf einen Mock-ServerBetriebs-URL als Staging-URL-Variable abtrennen
datasource von flow_jdbc_poll ändernVon Betriebs-DB → nur auf Staging-DB ändern
to_field von flow_send_email auf fake@example.comVerhindert versehentlichen Versand

Lasttest nach Zurücksetzen der Zähler

  1. Zähler zurücksetzen (gesamt) der neuen Flow-Version
  2. Normale Triggerauslösung 5 Minuten lang durchführen
  3. In der Listenansicht Verarbeitungs-/Fehlerzähler, durchschnittliche Verarbeitungszeit prüfen
  4. Steigt die p95-Verarbeitungszeit um mehr als 20% gegenüber vorher, Ursachenanalyse durchführen und Rollback erwägen

Performance-Grenzen und Tuning

Verarbeitungsgrenzen und Tuning-Tipps der Flow-Engine.

Standardgrenzen

ElementStandardBemerkung
Anzahl der Node-Besuche pro Nachricht (max_depth)100Erzwungener Abbruch, wenn nach Durchlaufen von 100 Nodes noch nicht beendet
Wiederbesuch desselben Nodes (max_revisit)3Verhinderung von Endlosschleifen bei Zyklen
Flow-Verarbeitungszeit (flow_timeout_ms)30.000 msErzwungener Abbruch bei Überschreitung von 30 Sekunden pro Nachricht
Timeout für externe IO-Nodes5.000 ms (timeout_ms)HTTP/Kafka/MQTT usw.
Timeout für Skriptausführung500 ms (timeout_ms)Nodeweise
Aufbewahrung der Ausführungshistorie7 TageDanach automatischer Ablauf

Empfohlene, häufig verwendete Fenstergrößen

NodeEmpfohlenes FensterBemerkung
flow_throttle1.000–60.000 msAn das API-Limit des externen Systems anpassen
flow_debounce500–5.000 msWenn nur stabile Werte durchgelassen werden sollen
flow_merge5.000–60.000 msZu kurz führt zu Fragmentierung, zu lang zu erhöhter Latenz
Backoff bei flow_retryStart 1.000 ms × 2×Bei 5 Wiederholungen: 1·2·4·8·16 Sekunden

Möglichkeiten zur Steigerung des Durchsatzes

  • Trigger-Vorabfilter — mit *_pattern nur benötigte Nachrichten einlassen (am effektivsten)
  • Vereinfachung des Graphen durch Subflow — Hauptgraph nur für Verzweigung·Routing, schwere Verarbeitung in Subflow
  • Externe IO asynchron verdrahten — mit flow_delay / flow_throttle die Last externer APIs glätten
  • Debug-Modus nur in der Validierungsphase — nach stabilem Betrieb Debug-Modus ausschalten
  • Nur benötigte Kategorien verdrahten — schwere Nodes wie Edge·externe Anbindung nicht zwangsläufig an alle Zweige anschließen

Nachrichtengröße

data / metadata der Nachricht werden JSON-serialisiert in der Ausführungshistorie abgelegt. Bei sehr großen Payloads (z. B. Antwortkörper von mehreren MB) extrahieren Sie möglichst mit einem Transformations-Node nur die benötigten Schlüssel. Sowohl bei der Aufbewahrung der Historie, der Debug-Anzeige als auch beim Subflow-Aufruf ist die Verarbeitungskosten proportional zur Nachrichtengröße.


Audit·Verlaufsverfolgung

Orte, an denen Sie Änderungen·Ausführungshistorie von Flows nachverfolgen können.

Graph-Änderungshistorie

  • Automatischer Snapshot — wird bei jedem Speichern des Graphen versionsweise abgelegt. Für eine Rückkehr zum vorherigen Zustand wenden Sie sich bitte an den Administrator.
  • Änderer/Änderungszeitpunkt — die Spalte Letzte Änderung in der Listenansicht zeigt den zuletzt gespeicherten Zeitpunkt. Der Änderer wird gemäß dem authentifizierten Systembenutzer erfasst.
  • Empfohlene Erfassung des Änderungsgrunds — im Feld Beschreibung der Flow-Metadaten den Änderungsgrund·Verantwortlichen·zugehörige Ticket-Nummer festzuhalten erhöht die Nachverfolgbarkeit.

Verfolgung von Ausführungsereignissen

  • Nachrichten-ID-Verfolgung — mit dem Filter Nachrichten-ID im Ausführungshistorie-Bildschirm können Sie den gesamten Ablauf (FLOW_START → alle NODE_IN/NODE_OUTFLOW_END) einer einzelnen Nachricht chronologisch abfragen.
  • CSV-Export — mit der Schaltfläche CSV herunterladen im Ausführungshistorie-Bildschirm können Sie das aktuelle Abfrageergebnis exportieren und an ein externes Audit-System übermitteln.

Domänenänderungshistorie

Domänenänderungen, die von Aktions-Nodes des Flows (flow_create_* / flow_update_* / flow_delete_*) durchgeführt werden, werden alle an denselben Domänenservice delegiert und daher gemeinsam in der domänenbezogenen Änderungshistorie im Back-Office-Bildschirm erfasst. Die Bearbeiter-ID wird z. B. als insert_user_id="flow" ausgewiesen, um sie von normalen Benutzeränderungen zu unterscheiden.

Langfristige Aufbewahrung durch externe Speicherung

Wenn eine langfristige Aufbewahrung über die Aufbewahrungsdauer der Ausführungshistorie (7 Tage) hinaus benötigt wird, erstellen Sie einen separaten Flow, um zentrale Ereignisse in ein externes System (Kafka·externe DB usw.) zu laden.

[flow_on_tag_alarm]


[flow_kafka_publish: topic=audit.alarm.events]

Checkliste für die Bereitstellung neuer Flows

Prüfpunkte vor der Bereitstellung eines neuen Flows in der Produktionsumgebung.

Graphstruktur

  • Ist genau ein (oder eine beabsichtigte Mehrzahl von) Trigger-Node(s) verdrahtet
  • Ist der FAILURE-Ausgang aller Aktions-Nodes verarbeitet (mindestens flow_log)
  • Ist ein vorhandener Zyklus eine beabsichtigte Verdrahtung wie flow_retry, innerhalb des Schutzes von max_revisit
  • Ist an externen IO-Nodes retry_count/retry_delay_ms oder flow_retry verdrahtet

Node-Konfiguration

  • Ist *_pattern des Triggers nicht zu eng oder zu weit
  • Existiert der dynamische Optionspfad *_field tatsächlich in der Nachricht
  • Werden alle NOT-NULL-Felder des Create-Nodes befüllt (zusätzlich zur automatischen Ergänzung)
  • Ist die Teilaktualisierung des Update-Nodes tatsächlich beabsichtigt

Validierung·Test

  • Ein Durchlauf des SUCCESS-Zweigs mit normaler Payload
  • Ein Durchlauf des FAILURE-Zweigs mit abnormaler Payload (z. B. fehlendes Pflichtfeld)
  • Durchlauf Retry → EXHAUSTED-Zweig mit Fehlschlagfall des externen IO (falls zutreffend)
  • Entspricht die INFO/ERROR-Anzeige im Live-Debug-Panel der Absicht
  • Werden alle Schritte im Bildschirm /flow/log protokolliert

Betriebssicherheit

  • Ist eine Sicherung (Export der Graph-JSON) extern aufbewahrt
  • Sind Änderungsgrund·Verantwortlicher in der Flow-Beschreibung erfasst
  • Sind bei vorhandenen Benachrichtigungsverdrahtungen (Email/SMS/Push) die Empfänger validiert
  • Gibt es einen Überwachungsplan für die 5–10 Minuten unmittelbar nach der Bereitstellung

Deployment-Strategien — Canary / Blue-Green / A·B-Test

3 Strategien für eine sichere Einführung neuer Flows. Alle Strategien lassen sich allein mit den Grundfunktionen der Plattform (Trigger-Muster·Nachrichten-Dispatch·Live-Debug) umsetzen.

Strategie 1 — Canary (schrittweise Anwendung auf einige Anlagen)

Wenden Sie den neuen Flow zunächst nur auf einige Anlagen an, beobachten Sie eine Weile und weiten Sie ihn danach auf alle aus.

[1단계 출시]
새 플로우 v2 — 트리거 패턴: asset_id LIKE 'LINE-1.%' (1개 라인만)
기존 플로우 v1 — 트리거 패턴: asset_id LIKE 'LINE-2.%' OR 'LINE-3.%' OR ...

[2단계 확대 (1주일 후 안정 확인)]
v2 패턴: 'LINE-1.%' OR 'LINE-2.%'
v1 패턴: 'LINE-3.%' OR 'LINE-4.%'

[3단계 전체 (2주 후)]
v2 패턴: '%' ← 모든 자산
v1 해제·보관

Canary-Fortschrittschecklist

ZeitraumÜberwachungspunkt
Tag 1Fehlerrate < 1% / durchschnittliche Verarbeitungszeit innerhalb ±20% des bisherigen Werts
1 WocheExterne Systemanbindung 100% normal / Alarmhäufigkeit angemessen
2 WochenKumulierte Statistik / Nutzerfeedback / Entscheidung über Erweiterung auf weitere Linien

Wählen Sie als Canary-Linie eine Linie mit geringem Einfluss unter den laufenden Linien (z. B. Linien mit hoher Wartungshäufigkeit oder nur nächtlichem Betrieb).

Strategie 2 — Blue-Green (gleichzeitiger Betrieb alt·neu, dann sofortiger Wechsel)

[Blue (현재)] [Green (새 버전)]
플로우 v1 — 배포됨 플로우 v2 — 배포 + 격리된 originator
모든 트리거 처리 metadata.test_mode=true 인 메시지만 처리

[전환 결정 시점]
v2 트리거 패턴을 v1 과 동일하게 변경 (1초)
v1 해제 토글 (1초)

Der Kern von Blue-Green ist der sofortige Wechsel, während beide Versionen gleichzeitig bereitgestellt sind — bei Problemen wird v1 sofort wieder bereitgestellt, um zurückzurollen.

Isoliertes Verdrahtungsmuster für v2

[trigger 모든 메시지]

[flow_script_filter — metadata.test_mode === true]
↓ TRUE
[새 로직]

Testnachrichten werden über die API /flow/{id}/run unter Angabe von metadata.test_mode=true gesendet.

Strategie 3 — A/B-Test (Vergleich von Performance·Ergebnis)

Beide Versionen empfangen dieselbe Nachricht, führen unterschiedliche Aktionen durch und vergleichen dann die Ergebnisse.

[trigger 메시지]

[flow_split (메시지 복제)]
├ A 경로 → 기존 v1 액션 → [flow_save_attributes target=stats_v1]
└ B 경로 → 새 v2 액션 → [flow_save_attributes target=stats_v2]

Anschließend im Tagesstatistik-Bildschirm die kumulierten Ergebnisse von stats_v1 vs stats_v2 vergleichen.

Automatische Analyse des A/B-Vergleichs

-- EQL 으로 두 버전 비교 (예: 알람 생성 누적)
context EVERY_1_HOURS
SELECT
count(CASE WHEN metadata.flow_version='v1' THEN 1 END) AS v1_count,
count(CASE WHEN metadata.flow_version='v2' THEN 1 END) AS v2_count
FROM AssetAlarm.win:time(1 hour)

Leitfaden zur Strategieauswahl

SituationEmpfohlene Strategie
Erste Einführung eines neuen AutomatisierungsszenariosCanary — nach Validierung auf einer Linie ausweiten
Große Änderung an bestehender Logik (Strukturreform)Blue-Green — sofortiges Rollback möglich
Messen, welcher von zwei Algorithmen besser istA/B-Test
Einfache Anpassung eines OptionswertsDirekt ändern — nach Notiz zu metadata.audit_diff 1 Woche überwachen

Rollback-Verfahren (gemeinsam)

Bei entdecktem Problem sofortiges Rollback:

  1. Neue Version in der Listenansicht mit dem Schalter Aufheben deaktivieren
  2. (bei Canary/A·B) Trigger-Muster auf 0 Treffer ändern
  3. 5 Minuten überwachen, ob die bestehende Version allein normal funktioniert
  4. Prüfen, ob im Diagnoselog kein code=FLOW_NOT_DEPLOYED vorliegt
  5. Ursachenanalyse — fehlgeschlagene Nachrichten in der Ausführungshistorie mit trace_id verfolgen

Vorabcheckliste vor Einführung (Kurzfassung)

Das Wesentliche der Checkliste für die Bereitstellung neuer Flows auf einen Blick:

[ ] 테스트 실행으로 정상·경계·실패 시나리오 모두 통과
[ ] 외부 IO 노드에 timeout_ms / 재시도 정책 설정됨
[ ] 자격 증명은 ${creds.*} 참조 (평문 미포함)
[ ] 트리거 패턴이 의도한 자산만 매칭
[ ] 영향받는 도메인 (자산/태그/주문) 식별됨
[ ] 운영 시간(특히 야간) 영향 검토됨
[ ] 롤백 시점·기준·담당자 결정됨
[ ] [감사 로그](#audit) 에 변경 의도 메모 작성됨

Node-Schnellkonfigurationsreferenz

Eine Cheat-Sheet-Sammlung mit den wichtigsten Konfigurationen häufig genutzter Nodes im Betrieb.

Trigger-Schnellkonfiguration

NodeZentrale Optionen
flow_schedulecron (z. B. 0 */5 * * * ? = alle 5 Minuten), oder interval_ms
flow_on_webhookKeine Option — Auslösung von außen über POST /flow/webhook/{flow_id}
flow_on_mqtt_subscribebroker_url, topic, client_id, username/password
flow_jdbc_polldsn, sql, interval_ms
flow_on_* (Domäne)*_pattern (Glob — z. B. MOTOR-*, SITE-?)

Transformations-Schnellkonfiguration

NodeZentrale Optionen
flow_script_transformlanguage (JS/EQL), script, timeout_ms (Standard 500)
flow_change_originatorentity_type, id_field
flow_rename_keysmapping (z. B. {"old":"new"})
flow_templatetemplate (${data.x} / ${metadata.y}-Ersetzung)
flow_splitpath (Array-Position, Standard data)
flow_to_emailsubject_template, body_template

Ablaufsteuerungs-Schnellkonfiguration

NodeZentrale Optionen
flow_delaydelay_ms
flow_throttlemax_msgs, window_ms, (Verzweigung: SUCCESS/THROTTLED)
flow_debouncewindow_ms
flow_mergewindow_ms (in data.merged-Array kumuliert)
flow_subflowtarget_flow_id
flow_retrymax_attempts (Standard 3), backoff_ms (Standard 1000), backoff_multiplier (Standard 2.0)
flow_loglevel (INFO/WARN/ERROR), prefix
flow_noop(keine Option)

Externe-Anbindungs-Schnellkonfiguration

NodeStatische OptionDynamische Option (*_field)
flow_http_requestmethod, url, headers, body_template, timeout_ms, retry_count, retry_delay_msurl_field, method_field, body_field
flow_kafka_publishbootstrap_servers, topic, value_template, headerstopic_field, key_field
flow_mqtt_publishbroker_url, topic, qostopic_field
flow_webhook_callbackurl, method, headersurl_field
flow_send_emailto, cc, subject, bodyto_field, cc_field, subject_field, body_field
flow_send_smsto, textto_field, text_field
flow_send_pushtitle, bodytitle_field, body_field
flow_jdbc_querydsn, sql, params_field

Schnellkonfiguration für Aktion — Integration/Speicherung

NodeZentrale Optionen
flow_save_tag_pointtag_id_field (Standard metadata.tag_id), value_field, timestamp_field
flow_save_attributesentity_type_field, id_field, attributes_field
flow_dds_publishtype, originator_field, payload_field
flow_publish_asset_eventasset_id_field, event_type_field, severity_field, details_field
flow_publish_asset_commandasset_id_field, tag_id, cmd_key_field, payload_field

Schnellkonfiguration für Domänen-CRUD

NodeZentrale Optionen
flow_create_*Domänenspezifische Felder + dynamische Option *_field. NOT-NULL-Felder werden teilweise automatisch ergänzt (siehe Tabelle Domänen-CRUD für die automatisch ergänzten Positionen)
flow_update_*Teilaktualisierung: nur eingegebene Felder werden aktualisiert, leere Werte werden ignoriert. Für vollständige Überschreibung Kombination Delete + Create
flow_delete_**_id_field
flow_start/end/pause/resume_work_orderorder_id_field (Standard data.order_id)
flow_abort_work_order+ abort_code_field, abort_notes_field
flow_update_tag_alarm_band_numerictag_id_field, hi_field usw. (nur eingegebene Felder werden aktualisiert)

Edge-Schnellkonfiguration

Edge-Nodes verwenden alle denselben Optionssatz.

OptionBeschreibung
urlEdge-REST-Endpunkt (z. B. http://edge.local:60000/opc/server)
methodHTTP-Methode (falls nicht gesetzt, Node-spezifischer Standardwert)
headersJSON-Header (Auth-Token usw.)
body_templateRequest-Body (falls nicht gesetzt, wird data unverändert gesendet)
timeout_ms5000

Flow-REST-API — Flows programmgesteuert bedienen

REST-API zur Verwendung, wenn Sie Flows aus einem externen Automatisierungswerkzeug (Ansible/GitOps/CI-Pipeline) codegesteuert verwalten oder wenn ein externes System einen Flow sofort ausführen lassen möchte.

Authentifizierung

Alle API-Aufrufe hängen ein bei Sicherheit → API-Authentifizierungstoken ausgestelltes Token als Header an.

Authorization: Bearer {api_token}

Liste der Endpunkte

1) Flow-Liste abfragen

GET /flow/list
curl -H "Authorization: Bearer ${TOKEN}" \
https://platform.example.com/flow/list

Antwort:

{
"data": [
{ "flow_id": "flow-abc123", "flow_name": "MES 동기화", "deployed": true,
"node_count": 12, "exec_count": 9430, "error_count": 2, "last_exec_at": 1746247200000 },
...
]
}

2) Einzelnen Flow abfragen

GET /flow/get/{flow_id}

Der Antwortkörper enthält alle Graph-Nodes·Relationen·Optionen. Kann direkt für Backup/Versionsverwaltung verwendet werden.

3) Flow erstellen

POST /flow/create
Content-Type: application/json

{
"flow_name": "신규 자동화",
"description": "외부 알림 → 워크오더 자동 생성",
"deployed": false
}

Verwenden Sie die flow_id aus der Antwort für nachfolgende Aufrufe.

4) Flow bearbeiten (Meta)

POST /flow/update
Content-Type: application/json

{
"flow_id": "flow-abc123",
"flow_name": "수정된 이름",
"description": "..."
}

5) Graph speichern (Massenersetzung von Nodes·Relationen)

POST /flow/{flow_id}/graph
Content-Type: application/json

{
"nodes": [ { "node_id": "n1", "type": "flow_on_tag_point", "options": {...}, "x": 100, "y": 100 }, ... ],
"relations": [ { "from_node_id": "n1", "to_node_id": "n2", "relation": "TRUE" }, ... ]
}

Das Speichern des Graphen ist eine Transaktion — bei Validierungsfehler wird der gesamte Graph zurückgerollt.

6) Bereitstellen / Aufheben

Ändern Sie das deployed-Feld der Flow-Metadaten, um automatisch bereitzustellen·aufzuheben.

# 배포
curl -X POST -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
-d '{"flow_id":"flow-abc123","deployed":true}' \
https://platform.example.com/flow/update

7) Sofortige Ausführung (manueller Trigger)

POST /flow/{flow_id}/run
Content-Type: application/json

{
"type": "WEBHOOK",
"originator": { "entity_type": "External", "id": "manual-run" },
"data": { "test": true }
}

Wird ohne Durchlaufen des Vorabfilters des Trigger-Nodes sofort ab dem ersten Node ausgeführt. Nützlich für manuelle Validierung·Debugging.

8) Dispatch (Auslösung unter Umgehung des Triggers)

POST /flow/dispatch
Content-Type: application/json

{
"type": "POST_TELEMETRY",
"originator": { "entity_type": "Tag", "id": "MOTOR-001.SPEED" },
"data": { "value": 1500 },
"metadata": { "tag_id": "MOTOR-001.SPEED", "ts": 1746247200000 }
}

Führt die Nachricht über den normalen Trigger-Verarbeitungspfad ein — alle Flows, die dieser Nachricht entsprechen, werden gleichzeitig ausgelöst.

9) Statistik zurücksetzen

POST /flow/{flow_id}/stats/reset-errors — 에러 카운트만 초기화
POST /flow/{flow_id}/stats/reset-all — 전체 카운트 초기화

10) Export / Import — Graph-Sicherung

# Export — JSON 파일로 다운로드
curl -H "Authorization: Bearer ${TOKEN}" \
https://platform.example.com/flow/${FLOW_ID}/export \
-o flow-backup.json

# Import — 같은 JSON 을 다른 환경에 등록
curl -X POST -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
--data @flow-backup.json \
https://platform.example.com/flow/import

Bei Import wird bei einer ID-Kollision automatisch eine neue ID vergeben. Externe Abhängigkeiten (Zugangsdaten·Anlagen-ID usw.) müssen Sie nach dem Import separat abbilden.

11) Alle Flows neu bereitstellen

POST /flow/redeploy

Wird nach umfangreichen Änderungen oder nach dem Neustart von Nodes zur Massensynchronisation verwendet. Rufen Sie diese Funktion im laufenden Betrieb mit Bedacht auf — es kann zu einer vorübergehenden Verarbeitungsverzögerung kommen.

12) Selbstdiagnose

POST /flow/selftest

Prüft die internen Komponenten der Flow-Engine (Trigger-Warteschlange·Dispatcher·Node-Registry·Skript-Laufzeit) einmal und gibt den Status zurück. Das Ergebnis wird auch im Diagnoselog erfasst.

13) Node-Katalog abfragen

GET /flow/catalog

Gibt alle aktuell registrierten Node-Typen·Optionsschemata zurück. Wird von der UI verwendet, um den Inspector dynamisch zu erzeugen. Auch nützlich, wenn ein externes Werkzeug automatisch einen Graphen erzeugt.

Auslösung von außen über Webhook-Trigger

Flows mit einem flow_on_webhook-Trigger können von externen Systemen direkt über folgende URL ausgelöst werden.

POST /flow/webhook/{flow_id}
Authorization: Bearer {token} 또는 X-API-Key: {token}
Content-Type: application/json

{
"order_no": "PO-001",
"customer": "ACME",
"quantity": 1000
}

Antwort:

{ "status": "ACCEPTED", "trace_id": "tr-..." }
AntwortcodeBedeutung
200In die Nachrichtenwarteschlange eingereiht (das tatsächliche Verarbeitungsergebnis ist asynchron)
401Authentifizierungstoken falsch/fehlend
404Flow-ID nicht vorhanden oder nicht bereitgestellt
413Body überschreitet 256 KB
422Trigger-Node ist nicht flow_on_webhook
429Aufruflimit pro Minute überschritten

Beispiele für die Anbindung externer Automatisierungswerkzeuge

GitHub Actions — Flow-Bereitstellung bei PR-Merge

- name: 플로우 배포
run: |
curl -X POST \
-H "Authorization: Bearer ${{ secrets.PP_TOKEN }}" \
-H "Content-Type: application/json" \
--data @flows/mes-sync.json \
https://platform.example.com/flow/import

Ansible — Batch-Verwaltung von Flows

- name: 모든 플로우 백업
uri:
url: "https://platform.example.com/flow/{{ item }}/export"
headers:
Authorization: "Bearer {{ pp_token }}"
dest: "/backups/{{ item }}.json"
loop: "{{ pp_flow_ids }}"

Jenkins — Selftest bei jedem neuen Build

stage('PlantPulse Flow Selftest') {
steps {
sh """
curl -X POST -H 'Authorization: Bearer ${PP_TOKEN}' \\
https://platform.example.com/flow/selftest \\
--fail-with-body
"""
}
}

API-Rate-Limit

EndpunktLimit pro Minute (pro Token)
GET /flow/list · get · catalog600
POST /flow/create · update · delete60
POST /flow/{id}/run · dispatch · webhook/{id}1.000
POST /flow/redeploy · selftest10

Bei Überschreiten des Limits Antwort 429 Too Many Requests.


OPC/PLC-Industrieintegrationsmuster

Eine Sammlung typischer Integrationsszenarien im industriellen Vor-Ort-Betrieb. Nutzung der Kombination aus 22 Edge-Node-Arten und 4 Anlagenereignis-Publikations-Arten.

Muster A — Automatische Registrierung eines OPC-Servers

Wenn eine neue Linie in Betrieb geht, wird die Linieninformation vom ERP empfangen und der OPC-Server automatisch im Edge registriert.

[flow_on_webhook]
↓ (data = {"line_id":"LINE-7","host":"10.0.7.10","port":4840})
[flow_change_originator]
↓ (originator → Edge:EDGE-A)
[flow_edge_opc_create]
↓ (path=/api/v1/opc, body={"opc_id":"OPC-${data.line_id}","host":"${data.host}","port":${data.port}})
[flow_edge_opc_start]
↓ (수집 시작 명령)
[flow_save_attributes]
↓ (등록 이력을 자산 메타에 기록)

Der Edge-Node führt automatisch ein Lookup von api_key in der Mastertabelle mm_edge durch. Der Operator muss keine separate Authentifizierungskonfiguration vornehmen.

Muster B — Automatische Ausgabe eines PLC-Befehls

Bei Auftreten eines Anlagenalarms wird automatisch ein Stoppbefehl an die PLC ausgegeben.

[flow_on_asset_alarm]
↓ where priority='ERROR' AND alarm_band='TRIP_HI'
[flow_publish_asset_command]
↓ (event_type='STOP', payload={"reason":"trip_high","triggered_by":"flow"})
[flow_log] (감사 로그)

flow_publish_asset_command wird sofort über das Befehls-Topic der Anlage (asset/{id}/cmd/STOP) zugestellt, sodass das Edge einen OPC-Write an die PLC durchführt.

Muster C — Massenregistrierung von OPC-Tags (Import aus CSV/Excel)

Bei einem neuen Anlagen-Setup werden 100–1000 Tags aus einer CSV auf einmal registriert.

[flow_jdbc_poll] ← 외부 DB 에 적재된 CSV 행
↓ (한 행 = 한 메시지)
[flow_script_transform] ← 태그 정의 가공

[flow_create_tag] ← 도메인 등록 (NOT NULL 자동 보강)

[flow_edge_tag_create] ← 엣지에 동기화

[flow_log] (성공 카운트)

Bei der Registrierung von 1.000 Tags wird empfohlen, mit flow_throttle auf höchstens 100 pro Minute zu glätten. Das Edge kann vorübergehend langsamer reagieren.

Muster D — Automatische Wiederherstellung bei OPC-Verbindungsabbruch

Wenn die OPC-Verbindung abbricht und sich erholt, wird automatisch neu gestartet.

[flow_on_opc_status]
↓ where prev_status='CONNECTED' AND status='DISCONNECTED'
[flow_delay 30s] ← 잠시 안정화 대기

[flow_edge_opc_start] ← 수집 재시작 시도
↓ SUCCESS: 정상
└ FAILURE: [flow_retry max=3] → EXHAUSTED: [관리자 알림]

Muster E — Statusprüfung der Linie bei Schichtbeginn

Prüft zum Beginn jeder Schicht alle Linien des Standorts.

[flow_schedule cron='0 0 7,15,23 * * ?'] ← 7시·15시·23시

[flow_edge_monitoring] ← 엣지에서 OPC 상태 전체 조회
↓ data.opcs = [...]
[flow_split] ← 배열을 행별 메시지로

[flow_script_filter] ← status != 'CONNECTED' 만

[flow_send_email] ← 비정상 OPC 만 한 통의 메일에 합쳐 발송

Muster F — Automatische Zuweisung von Mitarbeitern bei Schichtwechsel

Weist gemäß Änderungen im Dienstplan automatisch Mitarbeiter zu Arbeitsaufträgen zu.

[flow_on_entity_event type='ENTITY_UPDATED' Calendar]

[flow_script_filter (시프트 시작 시각이 지금인 경우만)]

[flow_jdbc_query (그 시프트의 작업자 목록 조회)]
↓ data.employees=[...]
[flow_split]

[flow_update_work_order (작업자 매핑)]

Muster G — Gleichzeitiger Aufruf mehrerer PLCs (Scatter-Gather)

Ruft Daten mehrerer PLCs gleichzeitig ab und führt die Ergebnisse zusammen.

[flow_on_webhook]
↓ data.targets=['PLC-1','PLC-2','PLC-3']
[flow_split]
↓ (3개로 분할)
[flow_edge_tag_read]
↓ (병렬 호출)
[flow_merge window=5s]
↓ data.merged=[...]
[flow_script_transform (data.summary 만들기)]

[flow_publish_asset_aggregation]

Muster H — Automatische Anpassung des Alarmbands

Wendet die trainierten LIMIT_MIN/MAX-Werte der Vorhersageanalyse automatisch auf das Alarmband an.

[flow_schedule cron='0 0 4 * * MON'] ← 매주 월요일 4시

[flow_jdbc_query (forecast 결과 조회)]
↓ data.tags=[{tag_id, limit_min, limit_max}]
[flow_split]

[flow_update_tag_alarm_band_numeric] ← lo=limit_min, hi=limit_max
↓ SUCCESS
[flow_log] (적용 결과 기록)

Muster I — Automatische Klassifizierung von Ausfallzeiten

Klassifiziert Anlagenstoppereignisse nach Ursache, um sie präzise in der OEE-Verfügbarkeit widerzuspiegeln.

[flow_on_asset_event event_type='SHUTDOWN']

[flow_switch]
├ CASE 점심: hour_of_day(ts) BETWEEN 12 AND 13 → [flow_create_calendar (계획정지)]
├ CASE 시프트 종료: 시프트 종료 시각 ±5분 → [flow_log (정상 종료)]
├ CASE 정기점검: 마지막 정비일 +30일 경과 → [flow_create_calendar (정기점검)]
└ DEFAULT (비계획) → [flow_send_email (긴급)]

Muster J — Bidirektionale Synchronisation von Arbeitsaufträgen mit externem ERP

Bidirektionale Spiegelung PlantPulse ↔ externes ERP.

입력 1: ERP → 플랜트펄스
[flow_on_webhook] → [flow_create_work_order]

입력 2: 플랜트펄스 → ERP
[flow_on_entity_event type='ENTITY_CREATED' WorkOrder]
→ [flow_script_filter (출처가 ERP 가 아닌 경우만)]
→ [flow_http_request (ERP REST PUT)]

Um Endlosschleifen zu vermeiden, kennzeichnen Sie von außen eingehende Nachrichten mit metadata.source='ERP' und filtern Sie diese Nachricht im Flow der Gegenrichtung heraus.

Hinweise bei der Industrieintegration

PunktEmpfehlung
OPC-Write-Befehl nach Sicherheitsinterlock ausgebenErst nach Bestätigung durch den Bediener oder Durchlaufen automatischer Sicherheitsregeln
Nicht zu kurzes PLC-Pollingintervall setzenUnter 1 Sekunde besteht das Risiko eines starken Anstiegs der PLC-CPU-Auslastung
Ressourcenlimit des Docker-Containers am Edge-GerätVorsicht bei OPC-Erfassung + zusätzlichem Container bei über 80% CPU/Speicher
In der Inbetriebnahmephase alle Befehle im Dry-Run-ModusOption dry_run=true von flow_edge_tag_write nutzen
Vorsorge für Stromausfall — nur permanenten Speichertriggern vertrauenflow_on_webhook usw. sind flüchtig, Domänenereignistrigger sind permanent

Cookbook für externe Systemintegration

Sammlung von flow_http_request-Konfigurationen und Payload-Beispielen für häufig aufgerufene externe Systeme.

Slack — Incoming-Webhook-Benachrichtigung

URL: https://hooks.slack.com/services/T0000/B0000/{secret}
Method: POST
Headers:
Content-Type: application/json
Body (body_template):
{
"text": "${data.title}",
"blocks": [
{ "type": "header", "text": { "type": "plain_text", "text": "${data.title}" } },
{ "type": "section", "text": { "type": "mrkdwn", "text": "*자산:* ${metadata.asset_id}\n*값:* ${data.value}\n*시각:* ${metadata.ts}" } }
]
}
  • Erfolg: 200 + Antwortkörper ok
  • Fehlschlag: 400 (fehlerhafte payload) / 404 (fehlerhaftes secret) / 429 (Aufruflimit pro Minute überschritten)
  • Empfehlung: höchstens 1× pro Minute mit flow_throttle verdrahten

Microsoft Teams — Webhook-Benachrichtigung

URL: https://{org}.webhook.office.com/webhookb2/{id}/IncomingWebhook/{secret}
Method: POST
Headers:
Content-Type: application/json
Body:
{
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"themeColor": "FF0000",
"title": "${data.title}",
"sections": [{
"facts": [
{ "name": "자산", "value": "${metadata.asset_id}" },
{ "name": "값", "value": "${data.value}" },
{ "name": "시각", "value": "${metadata.ts}" }
]
}]
}

Verzweigen Sie themeColor nach FF0000 (rot)/FFA500 (orange)/00C853 (grün), um die Priorität visuell darzustellen.

Jira — Automatische Ticketerstellung

URL: https://{org}.atlassian.net/rest/api/3/issue
Method: POST
Headers:
Authorization: Basic {base64(email:apitoken)}
Content-Type: application/json
Body:
{
"fields": {
"project": { "key": "OPS" },
"summary": "[자동] ${data.title}",
"description": {
"type": "doc",
"version": 1,
"content": [{
"type": "paragraph",
"content": [{ "type": "text", "text": "자산: ${metadata.asset_id}\n값: ${data.value}" }]
}]
},
"issuetype": { "name": "Bug" },
"priority": { "name": "High" }
}
}
  • Im Antwortkörper data.response_body.key steht ein Ticket-Schlüssel wie OPS-1234, nutzen Sie diesen im nachfolgenden Node
  • Fehlschlag: 400 (fehlerhaftes Feld) / 401 (Authentifizierung) / 403 (keine Projektberechtigung)

GitHub Issues — Automatische Ticketerstellung

URL: https://api.github.com/repos/{owner}/{repo}/issues
Method: POST
Headers:
Authorization: Bearer {pat_token}
Accept: application/vnd.github+json
Body:
{
"title": "[자동] ${data.title}",
"body": "자산: ${metadata.asset_id}\n값: ${data.value}\n시각: ${metadata.ts}\ntrace: ${metadata.trace_id}",
"labels": ["automation", "ops"]
}

ERP (SAP S/4HANA OData) — Arbeitsauftrag ausgeben

URL: https://{host}/sap/opu/odata/sap/API_MAINTNOTIFICATION/MaintenanceNotification
Method: POST
Headers:
Authorization: Basic {base64(user:pass)}
X-CSRF-Token: fetch ← 별도 GET 으로 토큰 받기
Content-Type: application/json
Body:
{
"NotificationType": "M2",
"MaintenanceNotificationType": "M2",
"TechnicalObject": "${metadata.asset_id}",
"NotificationText": "${data.title}",
"MalfunctionStartDate": "${data.start_date}",
"Priority": "${data.priority}"
}

Sie müssen zuerst per GET das CSRF-Token abrufen und dann mit demselben Session-Cookie POST senden. Verbinden Sie zwei flow_http_request-Nodes und übertragen Sie das Token aus dem Antwortheader des ersten Nodes in den Header des zweiten Nodes.

MES (direktes externes DB-INSERT) — flow_jdbc_query

Direkte Zeilenerstellung in der Arbeitsauftragstabelle eines externen MES-Systems.

INSERT INTO mes.work_order
(order_no, asset_id, product_id, qty, status, due_date, created_by)
VALUES
(:order_no, :asset_id, :product_id, :qty, 'NEW', :due_date, 'flow')
Node-OptionWert
datasource_idmes_db (vorab in den Systemeinstellungen registriert)
queryobiges SQL
binds{"order_no":"${data.order_no}","asset_id":"${metadata.asset_id}",...}

flow_jdbc_query unterstützt neben SELECT auch INSERT/UPDATE/DELETE. Transaktionen werden nodeweise automatisch commit/rollback.

Grafana — Automatische Dashboard-Aktualisierungsbenachrichtigung

URL: https://{host}/api/annotations
Method: POST
Headers:
Authorization: Bearer {api_key}
Content-Type: application/json
Body:
{
"dashboardUID": "...",
"panelId": 4,
"time": ${metadata.ts},
"tags": ["alarm", "${metadata.asset_id}"],
"text": "${data.title}"
}

Bei Alarmauslösung wird automatisch ein Marker auf dem Graphen angezeigt — sehr nützlich für nachträgliche Analysen.

Telegram — Bot-Nachricht

URL: https://api.telegram.org/bot{token}/sendMessage
Method: POST
Body:
{
"chat_id": "-1001234567890",
"text": "🚨 *${data.title}*\n자산: `${metadata.asset_id}`\n값: ${data.value}",
"parse_mode": "Markdown"
}

Schnellübersicht der REST-Authentifizierungsmuster

AuthentifizierungsmethodeHeader
API Key (Header)X-API-Key: {token}
API Key (Query)?api_key={token} am Ende der URL
Bearer TokenAuthorization: Bearer {token}
Basic AuthAuthorization: Basic {base64(user:pass)}
OAuth2 (Client Credentials)Token-Ausstellung → Bearer-Header (Erneuerung mit separatem Node)
HMAC-SignaturBody-/zeitbasierte Signatur per Skript berechnen und in Header X-Signature setzen

Muster zur Antwortauswertung

Nach der flow_http_request-Antwort data.response_body im nächsten Node nutzen:

// 응답에서 ID 추출
data.created_id = data.response_body.id;
data.status = data.response_body.status;

// 응답 배열에서 첫 행만
data.first_item = (data.response_body.items || [])[0] || null;

// 응답이 문자열이면 JSON 파싱
if (typeof data.response_body === 'string') {
try { data.response_body = JSON.parse(data.response_body); } catch (e) {}
}
msg

Sicherheitsempfehlungen bei externem Systemaufruf

PunktEmpfehlung
Token nicht im Klartext im Graphen belassenNach Registrierung im Zugangsdatenspeicher unter Systemeinstellungen → als ${creds.slack_webhook} referenzieren
Bei sensiblen Daten im Antwortkörper maskierenMit flow_script_transform PII/Token entfernen, bevor an den nächsten Node weitergegeben wird
Separate Retry-Richtlinie pro externem SystemBei häufig aufgerufenen Systemen separat flow_retry + flow_throttle verdrahten
Aufrufergebnis als Audit-Log speichernMit flow_save_attributes Aufrufhistorie-Metadaten der Anlage hinzufügen

Cookbook für Datentransformation

Eine Sammlung von Transformationsmustern, die Sie direkt in den flow_script_transform-Node übertragen können. Alle Beispiele basieren auf JavaScript und verwenden die Kurzaliase data / metadata.

Einheitenumrechnung

// 섭씨 → 화씨
data.temp_f = data.temp_c * 9 / 5 + 32;

// 바 → kPa
data.pressure_kpa = data.pressure_bar * 100;

// rpm → rad/s
data.angular_velocity = data.rpm * 2 * Math.PI / 60;

// kWh → MJ
data.energy_mj = data.energy_kwh * 3.6;

// 바이트 → MB (소수 1자리)
data.size_mb = Math.round(data.bytes / 1024 / 1024 * 10) / 10;

msg

Datums-/Zeittransformation

const d = new Date(metadata.ts);

// ISO 8601 — 2026-05-12T12:34:56.789Z
data.iso = d.toISOString();

// 사람용 — 2026-05-12 21:34:56 (KST)
data.local = d.toLocaleString('ko-KR', { hour12: false });

// 날짜만 — 2026-05-12
data.date = d.toISOString().slice(0, 10);

// 시간만 — 21:34:56
data.time = d.toTimeString().slice(0, 8);

// 분 단위로 내림 (스파크라인 키)
data.minute_key = Math.floor(metadata.ts / 60000) * 60000;

// 시간 단위로 내림
data.hour_key = Math.floor(metadata.ts / 3600000) * 3600000;

// 한국 시간 (UTC+9) 직접 더하기 (서버 시간이 UTC 인 경우)
data.kst_hour = new Date(metadata.ts + 9 * 3600000).getUTCHours();

msg

Stringnormalisierung

// 공백 trim + 소문자화
data.normalized = (data.text || '').trim().toLowerCase();

// 한글·영문 외 제거 (특수문자/공백 정리)
data.clean = (data.text || '').replace(/[^-a-zA-Z0-9]/g, '');

// camelCase → snake_case
data.snake = (data.text || '').replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');

// 전화번호 정규화 (숫자만)
data.phone_digits = (data.phone || '').replace(/\D/g, '');

// 한국 휴대전화 자동 포맷 (010-1234-5678)
const p = (data.phone || '').replace(/\D/g, '');
data.phone_formatted = p.length === 11 ? p.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3') : p;

msg

Abflachen verschachtelter Objekte

// data.location.address.city → data.city
function flatten(obj, prefix, out) {
out = out || {};
for (var k in obj) {
var v = obj[k];
var key = prefix ? prefix + '_' + k : k;
if (v && typeof v === 'object' && !Array.isArray(v)) flatten(v, key, out);
else out[key] = v;
}
return out;
}
data = flatten(data);
msg

Flaches Objekt → Verschachtelt

// data.user_name + data.user_email → data.user = {...}
function unflatten(obj) {
var out = {};
for (var k in obj) {
var parts = k.split('_');
var cur = out;
for (var i = 0; i < parts.length - 1; i++) {
cur[parts[i]] = cur[parts[i]] || {};
cur = cur[parts[i]];
}
cur[parts[parts.length - 1]] = obj[k];
}
return out;
}
data = unflatten(data);
msg

CSV-Zeilenerstellung

// 외부 시스템에 CSV 한 줄 보낼 때
function csvEscape(v) {
if (v === null || v === undefined) return '';
v = String(v);
return /[,"\n]/.test(v) ? '"' + v.replace(/"/g, '""') + '"' : v;
}
data.csv_row = [
csvEscape(metadata.ts),
csvEscape(metadata.asset_id),
csvEscape(data.value),
csvEscape(data.quality)
].join(',');
msg

Array-Aggregation

var arr = data.values || [];

// 합·평균·최소·최대
data.sum = arr.reduce(function(a, b) { return a + b; }, 0);
data.avg = arr.length ? data.sum / arr.length : 0;
data.min = arr.length ? Math.min.apply(null, arr) : null;
data.max = arr.length ? Math.max.apply(null, arr) : null;

// 중앙값
var sorted = arr.slice().sort(function(a, b) { return a - b; });
var mid = Math.floor(sorted.length / 2);
data.median = sorted.length === 0 ? null
: sorted.length % 2 ? sorted[mid]
: (sorted[mid - 1] + sorted[mid]) / 2;

msg

Bedingtes Hinzufügen von Feldern (Schema-Evolution)

// 알람 우선순위에 따라 색상·아이콘 자동 부여
var p = data.priority || 'INFO';
data.color = { ERROR: '#d32f2f', WARN: '#f57c00', INFO: '#1976d2' }[p] || '#9e9e9e';
data.icon = { ERROR: '🔴', WARN: '🟠', INFO: '🔵' }[p] || '⚪';
data.urgency = p === 'ERROR' ? 3 : p === 'WARN' ? 2 : 1;
msg

Teilweise Maskierung der Payload

function maskEmail(e) {
if (!e || e.indexOf('@') < 0) return e;
var parts = e.split('@');
return parts[0].slice(0, 2) + '***@' + parts[1];
}
function maskPhone(p) {
return (p || '').replace(/(\d{3})\d{4}(\d{4})/, '$1-****-$2');
}
data.user_email = maskEmail(data.user_email);
data.user_phone = maskPhone(data.user_phone);
msg

Mehrsprachige (i18n) Vorlage

// 메시지 본문을 사용자 로케일에 따라 분기
const tpl = {
'ko-KR': '🚨 ${asset} 온도 ${value}°C 임계 초과',
'en-US': '🚨 ${asset} temperature ${value}°C exceeds threshold',
'ja-JP': '🚨 ${asset} 温度 ${value}°C 閾値超過'
};
const locale = metadata.user_locale || 'ko-KR';
const template = tpl[locale] || tpl['ko-KR'];
data.notification = template
.replace('${asset}', metadata.asset_id)
.replace('${value}', data.value);
msg

Sichere JSON-Path-Abfrage

// data.deep.nested.field 처럼 깊은 경로를 안전하게 조회
function get(obj, path, dflt) {
var keys = path.split('.');
var cur = obj;
for (var i = 0; i < keys.length; i++) {
if (cur === null || cur === undefined) return dflt;
cur = cur[keys[i]];
}
return cur === undefined ? dflt : cur;
}
data.city = get(data, 'location.address.city', 'Unknown');
msg

Nachrichtenzusammenführung (Nachbearbeitung von flow_merge)

// flow_merge 가 data.merged 배열로 모은 메시지들을 1건으로 합침
var items = data.merged || [];
data.summary = {
count: items.length,
first_ts: items[0]?.metadata?.ts,
last_ts: items[items.length - 1]?.metadata?.ts,
assets: Array.from(new Set(items.map(function(m) { return m.metadata?.asset_id; }))),
max_value: Math.max.apply(null, items.map(function(m) { return m.data?.value || 0 }))
};
delete data.merged;
msg

Sammlung wiederverwendbarer Skripte

Eine Skriptbibliothek, die Sie direkt in die Nodes flow_script_filter / flow_script_transform / flow_switch übertragen können. Alle Skripte basieren auf JavaScript und verwenden die Kurzaliase data / metadata.

Transformationsskripte

Einheitenumrechnung·Labeling

// 섭씨 → 화씨 + 등급 라벨
data.temp_f = data.temp * 1.8 + 32;
data.grade = data.temp > 80 ? 'HIGH' : data.temp < 0 ? 'LOW' : 'OK';
msg

Ergänzung von Metadaten zu Zeit·Schicht·Wochentag

const d = new Date(metadata.ts);
const h = d.getHours();
metadata.shift = (h >= 6 && h < 14) ? 'A' : (h < 22) ? 'B' : 'C';
metadata.weekday = ['SUN','MON','TUE','WED','THU','FRI','SAT'][d.getDay()];
metadata.is_weekend = (d.getDay() === 0 || d.getDay() === 6);
msg

Berechnung des Alarmbands als Mittelwert ± 3σ

const m = data.mean, s = data.stddev || 1;
data.tag_id = originator.id + '.TEMP';
data.hi = m + 3*s; data.lo = m - 3*s;
data.hi_hi = m + 4*s; data.lo_lo = m - 4*s;
data.use_alarm = true;
msg

Zuordnung MES-PO → Arbeitsauftrag

const po = data;
data = {
master_id: 'WO-MES-' + po.po_no,
asset_id: po.line_id || 'UNASSIGNED',
title: po.product_name + ' (' + po.qty + ')',
due_date: po.delivery_date,
qty: po.qty,
product_id: po.product_code
};
msg

Normalisierung externer Payloads (Vereinheitlichung verschiedener Feldnamen)

// 외부 시스템에 따라 키 이름이 다른 경우 — 한 줄로 정규화
data.value = data.value ?? data.val ?? data.v;
data.timestamp = data.timestamp ?? data.ts ?? metadata.ts;
data.tag_id = data.tag_id ?? data.tagId ?? data.id;
msg

Kumulierte Anzahl von Schwellenwertverletzungen (Stateful-Muster)

// 자산 attribute 와 함께 사용 — 상태는 메시지 자체에 적재
data.consecutive_fail = (data.consecutive_fail ?? 0) + (data.passed ? 0 : 1);
data.alert = data.consecutive_fail >= 5;
msg

Zusammenfassung der Nachrichtenstatistik (Aufbereitung des Merge-Ergebnisses)

// flow_merge 후 data.merged 배열을 받아 요약
const arr = data.merged || [];
data.count = arr.length;
data.values = arr.map(m => m.data.value).filter(v => v != null);
data.mean = data.values.reduce((a,b)=>a+b, 0) / (data.values.length || 1);
data.max = Math.max(...data.values);
data.min = Math.min(...data.values);
delete data.merged;
msg

Anwendung von Schwellenwerten nach Tageszeit

const h = new Date(metadata.ts).getHours();
const threshold = (h >= 8 && h < 18) ? 90 : 70; // 주간 90, 야간 70
data.alarm = data.value > threshold;
data.threshold = threshold;
msg

Filterskripte

Prioritäts-Whitelist

['ERROR', 'CRITICAL'].includes(data.priority)

Zeitfenster (nur Werktage)

const h = new Date(metadata.ts).getHours();
h >= 8 && h < 20

Anlagen-·Tag-ID-Muster

/^MOTOR-.*$/.test(originator.id)
// 또는
metadata.tag_id && metadata.tag_id.startsWith('LINE-A.')

Schwellenwert + Stabilität (N-fach in Folge)

data.value > 100 && (data.consecutive_count ?? 0) >= 5

Prüfung von Geschäftszeiten·Feiertagen

const d = new Date(metadata.ts);
const h = d.getHours();
const wd = d.getDay();
// 평일 09-18시만 통과
wd >= 1 && wd <= 5 && h >= 9 && h < 18

Nur bestimmter Standort

['SITE-01', 'SITE-02'].includes(metadata.site_id)

Prüfung auf Vorhandensein aller Pflichtfelder

data.value != null && data.tag_id && metadata.ts

Blockade selbst publizierter Nachrichten (bidirektionale Synchronisation)

metadata.source !== 'flow'

Switch-Case-Skripte

Nach Prioritätsstufe

// case "Critical"
['CRITICAL', 'EMERGENCY'].includes(data.priority)

// case "High"
data.priority === 'ERROR'

// case "Normal"
['WARN', 'INFO'].includes(data.priority)

Nach Anlagenstatus

// case "Running"
data.status === 'RUN'

// case "Stopped"
['STOP', 'IDLE', 'PAUSED'].includes(data.status)

// case "Faulted"
data.status === 'FAULT' || data.error_count > 0

Nach Lebenszyklus des Arbeitsauftrags

// case "Start"
data.event_type === 'START_REQUEST'

// case "End"
data.event_type === 'COMPLETE' && data.qty_done >= data.qty_planned

// case "Abort"
data.event_type === 'CANCEL'

Die obigen Skripte sind eine Zusammenstellung von Mustern, die im Produktionsbetrieb häufig verwendet werden. Sie funktionieren, wenn Sie sie direkt im Graphen verdrahten, und Sie müssen nur Schwellenwerte·Feldnamen an Ihre Domäne anpassen.


Glossar

Flow-Engine-Begriffe

BegriffBedeutung
entity_typeArt der Subjekt-Entität der Nachricht — Asset, Tag, Site, Order, Customer, Product, Employee, Calendar usw.
originatorDie von der Nachricht referenzierte Subjekt-Entität (entity_type + id). Beispiel: Asset/MOTOR-001
typeKlassifizierungslabel der Nachricht. Identifiziert, welche Art von Ereignis der Trigger empfangen hat
dataDer Inhalt (Payload) der Nachricht — wird hauptsächlich von Transformations-·Aktions-Nodes gelesen und geschrieben
metadataKontext der Nachricht (Zeit·Standort·Schicht·Tag-ID usw.) — bleibt auch bei Transformation bis zum Ende des Ablaufs erhalten
relationLabel des Ausgangs-Wires eines Nodes. SUCCESS/FAILURE/TRUE/FALSE/MATCH/NO_MATCH/DEFAULT/THROTTLED/EXHAUSTED (alle in Großbuchstaben)
*_field dynamische OptionEingabemethode, bei der statt eines statischen Werts der Wert aus einem Pfad der Nachrichten-Payload (z. B. data.tag_id) gelesen wird
Glob-MusterWildcard-Darstellung der Option *_pattern des Triggers — * steht für 0 oder mehr Zeichen, ? für genau 1 Zeichen
SnapshotAutomatisch beim Speichern des Graphen abgelegtes versionsweises Backup. Wird bei Vorfällen zur Wiederherstellung des vorherigen Zustands verwendet
Teilaktualisierung (fetch+merge)Methode des Update-Nodes, bei der nach Abfrage des bestehenden Datensatzes nur eingegebene Felder zusammengeführt werden. Leere Werte werden ignoriert
SKIPPEDVerarbeitung, bei der Nachrichten, die dem Triggermuster nicht entsprechen, nicht an nachfolgende Nodes fließen und auch vom Zähler ausgeschlossen werden
EXHAUSTEDZweig, der ausgelöst wird, wenn der flow_retry-Node die maximale Anzahl an Wiederholungsversuchen überschritten hat
THROTTLEDZweig, der ausgelöst wird, wenn der flow_throttle-Node eine Nachricht blockiert, die das Limit innerhalb des Fensters überschritten hat

Domänen-·Abkürzungslexikon

Eine Übersicht häufig verwendeter Abkürzungen aus der Betriebsumgebung von Anlagen, damit Sie sie in diesem Handbuch schnell nachschlagen können.

AbkürzungBedeutungIn diesem Handbuch
MESManufacturing Execution System — Verwaltung von Arbeitsaufträgen·ProduktionsergebnissenZiel externer Anbindung (HTTP/MQTT/externe DB)
ERPEnterprise Resource Planning — unternehmensweites Ressourcen-·PlanungssystemZiel externer Anbindung
SCADASupervisory Control and Data Acquisition — Überwachung·SteuerungZiel externer Anbindung / Ausgang von flow_publish_asset_command
OPCOpen Platform Communications — IndustriekommunikationsstandardZiel der Kategorie Edge (flow_edge_opc_*)
OEEOverall Equipment Effectiveness — Verfügbarkeit × Leistung × QualitätTrigger flow_on_oee_event
RAMReliability·Availability·MaintainabilityTrigger flow_on_ram_event
EMSEnergy Management SystemTrigger flow_on_ems_event
EQLDomänenereignisregel-AusdruckOption language: "EQL" von flow_script_filter/flow_script_transform
CEPKomplexe Ereignisverarbeitung (Complex Event Processing)EQL-basierte Regelengine. Alarme müssen ausschließlich über den CEP-Pfad entstehen, um Konsistenz zu wahren
POPurchase Order — Einkaufs-·ProduktionsauftragEinheit, die bei MES-Anbindung in einen Arbeitsauftrag umgewandelt wird
WOWork Order (Arbeitsauftrag)Node-Gruppe flow_*_work_order
CMMSComputerized Maintenance Management SystemZiel externer Anbindung
MTTF/MTTRMean Time To Failure / To RepairZentrale Kennzahl von RAM-Ereignissen
HMIHuman–Machine InterfaceBedienbildschirm von SCADA usw.

Versionshinweise

Zeitpunkte der Einführung der wichtigsten Funktionsgruppen, die dieses Handbuch zum aktuellen Zeitpunkt behandelt. Falls Sie eine ältere Version betreiben, können sich einige Funktionen abweichend verhalten.

V2026.05 — Erweiterung der Domänenautomatisierung

  • 11 Arten der Edge-Kategorie neu eingeführt — Automatisierung von OPC-Server-/Tag-CRUD + Monitoring
  • 5 Arten von Statusübergängen des Arbeitsauftragsflow_start/end/pause/resume/abort_work_order
  • 2 Arten der Teilaktualisierung des Tag-Alarmbands — Aktualisierung nur der eingegebenen Felder für numerisches/boolesches Alarmband
  • Neue Ablaufsteuerung flow_retry — Backoff + maximale Versuche + EXHAUSTED-Zweig
  • 5 neue Trigger-Artenflow_on_asset_health_status / _connection_status / _oee_event / _ram_event / _ems_event
  • Teilaktualisierung des Update-Nodes (fetch+merge) — Zusammenführung nur der eingegebenen Felder nach Abfrage des bestehenden Datensatzes
  • Standardisierung der Relations auf GroßbuchstabenSUCCESS/FAILURE/... alle in Großbuchstaben, bestehende Graphen werden automatisch konvertiert
  • SKIPPED-Behandlung — Ausschluss von Nachrichten, die dem Triggermuster nicht entsprechen, aus dem Zähler
  • Betriebswerkzeug „Alle neu bereitstellen" (redeploy) — Massen-Neuladung aktiver Flows
  • Alle Zähler zurücksetzen — Massen-Reset der Statistiken auf Node- + Flow-Ebene

V2026.03 — Release-Stabilität

  • Automatischer Snapshot wird beim Speichern des Graphen abgelegt
  • Live-Debug-Panel (2-Sekunden-Aktualisierung unten im Inspector) + Node-LED·Anzeige der Dauer
  • Import/Export (Graph-JSON-Datei)
  • Einführung eines Lastwächters — Ausgabe eines Diagnoselogs bei anhaltender Last

Davor

  • M1 — Grundgerüst von Engine·UI, Graph-CRUD, visuelle Canvas
  • M2 — Domänen-Aktions-Nodes (Anlage·Tag·Arbeitsauftrag·Produktionsdomäne usw.)
  • M3 — Diversifizierung der Trigger, 8 Arten Filter/Transformation/externe Anbindung, Skript-Engine
  • M4 — Debug-Speicherung·Ausführungshistorie-Bildschirm, Statistik, Bereitstellen/Aufheben, Import/Export
  • M5 — Integration von Domänentriggern, Massenvalidierung von Szenarien

Alle in diesem Handbuch behandelten Funktionen und Verhaltensweisen basieren auf dem oben genannten Zeitpunkt V2026.05.


Verwandte Bildschirme

  • CEP (Complex Event Processing): EQL-basierte Domänenereignisregel-Engine
  • Alarm: Alarmauslösung·-historie
  • Datenpunkt: Abfrage·Analyse von Tag-Daten
  • Entwicklerhandbuch: Flow-Engine: Engine-Architektur·Node-Schnittstelle·DB-Schema