Explorar el Código

完成相机页面单次拍照前端和后端接口实现

niujiuru hace 3 semanas
padre
commit
e1c7d44d58

+ 70 - 0
web-ui.service/page5_handler.go

@@ -150,3 +150,73 @@ func cameraPingHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/json")
 	json.NewEncoder(w).Encode(map[string]string{"avar6": avar6})
 }
+
+func cameraTakePhotoHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method != http.MethodPost {
+		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+
+	var req struct {
+		Filename string `json:"filename"`
+	}
+
+	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+
+	if req.Filename == "" {
+		http.Error(w, "missing filename", http.StatusBadRequest)
+		return
+	}
+
+	params := map[string]string{
+		"format":      "jpg",
+		"outFilename": req.Filename,
+		"timeoutMs":   "300",
+	}
+
+	var result struct {
+		Mark struct {
+			CamModelName    string  `json:"CamModelName"`
+			CamSerialNum    string  `json:"CamSerialNum"`
+			ImgExposureTime float64 `json:"ImgExposureTime"`
+			ImgWidth        uint    `json:"ImgWidth"`
+			ImgHeight       uint    `json:"ImgHeight"`
+		} `json:"mark"`
+		Status string `json:"status"`
+	}
+
+	if err := callRPCResult(r.Context(), 7003, "core.takePhoto", params, &result); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(map[string]any{
+		"ok":   result.Status == "success",
+		"var1": result.Mark.CamModelName,
+		"var2": result.Mark.CamSerialNum,
+		"var3": fmt.Sprintf("%.0f us", result.Mark.ImgExposureTime),
+		"var4": result.Mark.ImgWidth,
+		"var5": result.Mark.ImgHeight,
+	})
+}
+
+func cameraGetImageHandler(w http.ResponseWriter, r *http.Request) {
+	file := r.URL.Query().Get("file")
+
+	if file == "" {
+		http.Error(w, "missing file", http.StatusBadRequest)
+		return
+	}
+
+	if _, err := os.Stat(file); err != nil {
+		http.Error(w, err.Error(), http.StatusNotFound)
+		return
+	}
+
+	w.Header().Set("Content-Type", "image/jpeg")
+	http.ServeFile(w, r, file)
+}

+ 1 - 1
web-ui.service/web/pages/page5.html

@@ -77,7 +77,7 @@
             </div>
           </div>
           <div class="camera-image-box">
-            <img id="camera-image">
+            <img id="camera-image" src="static/images/camera.png" alt="Camera Image">
           </div>
           <table class="camera-info-table">
             <tr>

+ 3 - 4
web-ui.service/web/static/css/page5.css

@@ -93,7 +93,7 @@
 .camera-image-box {
     flex:1;
     display:flex;
-    align-items:flex-start;
+    align-items:center;
     justify-content:center;
     min-height:0;
     overflow:hidden;
@@ -104,9 +104,8 @@
 }
 
 .camera-image-box img {
-    max-width:100%;
-    max-height:100%;
-    aspect-ratio:4 / 3;
+    width:100%;
+    height:100%;
     object-fit:contain;
 }
 

BIN
web-ui.service/web/static/images/camera.png


+ 76 - 8
web-ui.service/web/static/js/page5.js

@@ -114,10 +114,8 @@ function restartCameraService() {
 }
 
 function getCameraStatus() {
-  setBtnStatus("btn1", false, "page5");
-  setBtnStatus("btn2", false, "page5");
-  setBtnStatus("btn3", false, "page5");
-  setBtnStatus("btn4", false, "page5");
+  ["btn1", "btn2", "btn3", "btn4"]
+  .forEach(id => setBtnStatus(id, false, "page5"));
 
   fetch("/api/camera/status")
     .then(async r => {
@@ -138,10 +136,8 @@ function getCameraStatus() {
         .forEach(id => setText(id, null, "page5"));
     })
     .finally(() => {
-      setBtnStatus("btn1", true, "page5");
-      setBtnStatus("btn2", true, "page5");
-      setBtnStatus("btn3", true, "page5");
-      setBtnStatus("btn4", true, "page5");
+      ["btn1", "btn2", "btn3", "btn4"]
+      .forEach(id => setBtnStatus(id, true, "page5"));
     });
 
   getCameraLogLevel();
@@ -191,8 +187,80 @@ function cameraPing() {
   });
 }
 
+let cameraPreviewTimer = null;
+let cameraPreviewRunning = false;
+let cameraPhotoIndex = 0;
+let cameraCurrentFile = "";
+let cameraTakingPhoto = false; 
+
+const cameraPhotoFiles = [
+  "/tmp/camera_preview_0.jpg",
+  "/tmp/camera_preview_1.jpg"
+];
+
+async function cameraTakePhoto(filename) {
+  const r = await fetch("/api/camera/takePhoto", {
+    method: "POST",
+    headers: {
+      "Content-Type": "application/json"
+    },
+    body: JSON.stringify({
+      filename: filename
+    })
+  });
+  if (!r.ok) {
+    throw new Error(await r.text());
+  }
+  return await r.json();
+}
+
+function setImageSrc(id, url)
+{
+  const img = document.getElementById(id);
+  if (img) img.src = url;
+}
+
+async function takeOnePhoto() {
+  if (cameraTakingPhoto) {
+    return;
+  }
+  cameraTakingPhoto = true;
+
+  ["btn1", "btn2", "btn3", "btn4"]
+  .forEach(id => setBtnStatus(id, false, "page5"));
+
+  setText("cvar1", "拍照中, 请稍后...", "page5");
+  const filename = cameraPhotoFiles[cameraPhotoIndex];
+  cameraPhotoIndex = cameraPhotoIndex ? 0 : 1;
+
+  try {
+    const data = await cameraTakePhoto(filename);
+    if (!data.ok) throw new Error("take photo failed");
+
+    cameraCurrentFile = filename;
+    setImageSrc("camera-image", "/api/camera/getImage?file=" + encodeURIComponent(filename) + "&t=" + Date.now());
+
+    setText("cvar1", "拍照完成", "page5");
+    setText("cvar2", "1", "page5");
+    setText("cvar3", data.var1, "page5");
+    setText("cvar4", data.var2, "page5");
+    setText("cvar5", data.var3, "page5");
+    setText("cvar6", data.var4 + "x" + data.var5, "page5");
+  } catch(e) {
+    console.error("takeOnePhoto failed:", e);
+    setText("cvar1", "拍照失败", "page5");
+  } finally {
+    cameraTakingPhoto = false;
+    ["btn1", "btn2", "btn3", "btn4"]
+    .forEach(id => setBtnStatus(id, true, "page5"));
+  }
+}
+
 function initPage5() {
   getCameraStatus();
+  if (cameraTakingPhoto) {
+    setText("cvar1", "拍照中, 请稍后...", "page5");
+  }
   connectLog("yfkj-camera-capture.service", "text1");
 }
 

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

@@ -159,6 +159,16 @@ var routes = []Route{
 	},
 
 	{
+		"/api/camera/takePhoto",
+		cameraTakePhotoHandler,
+	},
+
+	{
+		"/api/camera/getImage",
+		cameraGetImageHandler,
+	},
+
+	{
 		"/api/ssh/ws",
 		sshWSHandler,
 	},