Watch 0.39 API v1

讀取 Watch 事件與串接系統

桌面事件轉送

讓其他系統收到 Watch 通知

在 Watch 介面設定接收網址,再用測試事件確認通知送達。一般使用者負責選擇要通知的系統;接收端程式與簽章密鑰由整合人員準備。

1. 準備接收端

請接收系統的負責人提供 Watch 主機能連到的網址。雙方需使用相同簽章密鑰;請管理員在 Watch 的啟動環境設定密鑰,並提供對應的環境變數名稱,例如 SENTINEL_CONNECTOR_SECRET。不要把密鑰內容填入網址或貼到聊天。

2. 在 Watch 建立事件轉送

  1. 開啟「設定 → API 與整合」,展開「進階:將事件轉送到其他系統」。
  2. 填入接收系統名稱、接收網址及密鑰的環境變數名稱。確認建立後顯示「已簽章」,而不是「缺少 secret」。
  3. 第一次測試選 critical,事件種類勾選 sdk.test。正式即時告警使用 live.event;需要離線影片事件時再選 offline.event。
  4. 接收端準備好後,取消「先模擬測試,不實際傳送」,再按「建立事件轉送」。保留勾選只會模擬,不會發出 HTTP 通知。

3. 確認真的收到測試通知

在「測試整條路徑」按 critical。顯示測試事件已加入佇列,只代表 Watch 已受理;請接收端確認簽章驗證成功且事件已保存,並核對 Watch 的傳送紀錄。若沒收到,先檢查 sdk.test 是否勾選、是否仍為 dry-run、密鑰是否可用,以及接收網址是否可連線。

測試成功後,由現場人員確認一次實際告警也能送達。測試通知只驗證傳送,不代表攝影機、任務條件或分析結果已驗收。已有 dry-run 項目時,可另建實際傳送用的項目,避免把模擬成功當成送達。

接收端格式:sentinel.alert.v1

v0.39 桌面介面建立的事件轉送預設使用以下格式,Content-Type 為 application/cloudevents+json。欄位直接位於最外層,沒有 data 包裝。以下只列常用欄位,值為示意。

{
  "schema": "sentinel.alert.v1",
  "contract_version": 2,
  "specversion": "1.0",
  "id": "evt_example",
  "type": "sdk.test",
  "time": "2026-08-29T23:41:08Z",
  "state": "raised",
  "severity": "critical",
  "title": "Integration test",
  "summary": "Test event from Watch",
  "camera_id": null,
  "snapshot_url": null,
  "correlation_id": "evt_example"
}
桌面轉送的 sentinel.alert.v1 與 GET /v1/events 的 sentinel.event.v1 格式不同。接收器須驗證正確的 schema;不要直接套用公開事件查詢的欄位。既有 Agent Alert Webhook 通道的 schema: 2 也不是本頁的桌面事件轉送格式。

驗證簽章

X-Sentinel-Delivery-ID: whd_example
X-Sentinel-Event-ID: evt_example
X-Sentinel-Timestamp: 1788056468
X-Sentinel-Signature: v1=<hex HMAC-SHA256>
Idempotency-Key: whd_example

signed_bytes = utf8(timestamp) + b"." + raw_request_body
import crypto from "node:crypto";

export function verifyWatch(secret, timestamp, rawBody, signature) {
  if (!secret || typeof timestamp !== "string" ||
      typeof signature !== "string" || !Buffer.isBuffer(rawBody)) return false;
  const seconds = Number(timestamp);
  if (!Number.isInteger(seconds) || Math.abs(Date.now() / 1000 - seconds) > 300) return false;
  const expected = "v1=" + crypto.createHmac("sha256", secret)
    .update(timestamp + ".").update(rawBody).digest("hex");
  const actualBytes = Buffer.from(signature);
  const expectedBytes = Buffer.from(expected);
  return actualBytes.length === expectedBytes.length &&
    crypto.timingSafeEqual(actualBytes, expectedBytes);
}

接收器先保留原始請求內容,檢查時間戳與簽章,通過後才解析 JSON。確認 schema 為 sentinel.alert.v1、specversion 為 1.0,並檢查 X-Sentinel-Event-ID 等於內容的 id,Idempotency-Key 等於 X-Sentinel-Delivery-ID。桌面只有在密鑰可讀取時才附簽章,接收器應拒絕未簽章的請求。

重送與圖片

通知可能重送。先以傳送 ID 去重並保存事件,再盡快回覆 2xx;你的業務流程也應避免重複處理同一事件。Watch 的重試與傳送紀錄在桌面介面查看,公開唯讀 API 不提供重送管理。

通知中的 snapshot_url 屬於桌面相容介面,不應直接拿到 LAN 入口使用。若接收端需要圖片,使用 events:read 金鑰查詢同一 id 的 GET /v1/events/{event_id},再依 evidence.image_url 下載可用截圖。

讀取事件與截圖