Skip to main content

2. Domain ID Rules

All master data in PlantPulse follows server-side regex validation. The server enforces regex matching; violations are rejected with E1002 (VALIDATION_FAILED). Accurate ID design is the starting point for building a scalable IoT system.

📖 For a summary of platform-wide conventions, refer to the Domain ID Naming Convention page.

2.1 ID Rules at a Glance (Based on Server Regex)​

New IDs follow the «Prefix Full Name + Number» format. When the Platform issues an ID automatically, it appends a six-digit number after the prefix (SITE_000001, TAG_000001). Each domain has its own sequence, and the number of digits increases once it exceeds 999999 (ORDER_1000000).

DomainOfficial PrefixOld Prefix (Still Valid)Issuance Example
EnterpriseENTERPRISE_—ENTERPRISE_000001
SiteSITE_—SITE_000001
AreaAREA_ASSET_AREA_000001
LineLINE_ASSET_LINE_000001
EquipmentEQUIPMENT_ASSET_EQUIPMENT_000001
Connection (OPC)OPC_—OPC_000001
TagTAG_—TAG_000001
EdgeEDGE_—Not issued — defined manually like EDGE_LINE1_01
AlarmConfigALARM_CONFIG_Five-digit number, ALARM_CONFIG_TAG_…ALARM_CONFIG_000001
EmployeeEMPLOYEE_EMP_EMPLOYEE_000001
CustomerCUSTOMER_—CUSTOMER_000001
ProductPRODUCT_—PRODUCT_000001
FlowFLOW_—FLOW_000001
OrderORDER_ORD_ORDER_000001
CalendarCALENDAR_CAL_CALENDAR_000001
Shift overrideSHIFT_OVERRIDE_OV_SHIFT_OVERRIDE_000001
Process segmentPROCESS_SEGMENT_SEG_PROCESS_SEGMENT_000001
Asset relationASSET_RELATION_REL_ASSET_RELATION_000001
Asset commandASSET_COMMAND_—ASSET_COMMAND_000001
Command areaCOMMAND_AREA_CMDAREA_COMMAND_AREA_000001
ImageIMAGE_IMG_IMAGE_000001
Maintenance orderMAINTENANCE_ORDER_Numeric onlyMAINTENANCE_ORDER_000001
UserNone—Not issued — ^[A-Z][A-Z0-9_]*$

The prefix is followed only by uppercase letters, numbers, and _ ([A-Z0-9_]+). New IDs for maintenance orders and alarm settings only accept numbers of six digits or more.

Layers are determined by asset_type, not ID

Old IDs are not re-keyed and will continue to appear. Since ASSET_ was used across areas, lines, and equipment, guessing the layer based on the prefix is incorrect. Always read the layer from asset_type (E · S · A · L · M).

When distinguishing domains by prefix, the longest prefix takes precedence — ASSET_RELATION_… and ASSET_COMMAND_… are not ASSET_, and SHIFT_PATTERN_… is not SHIFT_.

Manually provided IDs are stored as-is

If an ID is provided during creation, it is stored exactly as given, provided it passes format validation. Numbers are issued only when the ID field is left blank. In V5, blank IDs are permitted for areas, lines, equipment (asset_id), and calendars (calendar_id); however, POST /api/v5/site must receive site_id. New entries for areas, lines, and equipment are also accepted using old prefixes.

Numbers are not sequential — since rejected creation attempts consume a number, it is normal for gaps to exist in the numbering.

⚠️ Validation Enforcement: The server validates these rules. Violations are rejected with HTTP 422, code E1002. If an ID already exists, HTTP 409 is returned.

⚠️ Full Names are Required: CUST_ and PROD_ are not valid prefixes for any period and will be rejected. EMP_, ORD_, and CAL_ are old prefixes used for existing IDs; use full names when creating new ones.

⚠️ opc_id is exclusively OPC_: Whether from an Edge source or an external API channel, it must start with OPC_. EDGE_, TEST_, and API_ are rejected — Edge sources are attached after OPC_, such as OPC_EDGE_00303. edge_id is a separate domain and only accepts EDGE_.

2.2 Site ID​

정규식: ^SITE_[A-Z0-9_]+$
허용: SITE_… 만

Virtual or aggregation sites use the same prefix — names are created within the prefix, such as SITE_V_…. This is a naming convention rather than a separate pattern.

Examples​

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 정규식 확인 필요");
}

// 가상 사이트 (테스트·집계용) — 접두는 SITE_ 그대로
SiteRequestV5 vsite = new SiteRequestV5();
vsite.setSite_id("SITE_V_AGG_01");
vsite.setSite_name("집계 가상 사이트");
client.site().create(vsite);

❌ Incorrect Examples (All return null in V5)​

req.setSite_id("DJ_FACTORY"); // ❌ SITE_ 누락 → E1002
req.setSite_id("site_00001"); // ❌ 소문자 → E1002
req.setSite_id("00001"); // ❌ 접두사 없음 → E1002
req.setSite_id("VSITE_01"); // ❌ V 변형 접두는 없다 → E1002

2.3 OPC ID​

정규식: ^OPC_[A-Z0-9_]+$
허용: OPC_… 만

The OPC ID represents the physical or logical source of data collection. When semantic separation is required within the same OPC type, hierarchies are expressed using _.

OPC TypePurposeRecommended ID Prefix
OPCOPC UA / OPC DA serverOPC_<ua-server-name>_<number>
PLCSiemens, Mitsubishi, Allen-Bradley, etc.OPC_PLC_<line>_<number>
MODBUSModbus TCP/RTU deviceOPC_MB_<equipment>_<number>
DATABASEExternal RDBMS pollingOPC_DB_<system>
FILEREST API/File importOPC_FILE_<system>_<number>
VIRTUALTest/SimulationOPC_TEST_VIRTUAL_<number>
Edge GatewayEdge gateway (Separate edge_id domain — ^EDGE_[A-Z0-9_]+$)EDGE_<location>_<number>

⚠️ Use the OPC_FILE_… · OPC_TEST_… format in the OPC domain, whether for external API/file channels or testing.

Examples​

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

OPCRequestV5 req = new OPCRequestV5();
req.setOpc_id("OPC_PLC_L1_001");
req.setOpc_name("Line1 메인 PLC");
req.setOpc_protocol("S7"); // 프로토콜 코드 — 소스 유형(PLC)은 여기서 파생
req.setSite_id("SITE_DJ");
req.setOpc_source_ip("192.168.10.50");
req.setOpc_source_port(102);
client.opc().create(req);

// ERP 연동 — REST API 로 들어오는 연결
OPCRequestV5 erp = new OPCRequestV5();
erp.setOpc_id("OPC_API_ERP_001");
erp.setOpc_protocol("API");
erp.setSite_id("SITE_DJ");
client.opc().create(erp);

// 테스트·시뮬레이션
OPCRequestV5 testOpc = new OPCRequestV5();
testOpc.setOpc_id("OPC_TEST_001"); // TEST_ 로 시작하면 E1002
testOpc.setOpc_protocol("API");
testOpc.setSite_id("SITE_DJ");
client.opc().create(testOpc);

// 엣지 자기감시 연결 OPC_SYSTEM_<edge_id> 는 엣지가 sync 로 선언한다 — 직접 만들지 않는다.

2.4 Edge ID​

정규식: ^EDGE_[A-Z0-9_]+$

edge_id is an identifier for Edge gateway devices and is a different domain from opc_id.

req.setEdge_id("EDGE_LINE1_01");
// req.setEdge_id("OPC_EDGE_00303"); // ❌ OPC_ 는 edge_id 의 접두사가 아니다
// req.setEdge_id("TEST_EDGE_01"); // ❌ TEST_ 는 어느 도메인에서도 접두사가 아니다

2.5 Asset ID — Core of Hierarchy​

The asset hierarchy consists of five layers: Enterprise → Site → Area → Line → Equipment (ISA-95). All five layers are nodes in the asset tree, and the layer of a node is defined by asset_type.

asset_typeLayerRegex
EEnterprise^ENTERPRISE_[A-Z0-9_]+$
SSite^SITE_[A-Z0-9_]+$
AArea^(AREA_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$
LLine^(LINE_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$
MEquipment (Machine)^(EQUIPMENT_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$

💡 Why the EQUIPMENT code is M: Equipment = Machine. A short, clear single-character code is used for searching and filtering.

There is only one Enterprise per installation. Creating a second one or deleting the only existing Enterprise is rejected with 409 (enterprise.only_one) — see the Site service.

The layer of a node cannot be changed. Modifications attempting to change an Area to a Line will be rejected; if the layer is incorrect, create a new node rather than moving it.

Standard ID Pattern Example​

One Area, one Line within that Area, and one Equipment above it for Daejeon Plant (SITE_DJ) — when created with blank IDs, they appear as follows:

AREA_000001 ← 구역
└ LINE_000001 ← 라인
└ EQUIPMENT_000001 ← 설비

Example — Asset Tree Creation​

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_name("조립구역");
area.setAsset_type("A");
client.asset().create(area);

// asset_id 를 비워 두면 플랫폼이 발급합니다 — 응답에서 AREA_000001 을 받습니다

// 2) Area 산하 Line
AssetRequestV5 line = new AssetRequestV5();
line.setSite_id("SITE_DJ");
line.setParent_asset_id("AREA_000001"); // 부모는 Area
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("LINE_000001"); // 부모는 Line
equip.setAsset_name("CNC #1");
equip.setAsset_type("M");
equip.setAsset_class_code("CNC"); // 설비 분류 — 기준정보에 있는 코드
client.asset().create(equip);

parent_asset_id Rules​

Child Typeparent_asset_id Value
Area (A)Site ID (e.g., SITE_DJ)
Line (L)Area asset_id (e.g., AREA_000001)
Equipment (M)Line asset_id (e.g., LINE_000001)

The parent must be the immediately preceding layer. Skipping layers or assigning a node from a different site as the parent will result in rejection.

2.6 Tag ID​

정규식: ^TAG_[A-Z0-9_]+$
허용: TAG_… 만 (가상 태그도 TAG_ 로 시작한다)

A Tag is a definition of a data point (sensor value, counter, status, etc.). It has a 1:1 relationship with an OPC and a 0:N (optional connection) relationship with an Asset.

ScenarioPatternExample
OPC connection tagTAG_<part-of-opc-id>_<channel-no>TAG_EDGE_00303_90007
Manually defined tagTAG_<domain>_<number>TAG_PROD_COUNT_001
Virtual TagTAG_V_<purpose>_<number>TAG_V_OEE_LINE1

💡 Virtual Tag: Calculation and aggregation tags also use the prefix TAG_. If distinction is needed, the convention TAG_V_ is used (naming convention, not a separate pattern). Whether a tag is a «calculated value» is determined by the tag's calculation settings (use_calculation). See Virtual Tag for creation instructions.

Examples​

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("EQUIPMENT_000001");
req.setJava_type("Double");
req.setUnit("RPM");
req.setDescription("Spindle 회전수 (RPM)");
client.tag().create(req);

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

tag_id vs tag_name vs alias_name​

FieldChangeable in V5Purpose
tag_idNot changeable (Recreation recommended)Internal system unique key. Immutable
tag_nameupdate() or patchBasic()Name visible to user
alias_namepatchMetadata()Alias for mapping with external systems (e.g., HMI tag name)

It is recommended to keep tag_id immutable and use tag_name / alias_name for display names. Changing the tag_id may cause consistency issues with external time series data.

2.7 AlarmConfig / Employee / Customer / Product / Flow​

All these domains are subject to mandatory server validation. Use the accurate full prefix. AlarmConfig IDs only accept numeric formats (ALARM_CONFIG_000001).

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

// Employee
EmployeeRequestV5 emp = new EmployeeRequestV5();
emp.setEmployee_id("EMPLOYEE_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");

❌ Common Rejection Cases​

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

External System Name (external_system)​

The external_system for Customer, Product, and Employee only accepts 1–50 uppercase letters, numbers, _, and : (^[A-Z0-9_:]{1,50}$). : is used when appending a range to make the number unique within that system — e.g., SAP PM client-specific SAP_PM:100. The Platform does not interpret the range and uses the external_system + external_id pair as the key. Hyphens, such as in SAP-PM, are rejected, and the rejection message specifies the allowed characters.

2.8 User ID (Login Account)​

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

Unlike other domains, it has no fixed prefix, and the first letter must be uppercase.

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

2.9 Calendar / Order​

The server also validates the prefixes for these two domains. Calendar is ^(CALENDAR_[A-Z0-9_]+|CAL_[A-Z0-9_]+)$, and Work Order is ^(ORDER_[A-Z0-9_]+|ORD_[A-Z0-9_]+)$.

Calendar​

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

CalendarRequestV5 cal = new CalendarRequestV5();
// calendar_id 를 비워 두면 플랫폼이 CALENDAR_000001 꼴로 발급합니다
cal.setSite_id("SITE_DJ");
cal.setAsset_id("EQUIPMENT_000001");
cal.setTarget_type("MTN"); // 점검 일정
target_typeMeaning
MTNMaintenance
HOLIDAYHoliday/Non-operation
INSPECTIONInspection
MEETINGMeeting

Order​

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

OrderRequestV5 order = new OrderRequestV5();
order.setOrder_id("ORDER_000001");
order.setSite_id("SITE_DJ");
order.setAsset_id("EQUIPMENT_000001");
order.setCustomer_id("CUSTOMER_001"); // CUSTOMER_ 주의!
order.setProduct_id("PRODUCT_A001"); // PRODUCT_ 주의!
order.setEmployee_id("EMPLOYEE_E12345");
order.setPlanned_quantity(Quantity.of("500", "EA")); // ISA-95 Quantity — 값 + UN/ECE Rec 20 단위

Work order status (ISA-88): WAIT → START → END / ABORTED (For more details, see Order service)

2.10 ID Design Best Practices​

Recommendations​

  1. Maintain Immutability — Do not change an ID once assigned. If a change is necessary, migrating to a new ID is recommended.
  2. Do Not Embed Meaning in IDs — Layers are defined by asset_type, and locations are defined by parents/paths. If manually creating IDs, adhere to the prefix full name.
  3. Use Automatic IDs — If the ID field is left blank, the Platform issues an ID consisting of the prefix + six digits.
  4. Fix Uppercase and Underscores — Avoid mixing cases across the system and maintain the [A-Z0-9_] pattern.
  5. External System IDs in Separate Fields — Store original ERP/MES IDs in the external_*_id field and maintain the PlantPulse ID's own system.

Patterns to Avoid​

  • ❌ Use of Korean, spaces, or special characters — LINE_라인1, OPC 001
  • ❌ IDs that are too short or meaningless — S1, A, T01
  • ❌ Missing prefixes or incorrect abbreviations — CUST_001 (Correct: CUSTOMER_001), PROD_A001 (Correct: PRODUCT_A001)
  • ❌ Embedding meaning in IDs, making them unchangeable — LINE_DJ_OLD_BROKEN_LINE

2.11 Checking Validation Failure Responses​

In V5, upon validation failure, the method returns null (or false). Detailed errors can be found in the 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

Response envelope example:

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

For detailed error codes, refer to Response Format and Error Handling.

2.12 Pre-receiving IDs — POST /api/v5/domain-ids​

Used by simulators or external systems that need to know the ID before creating an object.

Request {"domain": "EQUIPMENT", "count": 3} → Response {"domain": "EQUIPMENT", "ids": ["EQUIPMENT_000123", ...]}

ColumnValue
domainDomain name (case-insensitive). Only for those with sequences — ASSET · EDGE · SHIFT · SHIFT_PATTERN · HOLIDAY · BLOB are not allowed
count1–1000, default 1

Requires ADMIN or API tokens. Since it retrieves a number without creating a row, it is normal for unused numbers to be missing. Calling it again yields a new number (unless the same Idempotency-Key is sent).

ResponseMeaning
400 domain_id.domain_requiredNo domain
404 domain_id.unknownDomain does not exist or has no sequence
422 domain_id.count_invalidcount is outside the 1–1000 range

ID Field in the Console Registration Screen​

To the right of the ID field in the registration screen, there is a Generate icon (shows «Generate» on hover). Clicking it fills the field with a new number. Manually entered text is converted to uppercase, and format/duplicate checks are performed when the field loses focus, with issues displayed below the field. In the edit screen, the ID field is locked and the icon is absent. Domains without an issuance sequence (Edge, Shift, Work Pattern, Holiday, Object) also lack the icon.

The ID field is mandatory in the Console. Use Generate or enter manually. The only field that is issued when left blank is the process segment. Generation and duplicate checks are available only to users with ADMIN or API roles.

Next Steps​