본문으로 건너뛰기

8. Tag 서비스

client.tag() 으로 접근합니다. Tag는 데이터 포인트(센서 값, 카운터, 상태)의 정의(메타데이터) 입니다. V5에서는 탭별 PATCH 10종을 통해 알람·집계·계산 등 세부 설정을 안전하게 부분 수정할 수 있습니다.

ID 규칙: TAG_ 접두사 필수. 자세한 내용은 도메인 ID 규칙 참고.

8.1 메서드 일람​

CRUD​

메서드반환 타입HTTP엔드포인트
create(TagRequestV5)TagResponseV5 또는 nullPOST/api/v5/tag
update(tag_id, TagRequestV5)TagResponseV5 또는 nullPUT/api/v5/tag/{id}
delete(tag_id)booleanDELETE/api/v5/tag/{id}
get(tag_id)TagResponseV5 또는 nullGET/api/v5/tag/{id}
exists(tag_id)booleanGET/api/v5/tag/{id}/exists

목록 / 카운트​

메서드반환 타입HTTP엔드포인트
list()List<TagResponseV5>GET/api/v5/tag
listBySite(site_id)List<TagResponseV5>GET/api/v5/tag?site_id=...
listByOpc(opc_id)List<TagResponseV5>GET/api/v5/tag?opc_id=...
listByAsset(asset_id)List<TagResponseV5>GET/api/v5/tag?asset_id=...
count()longGET/api/v5/tag/count
countBySite(site_id)longGET/api/v5/tag/count?site_id=...
countByOpc(opc_id)longGET/api/v5/tag/count?opc_id=...
countByAsset(asset_id)longGET/api/v5/tag/count?asset_id=...

PATCH — 탭별 부분 수정 (V5 핵심 기능)​

10종의 PATCH는 null 필드 = 변경 안 함 규칙을 따릅니다 (서버 DAO에서 COALESCE 처리). 일부 PATCH는 서버에서 CEP/EQL 재배포까지 자동 수행합니다.

메서드HTTP엔드포인트부수 효과
patchBasic(id, TagBasicPatchRequestV5)PATCH/api/v5/tag/{id}/basic—
patchAlarm(id, TagAlarmPatchRequestV5)PATCH/api/v5/tag/{id}/alarmCEP/EQL 재배포
patchMetadata(id, TagMetadataPatchRequestV5)PATCH/api/v5/tag/{id}/metadata—
patchCalculation(id, TagCalculationPatchRequestV5)PATCH/api/v5/tag/{id}/calculationdeployCalculation 재호출
patchSampling(id, TagSamplingPatchRequestV5)PATCH/api/v5/tag/{id}/sampling—
patchAggregation(id, TagAggregationPatchRequestV5)PATCH/api/v5/tag/{id}/aggregationdeployAggregation 재호출
patchAi(id, TagAiPatchRequestV5)PATCH/api/v5/tag/{id}/ai—
patchPublish(id, TagPublishPatchRequestV5)PATCH/api/v5/tag/{id}/publish—
patchAttribute(id, TagAttributePatchRequestV5)PATCH/api/v5/tag/{id}/attribute—
patchLink(id, TagLinkPatchRequestV5)PATCH/api/v5/tag/{id}/link—

8.2 TagRequestV5 / TagResponseV5 (전체 등록·수정용)​

필드타입설명
tag_idString태그 ID (PK, TAG_ 필수)
tag_nameString표시명
opc_idString소속 OPC (FK)
site_idString소속 사이트
linked_asset_idString연결된 자산(Equipment)
java_typeString값 자료형 — Double, Float, Int, Long, Short, Boolean, String, Date
unitString단위 (예: ℃, RPM, kPa)
source_typeString(응답 전용) 소스 유형 — 태그의 연결 프로토콜에서 파생 (OPC/PLC/MODBUS/DATABASE/MESSAGING/API/SYSTEM)
descriptionString설명

8.3 PATCH DTO 필드 (탭별)​

TagBasicPatchRequestV5 (기본)​

필드설명
tag_name표시명
java_type자료형
description설명

TagMetadataPatchRequestV5 (메타데이터)​

필드설명
tag_type태그 유형
importance중요도 (1~10)
use_metric메트릭 사용 여부
rate수신 주기 (ms) — 기록용. 실제 폴링 간격은 연결 설정에서 정한다
rw읽기/쓰기 (R/W/RW)
alias_name별칭
min_value / max_value게이지 차트의 눈금 기준 — 값을 검증하지 않는다
display_formatUI 표시 형식
unit단위
number_round / number_scale반올림 / 소수점
io_address / source_tag_nameI/O 주소·원본 태그명
lat / lng위경도

TagAlarmPatchRequestV5 (알람)​

필드설명
trip_hi, hi_hi, hi, lo, lo_lo, trip_lo임계치 (6단계)
bool_true, bool_true_priority, bool_true_message불린 TRUE 알람
bool_false, bool_false_priority, bool_false_message불린 FALSE 알람
band_message정상 밴드 메시지
duplicate_check_minutes중복 알람 차단 분
user_defined_alarm_class사용자 정의 클래스
use_alarm알람 사용 (Y/N)
recieve_me, recieve_others본인/타인 수신
send_email, send_sms이메일/SMS 발송

TagCalculationPatchRequestV5 (계산)​

필드설명
calculation_eqlEQL 표현식
use_calculation사용 여부 (Y/N)

TagSamplingPatchRequestV5 (샘플링)​

필드설명
use_sampling사용 여부 (Y/N)

TagAggregationPatchRequestV5 (집계)​

필드설명
use_aggregation사용 여부
aggregation_1_minutes ~ aggregation_1_hours5가지 주기 활성화 플래그

TagAiPatchRequestV5 (AI 이상 진단)​

필드설명
use_target다변량 상관관계 분석 대상 (Y/N) — 한 설비에 2개 이상이어야 분석이 활성화된다
use_category다변량 데이터를 나누는 분기 컬럼 (Y/N) — 레시피·설비 모드·운전 등

TagPublishPatchRequestV5 (발행)​

필드설명
publish_mqttMQTT 발행 (Y/N)
publish_kafkaKafka 발행 (Y/N) — OPC-UA 서버 플러그인이 데이터를 받으려면 Y 여야 한다

TagAttributePatchRequestV5 (노트)​

필드설명
note자유 형식 메모

TagLinkPatchRequestV5 (설비 매핑)​

필드설명
linked_asset_id연결 자산 ID. 빈 문자열 = 매핑 해제

8.4 사용 예시​

Tag 생성 (OPC 연결 태그)​

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

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 회전수");

TagResponseV5 created = client.tag().create(req);

단건 조회 / 존재 확인​

TagResponseV5 tag = client.tag().get("TAG_EDGE_00303_90007");
if (tag != null) {
System.out.println(tag.getTag_name() + " (" + tag.getUnit() + ")");
}

boolean exists = client.tag().exists("TAG_EDGE_00303_90007");

사이트 / OPC / 에셋별 목록​

List<TagResponseV5> siteTags = client.tag().listBySite("SITE_DJ");
List<TagResponseV5> opcTags = client.tag().listByOpc("OPC_PLC_L1_001");
List<TagResponseV5> assetTags = client.tag().listByAsset("EQUIPMENT_000001");

카운트​

long total = client.tag().count();
long siteTotal = client.tag().countBySite("SITE_DJ");
long opcTotal = client.tag().countByOpc("OPC_PLC_L1_001");
long assetTotal = client.tag().countByAsset("EQUIPMENT_000001");

전체 수정 (PUT)​

전체 필드를 다시 보낼 때:

TagRequestV5 update = new TagRequestV5();
update.setTag_id("TAG_EDGE_00303_90007");
update.setTag_name("Spindle RPM (변경됨)");
update.setOpc_id("OPC_EDGE_00303");
update.setSite_id("SITE_DJ");
update.setJava_type("Double");
update.setUnit("RPM");
// ... 모든 필드 ...
client.tag().update("TAG_EDGE_00303_90007", update);

부분 수정 — patchBasic​

이름과 설명만 변경:

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

TagBasicPatchRequestV5 patch = new TagBasicPatchRequestV5();
patch.setTag_name("Spindle RPM (보정 후)");
patch.setDescription("2026-05-14 보정 적용");
// java_type 은 null 로 두면 변경 안 함
client.tag().patchBasic("TAG_EDGE_00303_90007", patch);

부분 수정 — patchAlarm​

알람 임계치 설정 (서버에서 CEP/EQL 재배포):

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

TagAlarmPatchRequestV5 alarm = new TagAlarmPatchRequestV5();
alarm.setUse_alarm("Y");
alarm.setLo_lo("0");
alarm.setLo("10");
alarm.setHi("80");
alarm.setHi_hi("95");
alarm.setTrip_hi("100");
alarm.setDuplicate_check_minutes(5);
alarm.setSend_email("Y");
client.tag().patchAlarm("TAG_EDGE_00303_90007", alarm);

부분 수정 — patchMetadata​

별칭과 표시 형식 변경:

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

TagMetadataPatchRequestV5 meta = new TagMetadataPatchRequestV5();
meta.setAlias_name("HMI_TAG_RPM_01");
meta.setDisplay_format("#,##0");
meta.setNumber_scale(0);
meta.setImportance(8);
client.tag().patchMetadata("TAG_EDGE_00303_90007", meta);

부분 수정 — patchCalculation​

EQL 계산식 부착 (서버에서 deployCalculation 재호출):

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

TagCalculationPatchRequestV5 calc = new TagCalculationPatchRequestV5();
calc.setUse_calculation("Y");
calc.setCalculation_eql("VAL('TAG_RAW_RPM') * 60 / 1000"); // 가상의 EQL
client.tag().patchCalculation("TAG_EDGE_00303_90007", calc);

부분 수정 — patchAggregation​

5가지 주기 집계 활성화 (deployAggregation 재호출):

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

TagAggregationPatchRequestV5 agg = new TagAggregationPatchRequestV5();
agg.setUse_aggregation("Y");
agg.setAggregation_1_minutes("Y");
agg.setAggregation_5_minutes("Y");
agg.setAggregation_10_minutes("Y");
agg.setAggregation_30_minutes("N");
agg.setAggregation_1_hours("Y");
client.tag().patchAggregation("TAG_EDGE_00303_90007", agg);

부분 수정 — patchPublish​

MQTT/Kafka 발행 토글:

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

TagPublishPatchRequestV5 pub = new TagPublishPatchRequestV5();
pub.setPublish_mqtt("Y");
pub.setPublish_kafka("N");
client.tag().patchPublish("TAG_EDGE_00303_90007", pub);
import plantpulse.api.v5.dto.request.TagLinkPatchRequestV5;

// 자산에 연결
TagLinkPatchRequestV5 link = new TagLinkPatchRequestV5();
link.setLinked_asset_id("EQUIPMENT_000001");
client.tag().patchLink("TAG_EDGE_00303_90007", link);

// 매핑 해제 — 빈 문자열
TagLinkPatchRequestV5 unlink = new TagLinkPatchRequestV5();
unlink.setLinked_asset_id("");
client.tag().patchLink("TAG_EDGE_00303_90007", unlink);

삭제​

boolean ok = client.tag().delete("TAG_EDGE_00303_90007");

8.5 활용 시나리오​

시나리오 — 신규 라인 태그 자동 분류 후 일괄 설정​

// 1) 자동 등록된 태그 목록 (OPC 연결 직후)
List<TagResponseV5> tags = client.tag().listByOpc("OPC_PLC_L2_001");

// 2) 이름 패턴으로 자산 자동 연결 + 알람 일괄 설정
for (TagResponseV5 t : tags) {
String name = t.getTag_name();

// 자산 매핑
TagLinkPatchRequestV5 link = new TagLinkPatchRequestV5();
if (name.contains("CNC1")) {
link.setLinked_asset_id("EQUIPMENT_CNC1");
} else if (name.contains("CNC2")) {
link.setLinked_asset_id("EQUIPMENT_CNC2");
} else {
continue;
}
client.tag().patchLink(t.getTag_id(), link);

// 온도 태그는 알람 임계치 자동 설정
if (name.endsWith("_TEMP")) {
TagAlarmPatchRequestV5 alarm = new TagAlarmPatchRequestV5();
alarm.setUse_alarm("Y");
alarm.setHi("80");
alarm.setHi_hi("95");
client.tag().patchAlarm(t.getTag_id(), alarm);
}
}

시나리오 — 집계와 발행을 한꺼번에 활성화​

String tagId = "TAG_EDGE_00303_90007";

TagAggregationPatchRequestV5 agg = new TagAggregationPatchRequestV5();
agg.setUse_aggregation("Y");
agg.setAggregation_1_minutes("Y");
agg.setAggregation_1_hours("Y");
client.tag().patchAggregation(tagId, agg);

TagPublishPatchRequestV5 pub = new TagPublishPatchRequestV5();
pub.setPublish_mqtt("Y");
client.tag().patchPublish(tagId, pub);

다음 단계​