> For the complete documentation index, see [llms.txt](https://kopens.gitbook.io/plantpulse-platform/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kopens.gitbook.io/plantpulse-platform/developer/api-manual/alarm-service.md).

# 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 사용 예시

### 최근 알람 목록

```java
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)
```

### 단건 조회

```java
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는 서버 측 활성 필터를 지원하지 않으므로 클라이언트에서 처리합니다.

```java
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() + "건");
```

### 사이트별 그룹

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

### 우선순위별 카운트

```java
Map<String, Long> byPriority = client.alarm().list(1000).stream()
        .collect(Collectors.groupingBy(
                AlarmResponseV5::getPriority,
                Collectors.counting()));
```

## 9.5 활용 시나리오

### 시나리오 — 실시간 알람 대시보드

```java
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);
}
```

### 시나리오 — 특정 자산 라인의 알람만

```java
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());
```

## 다음 단계

* [Tag 서비스](/plantpulse-platform/developer/api-manual/tag-service.md) — `patchAlarm`으로 알람 임계치 설정
* [Path 서비스](/plantpulse-platform/developer/api-manual/path-service.md) — 알람 발생 자산의 트리 경로
