跳到主要内容

2. 域 ID 规则

PlantPulse 的所有主数据均遵循 服务器端正则表达式验证。服务器强制执行正则表达式匹配,若违反则以 E1002 (VALIDATION_FAILED) 为由拒绝。准确的 ID 设计是 构建可扩展 IoT 系统的起点。

📖 平台整体规范摘要请参考域 ID 命名规范页面。

2.1 ID 规则概览 (基于服务器正则表达式)​

新 ID 为 «前缀全称 + 编号»。 当平台自动发放时,会在前缀后加上六位数字 (SITE_000001, TAG_000001)。每个域拥有独立的序列,超过 999999 时将增加位数 (ORDER_1000000)。

域正式前缀旧前缀 (持续有效)发放示例
企业 (Enterprise)ENTERPRISE_—ENTERPRISE_000001
站点 (Site)SITE_—SITE_000001
区域 (Area)AREA_ASSET_AREA_000001
线体 (Line)LINE_ASSET_LINE_000001
设备 (Equipment)EQUIPMENT_ASSET_EQUIPMENT_000001
连接 (OPC)OPC_—OPC_000001
标签 (Tag)TAG_—TAG_000001
Edge (Edge)EDGE_—不发放 — 像 EDGE_LINE1_01 一样直接定义
报警配置 (AlarmConfig)ALARM_CONFIG_五位数字, ALARM_CONFIG_TAG_…ALARM_CONFIG_000001
员工 (Employee)EMPLOYEE_EMP_EMPLOYEE_000001
客户 (Customer)CUSTOMER_—CUSTOMER_000001
产品 (Product)PRODUCT_—PRODUCT_000001
流程 (Flow)FLOW_—FLOW_000001
工单 (Order)ORDER_ORD_ORDER_000001
日历 (Calendar)CALENDAR_CAL_CALENDAR_000001
排班例外 (Shift override)SHIFT_OVERRIDE_OV_SHIFT_OVERRIDE_000001
工艺段 (Process segment)PROCESS_SEGMENT_SEG_PROCESS_SEGMENT_000001
设备关系 (Asset relation)ASSET_RELATION_REL_ASSET_RELATION_000001
设备命令 (Asset command)ASSET_COMMAND_—ASSET_COMMAND_000001
PLC 命令区域 (Command area)COMMAND_AREA_CMDAREA_COMMAND_AREA_000001
图像 (Image)IMAGE_IMG_IMAGE_000001
维护单 (Maintenance order)MAINTENANCE_ORDER_仅数字MAINTENANCE_ORDER_000001
登录账号 (User)无—不发放 — ^[A-Z][A-Z0-9_]*$

前缀之后仅限大写字母、数字及 _ ([A-Z0-9_]+)。维护单和报警配置的新 ID 仅接受六位及以上的数字。

层级不通过 ID 而是通过 asset_type 来判断

旧 ID 不会重新分配键值,因此在今后仍会继续出现。由于 ASSET_ 一个 ID 可能被广泛用于区域、线体或设备,因此通过前缀推测层级可能会出错。 层的判断请始终读取 asset_type(E · S · A · L · M)。

在通过前缀区分域时,最长前缀优先 — ASSET_RELATION_… 和 ASSET_COMMAND_… 不是 ASSET_,SHIFT_PATTERN_… 不是 SHIFT_。

手动输入 ID 将原样保存

如果手动指定 ID 创建,只要通过格式校验,输入的值将原样保存。只有在 ID 留空时才会发放编号。 在 V5 中,可以留空的是区域、线体、设备 (asset_id) 和日历 (calendar_id),而 POST /api/v5/site 必须接收 site_id。使用旧前缀创建时,区域、线体、设备同样被接收。

编号并非连续的 — 由于被拒绝的创建请求也会占用编号,因此出现空缺编号是正常现象。

⚠️ 强制验证: 服务器会对上述规则进行检查。若违反,将以 HTTP 422, 代码 E1002 为由拒绝。若 ID 已存在,则返回 HTTP 409。

⚠️ 全称才是正确答案: CUST_, PROD_ 在任何时期都不是有效前缀,将被拒绝。EMP_, ORD_, CAL_ 是用于现有 ID 的旧前缀,定义新 ID 时请使用全称。

⚠️ opc_id 仅有 OPC_ 一种: 无论是 Edge 来源还是外部 API 通道,必须以 OPC_ 开头。EDGE_·TEST_·API_ 将被拒绝 — Edge 来源应像 OPC_EDGE_00303 一样附在 OPC_ 之后。edge_id 为独立域,仅接收 EDGE_。

2.2 Site ID​

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

虚拟或汇总站点的前缀相同 — 像 SITE_V_… 一样在前缀内部定义名称。这属于命名惯例而非独立模式。

示例​

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);

❌ 错误示例 (在 V5 中均返回 null)​

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_… 만

OPC ID 表示数据采集的物理或逻辑来源。在相同 OPC 类型中需要语义区分时,使用 _ 表示层级。

各 OPC Type 建议模式​

OPC Type用途建议 ID 前缀
OPCOPC UA / OPC DA 服务器OPC_<ua-server-name>_<number>
PLCSiemens, Mitsubishi, Allen-Bradley 等OPC_PLC_<line>_<number>
MODBUSModbus TCP/RTU 设备OPC_MB_<equipment>_<number>
DATABASE外部 RDBMS 轮询OPC_DB_<system>
FILEREST API/文件导入OPC_FILE_<system>_<number>
VIRTUAL测试·仿真OPC_TEST_VIRTUAL_<number>
Edge GatewayEdge 网关 (独立 edge_id 域 — ^EDGE_[A-Z0-9_]+$)EDGE_<location>_<number>

⚠️ 无论是外部 API/文件通道还是测试用途,在 OPC 域中请使用 OPC_FILE_… · OPC_TEST_… 形式。

示例​

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 是 Edge 网关设备的标识符,与 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 — 层级结构核心​

设备层级包含 企业 → 站点 → 区域 → 线体 → 设备 五层 (ISA-95)。这五层均为资产树的节点,节点的层级由 asset_type 指定。

asset_type层级正则表达式
E企业 (Enterprise)^ENTERPRISE_[A-Z0-9_]+$
S站点 (Site)^SITE_[A-Z0-9_]+$
A区域 (Area)^(AREA_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$
L线体 (Line)^(LINE_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$
M设备 (Equipment, Machine)^(EQUIPMENT_[A-Z0-9_]+|ASSET_[A-Z0-9_]+)$

💡 EQUIPMENT 代码为 M 的原因: Equipment = Machine。在搜索和过滤中使用简短且明确的单字母代码。

每个安装实例仅允许存在 一个 企业。若尝试创建第二个企业或删除唯一企业,将以 409(enterprise.only_one) 为由被拒绝 — 请参阅 Site 服务。

节点的层级不可更改。试图将区域修改为线体的操作将被拒绝。如果层级错误,请重新创建而非修改。

标准 ID 模式示例​

以大田工厂(SITE_DJ)的一个区域、该区域内的一条线体以及该线体上一台设备为例 — 若 ID 留空创建,结果如下。

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

示例 — 创建资产树​

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 规则​

子类型parent_asset_id 值
区域 (A)站点 ID (例如: SITE_DJ)
线体 (L)区域的 asset_id (例如: AREA_000001)
设备 (M)线体的 asset_id (例如: LINE_000001)

父节点必须是 直接上一层。跨层指定或将其他站点的节点指定为父节点将被拒绝。

2.6 Tag ID​

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

标签是数据点 (传感器值, 计数器, 状态等) 的定义。它与 OPC 呈 1:1 关系,与 Asset 呈 0:N (可选连接) 关系。

建议模式​

场景模式示例
OPC 连接标签TAG_<part-of-opc-id>_<channel-no>TAG_EDGE_00303_90007
自定义标签TAG_<domain>_<number>TAG_PROD_COUNT_001
Virtual TagTAG_V_<purpose>_<number>TAG_V_OEE_LINE1

💡 Virtual Tag: 计算式或汇总标签的前缀统一为 TAG_。如需区分,可按惯例使用 TAG_V_ (非独立模式,仅为命名惯例)。标签是否为 «计算值» 由标签的计算设置 (use_calculation) 决定。创建方法请参阅 虚拟标签。

示例​

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​

字段V5 中是否可修改用途
tag_id不可修改 (建议重新创建)系统内部唯一键。不可变
tag_nameupdate() 或 patchBasic()展示给用户的名称
alias_namepatchMetadata()与外部系统映射的别名 (如: HMI 标签名)

建议将 tag_id 保持 不可变,显示名称使用 tag_name / alias_name。修改 tag_id 可能会导致与外部时序数据的对齐问题。

2.7 AlarmConfig / Employee / Customer / Product / Flow​

这些域均 强制执行服务器验证。请使用完整的前缀。报警配置 ID 仅接受数字形式 (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");

❌ 常见拒绝案例​

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)​

客户、产品、员工的 external_system 仅限 1~50 个大写字母、数字、_、: (^[A-Z0-9_:]{1,50}$)。 : 用于在系统内使编号唯一时附加的范围 — 例如: SAP PM 的客户特定 SAP_PM:100。 平台不解析范围,而是将 external_system + external_id 对直接作为键使用。 像 SAP-PM 这样包含连字符的值将被拒绝,且拒绝信息会告知允许的字符。

2.8 User ID (登录账号)​

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

与其它域不同,没有固定前缀,且首字母必须为大写。

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

2.9 Calendar / Order​

这两个域的 前缀同样由服务器检查。日历为 ^(CALENDAR_[A-Z0-9_]+|CAL_[A-Z0-9_]+)$,工单为 ^(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_type含义
MTN定期巡检 (Maintenance)
HOLIDAY节假日/非作业
INSPECTION检验
MEETING会议

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 단위

作业指令状态 (ISA-88): WAIT → START → END / ABORTED (详细内容请参阅 Order 服务)

2.10 ID 设计最佳实践​

建议事项​

  1. 保持不可变性 — 一旦分配 ID,请勿更改。如需更改,建议迁移至新 ID。
  2. 不要在 ID 中承载含义 — 层级通过 asset_type 体现,位置通过父节点或路径体现。若必须手动定义,请遵守前缀全称。
  3. 使用自动 ID — ID 留空时,平台将按 «前缀 + 六位数字» 发放。
  4. 固定大写与下划线 — 避免在全系统混用大小写,维持 [A-Z0-9_] 模式。
  5. 外部系统 ID 使用独立字段 — ERP/MES 原始 ID 存放在 external_*_id 字段,PlantPulse ID 维持自身体系。

应避免的模式​

  • ❌ 使用韩文、空格、特殊字符 — LINE_라인1, OPC 001
  • ❌ 过短或无意义的 ID — S1, A, T01
  • ❌ 缺失前缀或使用错误缩写 — CUST_001 (正确: CUSTOMER_001), PROD_A001 (正确: PRODUCT_A001)
  • ❌ 含义被硬编码在 ID 中导致无法更改 — LINE_DJ_OLD_BROKEN_LINE

2.11 验证失败响应确认​

V5 在验证失败时,方法将返回 null (或 false)。详细错误可通过 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

响应 envelope 示例:

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

详细错误代码请参阅 响应格式及错误处理。

2.12 提前获取 ID — POST /api/v5/domain-ids​

适用于在创建对象前需要获知 ID 的模拟器或外部系统。

请求 {"domain": "EQUIPMENT", "count": 3} → 响应 {"domain": "EQUIPMENT", "ids": ["EQUIPMENT_000123", ...]}

栏目值
domain域名称 (不区分大小写)。仅限具有序列的域 — ASSET · EDGE · SHIFT · SHIFT_PATTERN · HOLIDAY · BLOB 不可用
count1~1000, 默认 1

需要 ADMIN 或 API 令牌。由于仅获取编号而未创建行,因此 未使用编号出现空缺是正常现象。再次调用将获得新编号 (发送相同的 Idempotency-Key 除外)。

响应含义
400 domain_id.domain_required无 domain
404 domain_id.unknown域不存在或无序列
422 domain_id.count_invalidcount 不在 1~1000 范围内

控制台注册页面的 ID 栏​

注册页面 ID 栏右侧有 生成 图标 (悬停显示 «生成»)。点击后将填充新编号。手动输入时将自动转换为大写,并在失去焦点时检查格式和重复,将问题显示在栏目下方。在修改页面中,ID 栏被锁定且无图标。不具备发放序列的域 (Edge, 班组, 排班模式, 节假日, 对象) 同样没有图标。

在控制台中,ID 栏为必填项。请点击 生成 或手动输入。仅工艺段在留空时会被自动发放。生成和重复检查功能仅限 ADMIN · API 角色使用。

下一步​