Zum Hauptinhalt springen

2. Domain-ID-Regeln

Alle Stammdaten in PlantPulse unterliegen einer serverseitigen Regex-Validierung. Die Domain-Validatoren (SiteValidator, OPCValidator, AssetValidator, TagValidator, …) erzwingen die Regex-Übereinstimmung; bei Verstößen liefern Aufrufe von create() / update() ein null zurück, und das Antwort-Envelope enthält _code=E1002 (VALIDATION_FAILED). Ein sauberes ID-Design ist der Ausgangspunkt für den Aufbau skalierbarer IoT-Systeme.

📖 Eine Zusammenfassung der plattformweiten Konventionen finden Sie auf der Seite zu den Domain-ID-Namenskonventionen.

2.1 ID-Regeln auf einen Blick (nach Server-Regex)

DomainRegexEmpfohlenes MusterBeispiel
Site^V?SITE_[A-Z0-9_]+$SITE_<token> (oder VSITE_… Virtual)SITE_DJ, VSITE_AGG_01
OPC^(OPC|EDGE|TEST)_[A-Z0-9_]+$OPC_<type>_<number> / EDGE_<location>_<number>OPC_00303, EDGE_GW01, TEST_VIRTUAL
Edge^(EDGE|OPC)_[A-Z0-9_]+$EDGE_<location>_<number>EDGE_LINE1_01
Asset (Area/Line/Equipment)^ASSET_[A-Z0-9_]+$ASSET_<site>_<type>_<number>ASSET_DJ_L_0001
Tag^V*TAG_[A-Z0-9_]+$TAG_<OPC>_<number> (oder VTAG_ virtueller Tag)TAG_EDGE_00303_90007, VTAG_OEE_LINE1
AlarmConfig^ALARM_CONFIG_[A-Z0-9_]+$ALARM_CONFIG_<metric>_<number>ALARM_CONFIG_TEMP_HIGH_01
Employee^EMP_[A-Z0-9_]+$EMP_<employee-no>EMP_E12345
Customer^CUSTOMER_[A-Z0-9_]+$CUSTOMER_<number>CUSTOMER_001
Product^PRODUCT_[A-Z0-9_]+$PRODUCT_<SKU>PRODUCT_A001
Flow^FLOW_[A-Z0-9_]+$FLOW_<purpose>_<interval>FLOW_OEE_DAILY
User (Login)^[A-Z][A-Z0-9_]*$Beginn mit Großbuchstabe, [A-Z0-9_]ADMIN, OPERATOR_01
Calendar(frei)CAL_<YYYYMMDD>_<seq>CAL_20260514_0001
Order(frei)ORD_<YYYYMMDD>_<seq>ORD_20260514_001

⚠️ Erzwungene Validierung: Alle Domains, für die in der Tabelle eine Regex angegeben ist, werden serverseitig geprüft. Bei Verstößen liefert V5 ein null zurück, und _code=E1002, _message="site_id must match ^V?SITE_[A-Z0-9_]+$" usw. sind in der Antwort enthalten.

⚠️ Customer/Product als vollständiges Wort: CUSTOMER_ und PRODUCT_ sind die korrekten Präfixe. Die kurzen Formen CUST_ und PROD_ werden abgelehnt.

⚠️ Präfix API_ ist bei OPC nicht zulässig: Auch bei externen API-Kanälen muss opc_id mit einem von OPC_ / EDGE_ / TEST_ beginnen.

2.2 Site ID

정규식: ^V?SITE_[A-Z0-9_]+$
허용: SITE_… 또는 VSITE_… (Virtual Site — 물리 사이트 없이 만드는 가상/집계용 사이트)

Beispiele

import plantpulse.api.v5.dto.request.SiteRequestV5;
import plantpulse.api.v5.dto.response.SiteResponseV5;

SiteRequestV5 req = new SiteRequestV5();
req.setSite_id("SITE_DJ"); // 대전공장
req.setSite_name("대전 1공장");
req.setLat("36.3504");
req.setLng("127.3845");

SiteResponseV5 created = client.site().create(req);
if (created == null) {
System.err.println("등록 실패 — site_id 정규식 확인 필요");
}

// Virtual Site (테스트·집계용)
SiteRequestV5 vsite = new SiteRequestV5();
vsite.setSite_id("VSITE_AGG_01");
vsite.setSite_name("집계 가상 사이트");
client.site().create(vsite);

❌ Ungültige Beispiele (alle liefern in V5 null zurück)

req.setSite_id("DJ_FACTORY"); // ❌ SITE_ 누락 → E1002
req.setSite_id("site_00001"); // ❌ 소문자 → E1002
req.setSite_id("00001"); // ❌ 접두사 없음 → E1002
req.setSite_id("VVSITE_01"); // ❌ V는 0 또는 1개만 (V?)

2.3 OPC ID

정규식: ^(OPC|EDGE|TEST)_[A-Z0-9_]+$
허용: OPC_… / EDGE_… / TEST_…

Die OPC ID kennzeichnet die physische bzw. logische Herkunft der Erfassung. Ist innerhalb desselben OPC-Typs eine semantische Trennung erforderlich, wird die Hierarchie über _ abgebildet.

Empfohlene Muster je OPC Type

OPC TypeVerwendungEmpfohlenes ID-Präfix
OPCOPC UA / OPC DA ServerOPC_<ua-server-name>_<number>
PLCSiemens, Mitsubishi, Allen-Bradley usw.OPC_PLC_<line>_<number>
MODBUSModbus TCP/RTU-GeräteOPC_MB_<equipment>_<number>
DATABASEPolling externer RDBMSOPC_DB_<system>
FILEREST API/DateiimportOPC_FILE_<system>_<number>
VIRTUALTest und SimulationTEST_VIRTUAL_<number>
Edge GatewayEdge-Gateway (verwendet separat edge_id)EDGE_<location>_<number>

⚠️ In älteren Dokumenten wurde das Präfix API_ erwähnt, die aktuelle Servervalidierung lässt jedoch nur OPC_/EDGE_/TEST_ zu. Verwenden Sie auch für externe API-/Dateikanäle in der OPC-Domain die Form OPC_FILE_….

Beispiele

import plantpulse.api.v5.dto.request.OPCRequestV5;

OPCRequestV5 req = new OPCRequestV5();
req.setOpc_id("OPC_EDGE_00303");
req.setOpc_name("Line1 Edge Gateway");
req.setOpc_type("PLC"); // OPC/PLC/MODBUS/DATABASE/FILE/VIRTUAL
req.setOpc_sub_type("SIEMENS_S7");
req.setSite_id("SITE_DJ");
req.setOpc_server_ip("192.168.10.50");
req.setOpc_agent_ip("192.168.10.5");
req.setOpc_agent_port(60000);
client.opc().create(req);

// ERP 연동 — OPC_FILE_ 접두사 (API_ 아님!)
OPCRequestV5 fileChannel = new OPCRequestV5();
fileChannel.setOpc_id("OPC_FILE_ERP_001");
fileChannel.setOpc_type("FILE");
fileChannel.setSite_id("SITE_DJ");
client.opc().create(fileChannel);

// 테스트·시뮬레이션
OPCRequestV5 testOpc = new OPCRequestV5();
testOpc.setOpc_id("TEST_VIRTUAL_001");
testOpc.setOpc_type("VIRTUAL");
testOpc.setSite_id("SITE_DJ");
client.opc().create(testOpc);

2.4 Edge ID

정규식: ^(EDGE|OPC)_[A-Z0-9_]+$

edge_id ist die Kennung eines Edge-Gateway-Geräts. Die Regex ist nahezu identisch mit der von OPC, das Präfix TEST_ ist jedoch nicht zulässig.

req.setEdge_id("EDGE_LINE1_01");
req.setEdge_id("OPC_EDGE_00303"); // OPC도 가능
// req.setEdge_id("TEST_EDGE_01"); // ❌ edge_id는 TEST_ 불가

2.5 Asset ID — Kern der Hierarchie

Assets bilden einen dreistufigen Baum aus Area → Line → Equipment. Es empfiehlt sich, den Typcode in die ID aufzunehmen, damit die Hierarchie visuell erkennbar ist.

정규식: ^ASSET_[A-Z0-9_]+$
권장 형식: ASSET_<site-token>_<type-code>_<number>

Asset-Type-Codes

Wert asset_typeBedeutungEmpfohlenes ID-Muster
AArea (Bereich)ASSET_<site>_A_<number>
LLine (Linie)ASSET_<site>_L_<number>
MEquipment (Anlage, Machine)ASSET_<site>_M_<number>

💡 Warum der EQUIPMENT-Code M lautet: Equipment = Machine. Für Suche und Filterung wird ein kurzer, eindeutiger Ein-Buchstaben-Code verwendet.

Beispiele für Standard-ID-Muster

Werk Daejeon (SITE_DJ), Bereich 1, darin Linie 2, darauf Anlage 3:

ASSET_DJ_A_0001 ← Area (1구역)
└ ASSET_DJ_L_0002 ← Line (2번 라인)
└ ASSET_DJ_M_0003 ← Equipment (3번 설비)

Beispiel — Anlagenbaum erstellen

import plantpulse.api.v5.dto.request.AssetRequestV5;
import plantpulse.api.v5.dto.response.AssetResponseV5;

// 1) 사이트 직속 Area
AssetRequestV5 area = new AssetRequestV5();
area.setSite_id("SITE_DJ");
area.setParent_asset_id("SITE_DJ"); // 부모는 사이트 ID
area.setAsset_id("ASSET_DJ_A_0001");
area.setAsset_name("조립구역");
area.setAsset_type("A");
client.asset().create(area);

// 2) Area 산하 Line
AssetRequestV5 line = new AssetRequestV5();
line.setSite_id("SITE_DJ");
line.setParent_asset_id("ASSET_DJ_A_0001"); // 부모는 Area
line.setAsset_id("ASSET_DJ_L_0001");
line.setAsset_name("1라인");
line.setAsset_type("L");
client.asset().create(line);

// 3) Line 산하 Equipment
AssetRequestV5 equip = new AssetRequestV5();
equip.setSite_id("SITE_DJ");
equip.setParent_asset_id("ASSET_DJ_L_0001"); // 부모는 Line
equip.setAsset_id("ASSET_DJ_M_0001");
equip.setAsset_name("CNC #1");
equip.setAsset_type("M");
equip.setTable_type("CNC");
client.asset().create(equip);

Regeln für parent_asset_id

Untergeordneter TypWert parent_asset_id
Area (A)Site-ID (z. B. SITE_DJ)
Line (L)asset_id der Area (z. B. ASSET_DJ_A_0001)
Equipment (M)asset_id der Line (z. B. ASSET_DJ_L_0001)

Unterhalb eines Equipment kann erneut ein untergeordnetes Equipment angelegt werden (Baugruppe). In diesem Fall ist parent_asset_id die asset_id des übergeordneten Equipment.

2.6 Tag ID

정규식: ^V*TAG_[A-Z0-9_]+$
허용: TAG_…, VTAG_…, VVTAG_… (V 누적 가능 — Virtual Tag 파생 단계)

Ein Tag ist die Definition eines Datenpunkts (Sensorwert, Zähler, Status usw.). Zu OPC besteht eine 1:1-Beziehung, zu Asset eine 0:N-Beziehung (optionale Verbindung).

Empfohlene Muster

SzenarioMusterBeispiel
Mit OPC verbundener TagTAG_<part-of-opc-id>_<channel-no>TAG_EDGE_00303_90007
Selbst definierter TagTAG_<domain>_<number>TAG_PROD_COUNT_001
Virtual Tag (Stufe 1)VTAG_<purpose>_<number>VTAG_OEE_LINE1
Virtual Tag (abgeleitet, Stufe 2)VVTAG_<purpose>_<number>VVTAG_AGGREGATED_01

💡 Kumulation von V bei Virtual Tags: Je tiefer die Ableitungsstufe von Formel- oder Aggregations-Tags, desto mehr V werden angehängt. In der Regel genügt eine Stufe VTAG_.

Beispiele

import plantpulse.api.v5.dto.request.TagRequestV5;

TagRequestV5 req = new TagRequestV5();
req.setTag_id("TAG_EDGE_00303_90007");
req.setTag_name("Spindle RPM");
req.setOpc_id("OPC_EDGE_00303");
req.setSite_id("SITE_DJ");
req.setLinked_asset_id("ASSET_DJ_M_0001");
req.setJava_type("Double");
req.setUnit("RPM");
req.setTag_source("OPC");
req.setDescription("Spindle 회전수 (RPM)");
client.tag().create(req);

// Virtual Tag — 라인별 OEE 집계
TagRequestV5 vtag = new TagRequestV5();
vtag.setTag_id("VTAG_OEE_LINE1");
vtag.setTag_name("Line1 OEE");
vtag.setSite_id("SITE_DJ");
vtag.setTag_source("VIRTUAL");
client.tag().create(vtag);

tag_id vs. tag_name vs. alias_name

FeldIn V5 änderbar?Verwendung
tag_idNicht änderbar (Neuanlage empfohlen)Systeminterner eindeutiger Schlüssel. Unveränderlich
tag_nameupdate() oder patchBasic()Für Benutzer sichtbarer Name
alias_namepatchMetadata()Alias für die Zuordnung zu externen Systemen (z. B. HMI-Tagname)

Belassen Sie tag_id nach Möglichkeit unveränderlich und verwenden Sie für Anzeigenamen tag_name / alias_name. Eine Änderung der tag_id kann zu Konsistenzproblemen mit externen Zeitreihendaten führen.

2.7 AlarmConfig / Employee / Customer / Product / Flow

Auch diese Domains unterliegen einer erzwungenen Servervalidierung. Verwenden Sie exakt die vollständigen Präfixe.

// Alarm Config
AlarmConfigRequestV5 alarm = new AlarmConfigRequestV5();
alarm.setAlarm_config_id("ALARM_CONFIG_TEMP_HIGH_01");
alarm.setSite_id("SITE_DJ");

// Employee
EmployeeRequestV5 emp = new EmployeeRequestV5();
emp.setEmployee_id("EMP_E12345");
emp.setRole_code("OPERATOR"); // OPERATOR, SUPERVISOR 등

// Customer — CUSTOMER_ (전체 단어, CUST_ 아님!)
CustomerRequestV5 cust = new CustomerRequestV5();
cust.setCustomer_id("CUSTOMER_001");
cust.setExternal_customer_id("ERP_C001");

// Product — PRODUCT_ (전체 단어, PROD_ 아님!)
ProductRequestV5 prod = new ProductRequestV5();
prod.setProduct_id("PRODUCT_A001");
prod.setProduct_code("SKU-A001");

// Flow
FlowRequestV5 flow = new FlowRequestV5();
flow.setFlow_id("FLOW_OEE_DAILY");
flow.setSite_id("SITE_DJ");

❌ Häufige Ablehnungsfälle

cust.setCustomer_id("CUST_001"); // ❌ CUST_ 아님 → E1002
prod.setProduct_id("PROD_A001"); // ❌ PROD_ 아님 → E1002
emp.setEmployee_id("E12345"); // ❌ EMP_ 누락 → E1002
flow.setFlow_id("flow_oee_daily"); // ❌ 소문자 → E1002

2.8 User ID (Login-Konto)

정규식: ^[A-Z][A-Z0-9_]*$
규칙: 대문자로 시작, 이후 [A-Z0-9_]만 허용

Anders als bei den übrigen Domains gibt es kein festes Präfix, das erste Zeichen muss jedoch ein Großbuchstabe sein.

✅ ADMIN
✅ OPERATOR_01
✅ KOPENS_USER
❌ admin → 소문자 시작
❌ 1USER → 숫자 시작
❌ _ADMIN → _ 시작

2.9 Calendar / Order — ohne Validierung

Für diese beiden Domains gibt es keine Servervalidierung, das ID-Format ist daher frei wählbar. Für konsistenten Betrieb und einfache Suche sollten Sie dennoch den empfohlenen Mustern folgen.

Calendar

import plantpulse.api.v5.dto.request.CalendarRequestV5;

CalendarRequestV5 cal = new CalendarRequestV5();
cal.setCalendar_id("CAL_20260514_0001"); // CAL_<YYYYMMDD>_<seq>
cal.setSite_id("SITE_DJ");
cal.setAsset_id("ASSET_DJ_M_0001");
cal.setTarget_type("MTN"); // 점검 일정
target_typeBedeutung
MTNRegelmäßige Inspektion (Maintenance)
HOLIDAYFeiertag/produktionsfreier Tag
INSPECTIONPrüfung
MEETINGBesprechung

Order

import plantpulse.api.v5.dto.request.OrderRequestV5;

OrderRequestV5 order = new OrderRequestV5();
order.setOrder_id("ORD_20260514_001"); // ORD_<YYYYMMDD>_<seq>
order.setSite_id("SITE_DJ");
order.setAsset_id("ASSET_DJ_M_0001");
order.setCustomer_id("CUSTOMER_001"); // CUSTOMER_ 주의!
order.setProduct_id("PRODUCT_A001"); // PRODUCT_ 주의!
order.setEmployee_id("EMP_E12345");
order.setTarget_units(500);

Status des Arbeitsauftrags (ISA-88): WAIT → START → END / ABORTED (Details siehe Order-Service)

2.10 Best Practices für das ID-Design

Empfehlungen

  1. Unveränderlichkeit wahren — Ändern Sie einmal vergebene IDs nicht. Ist eine Änderung erforderlich, empfiehlt sich eine Migration auf eine neue ID.
  2. Hierarchie in der ID abbilden — Enthält die ID Hierarchieinformationen wie ASSET_<site>_<type>_<number>, verbessert das die Transparenz im Betrieb.
  3. Feste Stellenanzahl verwenden — Füllen Sie den Zahlenteil wie bei 0001, 00001 auf, um die Sortierung zu erhalten.
  4. Großbuchstaben und Unterstriche beibehalten — Vermeiden Sie systemweit gemischte Groß-/Kleinschreibung und halten Sie das Muster [A-Z0-9_] ein.
  5. IDs externer Systeme in separaten Feldern — Bewahren Sie die Original-IDs aus ERP/MES im Feld external_*_id auf und behalten Sie für PlantPulse ein eigenes ID-Schema bei.

Zu vermeidende Muster

  • ❌ Koreanische Zeichen, Leerzeichen, Sonderzeichen — ASSET_라인1, OPC 001
  • ❌ Zu kurze oder nichtssagende IDs — S1, A, T01
  • ❌ Fehlendes Präfix oder falsche Abkürzung — CUST_001 (richtig: CUSTOMER_001), PROD_A001 (richtig: PRODUCT_A001)
  • ❌ Fest in der ID verankerte Bedeutung, die eine Änderung unmöglich macht — ASSET_DJ_L_OLD_BROKEN_LINE

2.11 Antwort bei fehlgeschlagener Validierung prüfen

Bei fehlgeschlagener Validierung liefert die Methode in V5 ein null (oder false) zurück. Details zum Fehler finden Sie im Envelope.

import plantpulse.api.v5.service.BaseServiceV5;
import plantpulse.json.JSONObject;

// V5 서비스 내부는 envelope를 외부에 노출하지 않으나,
// 디버그 모드를 켜면 로그에 출력됩니다.
client = new APIClient_V5(proto, host, port, user, token, true); // debug=true

Beispiel eines Antwort-Envelopes:

{
"_status": "ERROR",
"_code": "E1002",
"_message": "validation failed: site_id must match ^V?SITE_[A-Z0-9_]+$",
"_http_status": 400
}

Details zu den Fehlercodes siehe Antwortformat und Fehlerbehandlung.

Nächste Schritte