專案

一般

配置概況

動作

Bugs #11493

進行中

[點位告警機制]規則與紀錄

由 Sam Wang 於 14 天 前加入. 於 13 天 前更新.

狀態:
新建立
優先權:
正常速度
被分派者:
開始日期:
2026/03/05
完成日期:
完成百分比:

100%

預估工時:
使用工時:

概述

告警規則管理 (Alarm Rules)

告警規則初始由 CSV ALARM 欄位同步匯入,後續以 API 入 DB 為唯一來源,修改後立即生效不須重啟服務

Method Uri 說明
GET /api/v1/alarm-rules 取得告警規則列表(支援 ?deviceId= 過濾)
GET /api/v1/alarm-rules/{id} 取得單一告警規則
POST /api/v1/alarm-rules 新增告警規則
PUT /api/v1/alarm-rules/{id} 修改告警規則
PATCH /api/v1/alarm-rules/{id}/toggle 啟用/停用告警規則
DELETE /api/v1/alarm-rules/{id} 刪除告警規則
// Response  GET /api/v1/alarm-rules?deviceId=5
{
  "code": 0, "message": "", "timestamp": 1740902400000,
  "payload": [{
    "id": 1, "deviceListId": 5, "deviceName": "電錶-01",
    "alertId": "HighV", "alertName": "A相電壓高壓告警",
    "functionId": "01_Vol_A", "operator": ">=", "threshold": 260.0,
    "severity": "Warning",
    "messageTemplate": "{DeviceName} A相電壓 {Value}V 超過門檻 {Threshold}V",
    "isActive": true, "createdAt": "2026-03-02T00:00:00Z", "updatedAt": "2026-03-02T00:00:00Z"
  }]
}
// Request: POST /api/v1/alarm-rules
{
  "deviceListId": 5, "alertId": "HighV", "alertName": "A相電壓高壓告警",
  "functionId": "01_Vol_A", "operator": ">=", "threshold": 260.0,
  "severity": "Warning",
  "messageTemplate": "{DeviceName} A相電壓 {Value}V 超過門檻 {Threshold}V",
  "isActive": true
}
欄位 類型 說明
deviceListId 整數 關聯設備 ID
alertId 字串 告警代碼,同一設備下不可重複(e.g., AR_HighV_1)
Format: AR_{fun}_{no}
functionId 字串 觸發判斷的點位代碼。注意:若是 Modbus 設備,必須加上 群組_ 前綴(例如:01_Vol_A,對應 MQTT 上報之格式),不可僅填寫 Vol_A
operator 字串 比較運算子:>=, <=, >, <, ==
threshold 浮點數 告警門檻值
severity 字串 告警等級:Warning / Critical
messageTemplate 字串 訊息樣板,佔位符:{DeviceName}, {Value}, {Threshold}
isActive 布林 是否啟用

💡 告警等級說明 (Severity)

系統目前提供兩種標準的告警等級,主要作為前端介面展示區分管理員嚴重程度識別

  • Warning (警告)
    表示設備數據偏離正常範圍,但尚未危及整體系統運作或造成損壞。通常用於預防性維護或早期發現異常趨勢。
    情境範例:機房溫度略高於標準、電壓出現微幅波動。

  • Critical (嚴重)
    表示設備發生嚴重異常、狀態停機,或變數已達危險門檻,需要管理層或運維人員立即介入處理
    情境範例:設備斷電、機房溫度過高可能導致伺服器當機。

ℹ️ 系統行為關聯
在當前的後端邏輯中,無論等級為 WarningCritical,一旦觸發告警,系統皆會:

  1. 將紀錄寫入 alarm_log (預設 Status = 0 未結案)。
  2. 依照所屬系統 (EquipmentSystem) 在 system_config_mail 的設定,自動派發 Email 或 LINE 訊息。
  3. 目前尚未針對等級差異進行通知渠道的分流(例如:Warning 只發 Email、Critical 才發 LINE),這部分保留給後續業務邏輯或前端做彈性運用。
// PATCH /api/v1/alarm-rules/1/toggle
// Response 
{ "code": 0, "message": "告警規則已停用" }

關聯性資料表

資料表名稱 說明
device_list 設備清單
device_alarm_rule 告警規則
alarm_log 告警表
system_config_mail 通知群郵件紀錄

由 Sam Wang 於 14 天 前更新

由 Sam Wang 於 14 天 前更新

新增規則範例

POST {{baseUrl}}/api/v1/alarm-rules

模組斷線告警

{
  "deviceListId": 52,
  "alertId": "Online",
  "alertName": "14F燈控模組斷線告警",
  "functionId": "Online",
  "operator": "==",
  "threshold": 0,
  "severity": "Critical",
  "messageTemplate": "{DeviceName} 發生斷線異常 (狀態值: {Value})",
  "isActive": true
}

點位超出定義範圍告警

{
  "deviceListId": 1,
  "alertId": "HighV_2",
  "alertName": "A相電壓高壓告警",
  "functionId": "Vol_A",
  "operator": ">=",
  "threshold": 130,
  "severity": "Warning",
  "messageTemplate": "{DeviceName} A相電壓 {Value}V 超過門檻 {Threshold}V",
  "isActive": true
}

SMTP 設置說明

寄件參數設置於 appsettings.json

{
  "AppSettings":{
      "EmailSettings": {
          "SmtpHost": "smtp.gmail.com",
          "SmtpPort": 587,
          "SmtpUser": "sam8gamma@gmail.com",
          "SmtpPass": "xxxxxxxxx",
          "FromAddress": "sam8gamma@gmail.com",
          "FromName": "IoTServer 系統"
    }
   }
}

以gmail 為例,"SmtpPass" 取得參考如下:

  1. App Password 只有在開啟「兩步驟驗證」後才會出現。
    https://myaccount.google.com/security
  2. 進入 App Passwords,建立應用程式,並取得16 位密碼
    https://myaccount.google.com/apppasswords

由 Sam Wang 於 14 天 前更新

  • 被分派者 設定為 Sam Wang

由 Sam Wang 於 14 天 前更新

  • 完成百分比0 變更為 100

由 Sam Wang 於 13 天 前更新

  • 主旨[點位告警機制] 變更為 [點位告警機制]規則與紀錄

由 Sam Wang 於 13 天 前更新

由 Sam Wang 於 13 天 前更新

由 Sam Wang 於 13 天 前更新

告警紀錄API

提供告警紀錄查詢、Excel 匯出及人工結案功能。
人工結案後系統將透過 MQTT client/alarm 廣播 alarm.changed 通知。

Method Uri 說明
GET /api/v1/alarm-logs 取得告警紀錄列表(分頁)
GET /api/v1/alarm-logs/export 匯出告警紀錄為 Excel
PATCH /api/v1/alarm-logs/{alarmId}/close 人工關閉指定告警

◉ 取得告警紀錄列表 [GET]

:::info
GET /api/v1/alarm-logs支援多條件篩選與分頁,預設以最新時間排序
:::

Query 參數

參數 類型 說明
page 整數 頁碼(預設 1)
pageSize 整數 每頁筆數(預設 10)
keyword 字串 關鍵字搜尋(設備名稱、空間、告警描述)
status 整數 0=未結案,1=已結案(不填=全部)
floor 字串 依樓層篩選
startTime DateTimeOffset 觸發時間起始(ISO 8601)
endTime DateTimeOffset 觸發時間結束(ISO 8601)

:::spoiler Response ✅ 成功 (200 OK)

{
  "code": 0,
  "message": "Success",
  "timestamp": 1741248000000,
  "payload": {
    "items": [
      {
        "id": 1,
        "alarmId": "ALM-2026-0001",
        "deviceName": "E1401 電錶",
        "floor": "1F",
        "space": "機房A",
        "messageTemplate": "A相電壓 132.1V 超過門檻 120V",
        "status": 0,
        "triggerTime": "2026-03-06T13:49:02+08:00",
        "closeTime": null
      }
    ],
    "page": 1,
    "pageSize": 10,
    "totalRecords": 25,
    "totalPages": 3
  }
}

:::

◉ 匯出告警紀錄為 Excel [GET]

:::info
GET /api/v1/alarm-logs/export依據當前查詢條件將結果匯出成 .xlsx 檔案
:::

Query 參數與取得列表相同(page/pageSize 無效,匯出全部符合條件的紀錄)。

Response: Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,瀏覽器直接下載 AlarmLogs_Export_yyyyMMddHHmmss.xlsx

◉ 人工關閉告警 [PATCH]

:::info
PATCH /api/v1/alarm-logs/{alarmId}/close將指定告警標記為已完成,並透過 MQTT 廣播 alarm.changed 通知
:::

路由參數

參數 說明
alarmId 告警的 AlarmId,例如 ALM-2026-0001

此端點無 Request Body。操作成功後,系統自動:

  1. status 設為 1,記錄 closeTime
  2. 查詢當前 pendingCount(未結案告警數量)
  3. 發布 MQTT 通知至 client/{OmniID}(與設備狀態異動機制一致)

:::spoiler MQTT 通知範例 (alarm.changed)

{
  "system": "Omni_BC241195477F",
  "timestamp": 1772787333837,
  "cmd": "alarm.changed",
  "payload": {
    "alarmId": "ALM-2026-0001",
    "deviceName": "E1401 電錶",
    "message": "A相電壓 132.1V 超過門檻 120V",
    "status": 1,
    "triggerTime": "2026-03-06T13:49:02+08:00",
    "closeTime": "2026-03-06T17:05:00+08:00",
    "pendingCount": 4
  }
}

:::

:::spoiler Response ✅ 成功 (200 OK)

{
  "code": 0,
  "message": "告警已成功結案,MQTT 通知已廣播。",
  "timestamp": 1741248300000,
  "payload": null
}

:::

:::spoiler Response ❌ 紀錄不存在或已結案

{
  "code": 404,
  "message": "AlarmId 'ALM-2026-0001' 不存在或已結案。",
  "timestamp": 1741248300000,
  "payload": null
}

:::


◉ 告警狀態異動通知 (alarm.changed)

alarm_log 產生或狀態變更(結案)時,系統主動廣播通知。前端訂閱 client/{OmniID} 即可接收所有告警異動事件。

觸發場景:

  1. 告警規則評估後新產生告警status: 0
  2. 告警條件解除,自動關閉status: 1
  3. 透過 API PATCH /api/v1/alarm-logs/{alarmId}/close 人工結案status: 1
方向 MQTT 主題 訊息內容
通知 (Notify) client/{OmniID} JSON 格式告警異動通知

:::spoiler Event Message Example (alarm.changed)

{
  "system": "Omni_BC241195477F",
  "timestamp": 1772787333837,
  "cmd": "alarm.changed",
  "payload": {
    "alarmId": "ALM-2026-0001",
    "deviceName": "E1401 電錶",
    "message": "A相電壓 132.1V 超過門檻 120V",
    "status": 0,
    "triggerTime": "2026-03-06T13:49:02+08:00",
    "closeTime": null,
    "pendingCount": 5
  }
}

Payload 欄位說明:

欄位 類型 說明
alarmId 字串 告警唯一編號,例如 ALM-2026-0001
deviceName 字串 設備名稱(快照)
message 字串 告警描述文字
status 整數 0 = 未結案(新告警),1 = 已結案
triggerTime 字串 觸發時間(本地時間,ISO 8601 格式含時區)
closeTime 字串/null 結案時間(未結案時為 null)
pendingCount 整數 當前尚未結案告警總數量
:::
動作

匯出至 Atom PDF