page5.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. let cameraLogLevel = "";
  2. function setCameraLogLevel() {
  3. const level = logLevel.value;
  4. fetch("/api/camera/loglevel", {
  5. method: "POST",
  6. headers: {"Content-Type": "application/json"},
  7. body: JSON.stringify({level})
  8. })
  9. .then(async r => {
  10. if (!r.ok) throw new Error(await r.text());
  11. cameraLogLevel = level;
  12. })
  13. .catch(e => {
  14. logLevel.value = cameraLogLevel;
  15. });
  16. }
  17. function getCameraLogLevel() {
  18. fetch("/api/camera/loglevel")
  19. .then(async r => {
  20. if (!r.ok) throw new Error(await r.text());
  21. return r.json();
  22. })
  23. .then(d => {
  24. cameraLogLevel = d.log_level;
  25. logLevel.value = d.log_level;
  26. })
  27. .catch(e => {
  28. cameraLogLevel = "";
  29. logLevel.value = "";
  30. });
  31. }
  32. function downloadCameraLogFile(event) {
  33. const btn = event.currentTarget;
  34. btn.disabled = true;
  35. fetch("/api/camera/logfile")
  36. .then(async r => {
  37. if (!r.ok) {
  38. throw new Error("HTTP " + r.status);
  39. }
  40. const disposition = r.headers.get("Content-Disposition");
  41. let filename = "camera.log.tar.gz";
  42. if (disposition) {
  43. const match = disposition.match(/filename="?([^";]+)"?/);
  44. if (match) {
  45. filename = match[1];
  46. }
  47. }
  48. return {
  49. blob: await r.blob(),
  50. filename
  51. };
  52. })
  53. .then(({ blob, filename }) => {
  54. const url = URL.createObjectURL(blob);
  55. const a = document.createElement("a");
  56. a.href = url;
  57. a.download = filename;
  58. document.body.appendChild(a);
  59. a.click();
  60. a.remove();
  61. setTimeout(() => {
  62. URL.revokeObjectURL(url);
  63. }, 1000);
  64. alert("下载成功");
  65. })
  66. .catch(e => {
  67. console.error("download failed:", e);
  68. alert("下载失败: " + e.message);
  69. })
  70. .finally(() => {
  71. btn.disabled = false;
  72. btn.textContent = "下载";
  73. });
  74. }
  75. function restartCameraService(event) {
  76. if (!confirm("确定重启相机服务吗?")) {
  77. return;
  78. }
  79. if (cameraTakingPhoto || cameraPreviewRunning) {
  80. alert("相机使用中,请稍后再重试!");
  81. return;
  82. }
  83. const btn = event.currentTarget;
  84. btn.disabled = true;
  85. fetch("/api/camera/restart", {
  86. method: "POST"
  87. })
  88. .then(async r => {
  89. if (!r.ok) {
  90. throw new Error(await r.text());
  91. }
  92. logLevel.value = "info";
  93. cameraLogLevel = logLevel.value;
  94. disconnectLog();
  95. connectLog("yfkj-camera-capture.service", "text1");
  96. alert("重启成功");
  97. })
  98. .catch(e => {
  99. console.error("restart failed:", e);
  100. alert("重启失败: " + e.message);
  101. })
  102. .finally(() => {
  103. btn.disabled = false;
  104. });
  105. }
  106. function getCameraStatus() {
  107. ["btn1", "btn2", "btn3", "btn4"]
  108. .forEach(id => setBtnStatus(id, false, "page5"));
  109. fetch("/api/camera/status")
  110. .then(async r => {
  111. if (!r.ok) {
  112. throw new Error("HTTP " + r.status);
  113. }
  114. return r.json();
  115. })
  116. .then(data => {
  117. ["avar1","avar2","avar3","avar4","avar5", "avar6"]
  118. .forEach(id => setText(id, data[id], "page5"));
  119. })
  120. .catch(e => {
  121. console.error("getCameraStatus() failed:", e);
  122. ["avar1","avar2","avar3","avar4","avar5", "avar6"]
  123. .forEach(id => setText(id, null, "page5"));
  124. })
  125. .finally(() => {
  126. updateCameraButtons();
  127. });
  128. getCameraLogLevel();
  129. }
  130. function cameraPower(enable) {
  131. fetch("/api/camera/gpio22power", {
  132. method: "POST",
  133. headers: {
  134. "Content-Type": "application/json"
  135. },
  136. body: JSON.stringify({
  137. enable: enable
  138. })
  139. })
  140. .then(async r => {
  141. if (!r.ok) {
  142. throw new Error(await r.text());
  143. }
  144. return r.json();
  145. })
  146. .then(data => {
  147. if (data.ok) {
  148. setText("avar5", enable === "true" ? "🟢打开" : null, "page5");
  149. alert(enable === "true" ? "上电成功" : "断电成功");
  150. } else { // 目前后端不会这么返回,避免以后修改代码
  151. alert("操作失败");
  152. }
  153. })
  154. .catch(e => {
  155. setText("avar5", null, "page5");
  156. alert("操作失败: " + e.message);
  157. });
  158. }
  159. function cameraPing() {
  160. fetch("/api/camera/pingGigeCamera", {method:"POST"})
  161. .then(r => r.json())
  162. .then(data => {
  163. setText("avar6", data.avar6, "page5");
  164. alert(data.avar6 === "🟢正常" ? "网口相机Ping测试成功" : "网口相机Ping测试失败");
  165. })
  166. .catch(() => {
  167. setText("avar6", null, "page5");
  168. alert("网口相机Ping测试失败");
  169. });
  170. }
  171. let cameraPreviewTimer = null;
  172. let cameraPreviewRunning = false;
  173. let cameraPreviewFrames = 0;
  174. let cameraPhotoIndex = 0;
  175. let cameraCurrentFile = "";
  176. let cameraTakingPhoto = false;
  177. const cameraPhotoFiles = [
  178. "/tmp/camera_preview_0.jpg",
  179. "/tmp/camera_preview_1.jpg"
  180. ];
  181. function updateCameraButtons() {
  182. const normalEnable = !cameraPreviewRunning && !cameraTakingPhoto;
  183. ["btn1", "btn2", "btn3"]
  184. .forEach(id => setBtnStatus(id, normalEnable, "page5"));
  185. setBtnStatus("btn4", cameraPreviewRunning, "page5");
  186. }
  187. async function cameraTakePhoto(filename) {
  188. const r = await fetch("/api/camera/takePhoto", {
  189. method: "POST",
  190. headers: {
  191. "Content-Type": "application/json"
  192. },
  193. body: JSON.stringify({
  194. filename: filename
  195. })
  196. });
  197. if (!r.ok) {
  198. throw new Error(await r.text());
  199. }
  200. return await r.json();
  201. }
  202. let imageLoadSeq = 0;
  203. function setImageSrc(id, url, showLoadStatus = true)
  204. {
  205. const img = document.getElementById(id);
  206. if (!img) return;
  207. const seq = ++imageLoadSeq;
  208. const start = Date.now();
  209. img.onload = function() {
  210. if (seq !== imageLoadSeq || !showLoadStatus) return;
  211. setText("cvar1", "图片加载完成, 耗时:" + (Date.now() - start) + "ms", "page5");
  212. };
  213. img.onerror = function() {
  214. if (seq !== imageLoadSeq || !showLoadStatus) return;
  215. setText("cvar1", "图片加载失败, 耗时:" + (Date.now() - start) + "ms", "page5");
  216. }
  217. const separator = url.includes("?") ? "&" : "?";
  218. img.src = url + separator + "t=" + Date.now();
  219. }
  220. async function takeOnePhoto() {
  221. if (cameraPreviewRunning || cameraTakingPhoto) {
  222. return;
  223. }
  224. try {
  225. await setCameraWaitAEDone(true);
  226. } catch(e) {
  227. console.error("open wait AE failed:", e);
  228. }
  229. cameraTakingPhoto = true;
  230. updateCameraButtons();
  231. ["cvar1", "cvar2", "cvar3", "cvar4", "cvar5", "cvar6"]
  232. .forEach(id => setText(id, null, "page5"));
  233. setText("cvar1", "拍照中, 请稍后...", "page5");
  234. const filename = cameraPhotoFiles[cameraPhotoIndex];
  235. cameraPhotoIndex = cameraPhotoIndex ? 0 : 1;
  236. try {
  237. const data = await cameraTakePhoto(filename);
  238. if (!data.ok) throw new Error("take photo failed");
  239. setText("cvar1", "预览中, 请稍后...", "page5");
  240. setText("cvar2", "1", "page5");
  241. setText("cvar3", data.var1, "page5");
  242. setText("cvar4", data.var2, "page5");
  243. setText("cvar5", data.var3, "page5");
  244. setText("cvar6", data.var4 + "x" + data.var5, "page5");
  245. cameraCurrentFile = filename;
  246. setImageSrc("camera-image", "/api/camera/getImage?file=" + encodeURIComponent(cameraCurrentFile), true);
  247. } catch(e) {
  248. console.error("takeOnePhoto failed:", e);
  249. setText("cvar1", "拍照失败", "page5");
  250. } finally {
  251. cameraTakingPhoto = false;
  252. updateCameraButtons();
  253. }
  254. }
  255. async function setCameraWaitAEDone(waitAE) {
  256. const r = await fetch("/api/camera/setWaitAEDoneForTakePhoto", {
  257. method:"POST",
  258. headers:{
  259. "Content-Type":"application/json"
  260. },
  261. body:JSON.stringify({
  262. waitAE: waitAE ? "1" : "0"
  263. })
  264. });
  265. if (!r.ok) {
  266. throw new Error(await r.text());
  267. }
  268. }
  269. async function startCameraPreview() {
  270. if (cameraPreviewRunning || cameraTakingPhoto) {
  271. return;
  272. }
  273. try {
  274. await setCameraWaitAEDone(false);
  275. } catch(e) {
  276. console.error("close wait AE failed:", e);
  277. }
  278. cameraPreviewRunning = true;
  279. updateCameraButtons();
  280. cameraPreviewFrames = 0;
  281. ["cvar1", "cvar2", "cvar3", "cvar4", "cvar5", "cvar6"]
  282. .forEach(id => setText(id, null, "page5"));
  283. cameraPreviewLoop();
  284. }
  285. async function cameraPreviewLoop() {
  286. if (!cameraPreviewRunning) {
  287. return;
  288. }
  289. cameraTakingPhoto = true;
  290. updateCameraButtons();
  291. setText("cvar1", "拍照中, 请稍后...", "page5");
  292. const filename = cameraPhotoFiles[cameraPhotoIndex];
  293. cameraPhotoIndex = cameraPhotoIndex ? 0 : 1;
  294. try {
  295. const data = await cameraTakePhoto(filename);
  296. if (!data.ok) throw new Error("take photo failed");
  297. setText("cvar1", "预览中, 请稍后...", "page5");
  298. cameraPreviewFrames++;
  299. setText("cvar2", String(cameraPreviewFrames), "page5");
  300. setText("cvar3", data.var1, "page5");
  301. setText("cvar4", data.var2, "page5");
  302. setText("cvar5", data.var3, "page5");
  303. setText("cvar6", data.var4 + "x" + data.var5, "page5");
  304. cameraCurrentFile = filename;
  305. setImageSrc("camera-image", "/api/camera/getImage?file=" + encodeURIComponent(cameraCurrentFile), false);
  306. } catch(e) {
  307. console.error("cameraPreviewLoop failed:", e);
  308. stopCameraPreview();
  309. setText("cvar1", "拍照失败", "page5");
  310. } finally {
  311. cameraTakingPhoto = false;
  312. updateCameraButtons();
  313. if (cameraPreviewRunning) {
  314. cameraPreviewTimer = setTimeout(cameraPreviewLoop, 20);
  315. } else {
  316. setText("cvar1", "连拍已停止", "page5");
  317. setCameraWaitAEDone(true)
  318. .catch(e => {
  319. console.error("restore wait AE failed:", e);
  320. });
  321. }
  322. }
  323. }
  324. function stopCameraPreview() {
  325. if(!cameraPreviewRunning) {
  326. return;
  327. }
  328. cameraPreviewRunning = false;
  329. updateCameraButtons();
  330. if (cameraPreviewTimer) {
  331. clearTimeout(cameraPreviewTimer);
  332. cameraPreviewTimer = null;
  333. }
  334. setText("cvar1", "停止连怕中, 请稍后...", "page5");
  335. }
  336. function downloadCameraImage() {
  337. if (!cameraCurrentFile) {
  338. alert("暂无图片");
  339. return;
  340. }
  341. const a = document.createElement("a");
  342. a.href = "/api/camera/getImage?file=" + encodeURIComponent(cameraCurrentFile) + "&download=1";
  343. a.download = "camera.jpg";
  344. document.body.appendChild(a);
  345. a.click();
  346. a.remove();
  347. }
  348. function initPage5() {
  349. getCameraStatus();
  350. if (cameraTakingPhoto || cameraPreviewRunning) {
  351. setText("cvar1", "拍照中, 请稍后...", "page5");
  352. } else if (cameraCurrentFile) {
  353. setText("cvar1", "加载最后拍摄的图片...", "page5");
  354. setImageSrc("camera-image", "/api/camera/getImage?file=" + encodeURIComponent(cameraCurrentFile), true);
  355. }
  356. connectLog("yfkj-camera-capture.service", "text1");
  357. }
  358. function exitPage5() {
  359. if (cameraPreviewRunning) {
  360. stopCameraPreview();
  361. }
  362. disconnectLog();
  363. }