TREM 測站即時資料
trem.rts.v1 是 ExpTech TREM-net(TREM 地震觀測網)的即時快照。每 0.5 秒一則(2 Hz),列出最近 5 秒內有送資料的每一個測站的連續震度、加速度峰值(PGA)與是否參與地震,並附上最近 240 秒內的地震震源。適合用來畫即時震度地圖、顯示哪些測站正在搖晃。
連線方式、解碼與重連規則見 SSE 連線。
TREM 資料使用警語
TREM 資料是 ExpTech 自有觀測網(TREM-net)的自動化即時觀測結果,不是官方地震資訊。臺灣地震資訊的權威機構是交通部中央氣象署,一切以中央氣象署發布的內容為準。本警語所稱 TREM 資料,指 TREM-net 的觀測與檢知資訊;TREM EEW 只提供給經 ExpTech 個別同意或簽約的特定用戶,使用方式另依服務條款第四條之一。
使用 TREM 資料時,你必須:
- 以中央氣象署為準。地震報告、強震即時警報、震度與海嘯資訊,以中央氣象署發布者為準;TREM 資料與官方資訊不一致時,以官方資訊為準。
- 清楚標示非官方。在任何介面或內容中呈現 TREM 資料時,必須同時標示資料來源與「非官方資訊,以中央氣象署發布為準」。
- 遵守《氣象法》。依《氣象法》第 17 條第 1 項,地震之預報或警報由中央氣象主管機關統一發布;第 18 條並未開放其他機關、學校、團體或個人對不特定大眾發布地震預報或任何警報;提供給特定用戶不在此限。違者依同法第 24 條第 2 項,處新臺幣 20 萬元以上 100 萬元以下罰鍰,並得按次處罰。
- 不得用於違法用途。禁止利用 TREM 資料預測地震,或對外發布地震、海嘯警報;禁止散布未經證實的地震訊息。散播有關災害之謠言或不實訊息,足生損害於公眾或他人者,依《災害防救法》第 53 條第 3 項,處三年以下有期徒刑、拘役或新臺幣 100 萬元以下罰金;散佈謠言,足以影響公共之安寧者,依《社會秩序維護法》第 63 條第 1 項第 5 款,處三日以下拘留或新臺幣 3 萬元以下罰鍰。
- 了解資料限制。TREM 為自動化觀測,未經人工審核,可能因雜訊、設備異常或網路延遲而誤判、漏報或延遲。不得作為避難、停班停課或任何安全決策的唯一依據。
不需要 token(公開 topic)。帶有效 token 時,用量記在權限 trem.rts 下,超過配額也不會中斷。詳見 SSE 連線:驗證。
- 多工入口:
/api/v1/trem/sse?topics=trem.rts.v1,事件名稱trem.rts.v1。 - 單一 topic 路徑:
modesleep:只送至少有一個測站帶 alert 的快照;live:每 0.5 秒的快照都送。
tokenAPI Token(選填)。建議改用 Authorization: Bearer header。
curl -N --compressed "https://api.lb.exptech.dev/api/v1/trem/sse/rts"curl -N --compressed "https://api.lb-tpe1.exptech.dev/api/v1/trem/sse/rts"curl -N --compressed "https://api.lb-khh1.exptech.dev/api/v1/trem/sse/rts"const res = await fetch("https://api.lb.exptech.dev/api/v1/trem/sse/rts");if (!res.ok) throw new Error(`HTTP ${res.status}`);
// text/event-stream:逐段讀取const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();for (;;) { const { value, done } = await reader.read(); if (done) break; console.log(value);}const res = await fetch("https://api.lb-tpe1.exptech.dev/api/v1/trem/sse/rts");if (!res.ok) throw new Error(`HTTP ${res.status}`);
// text/event-stream:逐段讀取const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();for (;;) { const { value, done } = await reader.read(); if (done) break; console.log(value);}const res = await fetch("https://api.lb-khh1.exptech.dev/api/v1/trem/sse/rts");if (!res.ok) throw new Error(`HTTP ${res.status}`);
// text/event-stream:逐段讀取const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();for (;;) { const { value, done } = await reader.read(); if (done) break; console.log(value);}import requests
with requests.get( "https://api.lb.exptech.dev/api/v1/trem/sse/rts", stream=True, timeout=30,) as res: res.raise_for_status() for line in res.iter_lines(decode_unicode=True): if line: print(line)import requests
with requests.get( "https://api.lb-tpe1.exptech.dev/api/v1/trem/sse/rts", stream=True, timeout=30,) as res: res.raise_for_status() for line in res.iter_lines(decode_unicode=True): if line: print(line)import requests
with requests.get( "https://api.lb-khh1.exptech.dev/api/v1/trem/sse/rts", stream=True, timeout=30,) as res: res.raise_for_status() for line in res.iter_lines(decode_unicode=True): if line: print(line)text/event-stream;data 是 base64(gzip(JSON))
retry: 3000
event: infodata: {"location":"lb-tpe1"}
data: H4sIAAAAAAAC/02OywrDIBRE...token 無效、過期或已撤銷
invalid token每則 data 解碼後是一個 JSON 物件:
{ "source": "core-tnn1", "ts": 1790619680000, "stations": { "117825C": { "i": 0.0, "pga": 0.61 }, "11DFDBC": { "i": 0.4, "pga": 0.87, "alert": 1 }, "1A50B18": { "i": 3.3, "pga": 4.05, "alert": 1 }, "1C086D8": { "i": -3.0 } }, "eq": [[23.94, 121.52, 32, 1790619645]]}| 欄位 | 類型 | 說明 |
|---|---|---|
source | string | 發布這則快照的節點名稱,例如 core-tnn1。節點切換時會改變。 |
ts | int | 快照時間,Unix 毫秒(伺服器時間,經 NTP 校正)。 |
stations | object | 測站快照,key 是測站裝置 ID(例如 11DFDBC)。只包含最近 5 秒內有送資料的測站。 |
<裝置 ID>.i | number | 連續震度(計測震度),小數 1 位。可以是負數;沒有訊號時固定為 -3.0。換算震度級見下表。 |
<裝置 ID>.pga | number | 這 0.5 秒內的加速度峰值,單位 gal(cm/s²),三軸合成,小數 2 位。還沒量到時整個欄位不存在。 |
<裝置 ID>.alert | int | 固定為 1,表示這個測站參與一個進行中的地震。沒有參與時整個欄位不存在(不會出現 0)。 |
eq | array | 最近 240 秒內的地震震源,每筆是 [緯度, 經度, 深度(公里), 發震時間(Unix 秒)]。永遠存在,沒有地震時是 []。 |
i 換成震度級的界線:
i |
< 0.5 | 0.5–1.5 | 1.5–2.5 | 2.5–3.5 | 3.5–4.5 | 4.5–5.0 | 5.0–5.5 | 5.5–6.0 | 6.0–6.5 | ≥ 6.5 |
|---|---|---|---|---|---|---|---|---|---|---|
| 震度 | 0 級 | 1 級 | 2 級 | 3 級 | 4 級 | 5 弱 | 5 強 | 6 弱 | 6 強 | 7 級 |
每個區間含下限、不含上限。不要把 pga 代進震度公式換算震度,震度請讀 i。
stations 的 key 是測站裝置 ID。裝置 ID 對應的經緯度與鄉鎮代碼,請使用 ExpTech 公開的測站清單 station.csv(欄位 id 是裝置 ID,lat、lon 是座標,code 是鄉鎮代碼)。
瀏覽器用單一 topic 路徑接收 live 模式的快照:資料事件沒有名稱,用 onmessage 收資料、解碼,再把 i 換成震度級。
async function decodeData(b64) { const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("gzip")); return await new Response(stream).text();}
function toLevel(i) { const labels = ["0", "1", "2", "3", "4", "5弱", "5強", "6弱", "6強", "7"]; if (i < 4.5) return labels[Math.max(0, Math.round(i))]; return labels[Math.min(9, 5 + Math.floor((i - 4.5) / 0.5))];}
const es = new EventSource("https://api.lb.exptech.dev/api/v1/trem/sse/rts?mode=live");es.onmessage = async (e) => { const rts = JSON.parse(await decodeData(e.data)); for (const [id, s] of Object.entries(rts.stations)) { if ("alert" in s) console.log(id, `震度 ${toLevel(s.i)}`, s.pga !== undefined ? `${s.pga} gal` : ""); }};- 用「欄位在不在」判斷
alert與pga。 沒有參與地震的測站沒有alert欄位;還沒量到加速度峰值的測站沒有pga欄位。不會出現0。 alert會延後熄滅。 測站參與的地震都結束,而且i連續 15 秒低於 0.5,alert才會消失。i可以是負數。 測站很安靜(有效加速度低於約 0.34 gal)時i是負的;-0.0當作 0。-3.0是「沒有訊號」的固定值,不是量測結果。- 測站會出現與消失。 測站最近 5 秒沒有資料就不在
stations裡,有資料後會回來。不在清單上表示「這幾秒沒收到」,不是震度 0。 - 每則都是完整快照。 直接用新的一則取代上一則。快照沒有序號,漏收一則就用下一則。
- 不補送。 斷線重連後從最新的快照開始。
- 時間單位不同。
ts是 Unix 毫秒,eq裡的發震時間是 Unix 秒。 - 流量。 live 模式每秒 2 則、每則包含所有測站(解壓後每則數 KB)。只需要地震期間的資料時,用預設的 sleep 模式。
