diff --git a/README.md b/README.md
index 994696a8..1f621ba5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
![](https://img.shields.io/github/downloads/ExpTechTW/TREM-Lite/total)
+> **Note**
+> 2.0.0 版本修正新版 API(需進一步測試)
+
> **Note**
> 1.9.0 及後續版本加入 `P2P(中繼) 備援伺服器` `EEW 備援伺服器`
> - `p2p-1.exptech.com.tw:1015`
@@ -34,7 +37,7 @@ TREM Lite 是一款開源地震速報軟體,提供給您即時的地震資訊
## 注意事項
1. 使用過程中,請務必謹慎閱讀提示和注意事項
2. 使用過程中可能遇到無法理解的錯誤,但大部份不影響系統運作,如遇到錯誤請向開發人員回報
-3. 即時測站資訊僅供參考,實際請以中央氣象局為主
+3. 即時測站資訊僅供參考,實際請以中央氣象署為主
4. 此軟體僅供研究、學術及教育用途(不得營利),若使用則需接受相關風險
5. 任何不被官方所認可的行為均有可能被列入伺服器黑名單中,請務必遵守相關規範
6. 此程式為免費開源程式,不保證能永久營運
diff --git a/src/core/index/action.js b/src/core/index/action.js
index 1469f2e8..d5a25c21 100644
--- a/src/core/index/action.js
+++ b/src/core/index/action.js
@@ -19,11 +19,16 @@ document.getElementById("setting_button").onclick = () => {
ipcRenderer.send("openChildWindow");
};
+document.getElementById("refresh_button").onclick = () => {
+ close();
+ setTimeout(() => ipcMain.emit("reload"), 500);
+};
+
const location_button = document.getElementById("location_button");
location_button.style.border = "1px solid white";
location_button.onclick = () => {
- if (location_button.style.color == "white") {
- location_button.style.color = "grey";
+ if (location_button.style.color == "grey") {
+ location_button.style.color = "white";
location_button.style.border = "1px solid white";
focus_lock = false;
TREM.Maps.main.setView([23.6, 120.4], 7.8);
diff --git a/src/core/index/api.js b/src/core/index/api.js
index c8a24584..8d1a1fdb 100644
--- a/src/core/index/api.js
+++ b/src/core/index/api.js
@@ -2,6 +2,7 @@
let report_data = {};
let report_now_id = 0;
let start = false;
+let eew_last = '';
const info_list = [];
const item_disable_geojson_vt = storage.getItem("disable_geojson_vt") ?? false;
@@ -31,22 +32,50 @@ function intensity_float_to_int(float) {
function fetch_eew() {
const controller = new AbortController();
- setTimeout(() => controller.abort(), 2500);
- fetch("https://api.exptech.com.tw/api/v1/eq/eew", { signal: controller.signal })
+ setTimeout(() => controller.abort(), 1000);
+ fetch(`https://${api_domain}/api/v1/eq/eew?type=cwa`, { signal: controller.signal })
.then((ans) => ans.json())
.then((ans) => {
- const _now = Now().getTime();
- for (const eew of ans.eew) {
- eew.timestamp = _now;
- get_data(eew, "http");
- }
if (!start) {
refresh_report_list(true);
}
+ const _now = Now().getTime();
+ last_get_eew_time = _now;
+ type_list.time = now_time();
+ type_list.http = _now;
+ if (ans.length == 0) return;
+ const eew = ans[ans.length - 1];
+ if (eew.id === eew_last) {
+ return;
+ }
+ eew_last = eew.id;
+ eew.time = _now;
+ eew.type = "eew-cwb";
+ get_data(eew, "http");
})
.catch((err) => {
+ if(err.type == "aborted") return;
+ if (now_time() - disconnect_info > 60_000) {
+ disconnect_info = now_time();
+ add_info("fa-solid fa-satellite-dish fa-2x info_icon", "#FF0000", "網路異常", "#00BB00", "無法取得速報資訊
請檢查網路狀態或稍後重試", 30000);
+ }
+ if(err.type == "system") return;
log(err, 3, "api", "fetch_eew");
- setTimeout(() => fetch_eew(), 3000);
+ });
+}
+
+function fetch_rts() {
+ if(rts_replay_time) return;
+ const controller = new AbortController();
+ setTimeout(() => controller.abort(), 2500);
+ fetch(`https://${api_domain}/api/v1/trem/rts/`, { signal: controller.signal })
+ .then(async (ans) => {
+ ans = await ans.json();
+ on_rts_data(ans);
+ })
+ .catch((err) => {
+ if(err.type == "aborted" || err.type == "system") return;
+ log(err, 3, "loop", "fetch_rts");
});
}
@@ -57,7 +86,7 @@ async function fetch_trem_eq(id) {
const controller = new AbortController();
setTimeout(() => controller.abort(), 2500);
return await new Promise((c) => {
- fetch(`https://exptech.com.tw/api/v1/earthquake/trem-info/${id}`, { signal: controller.signal })
+ fetch(`https://${api_domain}/api/v2/eq/report/${id}`, { signal: controller.signal })
.then((ans) => ans.json())
.then((ans) => {
c(ans);
@@ -78,15 +107,15 @@ async function fetch_report() {
if (typeof _report_data != "object") {
_report_data = [];
}
- fetch(`https://data.exptech.com.tw/api/v1/eq/report?limit=50${(storage.getItem("show_reportInfo") ?? false) ? (storage.getItem("key") ?? false) ? `&key=${storage.getItem("key")}` : "" : ""}`, {
+ fetch(`https://${api_domain}/api/v2/eq/report?limit=50${(storage.getItem("show_reportInfo") ?? false) ? (storage.getItem("key") ?? false) ? `&key=${storage.getItem("key")}` : "" : ""}`, {
signal: controller.signal,
})
.then(async (ans) => {
ans = await ans.json();
for (let i = 0; i < ans.length; i++) {
- const id = ans[i].identifier;
+ const id = ans[i].id;
for (let _i = 0; _i < _report_data.length; _i++) {
- if (_report_data[_i].identifier == id) {
+ if (_report_data[_i].id == id) {
_report_data.splice(_i, 1);
break;
}
@@ -97,7 +126,7 @@ async function fetch_report() {
}
for (let i = 0; i < _report_data.length - 1; i++) {
for (let _i = 0; _i < _report_data.length - 1; _i++) {
- if (new Date(_report_data[_i].originTime.replaceAll("/", "-")).getTime() < new Date(_report_data[_i + 1].originTime.replaceAll("/", "-")).getTime()) {
+ if (_report_data[_i].time < _report_data[_i + 1].time) {
const temp = _report_data[_i + 1];
_report_data[_i + 1] = _report_data[_i];
_report_data[_i] = temp;
@@ -117,6 +146,24 @@ async function fetch_report() {
});
}
+async function fetch_report_single(i, id) {
+ return await new Promise((c) => {
+ const controller = new AbortController();
+ setTimeout(() => controller.abort(), 2500);
+ fetch(`https://${api_domain}/api/v2/eq/report/${id}`, {
+ signal: controller.signal,
+ })
+ .then(async (ans) => {
+ ans = await ans.json();
+ report_report(i, ans);
+ })
+ .catch((err) => {
+ log(err, 3, "api", "fetch_report");
+ c(false);
+ });
+ });
+}
+
async function refresh_report_list(_fetch = false, data = {}) {
if (_fetch) {
const ans = await fetch_report();
@@ -188,13 +235,8 @@ async function refresh_report_list(_fetch = false, data = {}) {
report.className = "report";
report.id = i;
if (i == -1) {
- const now = new Date(data.time);
- const _Now = now.getFullYear()
- + "/" + (now.getMonth() + 1 < 10 ? "0" : "") + (now.getMonth() + 1)
- + "/" + (now.getDate() < 10 ? "0" : "") + now.getDate()
- + " " + (now.getHours() < 10 ? "0" : "") + now.getHours()
- + ":" + (now.getMinutes() < 10 ? "0" : "") + now.getMinutes()
- + ":" + (now.getSeconds() < 10 ? "0" : "") + now.getSeconds();
+ ts_to_time(data.time)
+ const _Now = ts_to_time(data.time);
const report_text_intensity = document.createElement("div");
report_text_intensity.className = `report_text report_intensity intensity_${data.i}`;
report_text_intensity.style = `font-size: ${(data.i > 4 && data.i != 7) ? "50" : "60"}px;`;
@@ -212,14 +254,14 @@ async function refresh_report_list(_fetch = false, data = {}) {
report_text_box.append(report_text, report_text_time);
report.append(report_text_intensity, report_text_box);
} else {
- const originTime = new Date((new Date(`${report_data[i].originTime} GMT+08:00`)).toLocaleString("en-US", { timeZone: "Asia/Taipei" }));
+ const originTime = new Date(report_data[i].time + 28800);
if (report_now_id == originTime.getTime()) {
report.className = "report replay";
}
- const intensity = report_data[i].data[0]?.areaIntensity ?? 0;
- const time = report_data[i].originTime.substring(0, 16);
+ const intensity = report_data[i].int ?? 0;
+ const time = ts_to_time(report_data[i].time);
const cwb_code = "EQ"
- + report_data[i].earthquakeNo
+ + report_data[i].id
+ "-"
+ (originTime.getMonth() + 1 < 10 ? "0" : "") + (originTime.getMonth() + 1)
+ (originTime.getDate() < 10 ? "0" : "") + originTime.getDate()
@@ -227,7 +269,7 @@ async function refresh_report_list(_fetch = false, data = {}) {
+ (originTime.getHours() < 10 ? "0" : "") + originTime.getHours()
+ (originTime.getMinutes() < 10 ? "0" : "") + originTime.getMinutes()
+ (originTime.getSeconds() < 10 ? "0" : "") + originTime.getSeconds();
- let loc = report_data[i].location;
+ let loc = report_data[i].loc;
loc = loc.substring(loc.indexOf("(") + 3, loc.indexOf(")"));
const resize = (intensity > 4 && intensity != 7) ? true : false;
const intensity_level = (intensity == 0) ? "--" : int_to_intensity(intensity);
@@ -253,8 +295,8 @@ async function refresh_report_list(_fetch = false, data = {}) {
report_text_magnitudeValue_depth.style = "display: flex;";
const report_text_magnitudeValue = document.createElement("div");
report_text_magnitudeValue.className = "report_text";
- report_text_magnitudeValue.style.color = (report_data[i].earthquakeNo.toString().includes("000")) ? "white" : "goldenrod";
- report_text_magnitudeValue.innerHTML = `M ${report_data[i].magnitudeValue.toFixed(1)}`;
+ report_text_magnitudeValue.style.color = (report_data[i].id.includes("000")) ? "white" : "goldenrod";
+ report_text_magnitudeValue.innerHTML = `M ${report_data[i].mag.toFixed(1)}`;
const report_text_depth = document.createElement("div");
report_text_depth.className = "report_text report_scale";
report_text_depth.style = "width: 100%;text-align: right;";
@@ -278,9 +320,6 @@ async function refresh_report_list(_fetch = false, data = {}) {
}
report_click_replay.id = `${originTime.getTime()}_click_replay`;
report_click_replay.onclick = () => {
- if (!WS) {
- return;
- }
if (rts_replay_timestamp) {
const skip = (report_now_id == originTime.getTime()) ? true : false;
replay_stop();
@@ -303,13 +342,13 @@ async function refresh_report_list(_fetch = false, data = {}) {
"originTime" : originTime.getTime(),
"type" : "eew-report",
"time" : _now + 3000,
- "lon" : report_data[i].epicenterLon,
- "lat" : report_data[i].epicenterLat,
+ "lon" : report_data[i].lon,
+ "lat" : report_data[i].lat,
"depth" : Math.round(report_data[i].depth),
- "scale" : Number(report_data[i].magnitudeValue.toFixed(1)),
+ "scale" : Number(report_data[i].mag.toFixed(1)),
"timestamp" : _now,
"number" : 1,
- "id" : report_data[i].ID + "R",
+ "id" : report_data[i].id + "R",
"location" : loc,
"cancel" : false,
"replay_timestamp" : Date.now(),
@@ -319,9 +358,9 @@ async function refresh_report_list(_fetch = false, data = {}) {
const report_click_web = document.createElement("i");
report_click_web.className = "report_click_text fa fa-globe fa-2x";
report_click_web.id = `${originTime.getTime()}_click_web`;
- if (report_data[i].trem || !report_data[i].location.startsWith("地震資訊")) {
+ if (report_data[i].trem || !report_data[i].loc.startsWith("地震資訊")) {
report_click_web.onclick = () => {
- shell.openExternal((report_data[i].trem) ? `https://exptech.com.tw/api/v1/file/trem-info.html?id=${report_data[i].trem}` : `https://www.cwa.gov.tw/V8/C/E/EQ/${cwb_code}.html`);
+ shell.openExternal((report_data[i].trem) ? `https://exptech.com.tw/file/images/report/${report_data[i].id}.png` : `https://www.cwa.gov.tw/V8/C/E/EQ/${cwb_code}.html`);
};
} else {
report_click_web.style = "color: red;";
@@ -348,8 +387,8 @@ async function refresh_report_list(_fetch = false, data = {}) {
report_text_time.textContent = `${time}`;
const report_text_magnitudeValue = document.createElement("div");
report_text_magnitudeValue.className = "report_text report_scale";
- report_text_magnitudeValue.style.color = (report_data[i].earthquakeNo.toString().includes("000")) ? "white" : "goldenrod";
- report_text_magnitudeValue.innerHTML = `M ${report_data[i].magnitudeValue.toFixed(1)}`;
+ report_text_magnitudeValue.style.color = (report_data[i].id.includes("000")) ? "white" : "goldenrod";
+ report_text_magnitudeValue.innerHTML = `M ${report_data[i].mag.toFixed(1)}`;
report_text_box.append(report_text_loc, report_text_time);
report_info.append(report_text, report_text_box, report_text_magnitudeValue);
const report_click_box = document.createElement("div");
@@ -368,9 +407,6 @@ async function refresh_report_list(_fetch = false, data = {}) {
}
report_click_replay.id = `${originTime.getTime()}_click_replay`;
report_click_replay.onclick = () => {
- if (!WS) {
- return;
- }
if (rts_replay_timestamp) {
const skip = (report_now_id == originTime.getTime()) ? true : false;
replay_stop();
@@ -393,13 +429,13 @@ async function refresh_report_list(_fetch = false, data = {}) {
"originTime" : originTime.getTime(),
"type" : "eew-report",
"time" : _now + 3000,
- "lon" : report_data[i].epicenterLon,
- "lat" : report_data[i].epicenterLat,
+ "lon" : report_data[i].lon,
+ "lat" : report_data[i].lat,
"depth" : Math.round(report_data[i].depth),
- "scale" : Number(report_data[i].magnitudeValue.toFixed(1)),
+ "scale" : Number(report_data[i].mag.toFixed(1)),
"timestamp" : _now,
"number" : 1,
- "id" : report_data[i].ID + "R",
+ "id" : report_data[i].id + "R",
"location" : loc,
"cancel" : false,
"replay_timestamp" : Date.now(),
@@ -409,9 +445,9 @@ async function refresh_report_list(_fetch = false, data = {}) {
const report_click_web = document.createElement("i");
report_click_web.className = "report_click_text fa fa-globe fa-2x";
report_click_web.id = `${originTime.getTime()}_click_web`;
- if (report_data[i].trem || !report_data[i].location.startsWith("地震資訊")) {
+ if (report_data[i].trem || !report_data[i].loc.startsWith("地震資訊")) {
report_click_web.onclick = () => {
- shell.openExternal((report_data[i].trem) ? `https://exptech.com.tw/api/v1/file/trem-info.html?id=${report_data[i].trem}` : `https://www.cwa.gov.tw/V8/C/E/EQ/${cwb_code}.html`);
+ shell.openExternal((report_data[i].trem) ? `https://exptech.com.tw/file/images/report/${report_data[i].id}.png` : `https://www.cwa.gov.tw/V8/C/E/EQ/${cwb_code}.html`);
};
} else {
report_click_web.style = "color: red;";
@@ -421,9 +457,9 @@ async function refresh_report_list(_fetch = false, data = {}) {
}
if (!start) {
start = true;
- if (!Object.keys(TREM.EQ_list).length) {
+ /* if (!Object.keys(TREM.EQ_list).length) {
report_report(i);
- }
+ } */
}
report.onmouseenter = () => {
document.getElementById(`${originTime.getTime()}_click_box`).style.height = document.getElementById(`${originTime.getTime()}_info`).offsetHeight;
@@ -541,12 +577,12 @@ function eew_location_intensity(data, depth) {
for (const city of Object.keys(region)) {
for (const town of Object.keys(region[city])) {
const info = region[city][town];
- const dist_surface = dis(data.lat, data.lon, info.lat, info.lon);
- const dist = Math.sqrt(pow(dist_surface) + pow(data.depth));
- const pga = 1.657 * Math.pow(Math.E, (1.533 * data.scale)) * Math.pow(dist, -1.607);
+ const dist_surface = dis(data.eq.lat, data.eq.lon, info.lat, info.lon);
+ const dist = Math.sqrt(pow(dist_surface) + pow(data.eq.depth));
+ const pga = 1.657 * Math.pow(Math.E, (1.533 * data.eq.mag)) * Math.pow(dist, -1.607);
let i = pga_to_float(pga);
if (i > 3) {
- i = eew_i([data.lat, data.lon], [info.lat, info.lon], data.depth, data.scale);
+ i = eew_i([data.eq.lat, data.eq.lon], [info.lat, info.lon], data.eq.depth, data.eq.mag);
}
if (i > eew_max_i) {
eew_max_i = i;
@@ -562,12 +598,12 @@ function eew_location_intensity(data, depth) {
}
function eew_location_info(data) {
- const dist_surface = dis(data.lat, data.lon, TREM.user.lat, TREM.user.lon);
- const dist = Math.sqrt(pow(dist_surface) + pow(data.depth));
- const pga = 1.657 * Math.pow(Math.E, (1.533 * data.scale)) * Math.pow(dist, -1.607) * (storage.getItem("site") ?? 1.751);
+ const dist_surface = dis(data.eq.lat, data.eq.lon, TREM.user.lat, TREM.user.lon);
+ const dist = Math.sqrt(pow(dist_surface) + pow(data.eq.depth));
+ const pga = 1.657 * Math.pow(Math.E, (1.533 * data.eq.mag)) * Math.pow(dist, -1.607) * (storage.getItem("site") ?? 1.751);
let i = pga_to_float(pga);
if (i > 3) {
- i = eew_i([data.lat, data.lon], [TREM.user.lat, TREM.user.lon], data.depth, data.scale);
+ i = eew_i([data.eq.lat, data.eq.lon], [TREM.user.lat, TREM.user.lon], data.eq.depth, data.eq.mag);
}
return {
dist,
@@ -618,14 +654,26 @@ function int_to_color(int) {
return list[int];
}
-async function report_report(info) {
+function ts_to_time(ts) {
+ const now = new Date(ts);
+ const YYYY = now.getFullYear();
+ const MM = (now.getMonth() + 1).toString().padStart(2, "0");
+ const DD = now.getDate().toString().padStart(2, "0");
+ const hh = now.getHours().toString().padStart(2, "0");
+ const mm = now.getMinutes().toString().padStart(2, "0");
+ const ss = now.getSeconds().toString().padStart(2, "0");
+ const t = `${YYYY}/${MM}/${DD} ${hh}:${mm}:${ss}`;
+ return t;
+}
+
+async function report_report(info, report_detail=null) {
if (Object.keys(TREM.EQ_list).length) {
return;
}
- if (TREM.report_time) {
+ if (TREM.report_time && !report_detail) {
report_off();
}
- if (click_report_id == info) {
+ if (click_report_id == info && !report_detail) {
click_report_id = -1;
return;
}
@@ -636,42 +684,45 @@ async function report_report(info) {
iconUrl : "../resource/images/cross.png",
iconSize : [30, 30],
});
- const intensity = data.data[0]?.areaIntensity ?? 0;
+ const intensity = data.int ?? 0;
const intensity_level = (intensity == 0) ? "--" : int_to_intensity(intensity);
- TREM.report_epicenterIcon = L.marker([data.epicenterLat, data.epicenterLon],
+ if (TREM.report_epicenterIcon) {
+ TREM.report_epicenterIcon.remove();
+ }
+ TREM.report_epicenterIcon = L.marker([data.lat, data.lon],
{ icon: epicenterIcon, zIndexOffset: 6000 }).addTo(TREM.Maps.main);
- TREM.report_bounds.extend([data.epicenterLat, data.epicenterLon]);
- if (!data.location.startsWith("地震資訊")) {
- for (let _i = 0; _i < data.data.length; _i++) {
- const station_data = data.data[_i].eqStation;
- for (let i = 0; i < station_data.length; i++) {
- const station_Intensity = station_data[i].stationIntensity;
+ TREM.report_bounds.extend([data.lat, data.lon]);
+ if(!report_detail){
+ fetch_report_single(info, data.id);
+ } else {
+ for (const city of Object.keys(report_detail.list)) {
+ for (const town of Object.keys(report_detail.list[city].town)) {
const icon = L.divIcon({
- className : `dot intensity_${station_Intensity}`,
- html : `${int_to_intensity(station_Intensity)}`,
+ className : `dot intensity_${report_detail.list[city].town[town].int}`,
+ html : `${int_to_intensity(report_detail.list[city].town[town].int)}`,
iconSize : [30, 30],
});
- TREM.report_icon_list[`${station_data[i].stationName}-${Date.now()}`] = L.marker([station_data[i].stationLat, station_data[i].stationLon], { icon: icon, zIndexOffset: station_Intensity * 10 })
- .bindTooltip(`
站名: ${data.data[_i].areaName} ${station_data[i].stationName}
位置: ${station_data[i].stationLat} °N ${station_data[i].stationLon} °E
距離: ${station_data[i].distance} km
震度: ${int_to_intensity(station_Intensity)}
`, { opacity: 1 })
+ TREM.report_icon_list[`${city}${town}-${Date.now()}`] = L.marker([report_detail.list[city].town[town].lat, report_detail.list[city].town[town].lon], { icon: icon, zIndexOffset: report_detail.list[city].town[town].int * 10 })
+ .bindTooltip(`地點: ${city} ${town}
位置: ${report_detail.list[city].town[town].lat} °N ${report_detail.list[city].town[town].lon} °E
震度: ${int_to_intensity(report_detail.list[city].town[town].int)}
`, { opacity: 1 })
.addTo(TREM.Maps.main);
- TREM.report_bounds.extend([station_data[i].stationLat, station_data[i].stationLon]);
+ TREM.report_bounds.extend([report_detail.list[city].town[town].lat, report_detail.list[city].town[town].lon]);
}
}
}
Zoom = true;
TREM.Maps.main.setView(TREM.report_bounds.getCenter(), TREM.Maps.main.getBoundsZoom(TREM.report_bounds) - 0.5);
show_icon(true);
- document.getElementById("report_title_text").textContent = `${get_lang_string("report.title").replace("${type}", (data.location.startsWith("地震資訊")) ? get_lang_string("report.title.Local") : ((data.earthquakeNo % 1000) ? data.earthquakeNo : get_lang_string("report.title.Small")))}`;
- document.getElementById("report_max_intensity").textContent = (data.location.startsWith("地震資訊")) ? "最大震度" : `${data.data[0].areaName} ${data.data[0].eqStation[0].stationName}`;
+ document.getElementById("report_title_text").textContent = `${get_lang_string("report.title").replace("${type}", (data.loc.startsWith("地震資訊")) ? get_lang_string("report.title.Local") : get_lang_string("report.title.Small"))}`;
+ document.getElementById("report_max_intensity").textContent = (data.loc.startsWith("地震資訊")) ? "最大震度" : `${data.int}`;
const eew_intensity = document.getElementById("report_intensity");
eew_intensity.className = `intensity_${intensity} intensity_center`;
eew_intensity.textContent = intensity_level;
const report_location = document.getElementById("report_location");
- const loc = data.location.substring(data.location.indexOf("(") + 1, data.location.indexOf(")")).replace("位於", "");
+ const loc = data.loc;
report_location.style.fontSize = (loc.length > 10) ? "16px" : (loc.length > 7) ? "20px" : "24px";
report_location.textContent = loc;
- document.getElementById("report_time").textContent = get_lang_string("eew.time").replace("${time}", data.originTime);
- let report_magnitudeValue = data.magnitudeValue.toString();
+ document.getElementById("report_time").textContent = get_lang_string("eew.time").replace("${time}", ts_to_time(data.time));
+ let report_magnitudeValue = data.mag.toString();
if (report_magnitudeValue.length == 1) {
report_magnitudeValue = report_magnitudeValue + ".0";
}
@@ -696,7 +747,7 @@ async function report_report(info) {
}
TREM.report_epicenterIcon_trem = L.marker([trem_eew.lat, trem_eew.lon],
{ icon: epicenterIcon_trem, zIndexOffset: 6000 })
- .bindTooltip(`報數: 共 ${trem_eq.trem.eew.length} 報
位置: ${trem_eew.location} | ${trem_eew.lat}°N ${trem_eew.lon} °E
類型: ${trem_eew.model}
規模: M ${trem_eew.scale}
深度: ${trem_eew.depth} km
預估最大震度: ${int_to_intensity(trem_eew.max)}
`, { opacity: 1 })
+ .bindTooltip(`報數: 共 ${trem_eq.trem.eew.length} 報
位置: ${trem_eew.location} | ${trem_eew.lat}°N ${trem_eew.lon} °E
規模: M ${trem_eew.scale}
深度: ${trem_eew.depth} km
預估最大震度: ${int_to_intensity(trem_eew.max)}
`, { opacity: 1 })
.addTo(TREM.Maps.main);
if (TREM.report_circle_trem) {
TREM.report_circle_trem.remove();
diff --git a/src/core/index/client.jar b/src/core/index/client.jar
deleted file mode 100644
index 07ea1c79..00000000
Binary files a/src/core/index/client.jar and /dev/null differ
diff --git a/src/core/index/core.js b/src/core/index/core.js
index 52edc627..4a2d25f7 100644
--- a/src/core/index/core.js
+++ b/src/core/index/core.js
@@ -1,55 +1,6 @@
/* eslint-disable no-undef */
-const crypto = require("crypto");
-const dgram = require("dgram");
-const client = dgram.createSocket("udp4");
-
-const EventEmitter = require("events").EventEmitter;
-const event = new EventEmitter();
-
const win = BrowserWindow.fromId(process.env.window * 1);
-// if (fs.existsSync(path.resolve(app.getAppPath(), "./core/index/client.js"))) {
-// const vm = require("vm");
-// const v8 = require("v8");
-// v8.setFlagsFromString("--no-lazy");
-// const code = fs.readFileSync(path.resolve(app.getAppPath(), "./core/index/client.js"), "utf-8");
-// const script = new vm.Script(code);
-// const bytecode = script.createCachedData();
-// fs.writeFileSync(path.resolve(app.getAppPath(), "./core/index/client.jar"), bytecode);
-// }
-
-bytenode.runBytecodeFile(path.resolve(app.getAppPath(), "./core/index/client.jar"));
-
-event.on("data", (data) => get_data(data, "p2p"));
-
-event.on("log", (data) => log(data.msg, data.type));
-
-client.on("listening", () => {
- const address = client.address();
- log(`Client listening on ${address.address}:${address.port}`, 1);
-});
-
-get_server_info();
-async function get_server_info() {
- try {
- const controller = new AbortController();
- setTimeout(() => controller.abort(), 1500);
- let ans = await fetch("https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/resource/server_list.json", { signal: controller.signal })
- .catch((err) => void 0);
- if (controller.signal.aborted || !ans) {
- setTimeout(() => get_server_info(), 500);
- return;
- }
- ans = await ans.json();
- init(client, event, {
- server_list: ans.p2p,
- }, crypto);
- } catch (err) {
- log(err, 3, "core", "get_server_info");
- setTimeout(() => get_server_info(), 500);
- }
-}
-
log("Start", 1, "log", "~");
ipcMain.on("replay_start", (e, time) => {
diff --git a/src/core/index/eew.js b/src/core/index/eew.js
index 6ece42b2..644196e6 100644
--- a/src/core/index/eew.js
+++ b/src/core/index/eew.js
@@ -29,26 +29,22 @@ function eew(_eew) {
const data = TREM.EQ_list[show_eew_id].data;
const eew_max_intensity = TREM.EQ_list[show_eew_id].eew;
const alert = TREM.EQ_list[show_eew_id].alert;
- const unit = (data.type == "eew-jma") ? "JMA" : (data.type == "eew-nied") ? "NIED" : (data.type == "eew-kma") ? "KMA" : (data.type == "eew-scdzj") ? "SCDZJ" : (data.type == "eew-cwb") ? "CWA" : "TREM";
+ const unit = data.author;
document.getElementById("eew_title_text").textContent = `${unit} ${get_lang_string("eew.title").replace("${type}", (data.cancel) ? get_lang_string("eew.cancel") : (data.Test) ? get_lang_string("eew.test") : (alert) ? get_lang_string("eew.alert") : get_lang_string("eew.warn"))}${(eew_list.length == 1) ? "" : ` ${eew_number + 1}/${eew_list.length}`}`;
- document.getElementById("eew_title_text_number").textContent = `${get_lang_string("eew.number").replace("${number}", data.number)}${(data.final) ? `(${get_lang_string("eew.final")})` : ""}`;
- document.getElementById("eew_box").style.backgroundColor = (data.cancel) ? "#333439" : (data.Test) ? "darkviolet" : (data.model == "nsspe" || data.scale == 1) ? "darkblue" : (alert) ? "red" : "#FF9224";
+ document.getElementById("eew_title_text_number").textContent = `${get_lang_string("eew.number").replace("${number}", data.serial)}${(data.final) ? `(${get_lang_string("eew.final")})` : ""}`;
+ document.getElementById("eew_box").style.backgroundColor = (data.status == 2) ? "#333439" : (data.status == 3) ? "darkviolet" : (data.eq.mag == 1) ? "darkblue" : (alert) ? "red" : "#FF9224";
const eew_body = document.getElementById("eew_body");
eew_body.style.backgroundColor = "#514339";
eew_body.style.border = "2px solid black";
const eew_intensity = document.getElementById("eew_intensity");
eew_intensity.className = `intensity_${eew_max_intensity} intensity_center`;
- eew_intensity.textContent = (data.model == "nsspe" && !eew_max_intensity) ? "不明" : int_to_intensity(eew_max_intensity);
- if (data.model == "nsspe" && !eew_max_intensity) {
- eew_intensity.style.fontSize = 30;
- } else {
- eew_intensity.style.fontSize = 50;
- }
+ eew_intensity.textContent = int_to_intensity(eew_max_intensity);
+ eew_intensity.style.fontSize = 50;
const eew_location = document.getElementById("eew_location");
- eew_location.style.fontSize = (data.location.length > 10) ? "16px" : (data.location.length > 7) ? "20px" : "24px";
- eew_location.textContent = `${data.location}`;
+ eew_location.style.fontSize = (data.eq.loc.length > 10) ? "16px" : (data.eq.loc.length > 7) ? "20px" : "24px";
+ eew_location.textContent = `${data.eq.loc}`;
- const now = new Date((data.replay_time) ? data.replay_time : data.time);
+ const now = new Date((data.replay_time) ? data.replay_time : data.eq.time);
let eew_time = now.getFullYear().toString();
eew_time += "/";
if ((now.getMonth() + 1) < 10) {
@@ -80,31 +76,25 @@ function eew(_eew) {
} else {
eew_time += now.getSeconds().toString();
}
- let eew_scale = data.scale.toString();
+ let eew_scale = data.eq.mag.toString();
if (eew_scale.length == 1) {
eew_scale = eew_scale + ".0";
}
document.getElementById("eew_time").textContent = get_lang_string("eew.time").replace("${time}", eew_time);
const text_title = document.getElementById("eew_scale");
const text_body = document.getElementById("eew_args");
- if (data.scale == 1) {
+ if (data.eq.mag == 1) {
text_title.style.fontSize = 18;
text_title.textContent = "PLUM";
text_body.style.fontSize = 12;
text_body.style.textAlign = "start";
text_body.textContent = "局部無阻尼運動傳播法";
- } else if (data.model == "nsspe") {
- text_title.style.fontSize = 18;
- text_title.textContent = "NSSPE";
- text_body.style.fontSize = 14;
- text_body.style.textAlign = "start";
- text_body.textContent = "無震源參數推算";
} else {
text_title.style.fontSize = 26;
text_body.style.fontSize = 18;
text_body.style.textAlign = "right";
text_title.textContent = `M ${eew_scale}`;
- text_body.innerHTML = `${get_lang_string("word.depth")}: ${data.depth} km`;
+ text_body.innerHTML = `${get_lang_string("word.depth")}: ${data.eq.depth} km`;
}
}
}
\ No newline at end of file
diff --git a/src/core/index/event.js b/src/core/index/event.js
index 309cdbc0..8eb1ef63 100644
--- a/src/core/index/event.js
+++ b/src/core/index/event.js
@@ -15,8 +15,6 @@ let _id = "";
let type_list = {
time : 0,
http : 0,
- p2p : 0,
- fcm : 0,
websocket : 0,
};
@@ -44,11 +42,7 @@ const item_audio_eew2 = storage.getItem("audio.EEW2") ?? true;
function get_data(data, type = "websocket") {
if (data.type != "trem-rts") {
type_list.time = now_time();
- if (type == "p2p") {
- type_list.p2p = now_time();
- } else if (type == "fcm") {
- type_list.fcm = now_time();
- } else if (type == "websocket") {
+ if (type == "websocket") {
type_list.websocket = now_time();
} else if (type == "http") {
type_list.http = now_time();
@@ -80,12 +74,6 @@ function get_data(data, type = "websocket") {
if (data_cache.length > 15) {
data_cache.splice(0, 1);
}
- if (data.type == "trem-eew" && !item_trem_eew) {
- return;
- }
- if (data.model == "eew") {
- data.type = "eew-trem";
- }
if (data.type == "trem-rts") {
if (!rts_replay_time) {
on_rts_data(data.raw);
@@ -140,7 +128,7 @@ function get_data(data, type = "websocket") {
eq_station_list[station.stationIntensity].push(`${city.areaName}${station.stationName}`);
}
}
- console.log(eq_station_list);
+ // console.log(eq_station_list);
let count = 0;
for (let i = 9; i >= 1; i--) {
if (!eq_station_list[i].length) {
@@ -174,25 +162,7 @@ function get_data(data, type = "websocket") {
refresh_report_list(false, data);
screenshot_id = `report_${now_time()}`;
plugin.emit("trem.report.on-report", data);
- } else if (data.type == "eew-report" || data.type == "eew-trem" || data.type == "eew-cwb" || data.type == "eew-scdzj" || data.type == "eew-kma" || data.type == "eew-jma" || data.type == "eew-nied") {
- if ((data.type == "eew-jma" || data.type == "eew-nied") && data.location == "台湾付近") {
- return;
- }
- if (data.type == "eew-jma" && !item_jma_eew) {
- return;
- }
- if (data.type == "eew-kma" && !item_kma_eew) {
- return;
- }
- if (data.type == "eew-nied" && !item_nied_eew) {
- return;
- }
- if (data.type == "eew-scdzj" && !item_scdzj_eew) {
- return;
- }
- if (data.type == "eew-cwb" && !item_cwb_eew) {
- return;
- }
+ } else if (data.type == "eew-report" || data.type == "eew-cwb") {
if (Now().getTime() - data.time > 240_000 && !data.replay_timestamp) {
return;
}
@@ -225,6 +195,7 @@ function get_data(data, type = "websocket") {
}
function on_eew(data, type) {
+ // console.log(data)
TREM.eew = true;
let skip = false;
if (item_eew_level != -1) {
@@ -251,8 +222,8 @@ function on_eew(data, type) {
eew : 0,
alert : false,
};
- if (!eew_cache.includes(data.id + data.number)) {
- eew_cache.push(data.id + data.number);
+ if (!eew_cache.includes(data.id + data.serial)) {
+ eew_cache.push(data.id + data.serial);
if (!skip && item_audio_eew) {
TREM.audio.push("EEW");
}
@@ -262,14 +233,14 @@ function on_eew(data, type) {
TREM.EQ_list[data.id].loc = eew;
plugin.emit("trem.eew.on-eew-create", data);
} else {
- if (!data.location) {
- data.location = TREM.EQ_list[data.id].data.location;
+ if (!data.eq.loc) {
+ data.eq.loc = TREM.EQ_list[data.id].data.eq.loc;
}
- if (!data.lat) {
- data.lat = TREM.EQ_list[data.id].data.lat;
+ if (!data.eq.lat) {
+ data.eq.lat = TREM.EQ_list[data.id].data.eq.lat;
}
- if (!data.lon) {
- data.lon = TREM.EQ_list[data.id].data.lon;
+ if (!data.eq.lon) {
+ data.eq.lon = TREM.EQ_list[data.id].data.eq.lon;
}
TREM.EQ_list[data.id].data = data;
if (data.cancel) {
@@ -286,19 +257,19 @@ function on_eew(data, type) {
}
} else {
if (TREM.EQ_list[data.id].p_wave) {
- TREM.EQ_list[data.id].p_wave.setLatLng([data.lat, data.lon]);
+ TREM.EQ_list[data.id].p_wave.setLatLng([data.eq.lat, data.eq.lon]);
}
if (TREM.EQ_list[data.id].s_wave) {
- TREM.EQ_list[data.id].s_wave.setLatLng([data.lat, data.lon]);
+ TREM.EQ_list[data.id].s_wave.setLatLng([data.eq.lat, data.eq.lon]);
}
if (TREM.EQ_list[data.id].s_wave_back) {
- TREM.EQ_list[data.id].s_wave_back.setLatLng([data.lat, data.lon]);
+ TREM.EQ_list[data.id].s_wave_back.setLatLng([data.eq.lat, data.eq.lon]);
}
}
if (item_audio_update) {
TREM.audio.push("update");
}
- const eew = eew_location_intensity(data, data.depth);
+ const eew = eew_location_intensity(data, data.eq.depth);
data.max = intensity_float_to_int(eew.max_i);
TREM.EQ_list[data.id].loc = eew;
TREM.EQ_list[data.id].eew = intensity_float_to_int(TREM.EQ_list[data.id].loc.max_i);
@@ -314,8 +285,8 @@ function on_eew(data, type) {
TREM.EQ_list[data.id].epicenterIcon.remove();
delete TREM.EQ_list[data.id].epicenterIcon;
}
- if (data.type == "eew-cwb" && data.location.includes("海") && Number(data.depth) <= 35) {
- if (Number(data.scale) >= 7) {
+ if (data.type == "eew-cwb" && data.eq.loc.includes("海") && Number(data.eq.depth) <= 35) {
+ if (Number(data.eq.mag) >= 7) {
if (!TREM.EQ_list[data.id].alert_tsunami) {
TREM.EQ_list[data.id].alert_tsunami = true;
if (!skip && speecd_use) {
@@ -323,7 +294,7 @@ function on_eew(data, type) {
}
add_info("fa-solid fa-house-tsunami fa-2x info_icon", "#0072E3", "注意海嘯", "#FF5809", "震源位置及規模表明
可能發生海嘯
沿岸地區應慎防海水位突變
並留意 中央氣象署(CWA)
是否發布 [ 海嘯警報 ]");
}
- } else if (Number(data.scale) >= 6) {
+ } else if (Number(data.eq.mag) >= 6) {
if (!TREM.EQ_list[data.id].alert_sea) {
TREM.EQ_list[data.id].alert_sea = true;
if (!skip && speecd_use) {
@@ -333,28 +304,30 @@ function on_eew(data, type) {
}
}
}
- const notification = new Notification(`🚨 地震預警 第${data.number}報 | ${unit}`, {
- body : `${time_to_string((data.replay_time) ? data.replay_time : data.time)}\n${data.location} ${(data.cancel) ? "取消" : `發生 M${data.scale.toFixed(1)} 地震`}`,
- icon : "../TREM.ico",
- });
- notification.addEventListener("click", () => MainWindow.focus());
- if (_id != data.id) {
- _id = data.id;
- _list = "";
- _max = -1;
- _location = "";
+ if (!data.replay_timestamp) {
+ const notification = new Notification(`🚨 地震預警 第${data.serial}報 | ${unit}`, {
+ body : `${time_to_string((data.eq.time) ? data.eq.time : data.time)}\n${data.eq.loc} ${(data.status == 2) ? "取消" : `發生 M${data.eq.mag.toFixed(1)} 地震`}`,
+ icon : "../TREM.ico",
+ });
+ notification.addEventListener("click", () => MainWindow.focus());
+ if (_id != data.id) {
+ _id = data.id;
+ _list = "";
+ _max = -1;
+ _location = "";
+ }
}
- if (data.cancel) {
+ if (data.status == 2) {
if (!skip && speecd_use) {
loc_speech_clock = false;
eew_speech_clock = false;
- speech.speak({ text: `${data.location},取消` });
+ speech.speak({ text: `${data.eq.loc},取消` });
}
plugin.emit("trem.eew.on-eew-cancel", data);
} else if (!skip && speecd_use) {
eew_speech = {
- loc : data.location,
- max : data.max,
+ loc : data.eq.loc,
+ max : data.eq.max,
};
eew_speech_clock = true;
}
@@ -390,20 +363,20 @@ function on_eew(data, type) {
}
if (TREM.EQ_list[_data.id].epicenterIcon) {
TREM.EQ_list[_data.id].epicenterIcon.setIcon(epicenterIcon);
- TREM.EQ_list[_data.id].epicenterIcon.setLatLng([_data.lat + offsetY, _data.lon + offsetX]);
+ TREM.EQ_list[_data.id].epicenterIcon.setLatLng([_data.eq.lat + offsetY, _data.eq.lon + offsetX]);
} else {
- TREM.EQ_list[_data.id].epicenterIcon = L.marker([_data.lat + offsetY, _data.lon + offsetX], { icon: epicenterIcon, zIndexOffset: 6000 }).addTo(TREM.Maps.main);
+ TREM.EQ_list[_data.id].epicenterIcon = L.marker([_data.eq.lat + offsetY, _data.eq.lon + offsetX], { icon: epicenterIcon, zIndexOffset: 6000 }).addTo(TREM.Maps.main);
}
}
} else if (TREM.EQ_list[data.id].epicenterIcon) {
- TREM.EQ_list[data.id].epicenterIcon.setLatLng([data.lat, data.lon]);
+ TREM.EQ_list[data.id].epicenterIcon.setLatLng([data.eq.lat, data.eq.lon]);
} else {
epicenterIcon = L.icon({
iconUrl : "../resource/images/cross.png",
iconSize : [40 + TREM.size * 3, 40 + TREM.size * 3],
className : "flash",
});
- TREM.EQ_list[data.id].epicenterIcon = L.marker([data.lat, data.lon], { icon: epicenterIcon, zIndexOffset: 6000 })
+ TREM.EQ_list[data.id].epicenterIcon = L.marker([data.eq.lat, data.eq.lon], { icon: epicenterIcon, zIndexOffset: 6000 })
.addTo(TREM.Maps.main);
}
const _loc_list = TREM.EQ_list[data.id].loc;
diff --git a/src/core/index/globals.js b/src/core/index/globals.js
index 19bfa57c..a8de9ce2 100644
--- a/src/core/index/globals.js
+++ b/src/core/index/globals.js
@@ -12,7 +12,5 @@ const speech = new Speech.default();
await speech.init();
speech.setLanguage("zh-TW");
speech.setVoice("Microsoft Zhiwei - Chinese (Traditional, Taiwan)");
- // speech.setLanguage("ja-JP");
- // speech.setVoice("Microsoft Sayaka - Japanese (Japan)");
speech.setRate(1.8);
})();
\ No newline at end of file
diff --git a/src/core/index/loop.js b/src/core/index/loop.js
index ee670402..aabc6da1 100644
--- a/src/core/index/loop.js
+++ b/src/core/index/loop.js
@@ -56,14 +56,14 @@ map.onmousedown = () => {
Zoom = false;
focus_lock = true;
const location_button = document.getElementById("location_button");
- location_button.style.color = "white";
+ location_button.style.color = "grey";
location_button.style.border = "1px solid red";
};
map.onwheel = () => {
focus_lock = true;
const location_button = document.getElementById("location_button");
- location_button.style.color = "white";
+ location_button.style.color = "grey";
location_button.style.border = "1px solid red";
};
@@ -78,10 +78,27 @@ time.onclick = () => {
time.style.cursor = "";
};
+fetch_eew();
+fetch_rts();
+setInterval(() => {
+ if(WS) return;
+ fetch_eew();
+ if(sleep_state || parseInt(Date.now()/1000)%5!=0) return;
+ fetch_rts(); /* 每五秒抓一次RTS (CDN有快取時間) */
+}, 1_000);
+
+setInterval(() => {
+ if(sleep_state) return;
+ refresh_report_list();
+}, 120_000);
+
setInterval(() => {
setTimeout(() => {
const now = (rts_replay_time) ? rts_replay_time : Now().getTime();
- if (WS) {
+ if (rts_replay_time || Now().getTime() - last_get_rts_time < 10000) {
+ if(!rts_replay_time) {
+ time.style.color = "white";
+ }
time.innerHTML = `${time_to_string(now)}`;
if (!check_file_replay) {
check_file_replay = true;
@@ -90,6 +107,8 @@ setInterval(() => {
replay_run();
}
}
+ } else {
+ time.style.color = "red";
}
for (const item of document.getElementsByClassName("flash")) {
item.style.visibility = "hidden";
@@ -142,63 +161,42 @@ setInterval(() => {
if (screenshot_id != "") {
const _screenshot_id = screenshot_id;
screenshot_id = "";
- setTimeout(() => {
- ipcRenderer.send("screenshot_auto", { id: _screenshot_id });
- }, 1750);
}
if (!sleep_state) {
let _status_text = "";
if (rts_replay_time) {
_status_text = "🔁 重播資料";
- } else if (rts_lag < 100) {
+ } else if (rts_lag < 6000) {
_status_text = `⚡ 即時資料 ${(rts_lag / 1000).toFixed(1)}s`;
- } else if (rts_lag < 1000) {
+ } else if (rts_lag < 10000) {
_status_text = `📶 延遲較高 ${(rts_lag / 1000).toFixed(1)}s`;
} else {
_status_text = `⚠️ 延遲資料 ${(rts_lag / 1000).toFixed(1)}s`;
}
- if (rts_lag > 1500 && !rts_replay_time) {
+ if (rts_lag > 15000 && !rts_replay_time) {
icon_lag.style.display = "";
} else {
icon_lag.style.display = "none";
}
- if (!WS) {
- icon_server.style.display = "";
- } else {
+ if (WS || Now().getTime() - last_get_eew_time < 2500) {
icon_server.style.display = "none";
- }
- if (!FCM) {
- icon_fcm.style.display = "";
- } else {
- icon_fcm.style.display = "none";
- }
- if (!info.in.length) {
- icon_p2p.style.display = "";
} else {
- icon_p2p.style.display = "none";
+ icon_server.style.display = "";
}
+ icon_fcm.style.display = "none";
+ icon_p2p.style.display = "none";
_status.textContent = _status_text;
_get_data.innerHTML = "";
if (now_time() - type_list.time < 1000) {
_get_data.style.display = "";
if (now_time() - type_list.http < 1000) {
const div = document.createElement("div");
- div.textContent = "🟩 Http";
- _get_data.append(div);
- }
- if (now_time() - type_list.p2p < 1000) {
- const div = document.createElement("div");
- div.textContent = "🟦 P2P";
+ div.textContent = "🟩 HTTP";
_get_data.append(div);
}
if (now_time() - type_list.websocket < 1000) {
const div = document.createElement("div");
- div.textContent = "⬜ Websocket";
- _get_data.append(div);
- }
- if (now_time() - type_list.fcm < 1000) {
- const div = document.createElement("div");
- div.textContent = "🟥 FCM";
+ div.textContent = "⬜ WebSocket";
_get_data.append(div);
}
} else {
@@ -240,15 +238,8 @@ setInterval(() => {
setTimeout(() => controller.abort(), 2500);
const _replay_time = Math.round(rts_replay_time / 1000);
rts_replay_time += 1000;
- const now = new Date(_replay_time * 1000);
- const YYYY = now.getFullYear();
- const MM = (now.getMonth() + 1).toString().padStart(2, "0");
- const DD = now.getDate().toString().padStart(2, "0");
- const hh = now.getHours().toString().padStart(2, "0");
- const mm = now.getMinutes().toString().padStart(2, "0");
- const ss = now.getSeconds().toString().padStart(2, "0");
- const t = `${YYYY}${MM}${DD}${hh}${mm}${ss}`;
- fetch(`https://api.exptech.com.tw/api/v1/trem/rts/${t}`, { signal: controller.signal })
+ const t = _replay_time * 1000
+ fetch(`https://${api_domain}/api/v1/trem/rts/${t}`, { signal: controller.signal })
.then(async (ans) => {
ans = await ans.json();
if (!rts_replay_time) {
@@ -259,14 +250,16 @@ setInterval(() => {
.catch((err) => {
log(err, 3, "loop", "replay_rts");
});
- fetch(`https://api.exptech.com.tw/api/v1/eq/eew/${t}?type=all`, { signal: controller.signal })
+ fetch(`https://${api_domain}/api/v1/eq/eew/${t}?type=cwa`, { signal: controller.signal })
.then(async (ans_eew) => {
ans_eew = await ans_eew.json();
if (!rts_replay_time) {
return;
}
const _now = Now().getTime();
- for (const eew of ans_eew.eew) {
+ type_list.time = now_time();
+ type_list.http = _now;
+ for (const eew of ans_eew) {
// if (eew.type == "trem-eew") {
// eew.time = eew_list[eew.number - 1].time;
// eew.lat = eew_list[eew.number - 1].lat;
@@ -274,7 +267,8 @@ setInterval(() => {
// eew.depth = Math.round(eew_list[eew.number - 1].depth);
// eew.location = "未知區域";
// }
- eew.replay_timestamp = eew.timestamp;
+ eew.type = "eew-cwb";
+ eew.replay_timestamp = eew.eq.time;
eew.replay_time = eew.time;
eew.time = _now - (_replay_time * 1000 - eew.time);
eew.timestamp = _now - (_replay_time * 1000 - eew.timestamp);
@@ -320,8 +314,9 @@ setInterval(() => {
refresh_report_list(true);
}, 300_000);
+let is_playing = false;
setInterval(() => {
- if (TREM.audio.length) {
+ if (TREM.audio.length && !is_playing) {
const audioContext = new AudioContext();
const nextAudioPath = TREM.audio.shift();
if (!source_data[nextAudioPath]) {
@@ -334,8 +329,10 @@ setInterval(() => {
source.connect(audioContext.destination);
source.playbackRate = 1.1;
source.start();
+ is_playing = true;
source.onended = () => {
source.disconnect();
+ is_playing = false;
fs.readFile(path.resolve(app.getAppPath(), `./resource/audios/${nextAudioPath}.wav`), (err, data) => {
source_data[nextAudioPath] = data.buffer;
audioContext.close();
@@ -409,10 +406,10 @@ setInterval(() => {
continue;
}
const _eew_location_info = eew_location_info(data);
- const tr_time = _speed(data.depth, _eew_location_info.dist);
+ const tr_time = _speed(data.eq.depth, _eew_location_info.dist);
const intensity = intensity_float_to_int(_eew_location_info.i);
if (data.type == "eew-report") {
- data.time = _now - (rts_replay_time - data.originTime);
+ data.time = _now - (rts_replay_time - data.eq.time);
}
if (intensity > user_max_intensity) {
user_max_intensity = intensity;
@@ -450,7 +447,7 @@ setInterval(() => {
let p_dist = 0;
let s_dist = 0;
- const _time_table = time_table[findClosest(time_table_list, data.depth)];
+ const _time_table = time_table[findClosest(time_table_list, data.eq.depth)];
let prev_table = null;
for (const table of _time_table) {
if (!p_dist && table.P > (_now - data.time) / 1000) {
@@ -482,19 +479,19 @@ setInterval(() => {
}
if (!p_dist) {
- p_dist = Math.sqrt(pow((_now - data.time) / 1000 * 7) - pow(data.depth));
+ p_dist = Math.sqrt(pow((_now - data.time) / 1000 * 7) - pow(data.eq.depth));
}
if (!s_dist) {
- s_dist = Math.sqrt(pow((_now - data.time) / 1000 * 4) - pow(data.depth));
+ s_dist = Math.sqrt(pow((_now - data.time) / 1000 * 4) - pow(data.eq.depth));
}
p_dist *= 1000;
s_dist *= 1000;
TREM.EQ_list[key].dist = s_dist;
- if (p_dist > data.depth) {
+ if (p_dist > data.eq.depth) {
if (!TREM.EQ_list[key].p_wave) {
- TREM.EQ_list[key].p_wave = L.circle([data.lat, data.lon], {
+ TREM.EQ_list[key].p_wave = L.circle([data.eq.lat, data.eq.lon], {
color : "#00FFFF",
fillColor : "transparent",
radius : p_dist,
@@ -505,12 +502,12 @@ setInterval(() => {
TREM.EQ_list[key].p_wave.setRadius(p_dist);
}
}
- if (s_dist < data.depth) {
+ if (s_dist < data.eq.depth) {
if (TREM.EQ_list[key].s_wave) {
TREM.EQ_list[key].s_wave.remove();
delete TREM.EQ_list[key].s_wave;
}
- const progress = Math.round(((_now - data.time) / 1000 / time_table[data.depth][0].S) * 100);
+ const progress = Math.round(((_now - data.time) / 1000 / time_table[data.eq.depth][0].S) * 100);
const progress_bar = ``;
TREM.EQ_list[key].epicenterTooltip = true;
TREM.EQ_list[key].epicenterIcon.bindTooltip(progress_bar, { opacity: 1, permanent: true, direction: "right", offset: [10, 0], className: "progress-tooltip" });
@@ -520,7 +517,7 @@ setInterval(() => {
delete TREM.EQ_list[key].epicenterTooltip;
}
if (!TREM.EQ_list[key].s_wave) {
- TREM.EQ_list[key].s_wave = L.circle([data.lat, data.lon], {
+ TREM.EQ_list[key].s_wave = L.circle([data.eq.lat, data.eq.lon], {
color : (data.type == "eew-report") ? "grey" : (data.type == "eew-trem") ? "#73BF00" : (TREM.EQ_list[key].alert) ? "red" : "#FF8000",
fillColor : "transparent",
radius : s_dist,
@@ -532,7 +529,7 @@ setInterval(() => {
}
if (item_disable_geojson_vt) {
if (!TREM.EQ_list[key].s_wave_back) {
- TREM.EQ_list[key].s_wave_back = L.circle([data.lat, data.lon], {
+ TREM.EQ_list[key].s_wave_back = L.circle([data.eq.lat, data.eq.lon], {
color : "transparent",
fillColor : (data.type == "eew-report") ? "grey" : (data.type == "eew-trem") ? "#73BF00" : (TREM.EQ_list[key].alert) ? "red" : "#FF8000",
radius : s_dist,
@@ -565,7 +562,7 @@ setInterval(() => {
}
}
if (key == show_eew_id) {
- TREM.eew_bounds.extend([data.lat, data.lon]);
+ TREM.eew_bounds.extend([data.eq.lat, data.eq.lon]);
}
}
diff --git a/src/core/index/main.js b/src/core/index/main.js
index bbaa57b9..3e643853 100644
--- a/src/core/index/main.js
+++ b/src/core/index/main.js
@@ -2,7 +2,6 @@
require("leaflet");
require("leaflet-edgebuffer");
require("leaflet-geojson-vt");
-fetch_eew();
const TREM = {
Maps: {
@@ -11,7 +10,7 @@ const TREM = {
EQ_list : {},
Timers : {},
setting : {
- rts_station: "H-711-11334880-12",
+ rts_station: "H-711-11334880",
},
audio : [],
rts_audio : {
@@ -37,6 +36,7 @@ const TREM = {
lon : 0,
},
report_icon_list : {},
+ report_epicenterIcon: null,
size : 0,
};
@@ -68,7 +68,7 @@ TREM.Maps.main.on("zoomend", () => {
icon.options.iconSize = [40 + TREM.size * 3, 40 + TREM.size * 3];
}
TREM.EQ_list[key].epicenterIcon.remove();
- TREM.EQ_list[key].epicenterIcon = L.marker([data.lat, data.lon], { icon: icon, zIndexOffset: 6000 })
+ TREM.EQ_list[key].epicenterIcon = L.marker([data.eq.lat, data.eq.lon], { icon: icon, zIndexOffset: 6000 })
.addTo(TREM.Maps.main);
if (TREM.EQ_list[key].epicenterIcon._tooltip) {
TREM.EQ_list[key].epicenterIcon.bindTooltip(TREM.EQ_list[key].epicenterIcon._tooltip._content, { opacity: 1, permanent: true, direction: "right", offset: [10, 0], className: "progress-tooltip" });
diff --git a/src/core/index/rts.js b/src/core/index/rts.js
index 13769368..0aef9431 100644
--- a/src/core/index/rts.js
+++ b/src/core/index/rts.js
@@ -34,6 +34,7 @@ let last_package_lost_time = 0;
const icon_package = document.getElementById("icon-package");
const battery = document.getElementById("battery");
+battery.style.display = "none";
const detection_data = JSON.parse(fs.readFileSync(path.resolve(app.getAppPath(), "./resource/data/detection.json")).toString());
@@ -44,35 +45,79 @@ async function get_station_info() {
setTimeout(() => {
controller.abort();
}, 1500);
- let ans = await fetch("https://data.exptech.com.tw/file/resource/station.json", { signal: controller.signal })
+ let ans = await fetch("https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/resource/station.json", { signal: controller.signal })
.catch((err) => void 0);
if (controller.signal.aborted || !ans) {
setTimeout(() => get_station_info(), 500);
return;
}
- station = await ans.json();
+ station = station_exec(await ans.json());
} catch (err) {
log(err, 3, "rts", "get_station_info");
setTimeout(() => get_station_info(), 500);
}
}
+function station_exec(station_data) {
+ let stations = {};
+ for (let k = 0, k_ks = Object.keys(station_data), n = k_ks.length; k < n; k++) {
+ const station_id = k_ks[k];
+ const station_ = station_data[station_id];
+ const station_net = station_.net === "MS-Net" ? "H" : "L";
-function on_rts_data(data) {
- console.log(data);
- if (!WS) {
- return;
+ let station_new_id = "";
+ let station_code = "000";
+ let Loc = "";
+ let area = "";
+ let Lat = 0;
+ let Long = 0;
+
+ let latest = station_.info[0];
+
+ if (station_.info.length > 1)
+ for (let i = 1; i < station_.info.length; i++) {
+ const currentTime = new Date(station_.info[i].time);
+ const latestTime = new Date(latest.time);
+
+ if (currentTime > latestTime)
+ latest = station_.info[i];
+ }
+
+ for (let i = 0, ks = Object.keys(region), j = ks.length; i < j; i++) {
+ const reg_id = ks[i];
+ const reg = region[reg_id];
+
+ for (let r = 0, r_ks = Object.keys(reg), l = r_ks.length; r < l; r++) {
+ const ion_id = r_ks[r];
+ const ion = reg[ion_id];
+
+ if (ion.code === latest.code) {
+ station_code = latest.code.toString();
+ Loc = `${reg_id} ${ion_id}`;
+ area = ion.area;
+ Lat = latest.lat;
+ Long = latest.lon;
+ }
+ }
+ }
+ station_new_id = `${station_net}-${station_code}-${station_id}`;
+ stations[station_id] = { uuid: station_new_id, Lat, Long, Loc, area };
}
+ return stations;
+}
+
+function on_rts_data(data) {
+ data.Alert = (Object.keys(detection_list).length !== 0); // 測試
const _now = Date.now();
- if (_now - last_get_data_time > 1500) {
+ if (_now - last_get_rts_time > 10000) {
last_package_lost_time = _now;
}
- last_get_data_time = _now;
+ last_get_rts_time = _now;
if (!last_package_lost_time) {
icon_package.style.display = "none";
} else {
icon_package.style.display = "";
}
- if (_now - last_package_lost_time > 3000) {
+ if (_now - last_package_lost_time > 30000) {
last_package_lost_time = 0;
}
let target_count = 0;
@@ -100,378 +145,370 @@ function on_rts_data(data) {
const list = Object.keys(TREM.EQ_list);
if (data.station) {
- for (const id of Object.keys(data.station)) {
+ for (const station_id of Object.keys(data.station)) {
const icon = L.divIcon({
- className : `pga_dot pga_${data.station[id].i.toString().replace(".", "_")}`,
+ className : `pga_dot pga_${data.station[station_id].i.toString().replace(".", "_")}`,
html : "",
iconSize : [10 + TREM.size, 10 + TREM.size],
});
- const info = station[id].info[0];
-
- if (!station_icon[id]) {
- station_icon[id] = L.marker([info.lat, info.lon], { icon: icon })
- // .bindTooltip(station_info_text, { opacity: 1 })
+ if (!station_icon[station_id]) {
+ station_icon[station_id] = L.marker([station[station_id].Lat, station[station_id].Long], { icon: icon })
+ .bindTooltip("", { opacity: 1 })
.addTo(TREM.Maps.main);
} else {
- station_icon[id].setIcon(icon);
- // station_icon[uuid].setTooltipContent(station_info_text);
+ station_icon[station_id].setIcon(icon);
+ station_icon[uuid].setTooltipContent("");
}
}
- }
-
- // for (const uuid of Object.keys(data)) {
- // if (!station[uuid]) {
- // continue;
- // }
- // const info = station[uuid];
- // const station_data = data[uuid];
- // const intensity = intensity_float_to_int(station_data.i);
- // if (data.Alert) {
- // if (station_data.alert && station_data.v > max_pga) {
- // max_pga = station_data.v;
- // }
- // } else if (station_data.v > max_pga) {
- // max_pga = station_data.v;
- // }
- // let icon;
- // if (data.Alert && station_data.alert) {
- // if ((level_list[uuid] ?? 0) < station_data.v) {
- // level_list[uuid] = station_data.v;
- // }
- // target_count++;
- // if (map_style_v == "2" || map_style_v == "4") {
- // let int = 2 * Math.log10(station_data.v) + 0.7;
- // int = Number((int).toFixed(1));
- // icon = L.divIcon({
- // className : `pga_dot pga_${int.toString().replace(".", "_")}`,
- // html : "",
- // iconSize : [10 + TREM.size, 10 + TREM.size],
- // });
- // } else
- // if (intensity == 0) {
- // icon = L.divIcon({
- // className : "pga_dot pga_intensity_0",
- // html : "",
- // iconSize : [10 + TREM.size, 10 + TREM.size],
- // });
- // } else {
- // let _up = false;
- // if (!pga_up_level[uuid] || pga_up_level[uuid] < station_data.v) {
- // pga_up_level[uuid] = station_data.v;
- // pga_up_timestamp[uuid] = now_time();
- // }
- // if (now_time() - (pga_up_timestamp[uuid] ?? 0) < 5000) {
- // _up = true;
- // }
- // icon = L.divIcon({
- // className : `${(_up) ? "dot_max" : "dot"} intensity_${intensity}`,
- // html : `${int_to_intensity(intensity)}`,
- // iconSize : [20 + TREM.size, 20 + TREM.size],
- // });
- // }
- // } else {
- // icon = L.divIcon({
- // className : `pga_dot pga_${station_data.i.toString().replace(".", "_")}`,
- // html : "",
- // iconSize : [10 + TREM.size, 10 + TREM.size],
- // });
- // }
- // if (!station_data.alert) {
- // delete level_list[uuid];
- // }
- // const station_info_text = `${info.Loc}T${(station[uuid].UUID.includes("H")) ? "V" : "A"}S-Net_${uuid}
`;
- // if (map_style_v != "3") {
- // if (!station_icon[uuid]) {
- // station_icon[uuid] = L.marker([info.Lat, info.Long], { icon: icon })
- // .bindTooltip(station_info_text, { opacity: 1 })
- // .addTo(TREM.Maps.main);
- // } else {
- // station_icon[uuid].setIcon(icon);
- // station_icon[uuid].setTooltipContent(station_info_text);
- // }
- // }
- // if (station_icon[uuid]) {
- // if ((list.length && !station_data.alert && !(map_style_v == "2" || map_style_v == "4")) || TREM.report_time) {
- // station_icon[uuid].getElement().style.visibility = "hidden";
- // } else {
- // station_icon[uuid].getElement().style.visibility = "";
- // }
- // station_icon[uuid].setZIndexOffset((intensity == 0) ? Math.round(station_data.v + 5) : intensity * 10);
- // }
- // if (TREM.setting.rts_station.includes(uuid)) {
- // rts_sation_loc = info.Loc;
- // rts_sation_intensity = station_data.i;
- // rts_sation_intensity_number = intensity;
- // rts_sation_pga = station_data.v;
- // }
- // }
- // if (rts_clock == null) {
- // battery.style.color = "lawngreen";
- // } else {
- // battery.style.color = "red";
- // }
+ for (const station_id of Object.keys(data.station)) {
+ if (!station[station_id]) {
+ continue;
+ }
+ const info = station[station_id];
+ const station_data = data.station[station_id];
+ const intensity = intensity_float_to_int(station_data.i);
+ if (data.Alert) {
+ if (station_data.alert && station_data.pga > max_pga) {
+ max_pga = station_data.pga;
+ }
+ } else if (station_data.pga > max_pga) {
+ max_pga = station_data.pga;
+ }
+ let icon;
+ if (data.Alert && station_data.alert) {
+ if ((level_list[station_id] ?? 0) < station_data.pga) {
+ level_list[station_id] = station_data.pga;
+ }
+ target_count++;
+ if (map_style_v == "2" || map_style_v == "4") {
+ let int = 2 * Math.log10(station_data.pga) + 0.7;
+ int = Number((int).toFixed(1));
+ icon = L.divIcon({
+ className : `pga_dot pga_${int.toString().replace(".", "_")}`,
+ html : "",
+ iconSize : [10 + TREM.size, 10 + TREM.size],
+ });
+ } else
+ if (intensity == 0) {
+ icon = L.divIcon({
+ className : "pga_dot pga_intensity_0",
+ html : "",
+ iconSize : [10 + TREM.size, 10 + TREM.size],
+ });
+ } else {
+ let _up = false;
+ if (!pga_up_level[station_id] || pga_up_level[station_id] < station_data.pga) {
+ pga_up_level[station_id] = station_data.pga;
+ pga_up_timestamp[station_id] = now_time();
+ }
+ if (now_time() - (pga_up_timestamp[station_id] ?? 0) < 5000) {
+ _up = true;
+ }
+ icon = L.divIcon({
+ className : `${(_up) ? "dot_max" : "dot"} intensity_${intensity}`,
+ html : `${int_to_intensity(intensity)}`,
+ iconSize : [20 + TREM.size, 20 + TREM.size],
+ });
+ }
+ } else {
+ icon = L.divIcon({
+ className : `pga_dot pga_${station_data.i.toString().replace(".", "_")}`,
+ html : "",
+ iconSize : [10 + TREM.size, 10 + TREM.size],
+ });
+ }
+ if (!station_data.alert) {
+ delete level_list[station_id];
+ }
+ const station_info_text = ``;
+ if (map_style_v != "3") {
+ if (!station_icon[station_id]) {
+ station_icon[station_id] = L.marker([station_data.Lat, station_data.Long], { icon: icon })
+ .bindTooltip(station_info_text, { opacity: 1 })
+ .addTo(TREM.Maps.main);
+ } else {
+ station_icon[station_id].setIcon(icon);
+ station_icon[station_id].setTooltipContent(station_info_text);
+ }
+ }
+ if (station_icon[station_id]) {
+ if ((list.length && !station_data.alert && !(map_style_v == "2" || map_style_v == "4")) || TREM.report_time) {
+ station_icon[station_id].getElement().style.visibility = "hidden";
+ } else {
+ station_icon[station_id].getElement().style.visibility = "";
+ }
+ station_icon[station_id].setZIndexOffset((intensity == 0) ? Math.round(station_data.pga + 5) : intensity * 10);
+ }
+ if (TREM.setting.rts_station.includes(info.uuid)) {
+ rts_sation_loc = info.Loc;
+ rts_sation_intensity = station_data.i;
+ rts_sation_intensity_number = intensity;
+ rts_sation_pga = station_data.pga;
+ }
+ }
+ }
- // if (!data.Alert) {
- // level_list = {};
- // }
- // document.getElementById("rts_location").textContent = rts_sation_loc;
- // document.getElementById("rts_pga").textContent = `${get_lang_string("word.pga")} ${rts_sation_pga}`;
- // document.getElementById("rts_intensity").textContent = `${get_lang_string("word.intensity")} ${rts_sation_intensity}`;
- // const rts_intensity_level = document.getElementById("rts_intensity_level");
- // rts_intensity_level.textContent = int_to_intensity(rts_sation_intensity_number);
- // rts_intensity_level.className = `intensity_center intensity_${rts_sation_intensity_number}`;
- // const max_pga_text = document.getElementById("max_pga");
- // const max_intensity_text = document.getElementById("max_intensity");
- // const detection_location_1 = document.getElementById("detection_location_1");
- // const detection_location_2 = document.getElementById("detection_location_2");
- // let skip = false;
- // if (max_intensity < item_rts_level) {
- // skip = true;
- // }
- // if (data.eew) {
- // if (!eew_alert_state) {
- // eew_alert_state = true;
- // TREM.audio.push("Warn");
- // add_info("fa-solid fa-bell fa-2x info_icon", "#FF0080", "地震檢測", "#00EC00", "請留意 中央氣象署
是否發布 地震預警", 15000);
- // if (alert_timestamp && now_time() - alert_timestamp < 300_000) {
- // add_info("fa-solid fa-triangle-exclamation fa-2x info_icon", "yellow", "不穩定", "#E800E8", "受到地震的影響
即時測站可能不穩定");
- // }
- // alert_timestamp = now_time();
- // }
- // } else {
- // eew_alert_state = false;
- // }
- // if (data.Alert) {
- // if (TREM.report_time) {
- // report_off();
- // }
- // if (!skip && !rts_show) {
- // rts_show = true;
- // show_screen("rts");
- // }
- // if (max_intensity > TREM.rts_audio.intensity && TREM.rts_audio.intensity != 10) {
- // const loc = detection_location[0] ?? "未知區域";
- // if (max_intensity > 3) {
- // TREM.rts_audio.intensity = 10;
- // if (!skip && item_audio_shindo2) {
- // TREM.audio.push("Shindo2");
- // }
- // const notification = new Notification("🟥 強震檢測", {
- // body : `${loc}`,
- // icon : "../TREM.ico",
- // });
- // notification.addEventListener("click", () => {
- // MainWindow.focus();
- // });
- // rts_screenshot();
- // plugin.emit("trem.rts.detection-strong");
- // } else if (max_intensity > 1) {
- // TREM.rts_audio.intensity = 3;
- // if (!skip && item_audio_shindo1) {
- // TREM.audio.push("Shindo1");
- // }
- // const notification = new Notification("🟨 震動檢測", {
- // body : `${loc}`,
- // icon : "../TREM.ico",
- // });
- // notification.addEventListener("click", () => {
- // MainWindow.focus();
- // });
- // rts_screenshot();
- // plugin.emit("trem.rts.detection-shake");
- // } else {
- // TREM.rts_audio.intensity = 1;
- // if (!skip && item_audio_shindo0) {
- // TREM.audio.push("Shindo0");
- // }
- // const notification = new Notification("🟩 弱反應", {
- // body : `${loc}`,
- // icon : "../TREM.ico",
- // });
- // notification.addEventListener("click", () => {
- // MainWindow.focus();
- // });
- // rts_screenshot();
- // plugin.emit("trem.rts.detection-weak");
- // }
- // if (!rts_tts) {
- // rts_tts = true;
- // if (speecd_use) {
- // speech.speak({ text: `${loc},偵測到晃動` });
- // }
- // }
- // }
- // if (max_pga > TREM.rts_audio.pga && TREM.rts_audio.pga <= 200) {
- // if (max_pga > 200) {
- // TREM.rts_audio.pga = 250;
- // if (!skip && item_audio_pga2) {
- // TREM.audio.push("PGA2");
- // }
- // rts_screenshot();
- // plugin.emit("trem-rts.pga-high");
- // } else if (max_pga > 8) {
- // TREM.rts_audio.pga = 200;
- // if (!skip && item_audio_pga1) {
- // TREM.audio.push("PGA1");
- // }
- // rts_screenshot();
- // plugin.emit("trem.rts.pga-low");
- // }
- // }
- // if (!list.length) {
- // document.getElementById("eew_title_text").textContent = (max_intensity >= 4) ? get_lang_string("detection.high") : (max_intensity >= 2) ? get_lang_string("detection.middle") : get_lang_string("detection.low");
- // document.getElementById("eew_box").style.backgroundColor = (max_intensity >= 4) ? "#E80002" : (max_intensity >= 2) ? "#C79A00" : "#149A4C";
- // let _text_1 = "";
- // let _text_2 = "";
- // let count = 0;
- // for (let i = 0; i < detection_location.length; i++) {
- // const loc = detection_location[i];
- // if (count < 4) {
- // _text_1 += `${loc}
`;
- // } else {
- // _text_2 += `${loc}
`;
- // }
- // count++;
- // }
- // detection_location_1.innerHTML = _text_1;
- // detection_location_2.innerHTML = _text_2;
- // detection_location_1.className = "detection_location_text";
- // detection_location_2.className = "detection_location_text";
- // } else {
- // clear_eew_box(detection_location_1, detection_location_2);
- // }
- // } else {
- // rts_tts = false;
- // _max_intensity = 0;
- // pga_up_level = {};
- // pga_up_timestamp = {};
- // rts_show = false;
- // TREM.rts_audio.intensity = -1;
- // TREM.rts_audio.pga = 0;
- // if (!list.length) {
- // document.getElementById("eew_title_text").textContent = get_lang_string("eew.null");
- // }
- // max_intensity_text.textContent = "";
- // max_intensity_text.className = "";
- // if (!list.length) {
- // document.getElementById("eew_box").style.backgroundColor = "#333439";
- // clear_eew_box(detection_location_1, detection_location_2);
- // }
- // }
- // if (max_intensity > 0 && data.Alert) {
- // max_intensity_text.textContent = int_to_intensity(max_intensity);
- // max_intensity_text.className = `intensity_center intensity_${max_intensity}`;
- // }
- // max_pga_text.textContent = `${max_pga} gal`;
- // max_pga_text.className = `intensity_center intensity_${(!data.Alert || max_pga < 4) ? 0 : (max_pga < 5) ? 1 : pga_to_intensity(max_pga)}`;
- // const intensity_list = document.getElementById("intensity_list");
- // if (data.I) {
- // i_list.data = data.I;
- // i_list.time = 0;
- // } else if (!i_list.time) {
- // i_list.time = _now;
- // }
- // if (i_list.time && _now - i_list.time > 60000) {
- // if (!list.length) {
- // i_list.data = [];
- // }
- // i_list.time = 0;
- // }
- // if (i_list.data.length) {
- // intensity_list.innerHTML = "";
- // intensity_list.style.visibility = "visible";
- // if (i_list.data.length > 8) {
- // const city_I = {};
- // for (let i = 0; i < i_list.data.length; i++) {
- // let loc = "";
- // for (const uuid of Object.keys(station)) {
- // if (i_list.data[i].uuid.includes(uuid)) {
- // loc = station[uuid].Loc;
- // break;
- // }
- // }
- // if (loc == "") {
- // continue;
- // }
- // const _loc = loc.split(" ")[0];
- // if ((city_I[_loc] ?? -1) < i_list.data[i].intensity) {
- // city_I[_loc] = i_list.data[i].intensity;
- // }
- // }
- // const cities = Object.keys(city_I);
- // const maxItems = Math.min(8, cities.length);
+ if (!data.Alert) {
+ level_list = {};
+ }
+ document.getElementById("rts_location").textContent = rts_sation_loc;
+ document.getElementById("rts_pga").textContent = `${get_lang_string("word.pga")} ${rts_sation_pga}`;
+ document.getElementById("rts_intensity").textContent = `${get_lang_string("word.intensity")} ${rts_sation_intensity}`;
+ const rts_intensity_level = document.getElementById("rts_intensity_level");
+ rts_intensity_level.textContent = int_to_intensity(rts_sation_intensity_number);
+ rts_intensity_level.className = `intensity_center intensity_${rts_sation_intensity_number}`;
+ const max_pga_text = document.getElementById("max_pga");
+ const max_intensity_text = document.getElementById("max_intensity");
+ const detection_location_1 = document.getElementById("detection_location_1");
+ const detection_location_2 = document.getElementById("detection_location_2");
+ let skip = false;
+ if (max_intensity < item_rts_level) {
+ skip = true;
+ }
+ if (data.eew) {
+ if (!eew_alert_state) {
+ eew_alert_state = true;
+ TREM.audio.push("Warn");
+ add_info("fa-solid fa-bell fa-2x info_icon", "#FF0080", "地震檢測", "#00EC00", "請留意 中央氣象署
是否發布 地震預警", 15000);
+ if (alert_timestamp && now_time() - alert_timestamp < 300_000) {
+ add_info("fa-solid fa-triangle-exclamation fa-2x info_icon", "yellow", "不穩定", "#E800E8", "受到地震的影響
即時測站可能不穩定");
+ }
+ alert_timestamp = now_time();
+ }
+ } else {
+ eew_alert_state = false;
+ }
+ if (data.Alert) {
+ if (TREM.report_time) {
+ report_off();
+ }
+ if (!skip && !rts_show) {
+ rts_show = true;
+ show_screen("rts");
+ }
+ if (max_intensity > TREM.rts_audio.intensity && TREM.rts_audio.intensity != 10) {
+ const loc = detection_location[0] ?? "未知區域";
+ if (max_intensity > 3) {
+ TREM.rts_audio.intensity = 10;
+ if (!skip && item_audio_shindo2) {
+ TREM.audio.push("Shindo2");
+ }
+ const notification = new Notification("🟥 強震檢測", {
+ body : `${loc}`,
+ icon : "../TREM.ico",
+ });
+ notification.addEventListener("click", () => {
+ MainWindow.focus();
+ });
+ rts_screenshot();
+ plugin.emit("trem.rts.detection-strong");
+ } else if (max_intensity > 1) {
+ TREM.rts_audio.intensity = 3;
+ if (!skip && item_audio_shindo1) {
+ TREM.audio.push("Shindo1");
+ }
+ const notification = new Notification("🟨 震動檢測", {
+ body : `${loc}`,
+ icon : "../TREM.ico",
+ });
+ notification.addEventListener("click", () => {
+ MainWindow.focus();
+ });
+ rts_screenshot();
+ plugin.emit("trem.rts.detection-shake");
+ } else {
+ TREM.rts_audio.intensity = 1;
+ if (!skip && item_audio_shindo0) {
+ TREM.audio.push("Shindo0");
+ }
+ const notification = new Notification("🟩 弱反應", {
+ body : `${loc}`,
+ icon : "../TREM.ico",
+ });
+ notification.addEventListener("click", () => {
+ MainWindow.focus();
+ });
+ rts_screenshot();
+ plugin.emit("trem.rts.detection-weak");
+ }
+ if (!rts_tts) {
+ rts_tts = true;
+ if (speecd_use) {
+ speech.speak({ text: `${loc},偵測到晃動` });
+ }
+ }
+ }
+ if (max_pga > TREM.rts_audio.pga && TREM.rts_audio.pga <= 200) {
+ if (max_pga > 200) {
+ TREM.rts_audio.pga = 250;
+ if (!skip && item_audio_pga2) {
+ TREM.audio.push("PGA2");
+ }
+ rts_screenshot();
+ plugin.emit("trem-rts.pga-high");
+ } else if (max_pga > 8) {
+ TREM.rts_audio.pga = 200;
+ if (!skip && item_audio_pga1) {
+ TREM.audio.push("PGA1");
+ }
+ rts_screenshot();
+ plugin.emit("trem.rts.pga-low");
+ }
+ }
+ if (!list.length) {
+ document.getElementById("eew_title_text").textContent = (max_intensity >= 4) ? get_lang_string("detection.high") : (max_intensity >= 2) ? get_lang_string("detection.middle") : get_lang_string("detection.low");
+ document.getElementById("eew_box").style.backgroundColor = (max_intensity >= 4) ? "#E80002" : (max_intensity >= 2) ? "#C79A00" : "#149A4C";
+ let _text_1 = "";
+ let _text_2 = "";
+ let count = 0;
+ for (let i = 0; i < detection_location.length; i++) {
+ const loc = detection_location[i];
+ if (count < 4) {
+ _text_1 += `${loc}
`;
+ } else {
+ _text_2 += `${loc}
`;
+ }
+ count++;
+ }
+ detection_location_1.innerHTML = _text_1;
+ detection_location_2.innerHTML = _text_2;
+ detection_location_1.className = "detection_location_text";
+ detection_location_2.className = "detection_location_text";
+ } else {
+ clear_eew_box(detection_location_1, detection_location_2);
+ }
+ } else {
+ rts_tts = false;
+ _max_intensity = 0;
+ pga_up_level = {};
+ pga_up_timestamp = {};
+ rts_show = false;
+ TREM.rts_audio.intensity = -1;
+ TREM.rts_audio.pga = 0;
+ if (!list.length) {
+ document.getElementById("eew_title_text").textContent = get_lang_string("eew.null");
+ }
+ max_intensity_text.textContent = "";
+ max_intensity_text.className = "";
+ if (!list.length) {
+ document.getElementById("eew_box").style.backgroundColor = "#333439";
+ clear_eew_box(detection_location_1, detection_location_2);
+ }
+ }
+ if (max_intensity > 0 && data.Alert) {
+ max_intensity_text.textContent = int_to_intensity(max_intensity);
+ max_intensity_text.className = `intensity_center intensity_${max_intensity}`;
+ }
+ max_pga_text.textContent = `${max_pga} gal`;
+ max_pga_text.className = `intensity_center intensity_${(!data.Alert || max_pga < 4) ? 0 : (max_pga < 5) ? 1 : pga_to_intensity(max_pga)}`;
+ /*const intensity_list = document.getElementById("intensity_list");
+ if (data.I) {
+ i_list.data = data.I;
+ i_list.time = 0;
+ } else if (!i_list.time) {
+ i_list.time = _now;
+ }
+ if (i_list.time && _now - i_list.time > 60000) {
+ if (!list.length) {
+ i_list.data = [];
+ }
+ i_list.time = 0;
+ }
+ if (i_list.data.length) {
+ intensity_list.innerHTML = "";
+ intensity_list.style.visibility = "visible";
+ if (i_list.data.length > 8) {
+ const city_I = {};
+ for (let i = 0; i < i_list.data.length; i++) {
+ let loc = "";
+ for (const station_id of Object.keys(station)) {
+ if (i_list.data[i].uuid.includes(station_id)) {
+ loc = station[station_id].Loc;
+ break;
+ }
+ }
+ if (loc == "") {
+ continue;
+ }
+ const _loc = loc.split(" ")[0];
+ if ((city_I[_loc] ?? -1) < i_list.data[i].intensity) {
+ city_I[_loc] = i_list.data[i].intensity;
+ }
+ }
+ const cities = Object.keys(city_I);
+ const maxItems = Math.min(8, cities.length);
- // for (let i = 0; i < maxItems; i++) {
- // const city = cities[i];
- // const intensity = int_to_intensity(city_I[city]);
- // const intensity_list_item = document.createElement("intensity_list_item");
- // intensity_list_item.className = "intensity_list_item";
- // intensity_list_item.innerHTML = `${intensity}
${city}
`;
- // intensity_list.appendChild(intensity_list_item);
- // }
- // } else {
- // for (let i = 0; i < i_list.data.length; i++) {
- // if (i > 7) {
- // break;
- // }
- // const intensity_list_item = document.createElement("intensity_list_item");
- // intensity_list_item.className = "intensity_list_item";
- // let loc = "";
- // for (const uuid of Object.keys(station)) {
- // if (i_list.data[i].uuid.includes(uuid)) {
- // loc = station[uuid].Loc;
- // break;
- // }
- // }
- // if (loc == "") {
- // continue;
- // }
- // intensity_list_item.innerHTML = `${int_to_intensity(i_list.data[i].intensity)}
${loc}
`;
- // intensity_list.appendChild(intensity_list_item);
- // }
- // }
- // } else {
- // intensity_list.style.visibility = "hidden";
- // }
- // if (list.length || data.Alert) {
- // show_icon(true);
- // } else if (!TREM.report_time) {
- // show_icon(false);
- // }
- // let level = 0;
- // for (const uuid of Object.keys(level_list)) {
- // level += level_list[uuid];
- // }
+ for (let i = 0; i < maxItems; i++) {
+ const city = cities[i];
+ const intensity = int_to_intensity(city_I[city]);
+ const intensity_list_item = document.createElement("intensity_list_item");
+ intensity_list_item.className = "intensity_list_item";
+ intensity_list_item.innerHTML = `${intensity}
${city}
`;
+ intensity_list.appendChild(intensity_list_item);
+ }
+ } else {
+ for (let i = 0; i < i_list.data.length; i++) {
+ if (i > 7) {
+ break;
+ }
+ const intensity_list_item = document.createElement("intensity_list_item");
+ intensity_list_item.className = "intensity_list_item";
+ let loc = "";
+ for (const station_id of Object.keys(station)) {
+ if (i_list.data[i].uuid.includes(station_id)) {
+ loc = station[station_id].Loc;
+ break;
+ }
+ }
+ if (loc == "") {
+ continue;
+ }
+ intensity_list_item.innerHTML = `${int_to_intensity(i_list.data[i].intensity)}
${loc}
`;
+ intensity_list.appendChild(intensity_list_item);
+ }
+ }
+ } else {
+ intensity_list.style.visibility = "hidden";
+ }*/
+ if (list.length || data.Alert) {
+ show_icon(true);
+ } else if (!TREM.report_time) {
+ show_icon(false);
+ }
+ let level = 0;
+ for (const station_id of Object.keys(level_list)) {
+ level += level_list[station_id];
+ }
// document.getElementById("intensity_level_num").textContent = Math.round(level);
// document.getElementById("intensity_level_station").textContent = target_count;
- // if (!rts_replay_timestamp) {
- // if (data.investigate != undefined) {
- // if (data.investigate > palert_level) {
- // if (item_audio_palert) {
- // TREM.audio.push("palert");
- // }
- // palert_level = data.investigate;
- // refresh_report_list(false, {
- // type : "palert",
- // time : _now,
- // i : palert_level,
- // });
- // show_screen("palert");
- // screenshot_id = `palert_${now_time()}`;
- // plugin.emit("trem.palert.on-palert", data);
- // }
- // palert_time = _now;
- // } else {
- // palert_level = -1;
- // if (palert_time && _now - palert_time > 600000) {
- // palert_time = 0;
- // refresh_report_list();
- // }
- // }
- // }
+ if (!rts_replay_timestamp) {
+ if (data.investigate != undefined) {
+ if (data.investigate > palert_level) {
+ if (item_audio_palert) {
+ TREM.audio.push("palert");
+ }
+ palert_level = data.investigate;
+ refresh_report_list(false, {
+ type : "palert",
+ time : _now,
+ i : palert_level,
+ });
+ show_screen("palert");
+ screenshot_id = `palert_${now_time()}`;
+ plugin.emit("trem.palert.on-palert", data);
+ }
+ palert_time = _now;
+ } else {
+ palert_level = -1;
+ if (palert_time && _now - palert_time > 600000) {
+ palert_time = 0;
+ refresh_report_list();
+ }
+ }
+ }
}
function clear_eew_box(detection_location_1, detection_location_2) {
diff --git a/src/core/index/server.js b/src/core/index/server.js
index 4f84c968..186cf3f1 100644
--- a/src/core/index/server.js
+++ b/src/core/index/server.js
@@ -1,12 +1,5 @@
/* eslint-disable no-undef */
-const {
- NOTIFICATION_RECEIVED,
- NOTIFICATION_SERVICE_STARTED,
- START_NOTIFICATION_SERVICE,
-} = require("electron-fcm-push-receiver/src/constants");
-
let WS = false;
-let FCM = false;
let ws;
let ServerT = 0;
let Reconnect = 0;
@@ -15,9 +8,11 @@ let init_ = false;
let sleep_state = false;
let time_ntp = 0;
let time_local = 0;
-let last_get_data_time = Date.now();
+let last_get_eew_time = Date.now();
+let last_get_rts_time = Date.now();
-let rts_clock = null;
+const api_domain = "api-" + Math.ceil(Math.random() * 2) + ".exptech.com.tw";
+const lb_domain = "lb-" + Math.ceil(Math.random() * 4) + ".exptech.com.tw";
function _server_init() {
if (init_) {
@@ -28,7 +23,11 @@ function _server_init() {
}
function close() {
- ws.close();
+ if (ws && ws.readyState == 1){
+ ws.close();
+ }
+ ws = null;
+ WS = false;
}
function reconnect() {
@@ -44,18 +43,20 @@ function reconnect() {
}
function createWebSocket() {
- try {
- ws = new WebSocket("wss://exptech.com.tw/api");
- initEventHandle();
- } catch (e) {
- reconnect();
+ if(storage.getItem("key")){
+ try {
+ ws = new WebSocket(`wss://${lb_domain}/websocket`);
+ initEventHandle();
+ } catch (e) {
+ reconnect();
+ }
+ } else {
+ WS = false;
+ log("Using http fetch", 1, "log", "~");
}
}
function sleep(_state = null) {
- if (!WS) {
- return;
- }
if (_state != null) {
if (_state == sleep_state) {
return;
@@ -68,20 +69,24 @@ function sleep(_state = null) {
plugin.emit("trem.core.awake");
}
}
+ if (!WS) {
+ return;
+ }
if (!_state) {
last_get_data_time = Date.now();
}
- ws.send(JSON.stringify({
+ /*ws.send(JSON.stringify({
uuid : localStorage.UUID,
function : "subscriptionService",
value : ["trem-rts-v2", "trem-eew-v1", "report-trem-v1", "eew-v1", "report-v1"],
key : storage.getItem("key") ?? "",
addition : { "trem-rts-v2": { sleep: (_state == null) ? sleep_state : _state } },
- }));
+ }));*/
}
function initEventHandle() {
ws.onclose = () => {
+ if (storage.getItem("key")) add_info("fa-solid fa-satellite-dish fa-2x info_icon", "#FF0000", "連線錯誤", "#00BB00", "WebSocket 已斷線
正在使用 HTTP 連線", 5000);
void 0;
};
ws.onerror = () => {
@@ -89,45 +94,44 @@ function initEventHandle() {
};
ws.onopen = () => {
const config = {
- uuid : localStorage.UUID,
- function : "subscriptionService",
- value : ["trem-rts-v2", "trem-eew-v1", "report-trem-v1", "eew-v1", "report-v1"],
- key : storage.getItem("key") ?? "",
- addition : { "trem-rts-v2": { sleep: !win.isVisible() } },
+ type : "start",
+ service : ["trem.rts", "trem.eew", "websocket.eew", "websocket.report"],
+ key : storage.getItem("key") ?? "",
};
ws.send(JSON.stringify(config));
- sleep_state = config.addition["trem-rts-v2"].sleep;
plugin.emit("trem.core.websocket-connect");
- if (!FCM) {
- ipcRenderer.send(START_NOTIFICATION_SERVICE, "583094702393");
- }
};
ws.onmessage = (evt) => {
- if (!WS) {
+ if(!rts_replay_time) {
time.style.color = "white";
}
WS = true;
ServerT = now_time();
const json = JSON.parse(evt.data);
- if (json.response == "Subscription Succeeded" && json.type == undefined) {
- if (rts_clock) {
- clearInterval(rts_clock);
- rts_clock = null;
- }
- if (!json.list.includes("trem-rts-v2")) {
- log("rts clock start", 1, "server", "rts-clock");
- rts_clock = setInterval(async () => {
- try {
- const ans = await fetchDataWithRetry("https://data.exptech.com.tw/api/v1/trem/rts");
- get_data({
- type : "trem-rts",
- raw : ans,
- });
- } catch (err) {
- log(err, 3, "server", "rts-clock");
- }
- }, 1000);
- }
+ if (json.type == "info" && json.data.code != 200) {
+ add_info("fa-solid fa-satellite-dish fa-2x info_icon", "#FF0000", "連線錯誤", "#00BB00", "無法註冊 WebSocket 服務
請檢查 apiKey 是否正確", 5000);
+ log(`Websocket reg NG: ${json.data.message}`, 3, "log", "~");
+ close();
+ return;
+ }
+ // if (json.type != "data" && json.type != "ntp") {
+ // console.log(json)
+ // }
+ if (json.type == "verify") {
+ const config = {
+ type : "start",
+ service : ["trem.rts", "trem.eew", "websocket.eew", "websocket.report"],
+ key : storage.getItem("key") ?? "",
+ };
+ ws.send(JSON.stringify(config));
+ } else if (json.type == "info" && json.data.code == 200) {
+ add_info("fa-solid fa-network-wired fa-2x info_icon", "#00AA00", "連線成功", "#00BB00", "已連線並註冊 WebSocket 伺服器", 5000);
+ log("Websocket reg OK", 1, "log", "~");
+ } else if (json.type == "data" && json.data.type == "rts") {
+ get_data({
+ type : "trem-rts",
+ raw : json.data.data,
+ });
} else if (json.type == "ntp") {
time_ntp = json.time;
time_local = Date.now();
@@ -164,14 +168,16 @@ function Now() {
}
setInterval(() => {
- if (now_time() - ServerT > 15_000) {
+ if(!WS) return;
+ if (now_time() - ServerT > 120_000) {
plugin.emit("trem.core.websocket-disconnect");
WS = false;
time.style.color = "red";
+ log("Websocket long time no got msg, timeout", 1, "log", "~");
reconnect();
if (now_time() - disconnect_info > 60_000) {
disconnect_info = now_time();
- add_info("fa-solid fa-satellite-dish fa-2x info_icon", "#FF0000", "網路異常", "#00BB00", "客戶端無法與伺服器建立連線
請檢查網路狀態或稍後重試", 30000);
+ add_info("fa-solid fa-satellite-dish fa-2x info_icon", "#FF0000", "網路異常", "#00BB00", "WebSocket 伺服器沒有回應
請檢查網路狀態或稍後重試", 5000);
}
}
}, 3000);
@@ -214,16 +220,4 @@ function _speed(depth, distance) {
Stime = distance / 4;
}
return { Ptime: Ptime, Stime: Stime };
-}
-
-ipcRenderer.on(NOTIFICATION_SERVICE_STARTED, (_, token) => {
- FCM = true;
- localStorage.UUID = token;
-});
-
-ipcRenderer.on(NOTIFICATION_RECEIVED, (_, Notification) => {
- FCM = true;
- if (Notification.data.Data != undefined) {
- get_data(JSON.parse(Notification.data.Data), "fcm");
- }
-});
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/core/setting/init.js b/src/core/setting/init.js
index e73b0951..ecd58921 100644
--- a/src/core/setting/init.js
+++ b/src/core/setting/init.js
@@ -23,10 +23,10 @@ for (const btn of document.querySelectorAll("button.nav")) {
}
-document.getElementById("jma").checked = storage.getItem("jma") ?? true;
-document.getElementById("nied").checked = storage.getItem("nied") ?? true;
-document.getElementById("kma").checked = storage.getItem("kma") ?? true;
-document.getElementById("scdzj").checked = storage.getItem("scdzj") ?? true;
+// document.getElementById("jma").checked = storage.getItem("jma") ?? true;
+// document.getElementById("nied").checked = storage.getItem("nied") ?? true;
+// document.getElementById("kma").checked = storage.getItem("kma") ?? true;
+// document.getElementById("scdzj").checked = storage.getItem("scdzj") ?? true;
document.getElementById("show_eew").checked = storage.getItem("show_eew") ?? true;
document.getElementById("show_report").checked = storage.getItem("show_report") ?? true;
diff --git a/src/core/setting/setting.js b/src/core/setting/setting.js
index 678eec9d..83375762 100644
--- a/src/core/setting/setting.js
+++ b/src/core/setting/setting.js
@@ -4,8 +4,12 @@ const town = document.getElementById("town");
const input_lat = document.getElementById("lat");
const input_lon = document.getElementById("lon");
const site = document.getElementById("site");
-const key = document.getElementById("key");
const rts_station = document.getElementById("rts_station");
+const user_email = document.getElementById("email");
+const user_pass = document.getElementById("password");
+const login_btn = document.getElementById("login");
+const logout_btn = document.getElementById("logout");
+const register_btn = document.getElementById("register");
let rts_list_data = {};
@@ -26,10 +30,10 @@ function fetch_rts_station() {
setTimeout(() => {
controller.abort();
}, 1500);
- fetch("https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/Json/earthquake/station.json", { signal: controller.signal })
+ fetch("https://cdn.jsdelivr.net/gh/ExpTechTW/API@master/resource/station.json", { signal: controller.signal })
.then((ans) => ans.json())
.then((ans) => {
- rts_list_data = ans;
+ rts_list_data = station_v1(ans);
rts_list();
})
.catch((err) => {
@@ -37,6 +41,53 @@ function fetch_rts_station() {
setTimeout(() => fetch_rts_station(), 3000);
});
}
+function station_v1(station_data) {
+ let stations = {};
+ for (let k = 0, k_ks = Object.keys(station_data), n = k_ks.length; k < n; k++) {
+ const station_id = k_ks[k];
+ const station_ = station_data[station_id];
+ const station_net = station_.net === "MS-Net" ? "H" : "L";
+
+ let station_new_id = "";
+ let station_code = "000";
+ let Loc = "";
+ let area = "";
+ let Lat = 0;
+ let Long = 0;
+
+ let latest = station_.info[0];
+
+ if (station_.info.length > 1)
+ for (let i = 1; i < station_.info.length; i++) {
+ const currentTime = new Date(station_.info[i].time);
+ const latestTime = new Date(latest.time);
+
+ if (currentTime > latestTime)
+ latest = station_.info[i];
+ }
+
+ for (let i = 0, ks = Object.keys(region), j = ks.length; i < j; i++) {
+ const reg_id = ks[i];
+ const reg = region[reg_id];
+
+ for (let r = 0, r_ks = Object.keys(reg), l = r_ks.length; r < l; r++) {
+ const ion_id = r_ks[r];
+ const ion = reg[ion_id];
+
+ if (ion.code === latest.code) {
+ station_code = latest.code.toString();
+ Loc = `${reg_id} ${ion_id}`;
+ area = ion.area;
+ Lat = latest.lat;
+ Long = latest.lon;
+ }
+ }
+ }
+ station_new_id = `${station_net}-${station_code}-${station_id}`;
+ stations[station_new_id] = { uuid: station_new_id, Lat, Long, Loc, area };
+ }
+ return stations;
+}
function rts_list() {
const locations = {};
@@ -56,7 +107,7 @@ function rts_list() {
const o = document.createElement("option");
o.value = uuid;
o.textContent = `${uuid} ${c} ${t}`;
- if (uuid == (storage.getItem("rts_station") ?? "H-711-11334880-12")) {
+ if (uuid == (storage.getItem("rts_station") ?? "H-711-11334880")) {
o.selected = true;
}
g.appendChild(o);
@@ -132,6 +183,64 @@ const updateTownSelect = () => {
updateSiteField();
};
+login_display();
+function login_display(){
+ user_email.disabled = storage.getItem("key") ? true : false;
+ user_pass.disabled = storage.getItem("key") ? true : false;
+
+ login_btn.style.display = storage.getItem("key") ? "none" : "";
+ logout_btn.style.display = storage.getItem("key") ? "" : "none";
+ register_btn.style.display = storage.getItem("key") ? "none" : "";
+}
+
+async function login() {
+ try {
+ const client_name = localStorage.UUID.substr(0, 4);
+ const client_ver = app.getVersion();
+ const email = user_email.value;
+ const pass = user_pass.value;
+ const resp = await fetch("https://api.exptech.com.tw/api/v3/et/login", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ email: email, pass: pass, name: `TREM-Lite Client [${client_name}]/TREM-Lite/${client_ver}/0.0.0` }),
+ });
+ const ans = await resp.text();
+ if (!resp.ok){
+ alert(ans);
+ throw new Error(`${resp.status} ${ans}`);
+ return false;
+ }
+ storage.setItem("key", ans);
+ storage.setItem("reset", true);
+ login_display();
+ return true;
+ } catch (err) {
+ log(`Login failed: ${err}`, 3, "setting", "logout");
+ }
+}
+
+async function logout() {
+ try {
+ const api_key = storage.getItem("key");
+ const resp = await fetch(`https://api.exptech.com.tw/api/v3/et/logout`, {
+ method: "DELETE",
+ headers: { Authorization: `Basic ${api_key}` },
+ });
+ const ans = await resp.text();
+ if (!resp.ok){
+ alert(ans);
+ throw new Error(`${resp.status} ${ans}`);
+ return false;
+ }
+ storage.setItem("key", "");
+ storage.setItem("reset", true);
+ login_display();
+ return true;
+ } catch (err) {
+ log(`Logout failed: ${err}`, 3, "setting", "logout");
+ }
+}
+
// init
for (const _city in region) {
const o = document.createElement("option");
@@ -206,12 +315,6 @@ site.onchange = () => {
storage.setItem("site", site.value);
};
-key.value = storage.getItem("key") ?? "";
-key.onchange = () => {
- storage.setItem("key", key.value);
- storage.setItem("reset", true);
-};
-
function _onclick(id) {
const state = document.getElementById(id).checked;
storage.setItem(id, state);
diff --git a/src/css/main.css b/src/css/main.css
index 3eb1c3fc..f48b0f0b 100644
--- a/src/css/main.css
+++ b/src/css/main.css
@@ -282,7 +282,7 @@ body {
.version_text {
position: absolute;
bottom: 0px;
- right: 395px;
+ right: 432px;
color: white;
font-size: 12px;
}
@@ -437,13 +437,26 @@ body {
}
.location_button {
+ position: absolute;
+ bottom: 7.2px;
+ right: 392px;
+ margin: 2px;
+ padding: 5px;
+ border-radius: 5px;
+ color: white;
+ cursor: pointer;
+ z-index: 9999;
+}
+
+.refresh_button {
position: absolute;
bottom: 7.2px;
right: 355px;
margin: 2px;
padding: 5px;
+ border: 1px solid white;
border-radius: 5px;
- color: grey;
+ color: white;
cursor: pointer;
z-index: 9999;
}
diff --git a/src/css/setting.css b/src/css/setting.css
index 8197ed41..7c8ee87c 100644
--- a/src/css/setting.css
+++ b/src/css/setting.css
@@ -385,7 +385,7 @@ button[type="checkbox"] {
margin: 4px;
padding: 4px 8px;
border-radius: 4px;
- color: var(--md-on-surface-variant);
+ color: var(--md-on-primary);
background-color: hsl(0deg 0% 20%);
outline: 1px solid transparent;
font-family: var(--font);
diff --git a/src/main.js b/src/main.js
index 737e52e7..051d90fa 100644
--- a/src/main.js
+++ b/src/main.js
@@ -40,6 +40,7 @@ function createWindow() {
process.env.window = MainWindow.id;
require("@electron/remote/main").initialize();
require("@electron/remote/main").enable(MainWindow.webContents);
+ // MainWindow.webContents.openDevTools();
MainWindow.loadFile("./view/index.html");
MainWindow.setMenu(null);
MainWindow.webContents.on("did-finish-load", () => {
@@ -135,6 +136,7 @@ function createSettingWindow() {
SettingWindow.on("close", () => {
SettingWindow = null;
if (MainWindow) {
+ MainWindow.webContents.executeJavaScript("close()");
MainWindow.webContents.reload();
}
});
@@ -186,6 +188,9 @@ function trayIcon() {
}
function restart() {
+ if (MainWindow) {
+ MainWindow.webContents.executeJavaScript("close()");
+ }
TREM.relaunch();
TREM.isQuiting = true;
TREM.quit();
@@ -225,6 +230,9 @@ ipcMain.on("hide", () => {
TREM.on("before-quit", () => {
TREM.isQuiting = true;
+ if (MainWindow) {
+ MainWindow.webContents.executeJavaScript("close()");
+ }
if (tray) {
tray.destroy();
}
diff --git a/src/package.json b/src/package.json
index 35e79a4d..4d23a518 100644
--- a/src/package.json
+++ b/src/package.json
@@ -1,6 +1,6 @@
{
"name": "trem_lite",
- "version": "1.10.11",
+ "version": "2.0.0",
"description": "Taiwan Real-time Earthquake Monitoring ( 臺灣即時地震監測 )",
"homepage": "https://exptech.com.tw/",
"main": "main.js",
diff --git a/src/resource/data/detection.json b/src/resource/data/detection.json
index 47f3d620..180d7c9f 100644
--- a/src/resource/data/detection.json
+++ b/src/resource/data/detection.json
@@ -1 +1 @@
-{"1":[[24.94,120.95],[24.94,121.5],[25.44,121.5],[25.44,120.95]],"2":[[24.94,121.5],[24.94,122.05],[25.44,122.05],[25.44,121.5]],"3":[[24.44,120.4],[24.44,120.95],[24.94,120.95],[24.94,120.4]],"4":[[24.44,120.95],[24.44,121.5],[24.94,121.5],[24.94,120.95]],"5":[[24.44,121.5],[24.44,122.05],[24.94,122.05],[24.94,121.5]],"6":[[23.94,120.2],[23.94,120.75],[24.44,120.75],[24.44,120.2]],"7":[[23.94,120.75],[23.94,121.3],[24.44,121.3],[24.44,120.75]],"8":[[23.94,121.3],[23.94,121.85],[24.44,121.85],[24.44,121.3]],"9":[[23.44,120.1],[23.44,120.65],[23.94,120.65],[23.94,120.1]],"10":[[23.44,120.65],[23.44,121.2],[23.94,121.2],[23.94,120.65]],"11":[[23.44,121.2],[23.44,121.75],[23.94,121.75],[23.94,121.2]],"12":[[22.94,120],[22.94,120.55],[23.44,120.55],[23.44,120]],"13":[[22.94,120.55],[22.94,121.1],[23.44,121.1],[23.44,120.55]],"14":[[22.94,121.1],[22.94,121.65],[23.44,121.65],[23.44,121.1]],"15":[[22.44,120.2],[22.44,120.75],[22.94,120.75],[22.94,120.2]],"16":[[22.44,120.75],[22.44,121.3],[22.94,121.3],[22.94,120.75]],"17":[[21.94,120.5],[21.94,121.05],[22.44,121.05],[22.44,120.5]],"18":[[23.44,119.3],[23.44,119.85],[23.94,119.85],[23.94,119.3]]}
\ No newline at end of file
+{"0":[[25.1,121.38],[25.46,121.38],[25.46,120.89],[25.1,120.89]],"1":[[25.1,121.86],[25.46,121.86],[25.46,121.38],[25.1,121.38]],"2":[[25.1,122.35],[25.46,122.35],[25.46,121.86],[25.1,121.86]],"3":[[24.74,121.38],[25.1,121.38],[25.1,120.89],[24.74,120.89]],"4":[[24.74,121.86],[25.1,121.86],[25.1,121.38],[24.74,121.38]],"5":[[24.74,122.35],[25.1,122.35],[25.1,121.86],[24.74,121.86]],"6":[[24.38,120.89],[24.74,120.89],[24.74,120.4],[24.38,120.4]],"7":[[24.38,121.38],[24.74,121.38],[24.74,120.89],[24.38,120.89]],"8":[[24.38,121.86],[24.74,121.86],[24.74,121.38],[24.38,121.38]],"9":[[24.38,122.35],[24.74,122.35],[24.74,121.86],[24.38,121.86]],"10":[[24.02,120.4],[24.38,120.4],[24.38,119.92],[24.02,119.92]],"11":[[24.02,120.89],[24.38,120.89],[24.38,120.4],[24.02,120.4]],"12":[[24.02,121.38],[24.38,121.38],[24.38,120.89],[24.02,120.89]],"13":[[24.02,121.86],[24.38,121.86],[24.38,121.38],[24.02,121.38]],"14":[[23.66,119.92],[24.02,119.92],[24.02,119.43],[23.66,119.43]],"15":[[23.66,120.4],[24.02,120.4],[24.02,119.92],[23.66,119.92]],"16":[[23.66,120.89],[24.02,120.89],[24.02,120.4],[23.66,120.4]],"17":[[23.66,121.38],[24.02,121.38],[24.02,120.89],[23.66,120.89]],"18":[[23.66,121.86],[24.02,121.86],[24.02,121.38],[23.66,121.38]],"19":[[23.3,119.43],[23.66,119.43],[23.66,118.95],[23.3,118.95]],"20":[[23.3,119.92],[23.66,119.92],[23.66,119.43],[23.3,119.43]],"21":[[23.3,120.4],[23.66,120.4],[23.66,119.92],[23.3,119.92]],"22":[[23.3,120.89],[23.66,120.89],[23.66,120.4],[23.3,120.4]],"23":[[23.3,121.38],[23.66,121.38],[23.66,120.89],[23.3,120.89]],"24":[[23.3,121.86],[23.66,121.86],[23.66,121.38],[23.3,121.38]],"25":[[22.94,119.43],[23.3,119.43],[23.3,118.95],[22.94,118.95]],"26":[[22.94,119.92],[23.3,119.92],[23.3,119.43],[22.94,119.43]],"27":[[22.94,120.4],[23.3,120.4],[23.3,119.92],[22.94,119.92]],"28":[[22.94,120.89],[23.3,120.89],[23.3,120.4],[22.94,120.4]],"29":[[22.94,121.38],[23.3,121.38],[23.3,120.89],[22.94,120.89]],"30":[[22.94,121.86],[23.3,121.86],[23.3,121.38],[22.94,121.38]],"31":[[22.58,120.4],[22.94,120.4],[22.94,119.92],[22.58,119.92]],"32":[[22.58,120.89],[22.94,120.89],[22.94,120.4],[22.58,120.4]],"33":[[22.58,121.38],[22.94,121.38],[22.94,120.89],[22.58,120.89]],"34":[[22.58,121.86],[22.94,121.86],[22.94,121.38],[22.58,121.38]],"35":[[22.22,120.4],[22.58,120.4],[22.58,119.92],[22.22,119.92]],"36":[[22.22,120.89],[22.58,120.89],[22.58,120.4],[22.22,120.4]],"37":[[22.22,121.38],[22.58,121.38],[22.58,120.89],[22.22,120.89]],"38":[[21.86,120.89],[22.22,120.89],[22.22,120.4],[21.86,120.4]],"39":[[21.86,121.38],[22.22,121.38],[22.22,120.89],[21.86,120.89]],"40":[[21.86,121.86],[22.22,121.86],[22.22,121.38],[21.86,121.38]],"41":[[24.38,118.46],[24.74,118.46],[24.74,117.97],[24.38,117.97]],"42":[[24.38,118.95],[24.74,118.95],[24.74,118.46],[24.38,118.46]],"7735548":[[37.41,127.02],[37.41,127.57],[37.91,127.57],[37.91,127.02]],"13379360":[[29.54,106.1],[29.54,106.65],[30.14,106.65],[30.14,106.1]]}
\ No newline at end of file
diff --git a/src/resource/data/region.json b/src/resource/data/region.json
index 8057d0fc..4edc1673 100644
--- a/src/resource/data/region.json
+++ b/src/resource/data/region.json
@@ -1 +1 @@
-{"基隆市":{"中正區":{"code":1,"lat":25.1407924,"lon":121.7592534,"site":1.077,"site_s":1.3466,"site_d":2.3124},"七堵區":{"code":2,"lat":25.097653,"lon":121.7165013,"site":1.866,"site_s":1.346,"site_d":2.3113},"暖暖區":{"code":3,"lat":25.1001834,"lon":121.735933,"site":1.718,"site_s":1.3462,"site_d":2.3116},"仁愛區":{"code":4,"lat":25.125069,"lon":121.736754,"site":1.348,"site_s":1.3468,"site_d":2.3126},"中山區":{"code":5,"lat":25.152899,"lon":121.729552,"site":1.268,"site_s":1.3464,"site_d":2.312},"安樂區":{"code":6,"lat":25.121176,"lon":121.7230804,"site":1.16,"site_s":1.3465,"site_d":2.3121},"信義區":{"code":7,"lat":25.1294717,"lon":121.7512671,"site":1.353,"site_s":1.3468,"site_d":2.3127}},"臺北市":{"松山區":{"code":8,"lat":25.049847,"lon":121.577241,"site":1.96,"site_s":1.9475,"site_d":2.8642},"信義區":{"code":9,"lat":25.0331574,"lon":121.5668777,"site":2.106,"site_s":1.9478,"site_d":2.8646},"大安區":{"code":10,"lat":25.02642,"lon":121.534511,"site":1.833,"site_s":1.947,"site_d":2.8635},"中山區":{"code":11,"lat":25.0642771,"lon":121.5335776,"site":1.924,"site_s":1.9468,"site_d":2.8632},"中正區":{"code":12,"lat":25.0443212,"lon":121.5247613,"site":1.944,"site_s":1.9468,"site_d":2.8632},"大同區":{"code":13,"lat":25.0661934,"lon":121.515268,"site":2,"site_s":1.9463,"site_d":2.8624},"萬華區":{"code":14,"lat":25.034839,"lon":121.4997957,"site":1.724,"site_s":1.7938,"site_d":2.2365},"文山區":{"code":15,"lat":24.98964,"lon":121.5700826,"site":1.532,"site_s":1.9463,"site_d":2.8625},"南港區":{"code":16,"lat":25.0547059,"lon":121.6066929,"site":2.268,"site_s":1.9466,"site_d":2.8629},"內湖區":{"code":17,"lat":25.06929,"lon":121.588949,"site":2.023,"site_s":1.9467,"site_d":2.8632},"士林區":{"code":18,"lat":25.0927548,"lon":121.519565,"site":1.538,"site_s":1.9457,"site_d":2.8617},"北投區":{"code":19,"lat":25.1323666,"lon":121.5029268,"site":1.534,"site_s":1.518,"site_d":2.6464}},"新北市":{"板橋區":{"code":20,"lat":25.0096156,"lon":121.4592358,"site":2.065,"site_s":1.7948,"site_d":2.2378},"三重區":{"code":21,"lat":25.0607692,"lon":121.4884178,"site":1.926,"site_s":1.7933,"site_d":2.2359},"中和區":{"code":22,"lat":24.9985208,"lon":121.5007413,"site":1.948,"site_s":1.7939,"site_d":2.2366},"永和區":{"code":23,"lat":25.0091768,"lon":121.5202731,"site":1.873,"site_s":1.7934,"site_d":2.236},"新莊區":{"code":24,"lat":25.035976,"lon":121.450478,"site":2.623,"site_s":1.7941,"site_d":2.2369},"新店區":{"code":25,"lat":24.9749713,"lon":121.5431673,"site":1.931,"site_s":1.9457,"site_d":2.8616},"樹林區":{"code":26,"lat":24.9899673,"lon":121.4246321,"site":1.443,"site_s":1.7937,"site_d":2.2363},"鶯歌區":{"code":27,"lat":24.9560294,"lon":121.3544312,"site":0.959,"site_s":1.4265,"site_d":2.9728},"三峽區":{"code":28,"lat":24.9341863,"lon":121.369083,"site":1.325,"site_s":1.4259,"site_d":2.9716},"淡水區":{"code":29,"lat":25.1696463,"lon":121.4409722,"site":1.999,"site_s":1.5195,"site_d":2.6492},"汐止區":{"code":30,"lat":25.064261,"lon":121.65869,"site":2.09,"site_s":1.945,"site_d":2.8605},"瑞芳區":{"code":31,"lat":25.1087635,"lon":121.8098935,"site":1.286,"site_s":1.3455,"site_d":2.3104},"土城區":{"code":32,"lat":24.9723361,"lon":121.4429389,"site":1.667,"site_s":1.7936,"site_d":2.2363},"蘆洲區":{"code":33,"lat":25.0847112,"lon":121.4737354,"site":1.936,"site_s":1.7927,"site_d":2.2351},"五股區":{"code":34,"lat":25.0830393,"lon":121.4380781,"site":1.541,"site_s":1.7926,"site_d":2.2351},"泰山區":{"code":35,"lat":25.059291,"lon":121.431495,"site":2.448,"site_s":1.7932,"site_d":2.2358},"林口區":{"code":36,"lat":25.0768252,"lon":121.3886134,"site":2.111,"site_s":1.792,"site_d":2.2343},"深坑區":{"code":37,"lat":25.0025007,"lon":121.615944,"site":1.542,"site_s":1.946,"site_d":2.862},"石碇區":{"code":38,"lat":24.9914859,"lon":121.6579019,"site":1.423,"site_s":1.1106,"site_d":1.4761},"坪林區":{"code":39,"lat":24.9361367,"lon":121.7117653,"site":0.93,"site_s":1.112,"site_d":1.478},"三芝區":{"code":40,"lat":25.257748,"lon":121.5009345,"site":1.412,"site_s":1.5177,"site_d":2.6459},"石門區":{"code":41,"lat":25.291248,"lon":121.567631,"site":1.406,"site_s":1.5159,"site_d":2.6429},"八里區":{"code":42,"lat":25.1537592,"lon":121.4064305,"site":2.13,"site_s":1.5188,"site_d":2.6478},"平溪區":{"code":43,"lat":25.026689,"lon":121.73819,"site":1.543,"site_s":1.1102,"site_d":1.4756},"雙溪區":{"code":44,"lat":25.0337322,"lon":121.8657341,"site":1.622,"site_s":1.3435,"site_d":2.307},"貢寮區":{"code":45,"lat":25.021812,"lon":121.910293,"site":0.954,"site_s":1.3426,"site_d":2.3055},"金山區":{"code":46,"lat":25.222241,"lon":121.636629,"site":1.586,"site_s":1.3439,"site_d":2.3077},"萬里區":{"code":47,"lat":25.178066,"lon":121.689548,"site":1.581,"site_s":1.3454,"site_d":2.3103},"烏來區":{"code":48,"lat":24.8717802,"lon":121.5478634,"site":1.164,"site_s":1.3277,"site_d":2.1825}},"桃園市":{"桃園區":{"code":49,"lat":24.993919,"lon":121.3016657,"site":1.417,"site_s":1.428,"site_d":2.9759},"中壢區":{"code":50,"lat":24.9656124,"lon":121.2249927,"site":1.536,"site_s":1.4262,"site_d":2.9722},"大溪區":{"code":51,"lat":24.880548,"lon":121.287142,"site":1.498,"site_s":1.1562,"site_d":2.1567},"楊梅區":{"code":52,"lat":24.9128508,"lon":121.1444587,"site":1.328,"site_s":1.2597,"site_d":2.4895},"蘆竹區":{"code":53,"lat":25.046925,"lon":121.295077,"site":1.858,"site_s":1.4267,"site_d":2.9732},"大園區":{"code":54,"lat":25.0638556,"lon":121.1954603,"site":1.752,"site_s":1.425,"site_d":2.9698},"龜山區":{"code":55,"lat":24.9925139,"lon":121.337824,"site":2.038,"site_s":1.4272,"site_d":2.9743},"八德區":{"code":56,"lat":24.9289862,"lon":121.2846406,"site":1.568,"site_s":1.4264,"site_d":2.9726},"龍潭區":{"code":57,"lat":24.8704855,"lon":121.2224472,"site":1.427,"site_s":1.2579,"site_d":2.4859},"平鎮區":{"code":58,"lat":24.9456694,"lon":121.2181884,"site":1.549,"site_s":1.2583,"site_d":2.4867},"新屋區":{"code":59,"lat":24.9725439,"lon":121.105533,"site":1.309,"site_s":1.2588,"site_d":2.4875},"觀音區":{"code":60,"lat":25.0276516,"lon":121.0836028,"site":1.326,"site_s":1.2575,"site_d":2.485},"復興區":{"code":61,"lat":24.8147989,"lon":121.3511305,"site":1.148,"site_s":1.158,"site_d":2.16}},"新竹市":{"東區":{"code":62,"lat":24.8051881,"lon":120.9732327,"site":2.41,"site_s":1.6228,"site_d":2.7467},"北區":{"code":63,"lat":24.8163726,"lon":120.9703141,"site":1.373,"site_s":1.6228,"site_d":2.7466},"香山區":{"code":64,"lat":24.7940445,"lon":120.9422678,"site":1.902,"site_s":1.6222,"site_d":2.7457}},"新竹縣":{"竹北市":{"code":65,"lat":24.8395807,"lon":121.0040235,"site":2.246,"site_s":1.4016,"site_d":2.5963},"竹東鎮":{"code":66,"lat":24.7366942,"lon":121.0916513,"site":1.881,"site_s":1.6991,"site_d":2.6766},"新埔鎮":{"code":67,"lat":24.8256201,"lon":121.0740799,"site":1.555,"site_s":1.4006,"site_d":2.5945},"關西鎮":{"code":68,"lat":24.7922806,"lon":121.1759547,"site":1.558,"site_s":1.6975,"site_d":2.674},"湖口鄉":{"code":69,"lat":24.9010068,"lon":121.0478749,"site":1.07,"site_s":1.4,"site_d":2.5934},"新豐鄉":{"code":70,"lat":24.9007026,"lon":120.9852313,"site":1.395,"site_s":1.4001,"site_d":2.5935},"芎林鄉":{"code":71,"lat":24.773309,"lon":121.081855,"site":1.773,"site_s":1.6998,"site_d":2.6776},"橫山鄉":{"code":72,"lat":24.7167807,"lon":121.1414985,"site":1.653,"site_s":1.6979,"site_d":2.6747},"北埔鄉":{"code":73,"lat":24.7019901,"lon":121.0563354,"site":1.797,"site_s":1.6979,"site_d":2.6748},"寶山鄉":{"code":74,"lat":24.7654715,"lon":120.9913066,"site":1.758,"site_s":1.6217,"site_d":2.7447},"峨眉鄉":{"code":75,"lat":24.6887921,"lon":121.0195946,"site":1.696,"site_s":1.6971,"site_d":2.6734},"尖石鄉":{"code":76,"lat":24.705004,"lon":121.2020864,"site":1.262,"site_s":1.6964,"site_d":2.6723},"五峰鄉":{"code":77,"lat":24.6320786,"lon":121.119596,"site":1.275,"site_s":1.6959,"site_d":2.6716}},"苗栗縣":{"苗栗市":{"code":78,"lat":24.5616772,"lon":120.8190175,"site":1.705,"site_s":1.6629,"site_d":1.9209},"苑裡鎮":{"code":79,"lat":24.4396522,"lon":120.653261,"site":1.714,"site_s":1.0962,"site_d":1.3656},"通霄鎮":{"code":80,"lat":24.4912805,"lon":120.684249,"site":1.679,"site_s":1.6588,"site_d":1.9162},"竹南鎮":{"code":81,"lat":24.6838448,"lon":120.8733503,"site":2.078,"site_s":1.6593,"site_d":1.9167},"頭份市":{"code":82,"lat":24.6865276,"lon":120.9132454,"site":1.98,"site_s":1.6193,"site_d":2.7407},"後龍鎮":{"code":83,"lat":24.613682,"lon":120.792046,"site":1.839,"site_s":1.6614,"site_d":1.9192},"卓蘭鎮":{"code":84,"lat":24.3130501,"lon":120.8245152,"site":1.196,"site_s":1.4333,"site_d":1.4093},"大湖鄉":{"code":85,"lat":24.4234081,"lon":120.8661781,"site":1.116,"site_s":0.9111,"site_d":1.4285},"公館鄉":{"code":86,"lat":24.5058646,"lon":120.8284935,"site":1.292,"site_s":1.6613,"site_d":1.919},"銅鑼鄉":{"code":87,"lat":24.4870514,"lon":120.7878718,"site":1.456,"site_s":1.6606,"site_d":1.9182},"南庄鄉":{"code":88,"lat":24.5970648,"lon":121.000339,"site":1.119,"site_s":0.9096,"site_d":1.4262},"頭屋鄉":{"code":89,"lat":24.5778158,"lon":120.8511057,"site":1.399,"site_s":1.6621,"site_d":1.92},"三義鄉":{"code":90,"lat":24.4129179,"lon":120.7702392,"site":1.239,"site_s":1.4318,"site_d":1.4078},"西湖鄉":{"code":91,"lat":24.5567613,"lon":120.7570814,"site":1.544,"site_s":1.6613,"site_d":1.9191},"造橋鄉":{"code":92,"lat":24.638552,"lon":120.8651632,"site":1.807,"site_s":1.6606,"site_d":1.9182},"三灣鄉":{"code":93,"lat":24.6531425,"lon":120.9566265,"site":1.65,"site_s":1.6586,"site_d":1.9159},"獅潭鄉":{"code":94,"lat":24.539419,"lon":120.920496,"site":1.092,"site_s":0.9109,"site_d":1.4282},"泰安鄉":{"code":95,"lat":24.4471976,"lon":120.9081718,"site":0.985,"site_s":0.9117,"site_d":1.4295}},"臺中市":{"中區":{"code":96,"lat":24.1439458,"lon":120.6794414,"site":1.639,"site_s":1.7158,"site_d":2.5822},"東區":{"code":97,"lat":24.1366469,"lon":120.7037332,"site":1.24,"site_s":1.7152,"site_d":2.5812},"南區":{"code":98,"lat":24.1171412,"lon":120.6635905,"site":1.633,"site_s":1.7154,"site_d":2.5816},"西區":{"code":99,"lat":24.1413252,"lon":120.6710753,"site":1.431,"site_s":1.7159,"site_d":2.5824},"北區":{"code":100,"lat":24.1658534,"lon":120.6822936,"site":1.211,"site_s":1.716,"site_d":2.5825},"西屯區":{"code":101,"lat":24.1658213,"lon":120.6336717,"site":1.149,"site_s":1.7167,"site_d":2.5835},"南屯區":{"code":102,"lat":24.1345298,"lon":120.6442903,"site":1.506,"site_s":1.716,"site_d":2.5825},"北屯區":{"code":103,"lat":24.1826848,"lon":120.686403,"site":1.1,"site_s":1.7158,"site_d":2.5822},"豐原區":{"code":104,"lat":24.2419087,"lon":120.7181281,"site":1.207,"site_s":1.0978,"site_d":1.3675},"東勢區":{"code":105,"lat":24.2585728,"lon":120.8279546,"site":1.631,"site_s":1.2625,"site_d":1.2266},"大甲區":{"code":106,"lat":24.349083,"lon":120.622468,"site":1.403,"site_s":1.0973,"site_d":1.3668},"清水區":{"code":107,"lat":24.2681562,"lon":120.559717,"site":1.749,"site_s":1.7132,"site_d":2.5783},"沙鹿區":{"code":108,"lat":24.2333313,"lon":120.566317,"site":1.309,"site_s":1.7141,"site_d":2.5796},"梧棲區":{"code":109,"lat":24.2549063,"lon":120.5317002,"site":1.967,"site_s":1.7129,"site_d":2.5779},"后里區":{"code":110,"lat":24.3049377,"lon":120.7107454,"site":1.192,"site_s":1.099,"site_d":1.369},"神岡區":{"code":111,"lat":24.2579749,"lon":120.6614216,"site":1.119,"site_s":1.0978,"site_d":1.3675},"潭子區":{"code":112,"lat":24.2031708,"lon":120.7228978,"site":1.289,"site_s":1.7147,"site_d":2.5805},"大雅區":{"code":113,"lat":24.2291463,"lon":120.6478436,"site":1.063,"site_s":1.7152,"site_d":2.5812},"新社區":{"code":114,"lat":24.233957,"lon":120.809416,"site":1.299,"site_s":1.2625,"site_d":1.2265},"石岡區":{"code":115,"lat":24.274898,"lon":120.7803458,"site":1.227,"site_s":1.0976,"site_d":1.3673},"外埔區":{"code":116,"lat":24.3321248,"lon":120.654334,"site":1.276,"site_s":1.0979,"site_d":1.3676},"大安區":{"code":117,"lat":24.346126,"lon":120.5866075,"site":1.383,"site_s":1.0967,"site_d":1.3661},"烏日區":{"code":118,"lat":24.104605,"lon":120.6238467,"site":1.788,"site_s":1.715,"site_d":2.581},"大肚區":{"code":119,"lat":24.1511295,"lon":120.5457643,"site":1.81,"site_s":2.7664,"site_d":3.6392},"龍井區":{"code":120,"lat":24.1924488,"lon":120.5457999,"site":1.839,"site_s":1.7142,"site_d":2.5797},"霧峰區":{"code":121,"lat":24.0613153,"lon":120.7000868,"site":1.763,"site_s":1.7135,"site_d":2.5787},"太平區":{"code":122,"lat":24.1266572,"lon":120.7185562,"site":1.193,"site_s":1.7147,"site_d":2.5805},"大里區":{"code":123,"lat":24.0994693,"lon":120.6778413,"site":1.629,"site_s":1.7148,"site_d":2.5806},"和平區":{"code":124,"lat":24.1752225,"lon":120.8835809,"site":1.222,"site_s":1.2631,"site_d":1.2271}},"彰化縣":{"彰化市":{"code":125,"lat":24.0809056,"lon":120.5422565,"site":2.055,"site_s":2.7697,"site_d":3.6436},"鹿港鎮":{"code":126,"lat":24.0572566,"lon":120.4350548,"site":2.217,"site_s":2.7651,"site_d":3.6376},"和美鎮":{"code":127,"lat":24.1085584,"lon":120.4941497,"site":1.797,"site_s":2.7673,"site_d":3.6404},"線西鄉":{"code":128,"lat":24.1306678,"lon":120.470656,"site":2.288,"site_s":2.7658,"site_d":3.6385},"伸港鄉":{"code":129,"lat":24.1596067,"lon":120.4861141,"site":2.116,"site_s":2.7652,"site_d":3.6377},"福興鄉":{"code":130,"lat":24.0478713,"lon":120.4439546,"site":2.046,"site_s":2.7654,"site_d":3.6379},"秀水鄉":{"code":131,"lat":24.035321,"lon":120.5028098,"site":2.109,"site_s":2.7674,"site_d":3.6405},"花壇鄉":{"code":132,"lat":24.0296582,"lon":120.5382578,"site":1.661,"site_s":2.7678,"site_d":3.6411},"芬園鄉":{"code":133,"lat":24.013628,"lon":120.628964,"site":1.643,"site_s":2.7652,"site_d":3.6377},"員林市":{"code":134,"lat":23.9589162,"lon":120.5743943,"site":1.692,"site_s":2.9498,"site_d":2.9917},"溪湖鎮":{"code":135,"lat":23.9664245,"lon":120.4832787,"site":2.079,"site_s":2.9498,"site_d":2.9917},"田中鎮":{"code":136,"lat":23.8614831,"lon":120.5809585,"site":1.399,"site_s":2.9521,"site_d":2.9941},"大村鄉":{"code":137,"lat":23.9934239,"lon":120.547268,"site":1.682,"site_s":2.7661,"site_d":3.6388},"埔鹽鄉":{"code":138,"lat":24.000442,"lon":120.4636578,"site":1.998,"site_s":2.7649,"site_d":3.6374},"埔心鄉":{"code":139,"lat":23.952988,"lon":120.54354,"site":1.817,"site_s":2.9506,"site_d":2.9926},"永靖鄉":{"code":140,"lat":23.9245962,"lon":120.5477204,"site":1.919,"site_s":2.952,"site_d":2.9939},"社頭鄉":{"code":141,"lat":23.8968186,"lon":120.5858074,"site":1.488,"site_s":2.9517,"site_d":2.9936},"二水鄉":{"code":142,"lat":23.8066858,"lon":120.6190203,"site":1.501,"site_s":2.9493,"site_d":2.9912},"北斗鎮":{"code":143,"lat":23.8713826,"lon":120.5218625,"site":1.957,"site_s":2.955,"site_d":2.997},"二林鎮":{"code":144,"lat":23.8998045,"lon":120.3742654,"site":2.2,"site_s":2.9479,"site_d":2.9898},"田尾鄉":{"code":145,"lat":23.8922407,"lon":120.5259709,"site":2.175,"site_s":2.9539,"site_d":2.9959},"埤頭鄉":{"code":146,"lat":23.8914618,"lon":120.4621725,"site":2.32,"site_s":2.952,"site_d":2.994},"芳苑鄉":{"code":147,"lat":23.924354,"lon":120.320389,"site":2.117,"site_s":2.9452,"site_d":2.987},"大城鄉":{"code":148,"lat":23.852314,"lon":120.3208972,"site":2.15,"site_s":2.9455,"site_d":2.9874},"竹塘鄉":{"code":149,"lat":23.8605045,"lon":120.4277961,"site":2.029,"site_s":2.9506,"site_d":2.9925},"溪州鄉":{"code":150,"lat":23.8516188,"lon":120.498976,"site":1.834,"site_s":2.9536,"site_d":2.9955}},"南投縣":{"南投市":{"code":151,"lat":23.9116414,"lon":120.6874199,"site":1.566,"site_s":1.6047,"site_d":1.9467},"埔里鎮":{"code":152,"lat":23.9665377,"lon":120.9691809,"site":1.129,"site_s":1.145,"site_d":1.299},"草屯鎮":{"code":153,"lat":23.9736845,"lon":120.6802819,"site":1.551,"site_s":1.603,"site_d":1.9445},"竹山鎮":{"code":154,"lat":23.7578635,"lon":120.6716995,"site":1.36,"site_s":1.6009,"site_d":1.9421},"集集鎮":{"code":155,"lat":23.8283683,"lon":120.7864885,"site":1.19,"site_s":1.6018,"site_d":1.9431},"名間鄉":{"code":156,"lat":23.8382161,"lon":120.702985,"site":1.467,"site_s":1.6032,"site_d":1.9448},"鹿谷鄉":{"code":157,"lat":23.7458415,"lon":120.7534428,"site":1.183,"site_s":1.3568,"site_d":2.0077},"中寮鄉":{"code":158,"lat":23.8790067,"lon":120.7660301,"site":1.647,"site_s":1.603,"site_d":1.9445},"魚池鄉":{"code":159,"lat":23.8957849,"lon":120.9356849,"site":1.003,"site_s":1.1435,"site_d":1.2972},"國姓鄉":{"code":160,"lat":24.040019,"lon":120.8575192,"site":1.079,"site_s":1.1425,"site_d":1.2962},"水里鄉":{"code":161,"lat":23.8113991,"lon":120.8560852,"site":1.004,"site_s":1.357,"site_d":2.008},"信義鄉":{"code":162,"lat":23.696797,"lon":120.854557,"site":1.236,"site_s":1.3583,"site_d":2.01},"仁愛鄉":{"code":163,"lat":24.021544,"lon":121.1320616,"site":1.207,"site_s":1.1418,"site_d":1.2954}},"雲林縣":{"斗六市":{"code":164,"lat":23.6971143,"lon":120.5269987,"site":1.924,"site_s":2.3979,"site_d":2.9279},"斗南鎮":{"code":165,"lat":23.680105,"lon":120.47772,"site":1.783,"site_s":2.396,"site_d":2.9255},"虎尾鎮":{"code":166,"lat":23.7083539,"lon":120.4451923,"site":1.997,"site_s":2.3949,"site_d":2.9242},"西螺鎮":{"code":167,"lat":23.7977736,"lon":120.465685,"site":1.751,"site_s":2.9504,"site_d":2.9923},"土庫鎮":{"code":168,"lat":23.6820621,"lon":120.3899062,"site":1.907,"site_s":2.3927,"site_d":2.9216},"北港鎮":{"code":169,"lat":23.5759236,"lon":120.302446,"site":1.797,"site_s":2.493,"site_d":2.855},"古坑鄉":{"code":170,"lat":23.6426312,"lon":120.5619595,"site":1.824,"site_s":2.3953,"site_d":2.9247},"大埤鄉":{"code":171,"lat":23.6460343,"lon":120.4314818,"site":2.071,"site_s":2.3938,"site_d":2.9228},"莿桐鄉":{"code":172,"lat":23.7610077,"lon":120.5025072,"site":1.914,"site_s":2.3953,"site_d":2.9246},"林內鄉":{"code":173,"lat":23.7562156,"lon":120.6129427,"site":1.656,"site_s":2.3939,"site_d":2.923},"二崙鄉":{"code":174,"lat":23.7711012,"lon":120.4129596,"site":1.825,"site_s":2.3927,"site_d":2.9216},"崙背鄉":{"code":175,"lat":23.7619087,"lon":120.3591424,"site":1.818,"site_s":2.3911,"site_d":2.9196},"麥寮鄉":{"code":176,"lat":23.7539853,"lon":120.2513078,"site":2.471,"site_s":2.485,"site_d":2.8458},"東勢鄉":{"code":177,"lat":23.6753034,"lon":120.2525936,"site":2.434,"site_s":2.4883,"site_d":2.8496},"褒忠鄉":{"code":178,"lat":23.691007,"lon":120.3037335,"site":2.025,"site_s":2.488,"site_d":2.8493},"臺西鄉":{"code":179,"lat":23.700477,"lon":120.1957632,"site":2.379,"site_s":2.4861,"site_d":2.8471},"元長鄉":{"code":180,"lat":23.6497447,"lon":120.3148349,"site":1.902,"site_s":2.4898,"site_d":2.8513},"四湖鄉":{"code":181,"lat":23.6378317,"lon":120.2242949,"site":2.09,"site_s":2.4889,"site_d":2.8503},"口湖鄉":{"code":182,"lat":23.5827378,"lon":120.1858552,"site":2.016,"site_s":2.4884,"site_d":2.8497},"水林鄉":{"code":183,"lat":23.5727035,"lon":120.2459507,"site":1.816,"site_s":2.4908,"site_d":2.8524}},"嘉義市":{"東區":{"code":184,"lat":23.4786578,"lon":120.4534596,"site":1.857,"site_s":2.3869,"site_d":3.0399},"西區":{"code":185,"lat":23.4646967,"lon":120.4352822,"site":2.105,"site_s":2.386,"site_d":3.0388}},"嘉義縣":{"太保市":{"code":186,"lat":23.458967,"lon":120.3323479,"site":2.013,"site_s":2.5884,"site_d":2.3895},"朴子市":{"code":187,"lat":23.4575288,"lon":120.2459226,"site":2.029,"site_s":2.5881,"site_d":2.3892},"布袋鎮":{"code":188,"lat":23.3781734,"lon":120.1669564,"site":1.768,"site_s":2.5837,"site_d":2.3851},"大林鎮":{"code":189,"lat":23.603931,"lon":120.471178,"site":2.006,"site_s":2.3935,"site_d":2.9225},"民雄鄉":{"code":190,"lat":23.5516417,"lon":120.4283616,"site":1.989,"site_s":2.3839,"site_d":3.0361},"溪口鄉":{"code":191,"lat":23.6025304,"lon":120.392323,"site":2,"site_s":2.4892,"site_d":2.8507},"新港鄉":{"code":192,"lat":23.5519744,"lon":120.3478039,"site":1.758,"site_s":2.4909,"site_d":2.8526},"六腳鄉":{"code":193,"lat":23.4940922,"lon":120.2907962,"site":1.99,"site_s":2.5884,"site_d":2.3895},"東石鄉":{"code":194,"lat":23.4587147,"lon":120.1537883,"site":2.399,"site_s":2.5843,"site_d":2.3857},"義竹鄉":{"code":195,"lat":23.3361064,"lon":120.2430475,"site":2.322,"site_s":2.5159,"site_d":3.1512},"鹿草鄉":{"code":196,"lat":23.4113835,"lon":120.3082682,"site":1.852,"site_s":2.5878,"site_d":2.3889},"水上鄉":{"code":197,"lat":23.428531,"lon":120.398035,"site":1.995,"site_s":2.384,"site_d":3.0361},"中埔鄉":{"code":198,"lat":23.425139,"lon":120.522952,"site":1.726,"site_s":2.2181,"site_d":2.5808},"竹崎鄉":{"code":199,"lat":23.5230788,"lon":120.5513988,"site":1.666,"site_s":2.2177,"site_d":2.5803},"梅山鄉":{"code":200,"lat":23.5850678,"lon":120.5554676,"site":1.421,"site_s":2.3931,"site_d":2.922},"番路鄉":{"code":201,"lat":23.4644973,"lon":120.554286,"site":1.06,"site_s":2.22,"site_d":2.583},"大埔鄉":{"code":202,"lat":23.2986941,"lon":120.5869311,"site":1.192,"site_s":1.1427,"site_d":1.9364},"阿里山鄉":{"code":203,"lat":23.4712117,"lon":120.7135217,"site":1.031,"site_s":2.2143,"site_d":2.5764}},"臺南市":{"新營區":{"code":204,"lat":23.3101426,"lon":120.3167031,"site":2.103,"site_s":2.5189,"site_d":3.1549},"鹽水區":{"code":205,"lat":23.320027,"lon":120.266097,"site":1.829,"site_s":2.517,"site_d":3.1525},"白河區":{"code":206,"lat":23.3512886,"lon":120.415752,"site":1.057,"site_s":2.5145,"site_d":3.1494},"柳營區":{"code":207,"lat":23.278395,"lon":120.311673,"site":1.788,"site_s":2.5176,"site_d":3.1532},"後壁區":{"code":208,"lat":23.3659836,"lon":120.3619362,"site":1.736,"site_s":2.5159,"site_d":3.1511},"東山區":{"code":209,"lat":23.3261625,"lon":120.4045009,"site":1.403,"site_s":2.5153,"site_d":3.1504},"麻豆區":{"code":210,"lat":23.1849449,"lon":120.2584456,"site":2.204,"site_s":2.513,"site_d":3.1475},"下營區":{"code":211,"lat":23.2356921,"lon":120.2643838,"site":1.98,"site_s":2.5151,"site_d":3.1502},"六甲區":{"code":212,"lat":23.2318098,"lon":120.3474201,"site":1.782,"site_s":2.5153,"site_d":3.1503},"官田區":{"code":213,"lat":23.1930442,"lon":120.3154967,"site":1.704,"site_s":2.5138,"site_d":3.1485},"大內區":{"code":214,"lat":23.1192073,"lon":120.3568212,"site":1.533,"site_s":1.143,"site_d":1.9369},"佳里區":{"code":215,"lat":23.1652648,"lon":120.1770306,"site":2.17,"site_s":1.8808,"site_d":2.5266},"學甲區":{"code":216,"lat":23.2304835,"lon":120.1822926,"site":2.166,"site_s":2.5126,"site_d":3.147},"西港區":{"code":217,"lat":23.1229825,"lon":120.203413,"site":2.601,"site_s":1.8823,"site_d":2.5286},"七股區":{"code":218,"lat":23.1403809,"lon":120.1391359,"site":1.977,"site_s":1.8811,"site_d":2.5271},"將軍區":{"code":219,"lat":23.19905,"lon":120.158702,"site":1.888,"site_s":2.511,"site_d":3.145},"北門區":{"code":220,"lat":23.267723,"lon":120.125445,"site":2.124,"site_s":2.5112,"site_d":3.1452},"新化區":{"code":221,"lat":23.0385411,"lon":120.310896,"site":2.087,"site_s":1.8837,"site_d":2.5306},"善化區":{"code":222,"lat":23.1324288,"lon":120.2967849,"site":1.968,"site_s":1.8815,"site_d":2.5276},"新市區":{"code":223,"lat":23.0789967,"lon":120.2951827,"site":2.416,"site_s":1.8831,"site_d":2.5297},"安定區":{"code":224,"lat":23.121593,"lon":120.237118,"site":2.829,"site_s":1.8823,"site_d":2.5287},"山上區":{"code":225,"lat":23.1036173,"lon":120.3526487,"site":1.771,"site_s":1.1428,"site_d":1.9366},"玉井區":{"code":226,"lat":23.1237866,"lon":120.4601109,"site":1.161,"site_s":1.1448,"site_d":1.94},"楠西區":{"code":227,"lat":23.174143,"lon":120.486337,"site":1.145,"site_s":1.1452,"site_d":1.9406},"南化區":{"code":228,"lat":23.042988,"lon":120.477816,"site":0.857,"site_s":1.1438,"site_d":1.9383},"左鎮區":{"code":229,"lat":23.0567783,"lon":120.408708,"site":1.569,"site_s":1.1433,"site_d":1.9374},"仁德區":{"code":230,"lat":22.97243,"lon":120.251685,"site":1.342,"site_s":1.8861,"site_d":2.5338},"歸仁區":{"code":231,"lat":22.967286,"lon":120.2940045,"site":1.751,"site_s":1.8848,"site_d":2.5321},"關廟區":{"code":232,"lat":22.9630039,"lon":120.3278144,"site":1.747,"site_s":1.8838,"site_d":2.5307},"龍崎區":{"code":233,"lat":22.9632926,"lon":120.3649712,"site":1.57,"site_s":1.0188,"site_d":2.4227},"永康區":{"code":234,"lat":23.0260699,"lon":120.2570647,"site":1.951,"site_s":1.8852,"site_d":2.5325},"東區":{"code":235,"lat":22.9802421,"lon":120.224004,"site":1.711,"site_s":1.887,"site_d":2.535},"南區":{"code":236,"lat":22.9611326,"lon":120.1885687,"site":1.486,"site_s":1.8858,"site_d":2.5334},"北區":{"code":237,"lat":22.9997522,"lon":120.2030341,"site":2.299,"site_s":1.8861,"site_d":2.5338},"安南區":{"code":238,"lat":23.0472321,"lon":120.184714,"site":2.236,"site_s":1.8845,"site_d":2.5316},"安平區":{"code":239,"lat":22.9945789,"lon":120.1688523,"site":1.888,"site_s":1.8853,"site_d":2.5327},"中西區":{"code":240,"lat":22.9922364,"lon":120.2056571,"site":2.264,"site_s":1.8863,"site_d":2.5341}},"高雄市":{"鹽埕區":{"code":241,"lat":22.6247166,"lon":120.2868098,"site":1.496,"site_s":1.5344,"site_d":1.6413},"鼓山區":{"code":242,"lat":22.636776,"lon":120.2809626,"site":1.173,"site_s":1.5341,"site_d":1.6411},"左營區":{"code":243,"lat":22.6899834,"lon":120.2950135,"site":1.399,"site_s":1.5332,"site_d":1.64},"楠梓區":{"code":244,"lat":22.7283655,"lon":120.3263681,"site":1.394,"site_s":1.5322,"site_d":1.639},"三民區":{"code":245,"lat":22.647684,"lon":120.299851,"site":1.279,"site_s":1.5343,"site_d":1.6412},"新興區":{"code":246,"lat":22.6310347,"lon":120.3101095,"site":1.565,"site_s":1.5348,"site_d":1.6418},"前金區":{"code":247,"lat":22.6275276,"lon":120.2942181,"site":1.669,"site_s":1.5345,"site_d":1.6415},"苓雅區":{"code":248,"lat":22.621759,"lon":120.312194,"site":1.436,"site_s":1.535,"site_d":1.642},"前鎮區":{"code":249,"lat":22.5865658,"lon":120.318307,"site":1.569,"site_s":1.5341,"site_d":1.641},"旗津區":{"code":250,"lat":22.5900263,"lon":120.28471,"site":1.709,"site_s":1.5339,"site_d":1.6409},"小港區":{"code":251,"lat":22.5652134,"lon":120.3380368,"site":2.106,"site_s":1.5334,"site_d":1.6403},"鳳山區":{"code":252,"lat":22.627075,"lon":120.362525,"site":1.582,"site_s":1.5337,"site_d":1.6407},"林園區":{"code":253,"lat":22.5129453,"lon":120.3946805,"site":1.319,"site_s":1.5315,"site_d":1.6382},"大寮區":{"code":254,"lat":22.6055196,"lon":120.3956199,"site":1.901,"site_s":1.5329,"site_d":1.6397},"大樹區":{"code":255,"lat":22.6839054,"lon":120.4143416,"site":1.065,"site_s":1.0887,"site_d":1.3554},"大社區":{"code":256,"lat":22.730156,"lon":120.346671,"site":1.135,"site_s":1.532,"site_d":1.6388},"仁武區":{"code":257,"lat":22.7013806,"lon":120.3479837,"site":1.14,"site_s":1.5327,"site_d":1.6396},"鳥松區":{"code":258,"lat":22.6598339,"lon":120.364363,"site":1.181,"site_s":1.5334,"site_d":1.6403},"岡山區":{"code":259,"lat":22.7974649,"lon":120.2950724,"site":1.315,"site_s":1.5303,"site_d":1.637},"橋頭區":{"code":260,"lat":22.757591,"lon":120.305809,"site":1.29,"site_s":1.5314,"site_d":1.6381},"燕巢區":{"code":261,"lat":22.7881575,"lon":120.3619685,"site":1.202,"site_s":1.0182,"site_d":2.4214},"田寮區":{"code":262,"lat":22.8698825,"lon":120.3594334,"site":1.185,"site_s":1.0189,"site_d":2.4231},"阿蓮區":{"code":263,"lat":22.8832024,"lon":120.3274131,"site":1.114,"site_s":1.8825,"site_d":2.529},"路竹區":{"code":264,"lat":22.8547435,"lon":120.2592442,"site":1.097,"site_s":1.8827,"site_d":2.5293},"湖內區":{"code":265,"lat":22.9083136,"lon":120.211713,"site":1.162,"site_s":1.8846,"site_d":2.5318},"茄萣區":{"code":266,"lat":22.9065231,"lon":120.1824729,"site":1.204,"site_s":1.8843,"site_d":2.5314},"永安區":{"code":267,"lat":22.818298,"lon":120.224189,"site":1.3,"site_s":1.8817,"site_d":2.5279},"彌陀區":{"code":268,"lat":22.7814893,"lon":120.2507011,"site":1.511,"site_s":1.5305,"site_d":1.6372},"梓官區":{"code":269,"lat":22.7606303,"lon":120.2671523,"site":1.521,"site_s":1.5312,"site_d":1.6379},"旗山區":{"code":270,"lat":22.888642,"lon":120.48349,"site":0.836,"site_s":1.0208,"site_d":2.4276},"美濃區":{"code":271,"lat":22.8947952,"lon":120.5419493,"site":0.942,"site_s":1.02,"site_d":2.4256},"六龜區":{"code":272,"lat":22.9984391,"lon":120.6327082,"site":1.12,"site_s":1.0179,"site_d":2.4207},"甲仙區":{"code":273,"lat":23.0839058,"lon":120.587695,"site":0.807,"site_s":1.1442,"site_d":1.939},"杉林區":{"code":274,"lat":22.9717391,"lon":120.540058,"site":0.997,"site_s":1.0194,"site_d":2.4241},"內門區":{"code":275,"lat":22.9428391,"lon":120.462606,"site":1.139,"site_s":1.0201,"site_d":2.426},"茂林區":{"code":276,"lat":22.886187,"lon":120.663266,"site":1.412,"site_s":0.9985,"site_d":0.9985},"桃源區":{"code":277,"lat":23.1592827,"lon":120.7641372,"site":1.182,"site_s":1.1415,"site_d":1.9344},"那瑪夏區":{"code":278,"lat":23.277092,"lon":120.720243,"site":0.951,"site_s":1.1415,"site_d":1.9343}},"屏東縣":{"屏東市":{"code":279,"lat":22.662498,"lon":120.4914295,"site":1.138,"site_s":1.0896,"site_d":1.3565},"潮州鎮":{"code":280,"lat":22.549845,"lon":120.5429633,"site":1.085,"site_s":1.0873,"site_d":1.3536},"東港鎮":{"code":281,"lat":22.4666854,"lon":120.454361,"site":1.263,"site_s":1.5296,"site_d":1.6362},"恆春鎮":{"code":282,"lat":22.0037401,"lon":120.7472461,"site":1.392,"site_s":1.657,"site_d":2.085},"萬丹鄉":{"code":283,"lat":22.5894894,"lon":120.4850182,"site":1.18,"site_s":1.0882,"site_d":1.3548},"長治鄉":{"code":284,"lat":22.676538,"lon":120.5272963,"site":1.088,"site_s":1.0893,"site_d":1.3561},"麟洛鄉":{"code":285,"lat":22.6506473,"lon":120.5272056,"site":1.077,"site_s":1.0891,"site_d":1.3558},"九如鄉":{"code":286,"lat":22.740429,"lon":120.4903298,"site":0.97,"site_s":1.0889,"site_d":1.3556},"里港鄉":{"code":287,"lat":22.7792625,"lon":120.4944974,"site":1.197,"site_s":1.0882,"site_d":1.3547},"鹽埔鄉":{"code":288,"lat":22.7543743,"lon":120.5727019,"site":1.07,"site_s":0.9987,"site_d":0.9987},"高樹鄉":{"code":289,"lat":22.8267314,"lon":120.600241,"site":1.081,"site_s":1,"site_d":1},"萬巒鄉":{"code":290,"lat":22.5726416,"lon":120.567841,"site":1.209,"site_s":1.0875,"site_d":1.3539},"內埔鄉":{"code":291,"lat":22.6120045,"lon":120.5668293,"site":1.116,"site_s":1.0881,"site_d":1.3546},"竹田鄉":{"code":292,"lat":22.584724,"lon":120.543981,"site":1.132,"site_s":1.0879,"site_d":1.3544},"新埤鄉":{"code":293,"lat":22.4701881,"lon":120.5498736,"site":1.096,"site_s":1.0858,"site_d":1.3518},"枋寮鄉":{"code":294,"lat":22.3655097,"lon":120.5934906,"site":0.949,"site_s":1.2599,"site_d":1.4042},"新園鄉":{"code":295,"lat":22.5438351,"lon":120.4614914,"site":1.36,"site_s":1.0873,"site_d":1.3537},"崁頂鄉":{"code":296,"lat":22.5147343,"lon":120.5140493,"site":1.296,"site_s":1.0868,"site_d":1.353},"林邊鄉":{"code":297,"lat":22.431504,"lon":120.5097562,"site":1.46,"site_s":1.0852,"site_d":1.351},"南州鄉":{"code":298,"lat":22.490404,"lon":120.509879,"site":1.404,"site_s":1.0863,"site_d":1.3524},"佳冬鄉":{"code":299,"lat":22.419209,"lon":120.5524196,"site":1.274,"site_s":1.0849,"site_d":1.3506},"琉球鄉":{"code":300,"lat":22.348635,"lon":120.3827309,"site":1.632,"site_s":1.5275,"site_d":1.634},"車城鄉":{"code":301,"lat":22.0739409,"lon":120.714276,"site":1.045,"site_s":1.6548,"site_d":2.0822},"滿州鄉":{"code":302,"lat":22.020813,"lon":120.838632,"site":1.427,"site_s":1.6545,"site_d":2.0818},"枋山鄉":{"code":303,"lat":22.2639616,"lon":120.6524803,"site":1.363,"site_s":1.2609,"site_d":1.4053},"三地門鄉":{"code":304,"lat":22.7162015,"lon":120.6541301,"site":1.433,"site_s":0.9979,"site_d":0.9979},"霧臺鄉":{"code":305,"lat":22.7490518,"lon":120.7282593,"site":1.401,"site_s":0.9975,"site_d":0.9975},"瑪家鄉":{"code":306,"lat":22.7086763,"lon":120.6494041,"site":1.39,"site_s":0.9978,"site_d":0.9978},"泰武鄉":{"code":307,"lat":22.5919045,"lon":120.6319498,"site":1.084,"site_s":1.0869,"site_d":1.3532},"來義鄉":{"code":308,"lat":22.5261844,"lon":120.6315782,"site":0.774,"site_s":1.0861,"site_d":1.3521},"春日鄉":{"code":309,"lat":22.3710005,"lon":120.6290908,"site":0.837,"site_s":1.2606,"site_d":1.405},"獅子鄉":{"code":310,"lat":22.201775,"lon":120.705438,"site":1.205,"site_s":1.6512,"site_d":2.0776},"牡丹鄉":{"code":311,"lat":22.1261502,"lon":120.7743059,"site":1.17,"site_s":1.6534,"site_d":2.0804}},"臺東縣":{"臺東市":{"code":312,"lat":22.7548208,"lon":121.1465131,"site":1.532,"site_s":1.1479,"site_d":1.2229},"成功鎮":{"code":313,"lat":23.1050697,"lon":121.3808747,"site":1.6,"site_s":1.6645,"site_d":2.1652},"關山鎮":{"code":314,"lat":23.0474453,"lon":121.1630554,"site":1.417,"site_s":1.6664,"site_d":2.1676},"卑南鄉":{"code":315,"lat":22.7827393,"lon":121.0870294,"site":1.334,"site_s":1.1467,"site_d":1.2216},"鹿野鄉":{"code":316,"lat":22.9393083,"lon":121.1519859,"site":1.252,"site_s":1.1443,"site_d":1.2191},"池上鄉":{"code":317,"lat":23.1223101,"lon":121.2151887,"site":1.338,"site_s":1.669,"site_d":2.171},"東河鄉":{"code":318,"lat":22.9689404,"lon":121.3028937,"site":1.657,"site_s":1.664,"site_d":2.1644},"長濱鄉":{"code":319,"lat":23.3149961,"lon":121.4514207,"site":1.513,"site_s":1.2512,"site_d":1.4697},"太麻里鄉":{"code":320,"lat":22.615548,"lon":121.007607,"site":1.462,"site_s":1.1442,"site_d":1.2189},"大武鄉":{"code":321,"lat":22.340518,"lon":120.890073,"site":1.203,"site_s":1.266,"site_d":1.411},"綠島鄉":{"code":322,"lat":22.6658421,"lon":121.4705314,"site":1.287,"site_s":1.1418,"site_d":1.2164},"海端鄉":{"code":323,"lat":23.102057,"lon":121.176541,"site":1.228,"site_s":1.6678,"site_d":2.1695},"延平鄉":{"code":324,"lat":22.9025753,"lon":121.0860671,"site":1.198,"site_s":1.1448,"site_d":1.2196},"金峰鄉":{"code":325,"lat":22.5946397,"lon":120.9607096,"site":1.328,"site_s":1.1433,"site_d":1.218},"達仁鄉":{"code":326,"lat":22.296818,"lon":120.882973,"site":1.06,"site_s":1.265,"site_d":1.4099},"蘭嶼鄉":{"code":327,"lat":22.0244984,"lon":121.5560627,"site":2.15,"site_s":1.2508,"site_d":1.3941}},"花蓮縣":{"花蓮市":{"code":328,"lat":23.9820651,"lon":121.6067705,"site":1.433,"site_s":1.5194,"site_d":1.5864},"鳳林鎮":{"code":329,"lat":23.7447637,"lon":121.4515822,"site":1.379,"site_s":1.9153,"site_d":1.8274},"玉里鎮":{"code":330,"lat":23.335527,"lon":121.315197,"site":0.956,"site_s":1.254,"site_d":1.473},"新城鄉":{"code":331,"lat":24.0392994,"lon":121.6041173,"site":1.215,"site_s":1.519,"site_d":1.5859},"吉安鄉":{"code":332,"lat":23.9729455,"lon":121.5636438,"site":1.37,"site_s":1.5185,"site_d":1.5855},"壽豐鄉":{"code":333,"lat":23.8703424,"lon":121.5088259,"site":1.496,"site_s":1.5157,"site_d":1.5825},"光復鄉":{"code":334,"lat":23.669342,"lon":121.4233065,"site":1.396,"site_s":1.918,"site_d":1.83},"豐濱鄉":{"code":335,"lat":23.6012024,"lon":121.5211488,"site":1.223,"site_s":1.9142,"site_d":1.8264},"瑞穗鄉":{"code":336,"lat":23.4964553,"lon":121.3757788,"site":1.091,"site_s":1.2503,"site_d":1.4686},"富里鄉":{"code":337,"lat":23.1794845,"lon":121.250233,"site":1.263,"site_s":1.6671,"site_d":2.1685},"秀林鄉":{"code":338,"lat":24.1185835,"lon":121.6248326,"site":1.364,"site_s":1.5169,"site_d":1.5838},"萬榮鄉":{"code":339,"lat":23.714875,"lon":121.4109617,"site":1.794,"site_s":1.9164,"site_d":1.8285},"卓溪鄉":{"code":340,"lat":23.346478,"lon":121.303451,"site":1.004,"site_s":1.2537,"site_d":1.4726}},"宜蘭縣":{"宜蘭市":{"code":341,"lat":24.7520373,"lon":121.7531493,"site":1.609,"site_s":1.8492,"site_d":2.7708},"羅東鎮":{"code":342,"lat":24.6769245,"lon":121.7669529,"site":1.601,"site_s":1.8483,"site_d":2.7694},"蘇澳鎮":{"code":343,"lat":24.594315,"lon":121.8421903,"site":1.573,"site_s":2.421,"site_d":2.381},"頭城鎮":{"code":344,"lat":24.8548387,"lon":121.8213189,"site":0.733,"site_s":1.1095,"site_d":1.4747},"礁溪鄉":{"code":345,"lat":24.8234257,"lon":121.7711725,"site":0.949,"site_s":1.847,"site_d":2.7675},"壯圍鄉":{"code":346,"lat":24.746832,"lon":121.785759,"site":1.702,"site_s":1.8491,"site_d":2.7707},"員山鄉":{"code":347,"lat":24.7433944,"lon":121.7232538,"site":1.179,"site_s":1.8488,"site_d":2.7701},"冬山鄉":{"code":348,"lat":24.634338,"lon":121.792851,"site":1.387,"site_s":2.4185,"site_d":2.3785},"五結鄉":{"code":349,"lat":24.684772,"lon":121.7982898,"site":1.519,"site_s":1.8482,"site_d":2.7693},"三星鄉":{"code":350,"lat":24.665483,"lon":121.654047,"site":0.833,"site_s":1.3289,"site_d":2.1846},"大同鄉":{"code":351,"lat":24.677412,"lon":121.6090927,"site":1.188,"site_s":1.3296,"site_d":2.1858},"南澳鄉":{"code":352,"lat":24.465996,"lon":121.803714,"site":1.514,"site_s":2.4154,"site_d":2.3755}},"澎湖縣":{"馬公市":{"code":353,"lat":23.566159,"lon":119.578692,"site":2.42,"site_s":0.9998,"site_d":0.9998},"湖西鄉":{"code":354,"lat":23.584072,"lon":119.6528318,"site":2.42,"site_s":0.9986,"site_d":0.9986},"白沙鄉":{"code":355,"lat":23.666538,"lon":119.598639,"site":2.42,"site_s":0.9982,"site_d":0.9982},"西嶼鄉":{"code":356,"lat":23.601088,"lon":119.5069847,"site":2.42,"site_s":0.9989,"site_d":0.9989},"望安鄉":{"code":357,"lat":23.3576577,"lon":119.500894,"site":2.42,"site_s":0.9962,"site_d":0.9962},"七美鄉":{"code":358,"lat":23.2067107,"lon":119.4244825,"site":2.42,"site_s":0.9933,"site_d":0.9933}},"金門縣":{"金城鎮":{"code":359,"lat":24.432824,"lon":118.320697,"site_s":0.9999,"site_d":0.9999},"金沙鎮":{"code":360,"lat":24.488898,"lon":118.413132,"site_s":0.9983,"site_d":0.9983},"金湖鎮":{"code":361,"lat":24.4414641,"lon":118.4171018,"site_s":0.9984,"site_d":0.9984},"金寧鄉":{"code":362,"lat":24.450966,"lon":118.334887,"site_s":0.9996,"site_d":0.9996},"烈嶼鄉":{"code":363,"lat":24.4295409,"lon":118.2445892,"site_s":0.9988,"site_d":0.9988},"烏坵鄉":{"code":364,"lat":24.9887062,"lon":119.4531826,"site_s":0.98,"site_d":0.98}},"連江縣":{"南竿鄉":{"code":365,"lat":26.1529312,"lon":119.9387995,"site_s":0.9998,"site_d":0.9998},"北竿鄉":{"code":366,"lat":26.223938,"lon":119.997139,"site_s":0.9986,"site_d":0.9986},"莒光鄉":{"code":367,"lat":25.9687384,"lon":119.9369689,"site_s":0.9967,"site_d":0.9967},"東引鄉":{"code":368,"lat":26.3672636,"lon":120.4898789,"site_s":0.9909,"site_d":0.9909}}}
\ No newline at end of file
+{"基隆市":{"中正區":{"code":202,"lat":25.1407924,"lon":121.7592534,"site":1.077,"area":"基隆市東部"},"七堵區":{"code":206,"lat":25.097653,"lon":121.7165013,"site":1.866,"area":"基隆市西部"},"暖暖區":{"code":205,"lat":25.1001834,"lon":121.735933,"site":1.718,"area":"基隆市東部"},"仁愛區":{"code":200,"lat":25.125069,"lon":121.736754,"site":1.348,"area":"基隆市東部"},"中山區":{"code":203,"lat":25.152899,"lon":121.729552,"site":1.268,"area":"基隆市西部"},"安樂區":{"code":204,"lat":25.121176,"lon":121.7230804,"site":1.16,"area":"基隆市西部"},"信義區":{"code":201,"lat":25.1294717,"lon":121.7512671,"site":1.353,"area":"基隆市東部"}},"臺北市":{"松山區":{"code":105,"lat":25.049847,"lon":121.577241,"site":1.96,"area":"臺北市南部"},"信義區":{"code":110,"lat":25.0331574,"lon":121.5668777,"site":2.106,"area":"臺北市南部"},"大安區":{"code":106,"lat":25.02642,"lon":121.534511,"site":1.833,"area":"臺北市南部"},"中山區":{"code":104,"lat":25.0642771,"lon":121.5335776,"site":1.924,"area":"臺北市南部"},"中正區":{"code":100,"lat":25.0443212,"lon":121.5247613,"site":1.944,"area":"臺北市南部"},"大同區":{"code":103,"lat":25.0661934,"lon":121.515268,"site":2,"area":"臺北市南部"},"萬華區":{"code":108,"lat":25.034839,"lon":121.4997957,"site":1.724,"area":"臺北市南部"},"文山區":{"code":116,"lat":24.98964,"lon":121.5700826,"site":1.532,"area":"臺北市南部"},"南港區":{"code":115,"lat":25.0547059,"lon":121.6066929,"site":2.268,"area":"臺北市南部"},"內湖區":{"code":114,"lat":25.06929,"lon":121.588949,"site":2.023,"area":"臺北市北部"},"士林區":{"code":111,"lat":25.0927548,"lon":121.519565,"site":1.538,"area":"臺北市北部"},"北投區":{"code":112,"lat":25.1323666,"lon":121.5029268,"site":1.534,"area":"臺北市北部"}},"新北市":{"板橋區":{"code":220,"lat":25.0096156,"lon":121.4592358,"site":2.065,"area":"新北市北部"},"三重區":{"code":241,"lat":25.0607692,"lon":121.4884178,"site":1.926,"area":"新北市北部"},"中和區":{"code":235,"lat":24.9985208,"lon":121.5007413,"site":1.948,"area":"新北市北部"},"永和區":{"code":234,"lat":25.0091768,"lon":121.5202731,"site":1.873,"area":"新北市北部"},"新莊區":{"code":242,"lat":25.035976,"lon":121.450478,"site":2.623,"area":"新北市北部"},"新店區":{"code":231,"lat":24.9749713,"lon":121.5431673,"site":1.931,"area":"新北市南部"},"樹林區":{"code":238,"lat":24.9899673,"lon":121.4246321,"site":1.443,"area":"新北市北部"},"鶯歌區":{"code":239,"lat":24.9560294,"lon":121.3544312,"site":0.959,"area":"新北市北部"},"三峽區":{"code":237,"lat":24.9341863,"lon":121.369083,"site":1.325,"area":"新北市南部"},"淡水區":{"code":251,"lat":25.1696463,"lon":121.4409722,"site":1.999,"area":"新北市北部"},"汐止區":{"code":221,"lat":25.064261,"lon":121.65869,"site":2.09,"area":"新北市北部"},"瑞芳區":{"code":224,"lat":25.1087635,"lon":121.8098935,"site":1.286,"area":"新北市北部"},"土城區":{"code":236,"lat":24.9723361,"lon":121.4429389,"site":1.667,"area":"新北市北部"},"蘆洲區":{"code":247,"lat":25.0847112,"lon":121.4737354,"site":1.936,"area":"新北市北部"},"五股區":{"code":248,"lat":25.0830393,"lon":121.4380781,"site":1.541,"area":"新北市北部"},"泰山區":{"code":243,"lat":25.059291,"lon":121.431495,"site":2.448,"area":"新北市北部"},"林口區":{"code":244,"lat":25.0768252,"lon":121.3886134,"site":2.111,"area":"新北市北部"},"深坑區":{"code":222,"lat":25.0025007,"lon":121.615944,"site":1.542,"area":"新北市北部"},"石碇區":{"code":223,"lat":24.9914859,"lon":121.6579019,"site":1.423,"area":"新北市南部"},"坪林區":{"code":232,"lat":24.9361367,"lon":121.7117653,"site":0.93,"area":"新北市南部"},"三芝區":{"code":252,"lat":25.257748,"lon":121.5009345,"site":1.412,"area":"新北市北部"},"石門區":{"code":253,"lat":25.291248,"lon":121.567631,"site":1.406,"area":"新北市北部"},"八里區":{"code":249,"lat":25.1537592,"lon":121.4064305,"site":2.13,"area":"新北市北部"},"平溪區":{"code":226,"lat":25.026689,"lon":121.73819,"site":1.543,"area":"新北市北部"},"雙溪區":{"code":227,"lat":25.0337322,"lon":121.8657341,"site":1.622,"area":"新北市北部"},"貢寮區":{"code":228,"lat":25.021812,"lon":121.910293,"site":0.954,"area":"新北市北部"},"金山區":{"code":208,"lat":25.222241,"lon":121.636629,"site":1.586,"area":"新北市北部"},"萬里區":{"code":207,"lat":25.178066,"lon":121.689548,"site":1.581,"area":"新北市北部"},"烏來區":{"code":233,"lat":24.8717802,"lon":121.5478634,"site":1.164,"area":"新北市南部"}},"桃園市":{"桃園區":{"code":330,"lat":24.993919,"lon":121.3016657,"site":1.417,"area":"桃園市北部"},"中壢區":{"code":320,"lat":24.9656124,"lon":121.2249927,"site":1.536,"area":"桃園市北部"},"大溪區":{"code":335,"lat":24.880548,"lon":121.287142,"site":1.498,"area":"桃園市南部"},"楊梅區":{"code":326,"lat":24.9128508,"lon":121.1444587,"site":1.328,"area":"桃園市南部"},"蘆竹區":{"code":338,"lat":25.046925,"lon":121.295077,"site":1.858,"area":"桃園市北部"},"大園區":{"code":337,"lat":25.0638556,"lon":121.1954603,"site":1.752,"area":"桃園市北部"},"龜山區":{"code":333,"lat":24.9925139,"lon":121.337824,"site":2.038,"area":"桃園市北部"},"八德區":{"code":334,"lat":24.9289862,"lon":121.2846406,"site":1.568,"area":"桃園市北部"},"龍潭區":{"code":325,"lat":24.8704855,"lon":121.2224472,"site":1.427,"area":"桃園市南部"},"平鎮區":{"code":324,"lat":24.9456694,"lon":121.2181884,"site":1.549,"area":"桃園市南部"},"新屋區":{"code":327,"lat":24.9725439,"lon":121.105533,"site":1.309,"area":"桃園市北部"},"觀音區":{"code":328,"lat":25.0276516,"lon":121.0836028,"site":1.326,"area":"桃園市北部"},"復興區":{"code":336,"lat":24.8147989,"lon":121.3511305,"site":1.148,"area":"桃園市南部"}},"新竹市":{"東區":{"code":301,"lat":24.8051881,"lon":120.9732327,"site":2.41,"area":"新竹市東部"},"北區":{"code":300,"lat":24.8163726,"lon":120.9703141,"site":1.373,"area":"新竹市西部"},"香山區":{"code":300,"lat":24.7940445,"lon":120.9422678,"site":1.902,"area":"新竹市西部"}},"新竹縣":{"竹北市":{"code":302,"lat":24.8395807,"lon":121.0040235,"site":2.246,"area":"新竹縣北部"},"竹東鎮":{"code":310,"lat":24.7366942,"lon":121.0916513,"site":1.881,"area":"新竹縣北部"},"新埔鎮":{"code":305,"lat":24.8256201,"lon":121.0740799,"site":1.555,"area":"新竹縣北部"},"關西鎮":{"code":306,"lat":24.7922806,"lon":121.1759547,"site":1.558,"area":"新竹縣北部"},"湖口鄉":{"code":303,"lat":24.9010068,"lon":121.0478749,"site":1.07,"area":"新竹縣北部"},"新豐鄉":{"code":304,"lat":24.9007026,"lon":120.9852313,"site":1.395,"area":"新竹縣北部"},"芎林鄉":{"code":307,"lat":24.773309,"lon":121.081855,"site":1.773,"area":"新竹縣北部"},"橫山鄉":{"code":312,"lat":24.7167807,"lon":121.1414985,"site":1.653,"area":"新竹縣南部"},"北埔鄉":{"code":314,"lat":24.7019901,"lon":121.0563354,"site":1.797,"area":"新竹縣南部"},"寶山鄉":{"code":308,"lat":24.7654715,"lon":120.9913066,"site":1.758,"area":"新竹縣北部"},"峨眉鄉":{"code":315,"lat":24.6887921,"lon":121.0195946,"site":1.696,"area":"新竹縣南部"},"尖石鄉":{"code":313,"lat":24.705004,"lon":121.2020864,"site":1.262,"area":"新竹縣南部"},"五峰鄉":{"code":311,"lat":24.6320786,"lon":121.119596,"site":1.275,"area":"新竹縣南部"}},"苗栗縣":{"苗栗市":{"code":360,"lat":24.5616772,"lon":120.8190175,"site":1.705,"area":"苗栗縣北部"},"苑裡鎮":{"code":358,"lat":24.4396522,"lon":120.653261,"site":1.714,"area":"苗栗縣北部"},"通霄鎮":{"code":357,"lat":24.4912805,"lon":120.684249,"site":1.679,"area":"苗栗縣北部"},"竹南鎮":{"code":350,"lat":24.6838448,"lon":120.8733503,"site":2.078,"area":"苗栗縣北部"},"頭份市":{"code":351,"lat":24.6865276,"lon":120.9132454,"site":1.98,"area":"苗栗縣北部"},"後龍鎮":{"code":356,"lat":24.613682,"lon":120.792046,"site":1.839,"area":"苗栗縣北部"},"卓蘭鎮":{"code":369,"lat":24.3130501,"lon":120.8245152,"site":1.196,"area":"苗栗縣南部"},"大湖鄉":{"code":364,"lat":24.4234081,"lon":120.8661781,"site":1.116,"area":"苗栗縣南部"},"公館鄉":{"code":363,"lat":24.5058646,"lon":120.8284935,"site":1.292,"area":"苗栗縣南部"},"銅鑼鄉":{"code":366,"lat":24.4870514,"lon":120.7878718,"site":1.456,"area":"苗栗縣南部"},"南庄鄉":{"code":353,"lat":24.5970648,"lon":121.000339,"site":1.119,"area":"苗栗縣北部"},"頭屋鄉":{"code":362,"lat":24.5778158,"lon":120.8511057,"site":1.399,"area":"苗栗縣北部"},"三義鄉":{"code":367,"lat":24.4129179,"lon":120.7702392,"site":1.239,"area":"苗栗縣南部"},"西湖鄉":{"code":368,"lat":24.5567613,"lon":120.7570814,"site":1.544,"area":"苗栗縣北部"},"造橋鄉":{"code":361,"lat":24.638552,"lon":120.8651632,"site":1.807,"area":"苗栗縣北部"},"三灣鄉":{"code":352,"lat":24.6531425,"lon":120.9566265,"site":1.65,"area":"苗栗縣北部"},"獅潭鄉":{"code":354,"lat":24.539419,"lon":120.920496,"site":1.092,"area":"苗栗縣北部"},"泰安鄉":{"code":365,"lat":24.4471976,"lon":120.9081718,"site":0.985,"area":"苗栗縣南部"}},"臺中市":{"中區":{"code":400,"lat":24.1439458,"lon":120.6794414,"site":1.639,"area":"臺中市西部"},"東區":{"code":401,"lat":24.1366469,"lon":120.7037332,"site":1.24,"area":"臺中市西部"},"南區":{"code":402,"lat":24.1171412,"lon":120.6635905,"site":1.633,"area":"臺中市西部"},"西區":{"code":403,"lat":24.1413252,"lon":120.6710753,"site":1.431,"area":"臺中市西部"},"北區":{"code":404,"lat":24.1658534,"lon":120.6822936,"site":1.211,"area":"臺中市西部"},"西屯區":{"code":407,"lat":24.1658213,"lon":120.6336717,"site":1.149,"area":"臺中市西部"},"南屯區":{"code":408,"lat":24.1345298,"lon":120.6442903,"site":1.506,"area":"臺中市西部"},"北屯區":{"code":406,"lat":24.1826848,"lon":120.686403,"site":1.1,"area":"臺中市西部"},"豐原區":{"code":420,"lat":24.2419087,"lon":120.7181281,"site":1.207,"area":"臺中市西部"},"東勢區":{"code":423,"lat":24.2585728,"lon":120.8279546,"site":1.631,"area":"臺中市西部"},"大甲區":{"code":437,"lat":24.349083,"lon":120.622468,"site":1.403,"area":"臺中市西部"},"清水區":{"code":436,"lat":24.2681562,"lon":120.559717,"site":1.749,"area":"臺中市西部"},"沙鹿區":{"code":433,"lat":24.2333313,"lon":120.566317,"site":1.309,"area":"臺中市西部"},"梧棲區":{"code":435,"lat":24.2549063,"lon":120.5317002,"site":1.967,"area":"臺中市西部"},"后里區":{"code":421,"lat":24.3049377,"lon":120.7107454,"site":1.192,"area":"臺中市西部"},"神岡區":{"code":429,"lat":24.2579749,"lon":120.6614216,"site":1.119,"area":"臺中市西部"},"潭子區":{"code":427,"lat":24.2031708,"lon":120.7228978,"site":1.289,"area":"臺中市西部"},"大雅區":{"code":428,"lat":24.2291463,"lon":120.6478436,"site":1.063,"area":"臺中市西部"},"新社區":{"code":426,"lat":24.233957,"lon":120.809416,"site":1.299,"area":"臺中市西部"},"石岡區":{"code":422,"lat":24.274898,"lon":120.7803458,"site":1.227,"area":"臺中市西部"},"外埔區":{"code":438,"lat":24.3321248,"lon":120.654334,"site":1.276,"area":"臺中市西部"},"大安區":{"code":439,"lat":24.346126,"lon":120.5866075,"site":1.383,"area":"臺中市西部"},"烏日區":{"code":414,"lat":24.104605,"lon":120.6238467,"site":1.788,"area":"臺中市西部"},"大肚區":{"code":432,"lat":24.1511295,"lon":120.5457643,"site":1.81,"area":"臺中市西部"},"龍井區":{"code":434,"lat":24.1924488,"lon":120.5457999,"site":1.839,"area":"臺中市西部"},"霧峰區":{"code":413,"lat":24.0613153,"lon":120.7000868,"site":1.763,"area":"臺中市西部"},"太平區":{"code":411,"lat":24.1266572,"lon":120.7185562,"site":1.193,"area":"臺中市西部"},"大里區":{"code":412,"lat":24.0994693,"lon":120.6778413,"site":1.629,"area":"臺中市西部"},"和平區":{"code":424,"lat":24.1752225,"lon":120.8835809,"site":1.222,"area":"臺中市東部"}},"彰化縣":{"彰化市":{"code":500,"lat":24.0809056,"lon":120.5422565,"site":2.055,"area":"彰化縣北部"},"鹿港鎮":{"code":505,"lat":24.0572566,"lon":120.4350548,"site":2.217,"area":"彰化縣北部"},"和美鎮":{"code":508,"lat":24.1085584,"lon":120.4941497,"site":1.797,"area":"彰化縣北部"},"線西鄉":{"code":507,"lat":24.1306678,"lon":120.470656,"site":2.288,"area":"彰化縣北部"},"伸港鄉":{"code":509,"lat":24.1596067,"lon":120.4861141,"site":2.116,"area":"彰化縣北部"},"福興鄉":{"code":506,"lat":24.0478713,"lon":120.4439546,"site":2.046,"area":"彰化縣北部"},"秀水鄉":{"code":504,"lat":24.035321,"lon":120.5028098,"site":2.109,"area":"彰化縣北部"},"花壇鄉":{"code":503,"lat":24.0296582,"lon":120.5382578,"site":1.661,"area":"彰化縣北部"},"芬園鄉":{"code":502,"lat":24.013628,"lon":120.628964,"site":1.643,"area":"彰化縣北部"},"員林市":{"code":510,"lat":23.9589162,"lon":120.5743943,"site":1.692,"area":"彰化縣南部"},"溪湖鎮":{"code":514,"lat":23.9664245,"lon":120.4832787,"site":2.079,"area":"彰化縣南部"},"田中鎮":{"code":520,"lat":23.8614831,"lon":120.5809585,"site":1.399,"area":"彰化縣南部"},"大村鄉":{"code":515,"lat":23.9934239,"lon":120.547268,"site":1.682,"area":"彰化縣北部"},"埔鹽鄉":{"code":516,"lat":24.000442,"lon":120.4636578,"site":1.998,"area":"彰化縣北部"},"埔心鄉":{"code":513,"lat":23.952988,"lon":120.54354,"site":1.817,"area":"彰化縣南部"},"永靖鄉":{"code":512,"lat":23.9245962,"lon":120.5477204,"site":1.919,"area":"彰化縣南部"},"社頭鄉":{"code":511,"lat":23.8968186,"lon":120.5858074,"site":1.488,"area":"彰化縣南部"},"二水鄉":{"code":530,"lat":23.8066858,"lon":120.6190203,"site":1.501,"area":"彰化縣南部"},"北斗鎮":{"code":521,"lat":23.8713826,"lon":120.5218625,"site":1.957,"area":"彰化縣南部"},"二林鎮":{"code":526,"lat":23.8998045,"lon":120.3742654,"site":2.2,"area":"彰化縣南部"},"田尾鄉":{"code":522,"lat":23.8922407,"lon":120.5259709,"site":2.175,"area":"彰化縣南部"},"埤頭鄉":{"code":523,"lat":23.8914618,"lon":120.4621725,"site":2.32,"area":"彰化縣南部"},"芳苑鄉":{"code":528,"lat":23.924354,"lon":120.320389,"site":2.117,"area":"彰化縣南部"},"大城鄉":{"code":527,"lat":23.852314,"lon":120.3208972,"site":2.15,"area":"彰化縣南部"},"竹塘鄉":{"code":525,"lat":23.8605045,"lon":120.4277961,"site":2.029,"area":"彰化縣南部"},"溪州鄉":{"code":524,"lat":23.8516188,"lon":120.498976,"site":1.834,"area":"彰化縣南部"}},"南投縣":{"南投市":{"code":540,"lat":23.9116414,"lon":120.6874199,"site":1.566,"area":"南投縣西部"},"埔里鎮":{"code":545,"lat":23.9665377,"lon":120.9691809,"site":1.129,"area":"南投縣西部"},"草屯鎮":{"code":542,"lat":23.9736845,"lon":120.6802819,"site":1.551,"area":"南投縣西部"},"竹山鎮":{"code":557,"lat":23.7578635,"lon":120.6716995,"site":1.36,"area":"南投縣西部"},"集集鎮":{"code":552,"lat":23.8283683,"lon":120.7864885,"site":1.19,"area":"南投縣西部"},"名間鄉":{"code":551,"lat":23.8382161,"lon":120.702985,"site":1.467,"area":"南投縣西部"},"鹿谷鄉":{"code":558,"lat":23.7458415,"lon":120.7534428,"site":1.183,"area":"南投縣西部"},"中寮鄉":{"code":541,"lat":23.8790067,"lon":120.7660301,"site":1.647,"area":"南投縣西部"},"魚池鄉":{"code":555,"lat":23.8957849,"lon":120.9356849,"site":1.003,"area":"南投縣西部"},"國姓鄉":{"code":544,"lat":24.040019,"lon":120.8575192,"site":1.079,"area":"南投縣西部"},"水里鄉":{"code":553,"lat":23.8113991,"lon":120.8560852,"site":1.004,"area":"南投縣西部"},"信義鄉":{"code":556,"lat":23.696797,"lon":120.854557,"site":1.236,"area":"南投縣東部"},"仁愛鄉":{"code":546,"lat":24.021544,"lon":121.1320616,"site":1.207,"area":"南投縣東部"}},"雲林縣":{"斗六市":{"code":640,"lat":23.6971143,"lon":120.5269987,"site":1.924,"area":"雲林縣東部"},"斗南鎮":{"code":630,"lat":23.680105,"lon":120.47772,"site":1.783,"area":"雲林縣東部"},"虎尾鎮":{"code":632,"lat":23.7083539,"lon":120.4451923,"site":1.997,"area":"雲林縣東部"},"西螺鎮":{"code":648,"lat":23.7977736,"lon":120.465685,"site":1.751,"area":"雲林縣東部"},"土庫鎮":{"code":633,"lat":23.6820621,"lon":120.3899062,"site":1.907,"area":"雲林縣西部"},"北港鎮":{"code":651,"lat":23.5759236,"lon":120.302446,"site":1.797,"area":"雲林縣西部"},"古坑鄉":{"code":646,"lat":23.6426312,"lon":120.5619595,"site":1.824,"area":"雲林縣東部"},"大埤鄉":{"code":631,"lat":23.6460343,"lon":120.4314818,"site":2.071,"area":"雲林縣東部"},"莿桐鄉":{"code":647,"lat":23.7610077,"lon":120.5025072,"site":1.914,"area":"雲林縣東部"},"林內鄉":{"code":643,"lat":23.7562156,"lon":120.6129427,"site":1.656,"area":"雲林縣東部"},"二崙鄉":{"code":649,"lat":23.7711012,"lon":120.4129596,"site":1.825,"area":"雲林縣西部"},"崙背鄉":{"code":637,"lat":23.7619087,"lon":120.3591424,"site":1.818,"area":"雲林縣西部"},"麥寮鄉":{"code":638,"lat":23.7539853,"lon":120.2513078,"site":2.471,"area":"雲林縣西部"},"東勢鄉":{"code":635,"lat":23.6753034,"lon":120.2525936,"site":2.434,"area":"雲林縣西部"},"褒忠鄉":{"code":634,"lat":23.691007,"lon":120.3037335,"site":2.025,"area":"雲林縣西部"},"臺西鄉":{"code":636,"lat":23.700477,"lon":120.1957632,"site":2.379,"area":"雲林縣西部"},"元長鄉":{"code":655,"lat":23.6497447,"lon":120.3148349,"site":1.902,"area":"雲林縣西部"},"四湖鄉":{"code":654,"lat":23.6378317,"lon":120.2242949,"site":2.09,"area":"雲林縣西部"},"口湖鄉":{"code":653,"lat":23.5827378,"lon":120.1858552,"site":2.016,"area":"雲林縣西部"},"水林鄉":{"code":652,"lat":23.5727035,"lon":120.2459507,"site":1.816,"area":"雲林縣西部"}},"嘉義市":{"東區":{"code":600,"lat":23.4786578,"lon":120.4534596,"site":1.857,"area":"嘉義市東部"},"西區":{"code":601,"lat":23.4646967,"lon":120.4352822,"site":2.105,"area":"嘉義市西部"}},"嘉義縣":{"太保市":{"code":612,"lat":23.458967,"lon":120.3323479,"site":2.013,"area":"嘉義縣西部"},"朴子市":{"code":613,"lat":23.4575288,"lon":120.2459226,"site":2.029,"area":"嘉義縣西部"},"布袋鎮":{"code":625,"lat":23.3781734,"lon":120.1669564,"site":1.768,"area":"嘉義縣西部"},"大林鎮":{"code":622,"lat":23.603931,"lon":120.471178,"site":2.006,"area":"嘉義縣西部"},"民雄鄉":{"code":621,"lat":23.5516417,"lon":120.4283616,"site":1.989,"area":"嘉義縣西部"},"溪口鄉":{"code":623,"lat":23.6025304,"lon":120.392323,"site":2,"area":"嘉義縣西部"},"新港鄉":{"code":616,"lat":23.5519744,"lon":120.3478039,"site":1.758,"area":"嘉義縣西部"},"六腳鄉":{"code":615,"lat":23.4940922,"lon":120.2907962,"site":1.99,"area":"嘉義縣西部"},"東石鄉":{"code":614,"lat":23.4587147,"lon":120.1537883,"site":2.399,"area":"嘉義縣西部"},"義竹鄉":{"code":624,"lat":23.3361064,"lon":120.2430475,"site":2.322,"area":"嘉義縣西部"},"鹿草鄉":{"code":611,"lat":23.4113835,"lon":120.3082682,"site":1.852,"area":"嘉義縣西部"},"水上鄉":{"code":608,"lat":23.428531,"lon":120.398035,"site":1.995,"area":"嘉義縣西部"},"中埔鄉":{"code":606,"lat":23.425139,"lon":120.522952,"site":1.726,"area":"嘉義縣東部"},"竹崎鄉":{"code":604,"lat":23.5230788,"lon":120.5513988,"site":1.666,"area":"嘉義縣東部"},"梅山鄉":{"code":603,"lat":23.5850678,"lon":120.5554676,"site":1.421,"area":"嘉義縣東部"},"番路鄉":{"code":602,"lat":23.4644973,"lon":120.554286,"site":1.06,"area":"嘉義縣東部"},"大埔鄉":{"code":607,"lat":23.2986941,"lon":120.5869311,"site":1.192,"area":"嘉義縣東部"},"阿里山鄉":{"code":605,"lat":23.4712117,"lon":120.7135217,"site":1.031,"area":"嘉義縣東部"}},"臺南市":{"新營區":{"code":730,"lat":23.3101426,"lon":120.3167031,"site":2.103,"area":"臺南市北部"},"鹽水區":{"code":737,"lat":23.320027,"lon":120.266097,"site":1.829,"area":"臺南市北部"},"白河區":{"code":732,"lat":23.3512886,"lon":120.415752,"site":1.057,"area":"臺南市北部"},"柳營區":{"code":736,"lat":23.278395,"lon":120.311673,"site":1.788,"area":"臺南市北部"},"後壁區":{"code":731,"lat":23.3659836,"lon":120.3619362,"site":1.736,"area":"臺南市北部"},"東山區":{"code":733,"lat":23.3261625,"lon":120.4045009,"site":1.403,"area":"臺南市北部"},"麻豆區":{"code":721,"lat":23.1849449,"lon":120.2584456,"site":2.204,"area":"臺南市北部"},"下營區":{"code":735,"lat":23.2356921,"lon":120.2643838,"site":1.98,"area":"臺南市北部"},"六甲區":{"code":734,"lat":23.2318098,"lon":120.3474201,"site":1.782,"area":"臺南市北部"},"官田區":{"code":720,"lat":23.1930442,"lon":120.3154967,"site":1.704,"area":"臺南市北部"},"大內區":{"code":742,"lat":23.1192073,"lon":120.3568212,"site":1.533,"area":"臺南市南部"},"佳里區":{"code":722,"lat":23.1652648,"lon":120.1770306,"site":2.17,"area":"臺南市北部"},"學甲區":{"code":726,"lat":23.2304835,"lon":120.1822926,"site":2.166,"area":"臺南市北部"},"西港區":{"code":723,"lat":23.1229825,"lon":120.203413,"site":2.601,"area":"臺南市南部"},"七股區":{"code":724,"lat":23.1403809,"lon":120.1391359,"site":1.977,"area":"臺南市南部"},"將軍區":{"code":725,"lat":23.19905,"lon":120.158702,"site":1.888,"area":"臺南市北部"},"北門區":{"code":727,"lat":23.267723,"lon":120.125445,"site":2.124,"area":"臺南市北部"},"新化區":{"code":712,"lat":23.0385411,"lon":120.310896,"site":2.087,"area":"臺南市南部"},"善化區":{"code":741,"lat":23.1324288,"lon":120.2967849,"site":1.968,"area":"臺南市北部"},"新市區":{"code":744,"lat":23.0789967,"lon":120.2951827,"site":2.416,"area":"臺南市南部"},"安定區":{"code":745,"lat":23.121593,"lon":120.237118,"site":2.829,"area":"臺南市南部"},"山上區":{"code":743,"lat":23.1036173,"lon":120.3526487,"site":1.771,"area":"臺南市南部"},"玉井區":{"code":714,"lat":23.1237866,"lon":120.4601109,"site":1.161,"area":"臺南市南部"},"楠西區":{"code":715,"lat":23.174143,"lon":120.486337,"site":1.145,"area":"臺南市北部"},"南化區":{"code":716,"lat":23.042988,"lon":120.477816,"site":0.857,"area":"臺南市南部"},"左鎮區":{"code":713,"lat":23.0567783,"lon":120.408708,"site":1.569,"area":"臺南市南部"},"仁德區":{"code":717,"lat":22.97243,"lon":120.251685,"site":1.342,"area":"臺南市南部"},"歸仁區":{"code":711,"lat":22.967286,"lon":120.2940045,"site":1.751,"area":"臺南市南部"},"關廟區":{"code":718,"lat":22.9630039,"lon":120.3278144,"site":1.747,"area":"臺南市南部"},"龍崎區":{"code":719,"lat":22.9632926,"lon":120.3649712,"site":1.57,"area":"臺南市南部"},"永康區":{"code":710,"lat":23.0260699,"lon":120.2570647,"site":1.951,"area":"臺南市南部"},"東區":{"code":701,"lat":22.9802421,"lon":120.224004,"site":1.711,"area":"臺南市南部"},"南區":{"code":702,"lat":22.9611326,"lon":120.1885687,"site":1.486,"area":"臺南市南部"},"北區":{"code":704,"lat":22.9997522,"lon":120.2030341,"site":2.299,"area":"臺南市南部"},"安南區":{"code":709,"lat":23.0472321,"lon":120.184714,"site":2.236,"area":"臺南市南部"},"安平區":{"code":708,"lat":22.9945789,"lon":120.1688523,"site":1.888,"area":"臺南市南部"},"中西區":{"code":700,"lat":22.9922364,"lon":120.2056571,"site":2.264,"area":"臺南市南部"}},"高雄市":{"鹽埕區":{"code":803,"lat":22.6247166,"lon":120.2868098,"site":1.496,"area":"高雄市西部"},"鼓山區":{"code":804,"lat":22.636776,"lon":120.2809626,"site":1.173,"area":"高雄市西部"},"左營區":{"code":813,"lat":22.6899834,"lon":120.2950135,"site":1.399,"area":"高雄市西部"},"楠梓區":{"code":811,"lat":22.7283655,"lon":120.3263681,"site":1.394,"area":"高雄市西部"},"三民區":{"code":807,"lat":22.647684,"lon":120.299851,"site":1.279,"area":"高雄市西部"},"新興區":{"code":800,"lat":22.6310347,"lon":120.3101095,"site":1.565,"area":"高雄市西部"},"前金區":{"code":801,"lat":22.6275276,"lon":120.2942181,"site":1.669,"area":"高雄市西部"},"苓雅區":{"code":802,"lat":22.621759,"lon":120.312194,"site":1.436,"area":"高雄市西部"},"前鎮區":{"code":806,"lat":22.5865658,"lon":120.318307,"site":1.569,"area":"高雄市西部"},"旗津區":{"code":805,"lat":22.5900263,"lon":120.28471,"site":1.709,"area":"高雄市西部"},"小港區":{"code":812,"lat":22.5652134,"lon":120.3380368,"site":2.106,"area":"高雄市西部"},"鳳山區":{"code":830,"lat":22.627075,"lon":120.362525,"site":1.582,"area":"高雄市西部"},"林園區":{"code":832,"lat":22.5129453,"lon":120.3946805,"site":1.319,"area":"高雄市西部"},"大寮區":{"code":831,"lat":22.6055196,"lon":120.3956199,"site":1.901,"area":"高雄市西部"},"大樹區":{"code":840,"lat":22.6839054,"lon":120.4143416,"site":1.065,"area":"高雄市西部"},"大社區":{"code":815,"lat":22.730156,"lon":120.346671,"site":1.135,"area":"高雄市西部"},"仁武區":{"code":814,"lat":22.7013806,"lon":120.3479837,"site":1.14,"area":"高雄市西部"},"鳥松區":{"code":833,"lat":22.6598339,"lon":120.364363,"site":1.181,"area":"高雄市西部"},"岡山區":{"code":820,"lat":22.7974649,"lon":120.2950724,"site":1.315,"area":"高雄市西部"},"橋頭區":{"code":825,"lat":22.757591,"lon":120.305809,"site":1.29,"area":"高雄市西部"},"燕巢區":{"code":824,"lat":22.7881575,"lon":120.3619685,"site":1.202,"area":"高雄市西部"},"田寮區":{"code":823,"lat":22.8698825,"lon":120.3594334,"site":1.185,"area":"高雄市西部"},"阿蓮區":{"code":822,"lat":22.8832024,"lon":120.3274131,"site":1.114,"area":"高雄市西部"},"路竹區":{"code":821,"lat":22.8547435,"lon":120.2592442,"site":1.097,"area":"高雄市西部"},"湖內區":{"code":829,"lat":22.9083136,"lon":120.211713,"site":1.162,"area":"高雄市西部"},"茄萣區":{"code":852,"lat":22.9065231,"lon":120.1824729,"site":1.204,"area":"高雄市西部"},"永安區":{"code":828,"lat":22.818298,"lon":120.224189,"site":1.3,"area":"高雄市西部"},"彌陀區":{"code":827,"lat":22.7814893,"lon":120.2507011,"site":1.511,"area":"高雄市西部"},"梓官區":{"code":826,"lat":22.7606303,"lon":120.2671523,"site":1.521,"area":"高雄市西部"},"旗山區":{"code":842,"lat":22.888642,"lon":120.48349,"site":0.836,"area":"高雄市中部"},"美濃區":{"code":843,"lat":22.8947952,"lon":120.5419493,"site":0.942,"area":"高雄市中部"},"六龜區":{"code":844,"lat":22.9984391,"lon":120.6327082,"site":1.12,"area":"高雄市東部"},"甲仙區":{"code":847,"lat":23.0839058,"lon":120.587695,"site":0.807,"area":"高雄市東部"},"杉林區":{"code":846,"lat":22.9717391,"lon":120.540058,"site":0.997,"area":"高雄市中部"},"內門區":{"code":845,"lat":22.9428391,"lon":120.462606,"site":1.139,"area":"高雄市中部"},"茂林區":{"code":851,"lat":22.886187,"lon":120.663266,"site":1.412,"area":"高雄市東部"},"桃源區":{"code":848,"lat":23.1592827,"lon":120.7641372,"site":1.182,"area":"高雄市東部"},"那瑪夏區":{"code":849,"lat":23.277092,"lon":120.720243,"site":0.951,"area":"高雄市東部"}},"屏東縣":{"屏東市":{"code":900,"lat":22.662498,"lon":120.4914295,"site":1.138,"area":"屏東縣北部"},"潮州鎮":{"code":920,"lat":22.549845,"lon":120.5429633,"site":1.085,"area":"屏東縣北部"},"東港鎮":{"code":928,"lat":22.4666854,"lon":120.454361,"site":1.263,"area":"屏東縣中部"},"恆春鎮":{"code":946,"lat":22.0037401,"lon":120.7472461,"site":1.392,"area":"屏東縣南部"},"萬丹鄉":{"code":913,"lat":22.5894894,"lon":120.4850182,"site":1.18,"area":"屏東縣北部"},"長治鄉":{"code":908,"lat":22.676538,"lon":120.5272963,"site":1.088,"area":"屏東縣北部"},"麟洛鄉":{"code":909,"lat":22.6506473,"lon":120.5272056,"site":1.077,"area":"屏東縣北部"},"九如鄉":{"code":904,"lat":22.740429,"lon":120.4903298,"site":0.97,"area":"屏東縣北部"},"里港鄉":{"code":905,"lat":22.7792625,"lon":120.4944974,"site":1.197,"area":"屏東縣北部"},"鹽埔鄉":{"code":907,"lat":22.7543743,"lon":120.5727019,"site":1.07,"area":"屏東縣北部"},"高樹鄉":{"code":906,"lat":22.8267314,"lon":120.600241,"site":1.081,"area":"屏東縣北部"},"萬巒鄉":{"code":923,"lat":22.5726416,"lon":120.567841,"site":1.209,"area":"屏東縣北部"},"內埔鄉":{"code":912,"lat":22.6120045,"lon":120.5668293,"site":1.116,"area":"屏東縣北部"},"竹田鄉":{"code":911,"lat":22.584724,"lon":120.543981,"site":1.132,"area":"屏東縣北部"},"新埤鄉":{"code":925,"lat":22.4701881,"lon":120.5498736,"site":1.096,"area":"屏東縣中部"},"枋寮鄉":{"code":940,"lat":22.3655097,"lon":120.5934906,"site":0.949,"area":"屏東縣北部"},"新園鄉":{"code":932,"lat":22.5438351,"lon":120.4614914,"site":1.36,"area":"屏東縣中部"},"崁頂鄉":{"code":924,"lat":22.5147343,"lon":120.5140493,"site":1.296,"area":"屏東縣北部"},"林邊鄉":{"code":927,"lat":22.431504,"lon":120.5097562,"site":1.46,"area":"屏東縣中部"},"南州鄉":{"code":926,"lat":22.490404,"lon":120.509879,"site":1.404,"area":"屏東縣中部"},"佳冬鄉":{"code":931,"lat":22.419209,"lon":120.5524196,"site":1.274,"area":"屏東縣中部"},"琉球鄉":{"code":929,"lat":22.348635,"lon":120.3827309,"site":1.632,"area":"屏東縣西部"},"車城鄉":{"code":944,"lat":22.0739409,"lon":120.714276,"site":1.045,"area":"屏東縣南部"},"滿州鄉":{"code":947,"lat":22.020813,"lon":120.838632,"site":1.427,"area":"屏東縣南部"},"枋山鄉":{"code":941,"lat":22.2639616,"lon":120.6524803,"site":1.363,"area":"屏東縣南部"},"三地門鄉":{"code":901,"lat":22.7162015,"lon":120.6541301,"site":1.433,"area":"屏東縣北部"},"霧臺鄉":{"code":902,"lat":22.7490518,"lon":120.7282593,"site":1.401,"area":"屏東縣北部"},"瑪家鄉":{"code":903,"lat":22.7086763,"lon":120.6494041,"site":1.39,"area":"屏東縣北部"},"泰武鄉":{"code":921,"lat":22.5919045,"lon":120.6319498,"site":1.084,"area":"屏東縣北部"},"來義鄉":{"code":922,"lat":22.5261844,"lon":120.6315782,"site":0.774,"area":"屏東縣中部"},"春日鄉":{"code":942,"lat":22.3710005,"lon":120.6290908,"site":0.837,"area":"屏東縣中部"},"獅子鄉":{"code":943,"lat":22.201775,"lon":120.705438,"site":1.205,"area":"屏東縣南部"},"牡丹鄉":{"code":945,"lat":22.1261502,"lon":120.7743059,"site":1.17,"area":"屏東縣南部"}},"臺東縣":{"臺東市":{"code":950,"lat":22.7548208,"lon":121.1465131,"site":1.532,"area":"臺東縣中部"},"成功鎮":{"code":961,"lat":23.1050697,"lon":121.3808747,"site":1.6,"area":"臺東縣北部"},"關山鎮":{"code":956,"lat":23.0474453,"lon":121.1630554,"site":1.417,"area":"臺東縣北部"},"卑南鄉":{"code":954,"lat":22.7827393,"lon":121.0870294,"site":1.334,"area":"臺東縣北部"},"鹿野鄉":{"code":955,"lat":22.9393083,"lon":121.1519859,"site":1.252,"area":"臺東縣北部"},"池上鄉":{"code":958,"lat":23.1223101,"lon":121.2151887,"site":1.338,"area":"臺東縣北部"},"東河鄉":{"code":959,"lat":22.9689404,"lon":121.3028937,"site":1.657,"area":"臺東縣北部"},"長濱鄉":{"code":962,"lat":23.3149961,"lon":121.4514207,"site":1.513,"area":"臺東縣北部"},"太麻里鄉":{"code":963,"lat":22.615548,"lon":121.007607,"site":1.462,"area":"臺東縣南部"},"大武鄉":{"code":965,"lat":22.340518,"lon":120.890073,"site":1.203,"area":"臺東縣南部"},"綠島鄉":{"code":951,"lat":22.6658421,"lon":121.4705314,"site":1.287,"area":"臺東縣東部"},"海端鄉":{"code":957,"lat":23.102057,"lon":121.176541,"site":1.228,"area":"臺東縣北部"},"延平鄉":{"code":953,"lat":22.9025753,"lon":121.0860671,"site":1.198,"area":"臺東縣中部"},"金峰鄉":{"code":964,"lat":22.5946397,"lon":120.9607096,"site":1.328,"area":"臺東縣南部"},"達仁鄉":{"code":966,"lat":22.296818,"lon":120.882973,"site":1.06,"area":"臺東縣南部"},"蘭嶼鄉":{"code":952,"lat":22.0244984,"lon":121.5560627,"site":2.15,"area":"臺東縣東部"}},"花蓮縣":{"花蓮市":{"code":970,"lat":23.9820651,"lon":121.6067705,"site":1.433,"area":"花蓮縣北部"},"鳳林鎮":{"code":975,"lat":23.7447637,"lon":121.4515822,"site":1.379,"area":"花蓮縣中部"},"玉里鎮":{"code":981,"lat":23.335527,"lon":121.315197,"site":0.956,"area":"花蓮縣南部"},"新城鄉":{"code":971,"lat":24.0392994,"lon":121.6041173,"site":1.215,"area":"花蓮縣北部"},"吉安鄉":{"code":973,"lat":23.9729455,"lon":121.5636438,"site":1.37,"area":"花蓮縣北部"},"壽豐鄉":{"code":974,"lat":23.8703424,"lon":121.5088259,"site":1.496,"area":"花蓮縣中部"},"光復鄉":{"code":976,"lat":23.669342,"lon":121.4233065,"site":1.396,"area":"花蓮縣中部"},"豐濱鄉":{"code":977,"lat":23.6012024,"lon":121.5211488,"site":1.223,"area":"花蓮縣中部"},"瑞穗鄉":{"code":978,"lat":23.4964553,"lon":121.3757788,"site":1.091,"area":"花蓮縣中部"},"富里鄉":{"code":983,"lat":23.1794845,"lon":121.250233,"site":1.263,"area":"花蓮縣南部"},"秀林鄉":{"code":972,"lat":24.1185835,"lon":121.6248326,"site":1.364,"area":"花蓮縣北部"},"萬榮鄉":{"code":979,"lat":23.714875,"lon":121.4109617,"site":1.794,"area":"花蓮縣中部"},"卓溪鄉":{"code":982,"lat":23.346478,"lon":121.303451,"site":1.004,"area":"花蓮縣南部"}},"宜蘭縣":{"宜蘭市":{"code":260,"lat":24.7520373,"lon":121.7531493,"site":1.609,"area":"宜蘭縣北部"},"羅東鎮":{"code":265,"lat":24.6769245,"lon":121.7669529,"site":1.601,"area":"宜蘭縣北部"},"蘇澳鎮":{"code":270,"lat":24.594315,"lon":121.8421903,"site":1.573,"area":"宜蘭縣北部"},"頭城鎮":{"code":261,"lat":24.8548387,"lon":121.8213189,"site":0.733,"area":"宜蘭縣北部"},"礁溪鄉":{"code":262,"lat":24.8234257,"lon":121.7711725,"site":0.949,"area":"宜蘭縣北部"},"壯圍鄉":{"code":263,"lat":24.746832,"lon":121.785759,"site":1.702,"area":"宜蘭縣北部"},"員山鄉":{"code":264,"lat":24.7433944,"lon":121.7232538,"site":1.179,"area":"宜蘭縣北部"},"冬山鄉":{"code":269,"lat":24.634338,"lon":121.792851,"site":1.387,"area":"宜蘭縣北部"},"五結鄉":{"code":268,"lat":24.684772,"lon":121.7982898,"site":1.519,"area":"宜蘭縣北部"},"三星鄉":{"code":266,"lat":24.665483,"lon":121.654047,"site":0.833,"area":"宜蘭縣北部"},"大同鄉":{"code":267,"lat":24.677412,"lon":121.6090927,"site":1.188,"area":"宜蘭縣南部"},"南澳鄉":{"code":272,"lat":24.465996,"lon":121.803714,"site":1.514,"area":"宜蘭縣南部"}},"澎湖縣":{"馬公市":{"code":880,"lat":23.566159,"lon":119.578692,"site":2.42,"area":"澎湖縣中部"},"湖西鄉":{"code":885,"lat":23.584072,"lon":119.6528318,"site":2.42,"area":"澎湖縣中部"},"白沙鄉":{"code":884,"lat":23.666538,"lon":119.598639,"site":2.42,"area":"澎湖縣中部"},"西嶼鄉":{"code":881,"lat":23.601088,"lon":119.5069847,"site":2.42,"area":"澎湖縣中部"},"望安鄉":{"code":882,"lat":23.3576577,"lon":119.500894,"site":2.42,"area":"澎湖縣中部"},"七美鄉":{"code":883,"lat":23.2067107,"lon":119.4244825,"site":2.42,"area":"澎湖縣中部"}},"金門縣":{"金城鎮":{"code":893,"lat":24.432824,"lon":118.320697,"area":"金門縣中部"},"金沙鎮":{"code":890,"lat":24.488898,"lon":118.413132,"area":"金門縣中部"},"金湖鎮":{"code":891,"lat":24.4414641,"lon":118.4171018,"area":"金門縣中部"},"金寧鄉":{"code":892,"lat":24.450966,"lon":118.334887,"area":"金門縣中部"},"烈嶼鄉":{"code":894,"lat":24.4295409,"lon":118.2445892,"area":"金門縣中部"},"烏坵鄉":{"code":896,"lat":24.9887062,"lon":119.4531826,"area":"金門縣中部"}},"連江縣":{"南竿鄉":{"code":209,"lat":26.1529312,"lon":119.9387995,"area":"連江縣中部"},"北竿鄉":{"code":210,"lat":26.223938,"lon":119.997139,"area":"連江縣中部"},"莒光鄉":{"code":211,"lat":25.9687384,"lon":119.9369689,"area":"連江縣中部"},"東引鄉":{"code":212,"lat":26.3672636,"lon":120.4898789,"area":"連江縣中部"}}}
\ No newline at end of file
diff --git a/src/view/index.html b/src/view/index.html
index 80184322..eb23ee87 100644
--- a/src/view/index.html
+++ b/src/view/index.html
@@ -114,7 +114,7 @@
- - - - - -
-
+
-
-
-
-
預警條件
-
即時測站 (任一站) 為觸發時任一站震度門檻,預估震度 (所在地)
- 為地震預警時所在地震度門檻,達到下方任一條件後軟體將會發出音效及彈出視窗。
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -135,7 +116,7 @@
-
+
+
+
+
+
+
+
+
預警條件
+
即時測站 (任一站) 為觸發時任一站震度門檻,預估震度 (所在地)
+ 為地震預警時所在地震度門檻,達到下方任一條件後軟體將會發出音效及彈出視窗。
+
+
+
+
+
+
+
+
+
@@ -196,14 +196,27 @@
-
金鑰
-
使用個人金鑰可以讓你獲取最新即時資料、更多測站、進階功能等。
+
ExpTech
+
擁有 trem.vip 可以使用 WebSocket 取得最新即時資料、更多測站、進階功能等。