10. Alarm 서비스
client.alarm() 으로 접근합니다. 알람 이벤트의 단건/최근 조회 두 기능을 제공합니다. 상세 통계나 알람 설정(Config) CRUD가 필요하면 데이터 게이트웨이를 직접 사용하시면 됩니다.
9.1 메서드 일람
| 메서드 | 반환 타입 | HTTP | 엔드포인트 |
|---|---|---|---|
get(alarm_seq) | AlarmResponseV5 또는 null | GET | /api/v5/alarm/{seq} |
list(limit) | List<AlarmResponseV5> | GET | /api/v5/alarm?limit=... |
limit ≤ 1000권장. 더 많은 데이터가 필요하면 데이터 게이트웨이로 직접 조회하시는 것이 좋습니다.
9.2 AlarmResponseV5 DTO
알람 본체 + 위치(tag/opc/site) JOIN 결과를 함께 포함합니다.
알람 본체 필드
| 필드 | 타입 | 설명 |
|---|---|---|
alarm_seq | long | 알람 시퀀스 (PK) |
alarm_config_id | String | 알람 설정 ID |
priority | String | 우선순위 (HI_HI, HI, LO, LO_LO, TRIP) |
description | String | 알람 메시지 |
is_on | String | 현재 활성 여부 (Y/N) |
is_read | String | 읽음 여부 (Y/N) |
on_timestamp | long | 발생 시각 (밀리초) |
off_timestamp | long | 해제 시각 (0 = 미해제) |
on_duration | long | 지속 시간 (밀리초) |
위치 JOIN 필드 (list 응답에 포함)
| 필드 | 설명 |
|---|---|
tag_id, tag_name, tag_description | 태그 정보 |
opc_id, opc_name | OPC 정보 |
site_id, site_name | 사이트 정보 |
tag_location | 자산 경로 문자열 (SITE > AREA > LINE > EQUIPMENT) |
단건
get()응답은 mm_alarm 본체만 채워지고 JOIN 필드는null인 경우가 많습니다. UI 표시용이면list()결과를 사용하시는 것을 권장합니다.
9.3 알람 우선순위
| 코드 | 의미 | 일반 색상 |
|---|---|---|
HI_HI | 위험 (Critical) | 빨강 |
HI | 주의 (Warning) | 주황 |
LO | 정보 (Info) | 노랑 |
LO_LO | 회복 (Recovery) | 파랑 |
TRIP | 트립 (강제 종료) | 검정 |
9.4 사용 예시
최근 알람 목록
import java.util.List;
import plantpulse.api.v5.dto.response.AlarmResponseV5;
List<AlarmResponseV5> alarms = client.alarm().list(50);
for (AlarmResponseV5 a : alarms) {
System.out.printf("[%s] %s - %s (%s)%n",
a.getPriority(),
a.getSite_name(),
a.getDescription(),
a.getTag_location());
}
출력 예:
[HI_HI] 대전공장 - Spindle 온도 임계치 초과 (SITE_DJ > A_0001 > L_0001 > CNC #1)
[HI] 대전공장 - 압력 상한 (SITE_DJ > A_0001 > L_0001 > Press #2)
단건 조회
AlarmResponseV5 alarm = client.alarm().get(12345L);
if (alarm != null) {
System.out.println("발생 시각: " + alarm.getOn_timestamp());
System.out.println("우선순위: " + alarm.getPriority());
System.out.println("지속 시간: " + alarm.getOn_duration() + " ms");
}
활성 알람만 필터링 (클라이언트 측)
V5는 서버 측 활성 필터를 지원하지 않으므로 클라이언트에서 처리합니다.
import java.util.stream.Collectors;
List<AlarmResponseV5> active = client.alarm().list(500).stream()
.filter(a -> "Y".equals(a.getIs_on()))
.collect(Collectors.toList());
System.out.println("현재 활성 알람: " + active.size() + "건");
사이트별 그룹
import java.util.Map;
import java.util.stream.Collectors;
Map<String, Long> bySite = client.alarm().list(1000).stream()
.filter(a -> "Y".equals(a.getIs_on()))
.collect(Collectors.groupingBy(
AlarmResponseV5::getSite_id,
Collectors.counting()));
bySite.forEach((siteId, count) ->
System.out.printf("%s: %d건%n", siteId, count));
우선순위별 카운트
Map<String, Long> byPriority = client.alarm().list(1000).stream()
.collect(Collectors.groupingBy(
AlarmResponseV5::getPriority,
Collectors.counting()));
9.5 활용 시나리오
시나리오 — 실시간 알람 대시보드
while (running) {
List<AlarmResponseV5> alarms = client.alarm().list(100);
long critical = alarms.stream()
.filter(a -> "Y".equals(a.getIs_on()))
.filter(a -> "HI_HI".equals(a.getPriority()))
.count();
updateDashboard(alarms, critical);
Thread.sleep(1_000);
}
시나리오 — 특정 자산 라인의 알람만
String targetLine = "SITE_DJ > A_0001 > L_0001";
List<AlarmResponseV5> lineAlarms = client.alarm().list(500).stream()
.filter(a -> a.getTag_location() != null
&& a.getTag_location().startsWith(targetLine))
.collect(Collectors.toList());