Sfoglia il codice sorgente

完成page7一键自检页面的全部功能开发

niujiuru 1 giorno fa
parent
commit
dcea32b891

+ 214 - 0
web-ui.service/page7_handler.go

@@ -0,0 +1,214 @@
+package main
+
+import (
+	"encoding/json"
+	"net/http"
+	"os/exec"
+	"strconv"
+	"strings"
+)
+
+func healthCheckNetworkHandler(w http.ResponseWriter, r *http.Request) {
+	var modem struct {
+		ICCID string `json:"iccid"`
+		RSSI  string `json:"rssi"`
+	}
+	var net struct {
+		Status string `json:"net_ok"`
+		Type   string `json:"net_type"`
+	}
+
+	var avar1, avar2, avar3, avar4, avar5, avar6 string
+
+	avar1, avar2, avar3 = "已完成", "不通过", "网络服务异常"
+	avar4, avar5, avar6 = "已完成", "不通过", "网络连接异常"
+
+	if callRPCResult(r.Context(), 7000, "core.getNetStatus", nil, &net) != nil {
+		goto done
+	}
+
+	avar1, avar2, avar3 = "已完成", "通过", "网络服务正常"
+	if net.Status != "true" {
+		goto done
+	}
+
+	avar4, avar5, avar6 = "已完成", "通过", "网络连接正常("+net.Type+"网络)"
+	if net.Type != "蜂窝" {
+		goto done
+	}
+
+	if callRPCResult(r.Context(), 7000, "core.getModemInfo", nil, &modem) != nil {
+		avar5, avar6 = "不通过", "蜂窝模块异常"
+		goto done
+	}
+
+	if modem.ICCID == "" {
+		avar5, avar6 = "不通过", "SIM卡异常"
+		goto done
+	}
+
+	avar6 = "网络连接正常(蜂窝网络,SIM卡正常," + getCSQDesc(modem.RSSI) + ")"
+
+done:
+	w.Header().Set("Content-Type", "application/json; charset=utf-8")
+	json.NewEncoder(w).Encode(map[string]string{"avar1": avar1, "avar2": avar2, "avar3": avar3,
+		"avar4": avar4, "avar5": avar5, "avar6": avar6})
+}
+
+func getCSQDesc(csq string) string {
+	n, err := strconv.Atoi(csq)
+	if err != nil {
+		return "信号未知"
+	}
+
+	switch {
+	case n == 99 || n == 199:
+		return "信号未知"
+	case n >= 0 && n <= 9:
+		return "信号较弱"
+	case n >= 10 && n <= 19:
+		return "信号一般"
+	case n >= 20 && n <= 31:
+		return "信号良好"
+	case n >= 100 && n <= 191:
+		return "信号有效"
+	default:
+		return "信号未知"
+	}
+}
+
+func healthCheckTimeHandler(w http.ResponseWriter, r *http.Request) {
+	var status struct {
+		SystemTime string `json:"system_time"`
+		TimeSource string `json:"time_source"`
+		TimeSynced string `json:"time_synced"`
+	}
+
+	if err := callRPCResult(r.Context(), 7001, "core.getTimeSyncStatus", nil, &status); err != nil {
+		json.NewEncoder(w).Encode(map[string]string{
+			"bvar1": "已完成", "bvar2": "不通过", "bvar3": "时间服务检测失败",
+			"bvar4": "已完成", "bvar5": "不通过", "bvar6": "时间同步检测失败",
+		})
+		return
+	}
+
+	result := map[string]string{"bvar1": "已完成", "bvar2": "通过", "bvar3": "时间服务正常",
+		"bvar4": "已完成", "bvar5": "不通过", "bvar6": "系统时间未同步"}
+
+	if status.TimeSynced == "true" {
+		result["bvar5"] = "通过"
+		result["bvar6"] = "系统时间已同步"
+	}
+
+	json.NewEncoder(w).Encode(result)
+}
+
+func healthCheckPositionHandler(w http.ResponseWriter, r *http.Request) {
+	var pos struct {
+		Lat string `json:"lat"`
+		Lon string `json:"lon"`
+	}
+
+	if err := callRPCResult(r.Context(), 7002, "core.getPositionInfo", nil, &pos); err != nil {
+		json.NewEncoder(w).Encode(map[string]string{
+			"cvar1": "已完成", "cvar2": "不通过", "cvar3": "定位服务检测失败",
+			"cvar4": "已完成", "cvar5": "不通过", "cvar6": "定位状态检测失败",
+		})
+		return
+	}
+
+	result := map[string]string{"cvar1": "已完成", "cvar2": "通过", "cvar3": "定位服务正常",
+		"cvar4": "已完成", "cvar5": "不通过", "cvar6": "未能获取到确切的位置信息"}
+
+	if pos.Lat != "" && pos.Lon != "" {
+		result["cvar5"] = "通过"
+		result["cvar6"] = "已获取到确切的位置信息"
+	}
+
+	json.NewEncoder(w).Encode(result)
+}
+
+func healthCheckCameraHandler(w http.ResponseWriter, r *http.Request) {
+	var count string
+
+	if err := callRPCResult(r.Context(), 7003, "core.getSupportedCameraCount", map[string]string{"type": "all"}, &count); err != nil {
+		json.NewEncoder(w).Encode(map[string]string{
+			"dvar1": "已完成", "dvar2": "不通过", "dvar3": "相机服务检测失败",
+			"dvar4": "已完成", "dvar5": "不通过", "dvar6": "识别查找相机失败",
+		})
+		return
+	}
+
+	result := map[string]string{"dvar1": "已完成", "dvar2": "通过", "dvar3": "相机服务正常",
+		"dvar4": "已完成", "dvar5": "不通过", "dvar6": "未找到相机"}
+
+	if count != "" && count != "0" {
+		result["dvar5"] = "通过"
+		result["dvar6"] = "共找到(" + count + ")个相机"
+	}
+
+	json.NewEncoder(w).Encode(result)
+}
+
+func healthCheckCameraPhotoHandler(w http.ResponseWriter, r *http.Request) {
+	var result struct {
+		Mark   map[string]interface{} `json:"mark"`
+		Status string                 `json:"status"`
+	}
+
+	params := map[string]string{
+		"format":      "jpg",
+		"outFilename": "/tmp/health_check.jpg",
+		"timeoutMs":   "300",
+	}
+
+	if err := callRPCResult(r.Context(), 7003, "core.takePhoto", params, &result); err != nil {
+		json.NewEncoder(w).Encode(map[string]string{
+			"dvar7": "已完成",
+			"dvar8": "不通过",
+			"dvar9": "测试相机拍照失败",
+		})
+		return
+	}
+
+	if result.Status == "success" {
+		json.NewEncoder(w).Encode(map[string]string{
+			"dvar7": "已完成",
+			"dvar8": "通过",
+			"dvar9": "测试相机拍照成功",
+		})
+		return
+	} else {
+		json.NewEncoder(w).Encode(map[string]string{
+			"dvar7": "已完成",
+			"dvar8": "不通过",
+			"dvar9": "测试相机拍照失败",
+		})
+		return
+	}
+}
+
+func healthCheckUserAppHandler(w http.ResponseWriter, r *http.Request) {
+	var result = map[string]string{
+		"evar1": "已完成",
+		"evar2": "不通过",
+		"evar3": "用户应用尚未安装",
+	}
+
+	out, err := exec.Command("systemctl", "show", "yfkj-user-app.service",
+		"-p", "LoadState",
+		"-p", "ActiveState",
+		"-p", "SubState").Output()
+	if err == nil {
+		v := string(out)
+		switch {
+		case strings.Contains(v, "ActiveState=active") && strings.Contains(v, "SubState=running"):
+			result["evar2"] = "通过"
+			result["evar3"] = "用户应用已安装,运行正常"
+		case strings.Contains(v, "LoadState=loaded"):
+			result["evar3"] = "用户应用已安装,但未运行"
+		}
+	}
+
+	json.NewEncoder(w).Encode(result)
+}

+ 8 - 0
web-ui.service/web/static/css/page7.css

@@ -65,3 +65,11 @@
     font-size:14px;
     font-weight:500;
 }
+
+.page-health-check .check-success {
+  color: #22c55e;
+}
+
+.page-health-check .check-fail {
+  color: #ef4444;
+}

+ 334 - 0
web-ui.service/web/static/js/page7.js

@@ -1,5 +1,339 @@
+let healthCheckRunning = false;
+let healthCheckAbortController = null;
+
+async function startHealthCheck() {
+  if (healthCheckRunning) {
+    return;
+  }
+
+  healthCheckRunning = true;
+  healthCheckAbortController = new AbortController();
+  updateHealthCheckButtons();
+
+  resetHealthCheck();
+
+  try {
+    try {
+      setCheckText("avar1", "测试中...");
+      setCheckText("avar4", "测试中...");
+      await checkNetwork();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("avar1", "已完成");
+      setCheckText("avar2", "不通过");
+      setCheckText("avar3", "检测失败");
+      setCheckText("avar4", "已完成");
+      setCheckText("avar5", "不通过");
+      setCheckText("avar6", "检测失败");
+    }
+
+    if (!healthCheckRunning) {
+      return;
+    }
+
+    try {
+      setCheckText("bvar1", "测试中...");
+      setCheckText("bvar4", "测试中...");
+      await checkTime();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("bvar1", "已完成");
+      setCheckText("bvar2", "不通过");
+      setCheckText("bvar3", "检测失败");
+      setCheckText("bvar4", "已完成");
+      setCheckText("bvar5", "不通过");
+      setCheckText("bvar6", "检测失败");
+    }
+
+    if (!healthCheckRunning) {
+      return;
+    }
+
+    try {
+      setCheckText("cvar1", "测试中...");
+      setCheckText("cvar4", "测试中...");
+      await checkPosition();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("cvar1", "已完成");
+      setCheckText("cvar2", "不通过");
+      setCheckText("cvar3", "检测失败");
+      setCheckText("cvar4", "已完成");
+      setCheckText("cvar5", "不通过");
+      setCheckText("cvar6", "检测失败");
+    }
+
+    if (!healthCheckRunning) {
+      return;
+    }
+
+    try {
+      setCheckText("dvar1", "测试中...");
+      setCheckText("dvar4", "测试中...");
+      await checkCamera();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("dvar1", "已完成");
+      setCheckText("dvar2", "不通过");
+      setCheckText("dvar3", "检测失败");
+      setCheckText("dvar4", "已完成");
+      setCheckText("dvar5", "不通过");
+      setCheckText("dvar6", "检测失败");
+    }
+
+    if (!healthCheckRunning) {
+      return;
+    }
+
+    try {
+      setCheckText("dvar7", "测试中...");
+      await setCameraWaitAEDone(false);
+      await checkCameraPhoto();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("dvar7", "已完成");
+      setCheckText("dvar8", "不通过");
+      setCheckText("dvar9", "检测失败");
+    }
+
+    if (!healthCheckRunning) {
+      return;
+    }
+
+    try {
+      setCheckText("evar1", "测试中...");
+      await checkUserApp();
+    } catch (err) {
+      if (err.name === "AbortError") {
+        return;
+      }
+      setCheckText("evar1", "已完成");
+      setCheckText("evar2", "不通过");
+      setCheckText("evar3", "检测失败");
+    }
+  } finally {
+    try {
+      await setCameraWaitAEDone(true);
+    } finally {
+      healthCheckRunning = false;
+      healthCheckAbortController = null;
+      updateHealthCheckButtons();
+    }
+  }
+}
+
+function stopHealthCheck() {
+  if (!healthCheckRunning) {
+    return;
+  }
+  healthCheckAbortController?.abort();
+}
+
+function checkHealthCheckStopped() {
+  if (healthCheckAbortController?.signal.aborted) {
+    throw new DOMException("Health check stopped", "AbortError");
+  }
+}
+
+function updateHealthCheckButtons() {
+  if (currentPage !== "page7") {
+    return;
+  }
+  setBtnStatus("btn1", !healthCheckRunning, "page7");
+  setBtnStatus("btn2",  healthCheckRunning, "page7");
+}
+
+function resetHealthCheck() {
+  const ids = [
+    "avar1", "avar2", "avar3",
+    "avar4", "avar5", "avar6",
+
+    "bvar1", "bvar2", "bvar3",
+    "bvar4", "bvar5", "bvar6",
+
+    "cvar1", "cvar2", "cvar3",
+    "cvar4", "cvar5", "cvar6",
+
+    "dvar1", "dvar2", "dvar3",
+    "dvar4", "dvar5", "dvar6",
+    "dvar7", "dvar8", "dvar9",
+
+    "evar1", "evar2", "evar3"
+  ];
+
+  for (const id of ids) {
+    setCheckText(id, "--");
+  }
+}
+
+async function checkNetwork() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/network", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  for (const id of [
+    "avar1", "avar2", "avar3",
+    "avar4", "avar5", "avar6"
+  ]) {
+    setCheckText(id, data[id] ?? "--");
+  }
+}
+
+async function checkTime() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/time", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  setCheckText("bvar1", data.bvar1 ?? "--");
+  setCheckText("bvar2", data.bvar2 ?? "--");
+  setCheckText("bvar3", data.bvar3 ?? "--");
+
+  setCheckText("bvar4", data.bvar4 ?? "--");
+  setCheckText("bvar5", data.bvar5 ?? "--");
+  setCheckText("bvar6", data.bvar6 ?? "--");
+}
+
+async function checkPosition() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/position", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  setCheckText("cvar1", data.cvar1 ?? "--");
+  setCheckText("cvar2", data.cvar2 ?? "--");
+  setCheckText("cvar3", data.cvar3 ?? "--");
+
+  setCheckText("cvar4", data.cvar4 ?? "--");
+  setCheckText("cvar5", data.cvar5 ?? "--");
+  setCheckText("cvar6", data.cvar6 ?? "--");
+}
+
+async function checkCamera() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/camera", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  setCheckText("dvar1", data.dvar1 ?? "--");
+  setCheckText("dvar2", data.dvar2 ?? "--");
+  setCheckText("dvar3", data.dvar3 ?? "--");
+  setCheckText("dvar4", data.dvar4 ?? "--");
+  setCheckText("dvar5", data.dvar5 ?? "--");
+  setCheckText("dvar6", data.dvar6 ?? "--");
+}
+
+async function checkCameraPhoto() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/camera/photo", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  setCheckText("dvar7", data.dvar7 ?? "--");
+  setCheckText("dvar8", data.dvar8 ?? "--");
+  setCheckText("dvar9", data.dvar9 ?? "--");
+}
+
+async function checkUserApp() {
+  checkHealthCheckStopped();
+
+  const response = await fetch("/api/health-check/user-app", {
+    signal: healthCheckAbortController.signal
+  });
+
+  if (!response.ok) {
+    throw new Error("检测失败");
+  }
+
+  const data = await response.json();
+
+  checkHealthCheckStopped();
+
+  setCheckText("evar1", data.evar1 ?? "--");
+  setCheckText("evar2", data.evar2 ?? "--");
+  setCheckText("evar3", data.evar3 ?? "--");
+}
+
+function setCheckText(id, value) {
+  if (currentPage !== "page7") {
+    return;
+  }
+
+  setText(id, value, "page7");
+
+  const el = document.getElementById(id);
+  if (!el) {
+    return;
+  }
+
+  el.classList.remove("check-success", "check-fail");
+
+  if (value === "已完成" || value === "通过") {
+    el.classList.add("check-success");
+  } else if (value === "不通过") {
+    el.classList.add("check-fail");
+  }
+}
+
 function initPage7() {
 }
 
 function exitPage7() {
+  stopHealthCheck()
 }

+ 30 - 0
web-ui.service/web_route.go

@@ -231,6 +231,36 @@ var routes = []Route{
 	},
 
 	{
+		"/api/health-check/network",
+		healthCheckNetworkHandler,
+	},
+
+	{
+		"/api/health-check/time",
+		healthCheckTimeHandler,
+	},
+
+	{
+		"/api/health-check/position",
+		healthCheckPositionHandler,
+	},
+
+	{
+		"/api/health-check/camera",
+		healthCheckCameraHandler,
+	},
+
+	{
+		"/api/health-check/camera/photo",
+		healthCheckCameraPhotoHandler,
+	},
+
+	{
+		"/api/health-check/user-app",
+		healthCheckUserAppHandler,
+	},
+
+	{
 		"/api/ssh/ws",
 		sshWSHandler,
 	},