From 087e28dbb33bc2628ca6eeee5cd4aca18cabb7db Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 28 Aug 2023 14:25:45 +0300 Subject: [PATCH] playback and export video update --- package-lock.json | 134 +++++++++++ package.json | 2 + server.js | 68 ++++++ static/styles/main.css | 20 ++ static/templates/videos/export.html | 321 ++++++++++++++++---------- static/templates/videos/playback.html | 206 ++++++++++------- 6 files changed, 545 insertions(+), 206 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0dd0412..8f60141 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,14 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "axios": "^1.5.0", "dotenv": "^16.3.1", "express": "^4.18.2", "fs": "^0.0.1-security", "handlebars": "^4.7.7", "http": "^0.0.1-security", "mapbox-gl": "^2.15.0", + "moment": "^2.29.4", "multer": "^1.4.5-lts.1", "path": "^0.12.7", "pg": "^8.11.1", @@ -108,6 +110,21 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -169,6 +186,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -247,6 +275,14 @@ "ms": "2.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -401,6 +437,38 @@ "node": ">= 0.8" } }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -692,6 +760,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -957,6 +1033,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1378,6 +1459,21 @@ "safer-buffer": "~2.1.0" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1424,6 +1520,14 @@ "get-intrinsic": "^1.0.2" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", @@ -1486,6 +1590,11 @@ "ms": "2.0.0" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1610,6 +1719,21 @@ "unpipe": "~1.0.0" } }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1816,6 +1940,11 @@ "minimist": "^1.2.6" } }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2021,6 +2150,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", diff --git a/package.json b/package.json index 6fa4ad8..0f2b0b3 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,14 @@ "author": "", "license": "ISC", "dependencies": { + "axios": "^1.5.0", "dotenv": "^16.3.1", "express": "^4.18.2", "fs": "^0.0.1-security", "handlebars": "^4.7.7", "http": "^0.0.1-security", "mapbox-gl": "^2.15.0", + "moment": "^2.29.4", "multer": "^1.4.5-lts.1", "path": "^0.12.7", "pg": "^8.11.1", diff --git a/server.js b/server.js index 595b19c..5096148 100644 --- a/server.js +++ b/server.js @@ -8,6 +8,9 @@ require("dotenv").config(); const multer = require("multer"); const http = require("http"); const Client = require('ssh2').Client; +const axios = require('axios'); +const moment = require('moment'); + const storage = multer.diskStorage({ @@ -1647,6 +1650,71 @@ async function videoExport(req, res) { } } +app.get('/getData', async (req, res) => { + const selectedSerial = req.query.serial; + const selectedDate = req.query.selectedDate; + const selectedTime = req.query.selectedTime; + const selectedChannel = req.query.selectedChannel; + + try { + const successResponse = await axios.get(`http://krbl.ru:8080/http/filelist/request?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`); + if (successResponse.data.SUCCESS) { + const dataResponse = await axios.get(`http://krbl.ru:8080/http/filelist/get?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`); + if (successResponse.data.SUCCESS) { + const dataId = dataResponse.data.DATAID; + const dateRanges = dataResponse.data.DATA; + let dataFound = false; + let selectedDataId = null; + const selectedDateTime = moment(selectedDate + selectedTime, 'YYYYMMDDHHmmss').valueOf(); + + if (dateRanges.length === 1) { + // Если в массиве DATA только одно значение + const [startRange, endRange] = dateRanges[0].split('-'); + const startDateTime = moment(startRange, 'YYYYMMDDHHmmss').valueOf(); + const endDateTime = moment(endRange, 'YYYYMMDDHHmmss').valueOf(); + + if (!isNaN(selectedDateTime) && !isNaN(startDateTime) && !isNaN(endDateTime)) { + if (selectedDateTime >= startDateTime && selectedDateTime <= endDateTime) { + dataFound = true; + selectedDataId = dataId[0]; + } + } else { + console.error("Неверный формат данных для сравнения."); + } + } else { + // Если в массиве DATA больше одного значения + for (let i = 0; i < dateRanges.length; i++) { + const [startRange, endRange] = dateRanges[i].split('-'); + const startDateTime = moment(startRange, 'YYYYMMDDHHmmss').valueOf(); + const endDateTime = moment(endRange, 'YYYYMMDDHHmmss').valueOf(); + + if (!isNaN(selectedDateTime) && !isNaN(startDateTime) && !isNaN(endDateTime)) { + if (selectedDateTime >= startDateTime && selectedDateTime <= endDateTime) { + dataFound = true; + selectedDataId = dataId[i]; + break; + } + } else { + console.error("Неверный формат данных для сравнения."); + } + } + } + + + if (dataFound) { + // Здесь можно отправить запрос скоростей и отрисовать график + res.json({ success: true, dataId: selectedDataId }); + } else { + res.json({ success: false, message: 'Данных для выбранного периода нет' }); + } + }} else { + res.json({ success: false, message: 'Ошибка при получении данных' }); + } + } catch (error) { + console.error('Ошибка при отправке запроса:', error); + res.json({ success: false, message: 'Ошибка при отправке запроса' }); + } +}); app.post("/getspeedarchive", async (req, res) => { const { serial, datetime } = req.body; diff --git a/static/styles/main.css b/static/styles/main.css index 08c072b..445b8f8 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -1462,6 +1462,26 @@ input[type="datetime-local"] { padding-bottom: 0; } +.speedometr .speed-bg { + z-index: 10; + position: absolute; + top: 0; + left: -20px; + border-radius: 15px; + background-color: #FFFFFF99; + width: 100%; + height: 100%; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; +} + +.speedometr .speed-bg h1 { + text-align: center; + margin: 0 10px; +} + .report li { list-style-type: none; margin-bottom: 12px; diff --git a/static/templates/videos/export.html b/static/templates/videos/export.html index dbe7674..0385496 100644 --- a/static/templates/videos/export.html +++ b/static/templates/videos/export.html @@ -114,69 +114,69 @@
- Запустить 1 камеру + Экспортировать 1 камеру
- Запустить 2 камеру + Экспортировать 2 камеру
- Запустить 3 камеру + Экспортировать 3 камеру
- Запустить 4 камеру + Экспортировать 4 камеру
- Запустить 5 камеру + Экспортировать 5 камеру
- Запустить 6 камеру + Экспортировать 6 камеру
- Запустить 7 камеру + Экспортировать 7 камеру
- Запустить 8 камеру + Экспортировать 8 камеру
- Запустить 9 камеру + Экспортировать 9 камеру
- Запустить 10 камеру + Экспортировать 10 камеру
- Запустить 11 камеру + Экспортировать 11 камеру
- Запустить 12 камеру + Экспортировать 12 камеру
- Запустить 13 камеру + Экспортировать 13 камеру
- Запустить 14 камеру + Экспортировать 14 камеру
- Запустить 15 камеру + Экспортировать 15 камеру
- Запустить 16 камеру + Экспортировать 16 камеру
@@ -202,6 +202,9 @@
+

Скорость

км/ч 1 ч @@ -211,7 +214,10 @@
+ с + до +
@@ -267,117 +273,168 @@ function combineDateTime(dateString, timeString) { return combinedDateTime; } -function sendPostRequest() { +let HasData; +let recordID; +var selectedChannel = 1; + + + +async function sendPostRequest() { // Получение данных из полей ввода const selectedDate = document.getElementById("selectedDate").value; const videoTime = document.getElementById("video-time").value; + const videoEndTime = document.getElementById("video-end-time").value; const selectedSerial = document.querySelector('input[name="camera-serial"]:checked').value; + // Объединяем дату и время и преобразуем в нужный формат const combinedDateTime = combineDateTime(selectedDate, videoTime); - const requestData = { - serial: selectedSerial, - datetime: combinedDateTime, - }; + const response = await fetch(`/getData?serial=${selectedSerial}&selectedDate=${formatDate(selectedDate)}&selectedTime=${formatTime(videoTime)}&selectedChannel=${selectedChannel}`); - fetch("/getspeedarchive", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(requestData), - }) - .then((response) => response.json()) - .then((data) => { + const data = await response.json(); - const existingChart = Chart.getChart("speed"); + HasData = data.success; - if (existingChart) { - existingChart.destroy(); - } + if (data.success) { + console.log(`Данные доступны. DATAID: ${data.dataId}`) + recordID = data.dataId; + const requestData = { + serial: selectedSerial, + datetime: combinedDateTime, + }; - const numberOfLabels = data.speeds.length; - const labels = Array.from({ length: numberOfLabels }, () => ""); + fetch("/getspeedarchive", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(requestData), + }) + .then((response) => response.json()) + .then((data) => { - // Обновление данных графика - const chart = new Chart("speed", { - type: "line", - data: { - labels: labels, - datasets: [ - { - label: "Скорость", - borderColor: "#8086F9", - fill: false, - data: data.speeds, - pointStyle: false, - pointRadius: 25, - pointHoverRadius: 25, - tension: 0.1, - }, - ], - }, - options: { - plugins: { - legend: { - display: false, - }, - }, - labelStep: "3", - responsive: true, - maintainAspectRatio: false, - scales: { - y: { - stacked: true, - grid: { - display: true, - color: "#D9D9D9", - }, - ticks: { - stepSize: 10, - }, - }, - x: { - grid: { - display: false, - }, - }, - }, - }, - }); + const existingChart = Chart.getChart("speed"); + + if (existingChart) { + existingChart.destroy(); + } + + const numberOfLabels = data.speeds.length; + const labels = Array.from({ length: numberOfLabels }, () => ""); + + // Обновление данных графика + const chart = new Chart("speed", { + type: "line", + data: { + labels: labels, + datasets: [ + { + label: "Скорость", + borderColor: "#8086F9", + fill: false, + data: data.speeds, + pointStyle: false, + pointRadius: 25, + pointHoverRadius: 25, + tension: 0.1, + }, + ], + }, + options: { + plugins: { + legend: { + display: false, + }, + }, + labelStep: "3", + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + stacked: true, + grid: { + display: true, + color: "#D9D9D9", + }, + ticks: { + stepSize: 10, + }, + }, + x: { + grid: { + display: false, + }, + }, + }, + }, + }); - const geoData = data.geo; + const geoData = data.geo; - // Очищаем все слои на карте -map.eachLayer(layer => { - if (layer !== map) { - map.removeLayer(layer); - } -}); + // Очищаем все слои на карте + map.eachLayer(layer => { + if (layer !== map) { + map.removeLayer(layer); + } + }); -// Добавляем слой с плитками OpenStreetMap -L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}').addTo(map); + // Добавляем слой с плитками OpenStreetMap + L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}').addTo(map); -// Создаем слой для маршрута -const routeLayer = L.layerGroup().addTo(map); + // Создаем слой для маршрута + const routeLayer = L.layerGroup().addTo(map); -// Создаем слой для маркеров -const markerLayer = L.layerGroup().addTo(map); + // Создаем слой для маркеров + const markerLayer = L.layerGroup().addTo(map); -// Преобразуем координаты точек маршрута -const routePoints = geoData.map(point => [point.latitude, point.longitude]); + // Преобразуем координаты точек маршрута + const routePoints = geoData.map(point => [point.latitude, point.longitude]); -// Создаем линию маршрута -const route = L.polyline(routePoints, { color: 'red',weight: 5 }).addTo(routeLayer); + // Создаем линию маршрута + const route = L.polyline(routePoints, { color: 'red',weight: 5 }).addTo(routeLayer); - }) - .catch((error) => { - console.error("Ошибка при отправке запроса:", error); - }); + }) + .catch((error) => { + console.error("Ошибка при отправке запроса:", error); + }); + + const endResponse = await fetch(`/getData?serial=${selectedSerial}&selectedDate=${formatDate(selectedDate)}&selectedTime=${formatTime(videoEndTime)}&selectedChannel=${selectedChannel}`); + + const endData = await endResponse.json(); + + if (endData.success) { + console.log(`Конечные данные доступны. DATAID: ${endData.dataId}`) + const speedBG = document.getElementById("speed-bg"); + speedBG.style.display = 'none'; + HasData = true; + if (data.dataId != endData.dataId) { + HasData = false; + var h1Element = document.querySelector('.speedometr h1'); + h1Element.textContent = 'Временной диапазон находится в разных видео сессиях. Измените время.'; + const speedBG = document.getElementById("speed-bg"); + speedBG.style.display = 'flex'; + } + } else { + HasData = false; + const speedBG = document.getElementById("speed-bg"); + speedBG.style.display = 'flex'; + var h1Element = document.querySelector('.speedometr h1'); + h1Element.textContent = 'Данных для выбранного периода нет.'; + } + + + } else { + var h1Element = document.querySelector('.speedometr h1'); + h1Element.textContent = 'Данных для выбранного периода нет.'; + const speedBG = document.getElementById("speed-bg"); + speedBG.style.display = 'flex'; + } + + } @@ -392,6 +449,9 @@ selectedDateInput.addEventListener("change", sendPostRequest); const videoTimeInput = document.getElementById("video-time"); videoTimeInput.addEventListener("change", sendPostRequest); +const endVideoTimeInput = document.getElementById("video-end-time"); +endVideoTimeInput.addEventListener("change", sendPostRequest); + @@ -400,6 +460,20 @@ videoTimeInput.addEventListener("change", sendPostRequest); now.setHours(now.getHours() - 1); var formattedTime = now.toISOString().substr(11, 8); document.getElementById("video-time").value = formattedTime; + const startTimeInput = document.getElementById('video-time'); + const endTimeInput = document.getElementById('video-end-time'); + + const startTime = new Date(`1970-01-01T${startTimeInput.value}Z`); + + startTime.setHours(startTime.getHours() - 3); + startTime.setSeconds(startTime.getSeconds() + 10); + + const hours = startTime.getHours().toString().padStart(2, '0'); + const minutes = startTime.getMinutes().toString().padStart(2, '0'); + const seconds = startTime.getSeconds().toString().padStart(2, '0'); + const endTimeString = `${hours}:${minutes}:${seconds}`; + + endTimeInput.value = endTimeString; @@ -452,10 +526,11 @@ videoTimeInput.addEventListener("change", sendPostRequest); selectedDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); renderCalendar(); selectedDateInput.value = selectedDate.toISOString(); + sendPostRequest(); }); datesContainer.appendChild(dateCell); } - sendPostRequest(); + } // Перейти на предыдущий месяц @@ -477,7 +552,7 @@ videoTimeInput.addEventListener("change", sendPostRequest); diff --git a/static/templates/videos/playback.html b/static/templates/videos/playback.html index af505c5..a19174e 100644 --- a/static/templates/videos/playback.html +++ b/static/templates/videos/playback.html @@ -68,7 +68,7 @@
@@ -202,6 +202,9 @@
+

Скорость

км/ч 1 ч @@ -267,117 +270,134 @@ function combineDateTime(dateString, timeString) { return combinedDateTime; } -function sendPostRequest() { +let HasData; +var selectedChannel = 1; + +async function sendPostRequest() { // Получение данных из полей ввода const selectedDate = document.getElementById("selectedDate").value; const videoTime = document.getElementById("video-time").value; const selectedSerial = document.querySelector('input[name="camera-serial"]:checked').value; + // Объединяем дату и время и преобразуем в нужный формат const combinedDateTime = combineDateTime(selectedDate, videoTime); - const requestData = { - serial: selectedSerial, - datetime: combinedDateTime, - }; + const response = await fetch(`/getData?serial=${selectedSerial}&selectedDate=${formatDate(selectedDate)}&selectedTime=${formatTime(videoTime)}&selectedChannel=${selectedChannel}`); + const data = await response.json(); - fetch("/getspeedarchive", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(requestData), - }) - .then((response) => response.json()) - .then((data) => { + HasData = data.success; - const existingChart = Chart.getChart("speed"); + if (data.success) { + console.log(`Данные доступны. DATAID: ${data.dataId}`) + const requestData = { + serial: selectedSerial, + datetime: combinedDateTime, + }; - if (existingChart) { - existingChart.destroy(); - } + fetch("/getspeedarchive", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(requestData), + }) + .then((response) => response.json()) + .then((data) => { - const numberOfLabels = data.speeds.length; - const labels = Array.from({ length: numberOfLabels }, () => ""); + const existingChart = Chart.getChart("speed"); - // Обновление данных графика - const chart = new Chart("speed", { - type: "line", - data: { - labels: labels, - datasets: [ - { - label: "Скорость", - borderColor: "#8086F9", - fill: false, - data: data.speeds, - pointStyle: false, - pointRadius: 25, - pointHoverRadius: 25, - tension: 0.1, - }, - ], - }, - options: { - plugins: { - legend: { - display: false, - }, - }, - labelStep: "3", - responsive: true, - maintainAspectRatio: false, - scales: { - y: { - stacked: true, - grid: { - display: true, - color: "#D9D9D9", - }, - ticks: { - stepSize: 10, - }, - }, - x: { - grid: { - display: false, - }, - }, - }, - }, - }); + if (existingChart) { + existingChart.destroy(); + } + + const numberOfLabels = data.speeds.length; + const labels = Array.from({ length: numberOfLabels }, () => ""); + + // Обновление данных графика + const chart = new Chart("speed", { + type: "line", + data: { + labels: labels, + datasets: [ + { + label: "Скорость", + borderColor: "#8086F9", + fill: false, + data: data.speeds, + pointStyle: false, + pointRadius: 25, + pointHoverRadius: 25, + tension: 0.1, + }, + ], + }, + options: { + plugins: { + legend: { + display: false, + }, + }, + labelStep: "3", + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + stacked: true, + grid: { + display: true, + color: "#D9D9D9", + }, + ticks: { + stepSize: 10, + }, + }, + x: { + grid: { + display: false, + }, + }, + }, + }, + }); - const geoData = data.geo; + const geoData = data.geo; - // Очищаем все слои на карте -map.eachLayer(layer => { - if (layer !== map) { - map.removeLayer(layer); - } -}); + // Очищаем все слои на карте + map.eachLayer(layer => { + if (layer !== map) { + map.removeLayer(layer); + } + }); -// Добавляем слой с плитками OpenStreetMap -L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}').addTo(map); + // Добавляем слой с плитками OpenStreetMap + L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}').addTo(map); -// Создаем слой для маршрута -const routeLayer = L.layerGroup().addTo(map); + // Создаем слой для маршрута + const routeLayer = L.layerGroup().addTo(map); -// Создаем слой для маркеров -const markerLayer = L.layerGroup().addTo(map); + // Создаем слой для маркеров + const markerLayer = L.layerGroup().addTo(map); -// Преобразуем координаты точек маршрута -const routePoints = geoData.map(point => [point.latitude, point.longitude]); + // Преобразуем координаты точек маршрута + const routePoints = geoData.map(point => [point.latitude, point.longitude]); -// Создаем линию маршрута -const route = L.polyline(routePoints, { color: 'red',weight: 5 }).addTo(routeLayer); + // Создаем линию маршрута + const route = L.polyline(routePoints, { color: 'red',weight: 5 }).addTo(routeLayer); - }) - .catch((error) => { - console.error("Ошибка при отправке запроса:", error); - }); + }) + .catch((error) => { + console.error("Ошибка при отправке запроса:", error); + }); + } else { + const speedBG = document.getElementById("speed-bg"); + speedBG.style.display = 'flex'; + } + + } @@ -452,10 +472,11 @@ videoTimeInput.addEventListener("change", sendPostRequest); selectedDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); renderCalendar(); selectedDateInput.value = selectedDate.toISOString(); + sendPostRequest(); }); datesContainer.appendChild(dateCell); } - sendPostRequest(); + } // Перейти на предыдущий месяц @@ -508,6 +529,11 @@ videoTimeInput.addEventListener("change", sendPostRequest); alert('Пожалуйста, выберите устройство из списка.'); return; } + if (!HasData) { + alert('Пожалуйста, выберите другой временной период.'); + return; + } + const startTimeInput = document.getElementById('video-time'); const selectedDateInput = document.getElementById('selectedDate'); @@ -518,6 +544,8 @@ videoTimeInput.addEventListener("change", sendPostRequest); const serial = selectedDevice.value; + selectedChannel = channel; + const url = `http://localhost:8081/playback?url=http%3A%2F%2Fkrbl.ru%3A8080%2Fhttp%2Fplayback.flv%3Fserial%3D${serial}%26channel%3D${channel}%26quality%3D1%26queryTime%3D${selectedDate}%26startTime%3D${startTime}%26endTime%3D${endTime}`; window.open(url, '_blank'); }