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 仅接受六位及以上的数字。
asset_type 来判断旧 ID 不会重新分配键值,因此在今后仍会继续出现。由于 ASSET_ 一个 ID 可能被广泛用于区域、线体或设备,因此通过前缀推测层级可能会出错。 层的判断请始终读取 asset_type(E · S · A · L · M)。
在通过前缀区分域时,最长前缀优先 — ASSET_RELATION_… 和 ASSET_COMMAND_… 不是 ASSET_,SHIFT_PATTERN_… 不是 SHIFT_。
如果手动指定 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 前缀 |
|---|---|---|
OPC | OPC UA / OPC DA 服务器 | OPC_<ua-server-name>_<number> |
PLC | Siemens, Mitsubishi, Allen-Bradley 等 | OPC_PLC_<line>_<number> |
MODBUS | Modbus TCP/RTU 设备 | OPC_MB_<equipment>_<number> |
DATABASE | 外部 RDBMS 轮询 | OPC_DB_<system> |
FILE | REST API/文件导入 | OPC_FILE_<system>_<number> |
VIRTUAL | 测试·仿真 | OPC_TEST_VIRTUAL_<number> |
| Edge Gateway | Edge 网关 (独立 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 Tag | TAG_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_name | update() 或 patchBasic() | 展示给用户的名称 |
alias_name | patchMetadata() | 与外部系统映射的别名 (如: 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 设计最佳实践
建议事项
- 保持不可变性 — 一旦分配 ID,请勿更改。如需更改,建议迁移至新 ID。
- 不要在 ID 中承载含义 — 层级通过
asset_type体现,位置通过父节点或路径体现。若必须手动定义,请遵守前缀全称。 - 使用自动 ID — ID 留空时,平台将按 «前缀 + 六位数字» 发放。
- 固定大写与下划线 — 避免在全系统混用大小写,维持
[A-Z0-9_]模式。 - 外部系统 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 不可用 |
count | 1~1000, 默认 1 |
需要 ADMIN 或 API 令牌。由于仅获取编号而未创建行,因此 未使用编号出现空缺是正常现象。再次调用将获得新编号 (发送相同的 Idempotency-Key 除外)。
| 响应 | 含义 |
|---|---|
400 domain_id.domain_required | 无 domain |
404 domain_id.unknown | 域不存在或无序列 |
422 domain_id.count_invalid | count 不在 1~1000 范围内 |
控制台注册页面的 ID 栏
注册页面 ID 栏右侧有 生成 图标 (悬停显示 «生成»)。点击后将填充新编号。手动输入时将自动转换为大写,并在失去焦点时检查格式和重复,将问题显示在栏目下方。在修改页面中,ID 栏被锁定且无图标。不具备发放序列的域 (Edge, 班组, 排班模式, 节假日, 对象) 同样没有图标。
在控制台中,ID 栏为必填项。请点击 生成 或手动输入。仅工艺段在留空时会被自动发放。生成和重复检查功能仅限 ADMIN · API 角色使用。