2023-07-03 22:31:18 +00:00
|
|
|
|
const express = require("express");
|
|
|
|
|
const app = express();
|
|
|
|
|
const path = require("path");
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const { Pool } = require("pg");
|
|
|
|
|
const fs = require("fs");
|
|
|
|
|
const handlebars = require("handlebars");
|
|
|
|
|
require("dotenv").config();
|
|
|
|
|
const multer = require("multer");
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const http = require("http");
|
2023-08-28 11:25:45 +00:00
|
|
|
|
const axios = require('axios');
|
|
|
|
|
const moment = require('moment');
|
2023-09-04 09:11:22 +00:00
|
|
|
|
const bodyParser = require('body-parser');
|
|
|
|
|
const _ = require('lodash');
|
2023-09-06 19:07:19 +00:00
|
|
|
|
const puppeteer = require('puppeteer');
|
2023-09-11 09:57:10 +00:00
|
|
|
|
const session = require('express-session');
|
2023-08-28 04:40:58 +00:00
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
const storage = multer.diskStorage({
|
|
|
|
|
destination: function (req, file, cb) {
|
2023-08-13 17:52:23 +00:00
|
|
|
|
cb(null, "uploads");
|
2023-07-24 04:53:11 +00:00
|
|
|
|
},
|
|
|
|
|
filename: function (req, file, cb) {
|
|
|
|
|
cb(null, Date.now() + "-" + file.originalname);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const upload = multer({ storage: storage });
|
2023-07-03 22:31:18 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
app.use(
|
|
|
|
|
session({
|
2023-09-11 10:02:47 +00:00
|
|
|
|
secret: process.env.SEKRET,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
resave: false,
|
|
|
|
|
saveUninitialized: true,
|
|
|
|
|
cookie: { maxAge: 24 * 60 * 60 * 1000 },
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
2023-07-03 22:31:18 +00:00
|
|
|
|
app.use(express.static(path.join(__dirname, "static")));
|
2023-07-16 16:09:25 +00:00
|
|
|
|
app.use(express.json());
|
2023-07-24 04:53:11 +00:00
|
|
|
|
app.use(express.urlencoded({ extended: false }));
|
2023-09-04 09:11:22 +00:00
|
|
|
|
app.use(bodyParser.json());
|
2023-07-03 22:31:18 +00:00
|
|
|
|
|
|
|
|
|
app.get("/", index);
|
2023-09-11 09:57:10 +00:00
|
|
|
|
app.get("/signin", signin);
|
2023-07-03 22:31:18 +00:00
|
|
|
|
app.get("/register", register);
|
|
|
|
|
app.get("/live", live);
|
|
|
|
|
app.get("/reports", reports);
|
|
|
|
|
app.get("/devices", devices);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
// app.get("/devices/drivers", drivers);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
app.get("/devices/update", update);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
app.get("/devices/groups", groups)
|
2023-08-21 03:28:58 +00:00
|
|
|
|
app.get("/videos", videos);
|
2023-08-28 04:40:58 +00:00
|
|
|
|
app.get("/videos/export",videoExport);
|
|
|
|
|
app.get("/settings", settings);
|
2023-09-11 05:59:00 +00:00
|
|
|
|
app.get("/admin", adminPanel);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
app.get("/admin/organisation", organisation);
|
2023-08-28 04:40:58 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
async function getUserInfo(userId) {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
let userInfo = {
|
|
|
|
|
Organisation: "",
|
|
|
|
|
User: '',
|
|
|
|
|
Users: [],
|
2023-09-18 01:58:49 +00:00
|
|
|
|
EditTransport: false,
|
|
|
|
|
DeleteTransport: false,
|
|
|
|
|
Update: false,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (userId != "admin") {
|
|
|
|
|
const queryUsers = `
|
|
|
|
|
SELECT name, surname, devices, edittransport, deletetransport, update
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const usersResult = await client.query(queryUsers, [userId]);
|
|
|
|
|
const user = usersResult.rows[0];
|
|
|
|
|
userInfo.Users.push({
|
|
|
|
|
name: user.name,
|
|
|
|
|
surname: user.surname,
|
|
|
|
|
devices: user.devices,
|
|
|
|
|
edittransport: user.edittransport,
|
|
|
|
|
deletetransport: user.deletetransport,
|
|
|
|
|
update: user.update,
|
|
|
|
|
});
|
|
|
|
|
userInfo.User = user.name + " " + user.surname;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
userInfo.EditTransport = user.edittransport;
|
|
|
|
|
userInfo.DeleteTransport = user.deletetransport;
|
|
|
|
|
userInfo.Update = user.update;
|
2023-09-11 09:57:10 +00:00
|
|
|
|
} else {
|
|
|
|
|
userInfo.User = "Администратор"
|
2023-09-18 01:58:49 +00:00
|
|
|
|
userInfo.EditTransport = true;
|
|
|
|
|
userInfo.DeleteTransport = true;
|
|
|
|
|
userInfo.Update = true;
|
2023-09-11 09:57:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const queryMain = `SELECT organisation FROM main`;
|
|
|
|
|
const mainResult = await client.query(queryMain);
|
|
|
|
|
userInfo.Organisation = mainResult.rows[0].organisation;
|
|
|
|
|
|
|
|
|
|
return userInfo;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
throw error;
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-08-28 04:40:58 +00:00
|
|
|
|
app.post("/videos/restart", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-08-28 04:40:58 +00:00
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
var options = {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
url: `http://${process.env.SERVER_IP}:8080/http/restart`,
|
|
|
|
|
headers: {'Content-Type': 'application/json'},
|
|
|
|
|
data: {video: true}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
axios.request(options).then(function (response) {
|
|
|
|
|
res.status(200).json({ message: "Команда для рестарта выполнена." });
|
|
|
|
|
return;
|
|
|
|
|
}).catch(function (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
res.status(500).json({ error: "Ошибка сервера" });
|
|
|
|
|
return;
|
2023-08-28 04:40:58 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
});
|
2023-07-03 22:31:18 +00:00
|
|
|
|
|
2023-07-16 17:02:59 +00:00
|
|
|
|
|
2023-09-22 07:43:47 +00:00
|
|
|
|
// const DB_User = process.env.DB_USER;
|
|
|
|
|
// const DB_Password = process.env.DB_PASSWORD;
|
|
|
|
|
// const DB_Host = process.env.DB_HOST;
|
|
|
|
|
// const DB_Port = process.env.DB_PORT;
|
|
|
|
|
// const DB_Name = process.env.DB_NAME;
|
|
|
|
|
|
|
|
|
|
const DB_User = "postgres";
|
|
|
|
|
const DB_Password = process.env.POSTGRES_PASSWORD;
|
|
|
|
|
const DB_Host = "postgres";
|
|
|
|
|
const DB_Port = "5432";
|
|
|
|
|
const DB_Name = "postgres";
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
|
|
|
|
async function index(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
var templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-07-18 01:32:15 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Count: "",
|
2023-08-14 04:11:03 +00:00
|
|
|
|
AlarmsLast11Days: new Array(11).fill(0),
|
|
|
|
|
Alarms11DaysBefore: new Array(11).fill(0),
|
|
|
|
|
Dates: [],
|
|
|
|
|
PositionsLast11Days: new Array(11).fill(0),
|
2023-07-18 01:32:15 +00:00
|
|
|
|
};
|
2023-07-16 16:09:25 +00:00
|
|
|
|
try {
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const query = `
|
|
|
|
|
SELECT COUNT(*) AS count
|
|
|
|
|
FROM registrars
|
|
|
|
|
`;
|
|
|
|
|
const registrars = await client.query(query);
|
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
templateData.Count = registrars.rows[0].count;
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
2023-09-22 07:42:39 +00:00
|
|
|
|
templateData.Count = serialValues.length;
|
2023-09-22 07:55:07 +00:00
|
|
|
|
} else {
|
|
|
|
|
templateData.Count = 0;
|
|
|
|
|
}
|
2023-09-18 01:58:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 04:11:03 +00:00
|
|
|
|
const last11DaysQuery = `
|
2023-08-21 03:28:58 +00:00
|
|
|
|
WITH date_sequence AS (
|
2023-08-28 06:20:23 +00:00
|
|
|
|
SELECT DATE_TRUNC('day', NOW() - INTERVAL '10 days' - INTERVAL '3 hours') + (generate_series(0, 10) || ' days')::interval AS day
|
2023-08-21 03:28:58 +00:00
|
|
|
|
)
|
|
|
|
|
SELECT
|
|
|
|
|
date_sequence.day AS day,
|
2023-08-28 06:20:23 +00:00
|
|
|
|
COALESCE(COUNT(DISTINCT a.evtuuid), 0) AS count
|
2023-08-21 03:28:58 +00:00
|
|
|
|
FROM date_sequence
|
2023-08-28 06:20:23 +00:00
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT DISTINCT ON (evtuuid) evtuuid, time
|
|
|
|
|
FROM alarms
|
|
|
|
|
WHERE alarmtype = 56
|
|
|
|
|
AND time >= NOW() - INTERVAL '11 days' + INTERVAL '3 hours'
|
|
|
|
|
AND time <= NOW() + INTERVAL '1 day' + INTERVAL '3 hours'
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'AND serial = ANY($1)' : ''}
|
2023-08-28 06:20:23 +00:00
|
|
|
|
ORDER BY evtuuid, time DESC
|
|
|
|
|
LIMIT 100
|
|
|
|
|
) AS a ON DATE_TRUNC('day', a.time) = date_sequence.day
|
2023-08-21 03:28:58 +00:00
|
|
|
|
GROUP BY date_sequence.day
|
2023-08-28 06:20:23 +00:00
|
|
|
|
ORDER BY date_sequence.day DESC;
|
2023-08-14 04:11:03 +00:00
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const last11DaysAlarms = await client.query(last11DaysQuery, templateData.isAdmin ? [] : [serialValues]);
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
|
|
|
|
const daysBeforeQuery = `
|
2023-08-28 04:40:58 +00:00
|
|
|
|
WITH date_sequence AS (
|
2023-08-28 06:20:23 +00:00
|
|
|
|
SELECT DATE_TRUNC('day', NOW() - INTERVAL '21 days' - INTERVAL '3 hours') + (generate_series(0, 10) || ' days')::interval AS day
|
2023-08-28 04:40:58 +00:00
|
|
|
|
)
|
|
|
|
|
SELECT
|
|
|
|
|
date_sequence.day AS day,
|
2023-08-28 06:20:23 +00:00
|
|
|
|
COALESCE(COUNT(DISTINCT a.evtuuid), 0) AS count
|
2023-08-28 04:40:58 +00:00
|
|
|
|
FROM date_sequence
|
2023-08-28 06:20:23 +00:00
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT DISTINCT ON (evtuuid) evtuuid, time
|
|
|
|
|
FROM alarms
|
|
|
|
|
WHERE alarmtype = 56
|
|
|
|
|
AND time >= NOW() - INTERVAL '21 days' + INTERVAL '3 hours'
|
|
|
|
|
AND time <= NOW() + INTERVAL '10 day' + INTERVAL '3 hours'
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'AND serial = ANY($1)' : ''}
|
2023-08-28 06:20:23 +00:00
|
|
|
|
ORDER BY evtuuid, time DESC
|
|
|
|
|
LIMIT 100
|
|
|
|
|
) AS a ON DATE_TRUNC('day', a.time) = date_sequence.day
|
2023-08-28 04:40:58 +00:00
|
|
|
|
GROUP BY date_sequence.day
|
2023-08-28 06:20:23 +00:00
|
|
|
|
ORDER BY date_sequence.day DESC;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
`;
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const daysBeforeAlarms = await client.query(daysBeforeQuery, templateData.isAdmin ? [] : [serialValues]);
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
|
|
|
|
const currentDate = new Date();
|
|
|
|
|
const dates = [];
|
2023-08-28 04:40:58 +00:00
|
|
|
|
const dates11DaysAgo = [];
|
2023-08-14 04:11:03 +00:00
|
|
|
|
for (let i = 10; i >= 0; i--) {
|
|
|
|
|
const date = new Date(currentDate - i * 24 * 60 * 60 * 1000);
|
|
|
|
|
const formattedDate = date.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit' });
|
|
|
|
|
dates.push(formattedDate);
|
2023-08-28 04:40:58 +00:00
|
|
|
|
|
|
|
|
|
const date11DaysAgo = new Date(currentDate - i * 24 * 60 * 60 * 1000 - 11 * 24 * 60 * 60 * 1000);
|
|
|
|
|
const formattedDate11DaysAgo = date11DaysAgo.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit' });
|
|
|
|
|
dates11DaysAgo.push(formattedDate11DaysAgo);
|
2023-08-14 04:11:03 +00:00
|
|
|
|
}
|
|
|
|
|
templateData.Dates = dates;
|
2023-08-28 04:40:58 +00:00
|
|
|
|
dates11DaysAgo.reverse();
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
|
|
|
|
const positionsLast11DaysQuery = `
|
2023-09-18 01:58:49 +00:00
|
|
|
|
SELECT
|
2023-08-21 03:28:58 +00:00
|
|
|
|
COUNT(*) AS count,
|
|
|
|
|
DATE_TRUNC('day', time) AS day,
|
|
|
|
|
CASE WHEN COUNT(*) = 0 THEN 0 ELSE 1 END AS sort_value
|
|
|
|
|
FROM geo
|
|
|
|
|
WHERE time >= NOW() - INTERVAL '10 days' + INTERVAL '3 hours'
|
|
|
|
|
AND time <= NOW() + INTERVAL '1 day' + INTERVAL '3 hours'
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'AND serial = ANY($1)' : ''}
|
2023-08-21 03:28:58 +00:00
|
|
|
|
GROUP BY DATE_TRUNC('day', time)
|
2023-09-18 01:58:49 +00:00
|
|
|
|
ORDER BY sort_value DESC, day DESC;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const positionsLast11Days = await client.query(positionsLast11DaysQuery, templateData.isAdmin ? [] : [serialValues]);
|
|
|
|
|
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
|
|
|
|
templateData.Dates.reverse();
|
|
|
|
|
|
|
|
|
|
const last11DaysMap = new Map(last11DaysAlarms.rows.map(row => [row.day.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit' }), parseInt(row.count, 10)]));
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
2023-08-21 03:28:58 +00:00
|
|
|
|
for (let i = 0; i < dates.length; i++) {
|
|
|
|
|
const dateKey = dates[i];
|
|
|
|
|
templateData.AlarmsLast11Days[i] = last11DaysMap.has(dateKey) ? last11DaysMap.get(dateKey) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const beforeDaysMap = new Map(daysBeforeAlarms.rows.map(row => [row.day.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit' }), parseInt(row.count, 10)]));
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < dates.length; i++) {
|
2023-08-28 04:40:58 +00:00
|
|
|
|
const dateKey = dates11DaysAgo[i];
|
2023-08-21 03:28:58 +00:00
|
|
|
|
templateData.Alarms11DaysBefore[i] = beforeDaysMap.has(dateKey) ? beforeDaysMap.get(dateKey) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const positionsMap = new Map(positionsLast11Days.rows.map(row => [row.day.toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit' }), parseInt(row.count, 10)]));
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < dates.length; i++) {
|
|
|
|
|
const dateKey = dates[i];
|
|
|
|
|
templateData.PositionsLast11Days[i] = positionsMap.has(dateKey) ? positionsMap.get(dateKey) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// console.log(templateData);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/index.html", "utf8");
|
|
|
|
|
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/index.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
function signin(req, res) {
|
|
|
|
|
if (req.session.userId != undefined) {
|
|
|
|
|
return res.redirect("/");
|
|
|
|
|
}
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
pool.query('SELECT COUNT(*) FROM main', (error, result) => {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error('Ошибка при выполнении запроса к базе данных:', error);
|
|
|
|
|
res.status(500).send('Ошибка сервера');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const rowCount = parseInt(result.rows[0].count, 10);
|
|
|
|
|
|
|
|
|
|
if (rowCount === 0) {
|
|
|
|
|
res.redirect('/register');
|
|
|
|
|
} else {
|
|
|
|
|
res.sendFile(path.join(__dirname, 'static/templates/signin.html'));
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-09-11 09:57:10 +00:00
|
|
|
|
|
2023-07-03 22:31:18 +00:00
|
|
|
|
function register(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId != undefined) {
|
|
|
|
|
return res.redirect("/");
|
|
|
|
|
}
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
pool.query('SELECT COUNT(*) FROM main', (err, result) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error('Ошибка выполнения SQL-запроса:', err);
|
|
|
|
|
res.status(500).send('Внутренняя ошибка сервера');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.rows[0].count > 0) {
|
|
|
|
|
res.redirect('/signin');
|
|
|
|
|
} else {
|
|
|
|
|
res.sendFile(path.join(__dirname, 'static/templates/register.html'));
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
app.post('/setup', async (req, res) => {
|
|
|
|
|
if (req.session.userId != undefined) {
|
|
|
|
|
return res.redirect("/");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const { name, login, password } = req.body;
|
|
|
|
|
|
|
|
|
|
const checkQuery = 'SELECT * FROM main LIMIT 1';
|
|
|
|
|
const checkResult = await pool.query(checkQuery);
|
|
|
|
|
|
|
|
|
|
if (checkResult.rows.length > 0) {
|
|
|
|
|
res.redirect('/signin');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const insertQuery = 'INSERT INTO main (organisation, login, password) VALUES ($1, $2, $3)';
|
|
|
|
|
await pool.query(insertQuery, [name, login, password]);
|
|
|
|
|
|
|
|
|
|
res.status(200).json({ message: 'Данные успешно добавлены' });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Ошибка при обработке запроса:', error);
|
|
|
|
|
res.status(500).json({ error: 'Произошла ошибка при обработке запроса' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post('/login', async (req, res) => {
|
|
|
|
|
if (req.session.userId != undefined) {
|
|
|
|
|
return res.redirect("/");
|
|
|
|
|
}
|
|
|
|
|
const { email, password } = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const mainQuery = await pool.query(
|
|
|
|
|
'SELECT * FROM main WHERE login = $1 AND password = $2',
|
|
|
|
|
[email, password]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const mainUser = mainQuery.rows[0];
|
|
|
|
|
|
|
|
|
|
if (mainUser) {
|
|
|
|
|
req.session.userId = "admin";
|
|
|
|
|
|
|
|
|
|
console.log("Авторизация успешна (из таблицы main)");
|
|
|
|
|
return res.status(200).json({ message: 'Авторизация успешна' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const userQuery = await pool.query(
|
|
|
|
|
'SELECT id, name, surname FROM users WHERE email = $1 AND password = $2',
|
|
|
|
|
[email, password]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const user = userQuery.rows[0];
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
|
return res.status(401).json({ message: 'Неправильное имя пользователя или пароль' });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.session.userId = user.id;
|
|
|
|
|
|
|
|
|
|
console.log("Авторизация успешна (из таблицы users)");
|
|
|
|
|
res.status(200).json({ message: 'Авторизация успешна' });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Ошибка при выполнении запроса к базе данных:', error);
|
|
|
|
|
res.status(500).json({ message: 'Ошибка сервера' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.get('/logout', (req, res) => {
|
|
|
|
|
req.session.destroy((err) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
console.error('Ошибка при выходе из системы:', err);
|
|
|
|
|
res.status(500).json({ message: 'Ошибка сервера' });
|
|
|
|
|
} else {
|
|
|
|
|
res.redirect('/signin');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
async function live(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-07-18 01:32:15 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: [],
|
2023-08-07 01:15:36 +00:00
|
|
|
|
Alarms: [],
|
|
|
|
|
Count: 0,
|
2023-09-04 09:11:22 +00:00
|
|
|
|
Groups: [],
|
2023-07-18 01:32:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
2023-08-07 01:15:36 +00:00
|
|
|
|
const minuteInMillis = 90 * 1000;
|
2023-08-01 12:35:10 +00:00
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const query = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, channels, lastkeepalive, number FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''} ORDER BY id ASC
|
2023-07-18 01:32:15 +00:00
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrars = await client.query(query, templateData.isAdmin ? [] : [serialValues]);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
2023-08-01 11:52:35 +00:00
|
|
|
|
templateData.Registrars = registrars.rows.map((row) => ({
|
|
|
|
|
id: row.id,
|
|
|
|
|
serial: row.serial,
|
2023-08-28 04:40:58 +00:00
|
|
|
|
channels: row.channels,
|
2023-08-01 12:35:10 +00:00
|
|
|
|
status: Date.now() - Date.parse(row.lastkeepalive) <= minuteInMillis,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: row.number,
|
2023-08-01 11:52:35 +00:00
|
|
|
|
}));
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
2023-08-07 01:15:36 +00:00
|
|
|
|
const subquery = `
|
2023-08-13 17:52:23 +00:00
|
|
|
|
SELECT a.evtuuid, a.id, a.cmdno, a.time, a.serial, a.st, r.plate, g.latitude, g.longitude
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT DISTINCT ON (evtuuid) evtuuid, id, cmdno, time, serial, st
|
|
|
|
|
FROM alarms
|
|
|
|
|
WHERE alarmtype = 56
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'AND serial = ANY($2)' : ''}
|
2023-08-13 17:52:23 +00:00
|
|
|
|
ORDER BY evtuuid, time DESC
|
|
|
|
|
LIMIT 100
|
|
|
|
|
) AS a
|
|
|
|
|
LEFT JOIN registrars AS r ON a.serial = r.serial
|
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT *,
|
|
|
|
|
ROW_NUMBER() OVER (PARTITION BY serial ORDER BY ABS(EXTRACT(EPOCH FROM (time - $1)))) AS row_num
|
|
|
|
|
FROM geo
|
|
|
|
|
) AS g ON a.serial = g.serial AND g.row_num = 1
|
|
|
|
|
ORDER BY a.time DESC;
|
2023-08-07 01:15:36 +00:00
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const alarms = await client.query(subquery, templateData.isAdmin ? [new Date()] : [new Date(), serialValues]);
|
2023-08-07 01:15:36 +00:00
|
|
|
|
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
const options = {
|
|
|
|
|
year: "2-digit",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
};
|
2023-08-13 17:52:23 +00:00
|
|
|
|
const adjustedDate = new Date(date);
|
|
|
|
|
adjustedDate.setHours(adjustedDate.getHours() - 3);
|
|
|
|
|
|
|
|
|
|
const formattedDate = adjustedDate.toLocaleString("ru-RU", options);
|
2023-08-07 01:15:36 +00:00
|
|
|
|
return formattedDate.replace(",", "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(templateData.Alarms = alarms.rows.map((alarm) => {
|
|
|
|
|
let type;
|
|
|
|
|
switch (alarm.st) {
|
|
|
|
|
case "0":
|
|
|
|
|
type = "Усталость";
|
|
|
|
|
break;
|
|
|
|
|
case "1":
|
|
|
|
|
type = "Водитель пропал";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
type = "Разговор по телефону";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
type = "Курение за рулём";
|
|
|
|
|
break;
|
|
|
|
|
case "4":
|
|
|
|
|
type = "Водитель отвлекся";
|
|
|
|
|
break;
|
|
|
|
|
case "5":
|
|
|
|
|
type = "Выезд с полосы движения";
|
|
|
|
|
break;
|
|
|
|
|
case "6":
|
|
|
|
|
type = "!!! Лобовое столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "7":
|
|
|
|
|
type = "Скорость превышена";
|
|
|
|
|
break;
|
|
|
|
|
case "8":
|
|
|
|
|
type = "Распознавание номерных знаков";
|
|
|
|
|
break;
|
|
|
|
|
case "9":
|
|
|
|
|
type = "!! Маленькое расстояние спереди";
|
|
|
|
|
break;
|
|
|
|
|
case "10":
|
|
|
|
|
type = "Водитель зевает";
|
|
|
|
|
break;
|
|
|
|
|
case "11":
|
|
|
|
|
type = "!!! Столкновение с пешеходом";
|
|
|
|
|
break;
|
|
|
|
|
case "12":
|
|
|
|
|
type = "Проходы переполнены";
|
|
|
|
|
break;
|
|
|
|
|
case "13":
|
|
|
|
|
type = "!! Посадка/высадка вне остановки";
|
|
|
|
|
break;
|
|
|
|
|
case "14":
|
|
|
|
|
type = "!! Смена полосы с нарушением ПДД";
|
|
|
|
|
break;
|
|
|
|
|
case "15":
|
|
|
|
|
type = "! Включенный телефон у водителя";
|
|
|
|
|
break;
|
|
|
|
|
case "16":
|
|
|
|
|
type = "!!! Ремень безопасности";
|
|
|
|
|
break;
|
|
|
|
|
case "17":
|
|
|
|
|
type = "Проверка не удалась";
|
|
|
|
|
break;
|
|
|
|
|
case "18":
|
|
|
|
|
type = "Слепые зоны справа";
|
|
|
|
|
break;
|
|
|
|
|
case "19":
|
|
|
|
|
type = "!!! Заднее столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "20":
|
|
|
|
|
type = "!!! Управление без рук";
|
|
|
|
|
break;
|
|
|
|
|
case "21":
|
|
|
|
|
type = "!! Управление одной рукой";
|
|
|
|
|
break;
|
|
|
|
|
case "22":
|
2023-09-18 01:58:49 +00:00
|
|
|
|
type = "Очки, блокирующие инфракрасное";
|
2023-08-07 01:15:36 +00:00
|
|
|
|
break;
|
|
|
|
|
case "23":
|
|
|
|
|
type = "Слепые зоны слева";
|
|
|
|
|
break;
|
|
|
|
|
case "24":
|
|
|
|
|
type = "Помехи для пассажиров";
|
|
|
|
|
break;
|
|
|
|
|
case "25":
|
|
|
|
|
type = "На перекрестке ограничена скорость";
|
|
|
|
|
break;
|
|
|
|
|
case "26":
|
|
|
|
|
type = "Обнаружен перекресток";
|
|
|
|
|
break;
|
|
|
|
|
case "27":
|
|
|
|
|
type = "Пешеходы на переходе";
|
|
|
|
|
break;
|
|
|
|
|
case "28":
|
|
|
|
|
type = "! Неучтивое отношение к пешеходам";
|
|
|
|
|
break;
|
|
|
|
|
case "29":
|
|
|
|
|
type = "Обнаружен пешеходный переход";
|
|
|
|
|
break;
|
|
|
|
|
case "30":
|
|
|
|
|
type = "Водитель матерится";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
type = "Неизвестный тип";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: alarm.id,
|
|
|
|
|
cmdno: alarm.cmdno,
|
|
|
|
|
time: formatDate(alarm.time),
|
|
|
|
|
serial: alarm.serial,
|
|
|
|
|
st: alarm.st,
|
|
|
|
|
type: type,
|
|
|
|
|
plate: alarm.plate,
|
|
|
|
|
latitude: (alarm.latitude).toFixed(6),
|
|
|
|
|
longitude: (alarm.longitude).toFixed(6),
|
|
|
|
|
geo: alarm.latitude + "," + alarm.longitude,
|
|
|
|
|
};
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
templateData.Count = templateData.Alarms.length;
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
// Получаем список групп и их идентификаторов из таблицы groups
|
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// Выполняем запрос, чтобы получить все данные из таблицы registrars
|
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-18 01:58:49 +00:00
|
|
|
|
FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''}
|
2023-09-04 09:11:22 +00:00
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrarsResult = await client.query(queryRegistrars, templateData.isAdmin ? [] : [serialValues]);
|
2023-09-04 09:11:22 +00:00
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
|
|
|
|
|
|
|
|
|
const groupedRegistrars = {};
|
|
|
|
|
allRegistrars.forEach((registrar) => {
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
2023-09-04 09:11:22 +00:00
|
|
|
|
}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
groupedRegistrars[groupName].push({
|
2023-09-04 09:11:22 +00:00
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
2023-09-04 09:11:22 +00:00
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: registrar.number,
|
2023-09-04 09:11:22 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
templateData.Registrars = allRegistrars.map((registrar) => ({
|
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
|
2023-09-04 09:11:22 +00:00
|
|
|
|
name: groupName,
|
|
|
|
|
devices: groupedRegistrars[groupName],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}));
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const source = fs.readFileSync("static/templates/live.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultHTML = template(templateData);
|
|
|
|
|
res.send(resultHTML);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/live.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
app.post("/devices-geo", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const selectedDevices = req.body.devices;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const placeholders = selectedDevices
|
2023-08-01 13:05:54 +00:00
|
|
|
|
.map((_, index) => `$${index + 1}`)
|
|
|
|
|
.join(",");
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const subquery = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT g.serial, g.longitude, g.latitude, g.direction, g.speed, r.lastkeepalive, r.plate, r.group, r.number
|
2023-08-01 13:05:54 +00:00
|
|
|
|
FROM geo g
|
|
|
|
|
INNER JOIN (
|
|
|
|
|
SELECT serial, MAX(time) AS time
|
2023-07-18 01:32:15 +00:00
|
|
|
|
FROM geo
|
|
|
|
|
WHERE serial IN (
|
|
|
|
|
SELECT serial
|
|
|
|
|
FROM registrars
|
|
|
|
|
WHERE id IN (${placeholders})
|
|
|
|
|
)
|
|
|
|
|
GROUP BY serial
|
2023-08-01 13:05:54 +00:00
|
|
|
|
) s ON g.serial = s.serial AND g.time = s.time
|
|
|
|
|
INNER JOIN registrars r ON g.serial = r.serial
|
|
|
|
|
`;
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
pool.query(subquery, selectedDevices, async (err, result) => {
|
2023-08-01 13:05:54 +00:00
|
|
|
|
if (err) {
|
|
|
|
|
console.error("Ошибка выполнения запроса:", err);
|
|
|
|
|
res.status(500).json({ error: "Ошибка сервера" });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const minuteInMillis = 60000;
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const devicesData = [];
|
|
|
|
|
|
|
|
|
|
for (const row of result.rows) {
|
2023-08-17 09:31:56 +00:00
|
|
|
|
if (row.speed > 150) {
|
|
|
|
|
row.speed /= 100;
|
|
|
|
|
}
|
2023-09-21 05:54:26 +00:00
|
|
|
|
|
|
|
|
|
const groupName = await getGroupNameById(pool, row.group);
|
|
|
|
|
|
|
|
|
|
const deviceData = {
|
2023-08-17 09:31:56 +00:00
|
|
|
|
serial: row.serial,
|
|
|
|
|
longitude: row.longitude,
|
|
|
|
|
latitude: row.latitude,
|
|
|
|
|
direction: row.direction,
|
|
|
|
|
speed: row.speed,
|
|
|
|
|
status: Date.now() - Date.parse(row.lastkeepalive) <= minuteInMillis,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: row.number,
|
2023-08-17 09:31:56 +00:00
|
|
|
|
plate: row.plate,
|
|
|
|
|
group: row.group,
|
2023-09-21 05:54:26 +00:00
|
|
|
|
groupName: groupName,
|
2023-08-17 09:31:56 +00:00
|
|
|
|
};
|
2023-09-21 05:54:26 +00:00
|
|
|
|
|
|
|
|
|
devicesData.push(deviceData);
|
|
|
|
|
}
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
2023-08-01 13:05:54 +00:00
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
res.json({ devicesData });
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
async function getGroupNameById(pool, groupId) {
|
|
|
|
|
const query = "SELECT name FROM groups WHERE id = $1";
|
|
|
|
|
const result = await pool.query(query, [groupId]);
|
|
|
|
|
if (result.rows.length > 0) {
|
|
|
|
|
return result.rows[0].name;
|
|
|
|
|
}
|
|
|
|
|
return 'Другое';
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 04:11:03 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
async function reports(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-07-24 04:53:11 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: [],
|
2023-09-04 09:11:22 +00:00
|
|
|
|
Groups: [],
|
2023-07-24 04:53:11 +00:00
|
|
|
|
};
|
2023-07-16 16:09:25 +00:00
|
|
|
|
try {
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const query = `
|
2023-08-13 17:52:23 +00:00
|
|
|
|
SELECT a.evtuuid, a.id, a.cmdno, a.time, a.serial, a.st, r.plate, g.latitude, g.longitude
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT DISTINCT ON (evtuuid) evtuuid, id, cmdno, time, serial, st
|
|
|
|
|
FROM alarms
|
|
|
|
|
WHERE alarmtype = 56
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'AND serial = ANY($2)' : ''}
|
2023-08-13 17:52:23 +00:00
|
|
|
|
ORDER BY evtuuid, time DESC
|
|
|
|
|
LIMIT 100
|
|
|
|
|
) AS a
|
|
|
|
|
LEFT JOIN registrars AS r ON a.serial = r.serial
|
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT *,
|
|
|
|
|
ROW_NUMBER() OVER (PARTITION BY serial ORDER BY ABS(EXTRACT(EPOCH FROM (time - $1)))) AS row_num
|
|
|
|
|
FROM geo
|
|
|
|
|
) AS g ON a.serial = g.serial AND g.row_num = 1
|
|
|
|
|
ORDER BY a.time DESC;
|
2023-07-16 16:09:25 +00:00
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const alarms = await client.query(query, templateData.isAdmin ? [new Date()] : [new Date(), serialValues]);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
const options = {
|
|
|
|
|
year: "2-digit",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
};
|
2023-08-13 17:52:23 +00:00
|
|
|
|
const adjustedDate = new Date(date);
|
|
|
|
|
adjustedDate.setHours(adjustedDate.getHours() - 3);
|
|
|
|
|
|
|
|
|
|
const formattedDate = adjustedDate.toLocaleString("ru-RU", options);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
return formattedDate.replace(",", "");
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
(templateData.Alarms = alarms.rows.map((alarm) => {
|
|
|
|
|
let type;
|
|
|
|
|
switch (alarm.st) {
|
|
|
|
|
case "0":
|
|
|
|
|
type = "Усталость";
|
|
|
|
|
break;
|
|
|
|
|
case "1":
|
|
|
|
|
type = "Водитель пропал";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
type = "Разговор по телефону";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
type = "Курение за рулём";
|
|
|
|
|
break;
|
|
|
|
|
case "4":
|
|
|
|
|
type = "Водитель отвлекся";
|
|
|
|
|
break;
|
|
|
|
|
case "5":
|
|
|
|
|
type = "Выезд с полосы движения";
|
|
|
|
|
break;
|
|
|
|
|
case "6":
|
|
|
|
|
type = "!!! Лобовое столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "7":
|
|
|
|
|
type = "Скорость превышена";
|
|
|
|
|
break;
|
|
|
|
|
case "8":
|
|
|
|
|
type = "Распознавание номерных знаков";
|
|
|
|
|
break;
|
|
|
|
|
case "9":
|
|
|
|
|
type = "!! Маленькое расстояние спереди";
|
|
|
|
|
break;
|
|
|
|
|
case "10":
|
|
|
|
|
type = "Водитель зевает";
|
|
|
|
|
break;
|
|
|
|
|
case "11":
|
|
|
|
|
type = "!!! Столкновение с пешеходом";
|
|
|
|
|
break;
|
|
|
|
|
case "12":
|
|
|
|
|
type = "Проходы переполнены";
|
|
|
|
|
break;
|
|
|
|
|
case "13":
|
|
|
|
|
type = "!! Посадка/высадка вне остановки";
|
|
|
|
|
break;
|
|
|
|
|
case "14":
|
|
|
|
|
type = "!! Смена полосы с нарушением ПДД";
|
|
|
|
|
break;
|
|
|
|
|
case "15":
|
|
|
|
|
type = "! Включенный телефон у водителя";
|
|
|
|
|
break;
|
|
|
|
|
case "16":
|
|
|
|
|
type = "!!! Ремень безопасности";
|
|
|
|
|
break;
|
|
|
|
|
case "17":
|
|
|
|
|
type = "Проверка не удалась";
|
|
|
|
|
break;
|
|
|
|
|
case "18":
|
|
|
|
|
type = "Слепые зоны справа";
|
|
|
|
|
break;
|
|
|
|
|
case "19":
|
|
|
|
|
type = "!!! Заднее столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "20":
|
|
|
|
|
type = "!!! Управление без рук";
|
|
|
|
|
break;
|
|
|
|
|
case "21":
|
|
|
|
|
type = "!! Управление одной рукой";
|
|
|
|
|
break;
|
|
|
|
|
case "22":
|
|
|
|
|
type = "Очки, блокирующие инфракрасное излучение";
|
|
|
|
|
break;
|
|
|
|
|
case "23":
|
|
|
|
|
type = "Слепые зоны слева";
|
|
|
|
|
break;
|
|
|
|
|
case "24":
|
|
|
|
|
type = "Помехи для пассажиров";
|
|
|
|
|
break;
|
|
|
|
|
case "25":
|
|
|
|
|
type = "На перекрестке ограничена скорость";
|
|
|
|
|
break;
|
|
|
|
|
case "26":
|
|
|
|
|
type = "Обнаружен перекресток";
|
|
|
|
|
break;
|
|
|
|
|
case "27":
|
|
|
|
|
type = "Пешеходы на переходе";
|
|
|
|
|
break;
|
|
|
|
|
case "28":
|
|
|
|
|
type = "! Неучтивое отношение к пешеходам";
|
|
|
|
|
break;
|
|
|
|
|
case "29":
|
|
|
|
|
type = "Обнаружен пешеходный переход";
|
|
|
|
|
break;
|
|
|
|
|
case "30":
|
|
|
|
|
type = "Водитель матерится";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
type = "Неизвестный тип";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
id: alarm.id,
|
|
|
|
|
cmdno: alarm.cmdno,
|
|
|
|
|
time: formatDate(alarm.time),
|
|
|
|
|
serial: alarm.serial,
|
|
|
|
|
st: alarm.st,
|
|
|
|
|
type: type,
|
|
|
|
|
plate: alarm.plate,
|
2023-08-07 01:15:36 +00:00
|
|
|
|
latitude: (alarm.latitude).toFixed(6),
|
|
|
|
|
longitude: (alarm.longitude).toFixed(6),
|
|
|
|
|
geo: (alarm.latitude).toFixed(6) + "," + (alarm.longitude).toFixed(6),
|
2023-07-24 04:53:11 +00:00
|
|
|
|
};
|
2023-08-07 01:15:36 +00:00
|
|
|
|
}))
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const minuteInMillis = 90 * 1000;
|
|
|
|
|
|
|
|
|
|
// Выполняем запрос, чтобы получить все данные из таблицы registrars
|
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-18 01:58:49 +00:00
|
|
|
|
FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrarsResult = await client.query(queryRegistrars, templateData.isAdmin ? [] : [serialValues]);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
const groupedRegistrars = {};
|
2023-09-19 13:31:40 +00:00
|
|
|
|
const groupedNumbers = {};
|
2023-09-04 09:11:22 +00:00
|
|
|
|
allRegistrars.forEach((registrar) => {
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName] = [];
|
2023-09-04 09:11:22 +00:00
|
|
|
|
}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
groupedRegistrars[groupName].push(registrar.serial);
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName].push(registrar.number);
|
2023-09-04 09:11:22 +00:00
|
|
|
|
});
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
|
2023-09-04 09:11:22 +00:00
|
|
|
|
name: groupName,
|
|
|
|
|
serials: groupedRegistrars[groupName],
|
2023-09-19 13:31:40 +00:00
|
|
|
|
numbers: groupedNumbers[groupName],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}));
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/reports/index.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
templateData.ifDBError = true;
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/reports/index.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
app.get("/api/devices", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const { page = 1, limit = 10 } = req.query;
|
|
|
|
|
const offset = (page - 1) * limit;
|
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const query = `
|
|
|
|
|
SELECT a.id, a.cmdno, a.time, a.serial, a.st, r.plate, g.latitude, g.longitude
|
|
|
|
|
FROM (
|
|
|
|
|
SELECT id, cmdno, time, serial, st
|
|
|
|
|
FROM alarms
|
2023-09-18 01:58:49 +00:00
|
|
|
|
${!templateData.isAdmin ? 'WHERE serial = ANY($4)' : ''}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
ORDER BY time DESC
|
|
|
|
|
LIMIT $1 OFFSET $2
|
|
|
|
|
) AS a
|
|
|
|
|
LEFT JOIN registrars AS r ON a.serial = r.serial
|
|
|
|
|
LEFT JOIN (
|
|
|
|
|
SELECT *,
|
|
|
|
|
ROW_NUMBER() OVER (PARTITION BY serial ORDER BY ABS(EXTRACT(EPOCH FROM (time - $3)))) AS row_num
|
|
|
|
|
FROM geo
|
|
|
|
|
) AS g ON a.serial = g.serial AND g.row_num = 1
|
|
|
|
|
ORDER BY a.time DESC;
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const alarms = await pool.query(query, templateData.isAdmin ? [limit, offset, new Date()] : [limit, offset, new Date(), serialValues]);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
const options = {
|
|
|
|
|
year: "2-digit",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
};
|
2023-08-13 17:52:23 +00:00
|
|
|
|
const adjustedDate = new Date(date);
|
|
|
|
|
adjustedDate.setHours(adjustedDate.getHours() - 3);
|
|
|
|
|
|
|
|
|
|
const formattedDate = adjustedDate.toLocaleString("ru-RU", options);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
return formattedDate.replace(",", "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const alarmsData = alarms.rows.map((alarm) => {
|
|
|
|
|
let type;
|
|
|
|
|
switch (alarm.st) {
|
|
|
|
|
case "0":
|
|
|
|
|
type = "Усталость";
|
|
|
|
|
break;
|
|
|
|
|
case "1":
|
|
|
|
|
type = "Отсутствие водителя";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
type = "Разговор по телефону";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
type = "Неизвестный тип";
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
id: alarm.id,
|
|
|
|
|
cmdno: alarm.cmdno,
|
|
|
|
|
time: formatDate(alarm.time),
|
|
|
|
|
serial: alarm.serial,
|
|
|
|
|
st: alarm.st,
|
|
|
|
|
type: type,
|
|
|
|
|
plate: alarm.plate,
|
|
|
|
|
latitude: alarm.latitude,
|
|
|
|
|
longitude: alarm.longitude,
|
|
|
|
|
geo: alarm.latitude + "," + alarm.longitude,
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const totalCountQuery = `SELECT COUNT(*) FROM alarms ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''};`;
|
|
|
|
|
const totalCount = await pool.query(totalCountQuery, templateData.isAdmin ? [] : [serialValues]);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
const totalPages = Math.ceil(totalCount.rows[0].count / limit);
|
|
|
|
|
|
|
|
|
|
res.json({
|
|
|
|
|
data: alarmsData,
|
|
|
|
|
totalPages: totalPages,
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error executing query:", error);
|
|
|
|
|
res.status(500).json({ error: "Internal server error" });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-06 19:07:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-07 11:44:15 +00:00
|
|
|
|
app.get('/reports/:id', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-08-07 11:44:15 +00:00
|
|
|
|
const id = req.params.id;
|
|
|
|
|
|
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-08-07 11:44:15 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Id: id,
|
|
|
|
|
Type: "",
|
|
|
|
|
Speed: "",
|
|
|
|
|
Date: "",
|
|
|
|
|
Serial: "",
|
|
|
|
|
Geo: "",
|
2023-08-13 17:52:23 +00:00
|
|
|
|
Latitude: "",
|
|
|
|
|
Longitude: "",
|
2023-09-10 16:36:39 +00:00
|
|
|
|
QueryTime: "",
|
|
|
|
|
StartTime: "",
|
|
|
|
|
EndTime: "",
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
2023-08-07 11:44:15 +00:00
|
|
|
|
DriverName: "",
|
|
|
|
|
DriverPhone: "",
|
|
|
|
|
DriverEmail: "",
|
|
|
|
|
DriverLicense: "",
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
|
|
|
|
PrevLatitude: "",
|
|
|
|
|
PrevLongitude: "",
|
|
|
|
|
NextLatitude: "",
|
|
|
|
|
NextLongitude: "",
|
|
|
|
|
Speeds: "",
|
2023-08-07 11:44:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
const minuteInMillis = 90 * 1000;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
|
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-07 11:44:15 +00:00
|
|
|
|
|
|
|
|
|
const query = `
|
2023-08-13 17:52:23 +00:00
|
|
|
|
WITH PrevNextGeo AS (
|
|
|
|
|
SELECT
|
|
|
|
|
a.serial,
|
|
|
|
|
a.st,
|
|
|
|
|
a.time,
|
|
|
|
|
a.geoid,
|
|
|
|
|
(SELECT g1.latitude FROM alarms a1 LEFT JOIN geo g1 ON a1.geoid = g1.id WHERE a1.evtuuid = a.evtuuid ORDER BY a1.time ASC LIMIT 1) AS prev_latitude,
|
|
|
|
|
(SELECT g2.longitude FROM alarms a2 LEFT JOIN geo g2 ON a2.geoid = g2.id WHERE a2.evtuuid = a.evtuuid ORDER BY a2.time ASC LIMIT 1) AS prev_longitude,
|
|
|
|
|
(SELECT g3.latitude FROM alarms a3 LEFT JOIN geo g3 ON a3.geoid = g3.id WHERE a3.evtuuid = a.evtuuid ORDER BY a3.time DESC LIMIT 1) AS next_latitude,
|
|
|
|
|
(SELECT g4.longitude FROM alarms a4 LEFT JOIN geo g4 ON a4.geoid = g4.id WHERE a4.evtuuid = a.evtuuid ORDER BY a4.time DESC LIMIT 1) AS next_longitude,
|
|
|
|
|
g.longitude,
|
|
|
|
|
g.latitude,
|
|
|
|
|
g.speed,
|
|
|
|
|
d.name,
|
|
|
|
|
d.surname,
|
|
|
|
|
d.card,
|
|
|
|
|
d.phone,
|
|
|
|
|
d.email
|
|
|
|
|
FROM alarms a
|
|
|
|
|
LEFT JOIN geo g ON a.geoid = g.id
|
|
|
|
|
LEFT JOIN drivers d ON a.serial = d.transport
|
|
|
|
|
WHERE a.id = ${id}
|
|
|
|
|
LIMIT 1
|
|
|
|
|
),
|
|
|
|
|
Speeds AS (
|
|
|
|
|
SELECT
|
|
|
|
|
g.speed,
|
|
|
|
|
ROW_NUMBER() OVER (ORDER BY ABS(EXTRACT(EPOCH FROM (a.time - (SELECT time FROM PrevNextGeo)))) ASC) AS row_number
|
|
|
|
|
FROM alarms a
|
|
|
|
|
LEFT JOIN geo g ON a.geoid = g.id
|
|
|
|
|
WHERE g.serial = (SELECT serial FROM PrevNextGeo) -- Ограничиваем результаты только записями с тем же serial
|
|
|
|
|
)
|
|
|
|
|
SELECT
|
|
|
|
|
*,
|
|
|
|
|
(
|
|
|
|
|
SELECT array_agg(speed) FROM Speeds
|
|
|
|
|
WHERE row_number <= 11
|
|
|
|
|
) AS nearest_speeds
|
|
|
|
|
FROM PrevNextGeo;
|
2023-08-07 11:44:15 +00:00
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const alarm = (await client.query(query)).rows[0];
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log(alarm);
|
2023-08-07 11:44:15 +00:00
|
|
|
|
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
const options = {
|
|
|
|
|
year: "2-digit",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
};
|
2023-08-13 17:52:23 +00:00
|
|
|
|
const adjustedDate = new Date(date);
|
|
|
|
|
adjustedDate.setHours(adjustedDate.getHours() - 3);
|
|
|
|
|
|
|
|
|
|
const formattedDate = adjustedDate.toLocaleString("ru-RU", options);
|
2023-08-07 11:44:15 +00:00
|
|
|
|
return formattedDate.replace(",", "");
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-10 16:36:39 +00:00
|
|
|
|
function formatDateToYYYYMMDD(sqlDate) {
|
|
|
|
|
const date = new Date(sqlDate);
|
|
|
|
|
const year = date.getFullYear();
|
|
|
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
|
|
|
return `${year}${month}${day}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatTimeToHHMMSSBefore(sqlDate) {
|
|
|
|
|
const date = new Date(sqlDate);
|
|
|
|
|
date.setSeconds(date.getSeconds() - 10);
|
|
|
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
|
return `${hours}${minutes}${seconds}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function formatTimeToHHMMSSAfter(sqlDate) {
|
|
|
|
|
const date = new Date(sqlDate);
|
|
|
|
|
date.setSeconds(date.getSeconds() + 10);
|
|
|
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
|
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
|
return `${hours}${minutes}${seconds}`;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-07 11:44:15 +00:00
|
|
|
|
let type;
|
|
|
|
|
switch (alarm.st) {
|
|
|
|
|
case "0":
|
|
|
|
|
type = "Усталость";
|
|
|
|
|
break;
|
|
|
|
|
case "1":
|
|
|
|
|
type = "Водитель пропал";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
type = "Разговор по телефону";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
type = "Курение за рулём";
|
|
|
|
|
break;
|
|
|
|
|
case "4":
|
|
|
|
|
type = "Водитель отвлекся";
|
|
|
|
|
break;
|
|
|
|
|
case "5":
|
|
|
|
|
type = "Выезд с полосы движения";
|
|
|
|
|
break;
|
|
|
|
|
case "6":
|
|
|
|
|
type = "!!! Лобовое столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "7":
|
|
|
|
|
type = "Скорость превышена";
|
|
|
|
|
break;
|
|
|
|
|
case "8":
|
|
|
|
|
type = "Распознавание номерных знаков";
|
|
|
|
|
break;
|
|
|
|
|
case "9":
|
|
|
|
|
type = "!! Маленькое расстояние спереди";
|
|
|
|
|
break;
|
|
|
|
|
case "10":
|
|
|
|
|
type = "Водитель зевает";
|
|
|
|
|
break;
|
|
|
|
|
case "11":
|
|
|
|
|
type = "!!! Столкновение с пешеходом";
|
|
|
|
|
break;
|
|
|
|
|
case "12":
|
|
|
|
|
type = "Проходы переполнены";
|
|
|
|
|
break;
|
|
|
|
|
case "13":
|
|
|
|
|
type = "!! Посадка/высадка вне остановки";
|
|
|
|
|
break;
|
|
|
|
|
case "14":
|
|
|
|
|
type = "!! Смена полосы с нарушением ПДД";
|
|
|
|
|
break;
|
|
|
|
|
case "15":
|
|
|
|
|
type = "! Включенный телефон у водителя";
|
|
|
|
|
break;
|
|
|
|
|
case "16":
|
|
|
|
|
type = "!!! Ремень безопасности";
|
|
|
|
|
break;
|
|
|
|
|
case "17":
|
|
|
|
|
type = "Проверка не удалась";
|
|
|
|
|
break;
|
|
|
|
|
case "18":
|
|
|
|
|
type = "Слепые зоны справа";
|
|
|
|
|
break;
|
|
|
|
|
case "19":
|
|
|
|
|
type = "!!! Заднее столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "20":
|
|
|
|
|
type = "!!! Управление без рук";
|
|
|
|
|
break;
|
|
|
|
|
case "21":
|
|
|
|
|
type = "!! Управление одной рукой";
|
|
|
|
|
break;
|
|
|
|
|
case "22":
|
|
|
|
|
type = "Очки, блокирующие инфракрасное излучение";
|
|
|
|
|
break;
|
|
|
|
|
case "23":
|
|
|
|
|
type = "Слепые зоны слева";
|
|
|
|
|
break;
|
|
|
|
|
case "24":
|
|
|
|
|
type = "Помехи для пассажиров";
|
|
|
|
|
break;
|
|
|
|
|
case "25":
|
|
|
|
|
type = "На перекрестке ограничена скорость";
|
|
|
|
|
break;
|
|
|
|
|
case "26":
|
|
|
|
|
type = "Обнаружен перекресток";
|
|
|
|
|
break;
|
|
|
|
|
case "27":
|
|
|
|
|
type = "Пешеходы на переходе";
|
|
|
|
|
break;
|
|
|
|
|
case "28":
|
|
|
|
|
type = "! Неучтивое отношение к пешеходам";
|
|
|
|
|
break;
|
|
|
|
|
case "29":
|
|
|
|
|
type = "Обнаружен пешеходный переход";
|
|
|
|
|
break;
|
|
|
|
|
case "30":
|
|
|
|
|
type = "Водитель матерится";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
type = "Неизвестный тип";
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-17 09:33:22 +00:00
|
|
|
|
var actualSpeed;
|
|
|
|
|
if (alarm.speed > 150) {
|
|
|
|
|
actualSpeed = alarm.speed / 100
|
|
|
|
|
} else {
|
|
|
|
|
actualSpeed = alarm.speed
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-18 02:03:16 +00:00
|
|
|
|
if (serialValues.includes(alarm.serial) || templateData.isAdmin) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
|
2023-08-07 11:44:15 +00:00
|
|
|
|
templateData.Type = type;
|
2023-08-17 09:31:56 +00:00
|
|
|
|
templateData.Speed = actualSpeed;
|
2023-08-07 11:44:15 +00:00
|
|
|
|
templateData.Date = formatDate(alarm.time);
|
|
|
|
|
templateData.Serial = alarm.serial;
|
|
|
|
|
templateData.Geo = alarm.latitude + "," + alarm.longitude;
|
2023-08-13 17:52:23 +00:00
|
|
|
|
templateData.Latitude = alarm.latitude
|
|
|
|
|
templateData.Longitude = alarm.longitude
|
2023-09-10 16:36:39 +00:00
|
|
|
|
templateData.QueryTime = formatDateToYYYYMMDD(alarm.time);
|
|
|
|
|
templateData.StartTime = formatTimeToHHMMSSBefore(alarm.time);
|
|
|
|
|
templateData.EndTime = formatTimeToHHMMSSAfter(alarm.time);
|
2023-08-07 11:44:15 +00:00
|
|
|
|
|
|
|
|
|
templateData.DriverName = alarm.name + " " + alarm.surname;
|
|
|
|
|
templateData.DriverPhone = alarm.phone;
|
|
|
|
|
templateData.DriverEmail = alarm.email;
|
|
|
|
|
templateData.DriverLicense = alarm.card;
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
|
|
|
|
templateData.PrevLatitude = alarm.prev_latitude;
|
|
|
|
|
templateData.PrevLongitude = alarm.prev_longitude;
|
|
|
|
|
templateData.NextLatitude = alarm.next_latitude;
|
|
|
|
|
templateData.NextLongitude = alarm.next_longitude;
|
|
|
|
|
|
2023-08-17 09:31:56 +00:00
|
|
|
|
templateData.Speeds = alarm.nearest_speeds
|
|
|
|
|
templateData.Speeds = templateData.Speeds.map(speed => {
|
|
|
|
|
if (speed > 150) {
|
|
|
|
|
return speed / 100;
|
|
|
|
|
} else {
|
|
|
|
|
return speed;
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-09-18 01:58:49 +00:00
|
|
|
|
} else {
|
|
|
|
|
console.log("Нет доступа к данному аларму")
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
}
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log(templateData);
|
2023-08-07 11:44:15 +00:00
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/reports/report.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/reports/report.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-06 19:07:19 +00:00
|
|
|
|
app.get('/generate-pdf/:id', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-09-06 19:07:19 +00:00
|
|
|
|
const id = req.params.id;
|
|
|
|
|
|
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-09-06 19:07:19 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Id: id,
|
|
|
|
|
Type: "",
|
|
|
|
|
Speed: "",
|
|
|
|
|
Date: "",
|
|
|
|
|
Serial: "",
|
|
|
|
|
Geo: "",
|
|
|
|
|
Latitude: "",
|
|
|
|
|
Longitude: "",
|
|
|
|
|
|
|
|
|
|
DriverName: "",
|
|
|
|
|
DriverPhone: "",
|
|
|
|
|
DriverEmail: "",
|
|
|
|
|
DriverLicense: "",
|
|
|
|
|
|
|
|
|
|
PrevLatitude: "",
|
|
|
|
|
PrevLongitude: "",
|
|
|
|
|
NextLatitude: "",
|
|
|
|
|
NextLongitude: "",
|
|
|
|
|
Speeds: "",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
const minuteInMillis = 90 * 1000;
|
|
|
|
|
|
|
|
|
|
const query = `
|
|
|
|
|
WITH PrevNextGeo AS (
|
|
|
|
|
SELECT
|
|
|
|
|
a.serial,
|
|
|
|
|
a.st,
|
|
|
|
|
a.time,
|
|
|
|
|
a.geoid,
|
|
|
|
|
(SELECT g1.latitude FROM alarms a1 LEFT JOIN geo g1 ON a1.geoid = g1.id WHERE a1.evtuuid = a.evtuuid ORDER BY a1.time ASC LIMIT 1) AS prev_latitude,
|
|
|
|
|
(SELECT g2.longitude FROM alarms a2 LEFT JOIN geo g2 ON a2.geoid = g2.id WHERE a2.evtuuid = a.evtuuid ORDER BY a2.time ASC LIMIT 1) AS prev_longitude,
|
|
|
|
|
(SELECT g3.latitude FROM alarms a3 LEFT JOIN geo g3 ON a3.geoid = g3.id WHERE a3.evtuuid = a.evtuuid ORDER BY a3.time DESC LIMIT 1) AS next_latitude,
|
|
|
|
|
(SELECT g4.longitude FROM alarms a4 LEFT JOIN geo g4 ON a4.geoid = g4.id WHERE a4.evtuuid = a.evtuuid ORDER BY a4.time DESC LIMIT 1) AS next_longitude,
|
|
|
|
|
g.longitude,
|
|
|
|
|
g.latitude,
|
|
|
|
|
g.speed,
|
|
|
|
|
d.name,
|
|
|
|
|
d.surname,
|
|
|
|
|
d.card,
|
|
|
|
|
d.phone,
|
|
|
|
|
d.email
|
|
|
|
|
FROM alarms a
|
|
|
|
|
LEFT JOIN geo g ON a.geoid = g.id
|
|
|
|
|
LEFT JOIN drivers d ON a.serial = d.transport
|
|
|
|
|
WHERE a.id = ${id}
|
|
|
|
|
LIMIT 1
|
|
|
|
|
),
|
|
|
|
|
Speeds AS (
|
|
|
|
|
SELECT
|
|
|
|
|
g.speed,
|
|
|
|
|
ROW_NUMBER() OVER (ORDER BY ABS(EXTRACT(EPOCH FROM (a.time - (SELECT time FROM PrevNextGeo)))) ASC) AS row_number
|
|
|
|
|
FROM alarms a
|
|
|
|
|
LEFT JOIN geo g ON a.geoid = g.id
|
|
|
|
|
WHERE g.serial = (SELECT serial FROM PrevNextGeo) -- Ограничиваем результаты только записями с тем же serial
|
|
|
|
|
)
|
|
|
|
|
SELECT
|
|
|
|
|
*,
|
|
|
|
|
(
|
|
|
|
|
SELECT array_agg(speed) FROM Speeds
|
|
|
|
|
WHERE row_number <= 11
|
|
|
|
|
) AS nearest_speeds
|
|
|
|
|
FROM PrevNextGeo;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const alarm = (await client.query(query)).rows[0];
|
|
|
|
|
// console.log(alarm);
|
|
|
|
|
|
|
|
|
|
function formatDate(date) {
|
|
|
|
|
const options = {
|
|
|
|
|
year: "2-digit",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
};
|
|
|
|
|
const adjustedDate = new Date(date);
|
|
|
|
|
adjustedDate.setHours(adjustedDate.getHours() - 3);
|
|
|
|
|
|
|
|
|
|
const formattedDate = adjustedDate.toLocaleString("ru-RU", options);
|
|
|
|
|
return formattedDate.replace(",", "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let type;
|
|
|
|
|
switch (alarm.st) {
|
|
|
|
|
case "0":
|
|
|
|
|
type = "Усталость";
|
|
|
|
|
break;
|
|
|
|
|
case "1":
|
|
|
|
|
type = "Водитель пропал";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
type = "Разговор по телефону";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
type = "Курение за рулём";
|
|
|
|
|
break;
|
|
|
|
|
case "4":
|
|
|
|
|
type = "Водитель отвлекся";
|
|
|
|
|
break;
|
|
|
|
|
case "5":
|
|
|
|
|
type = "Выезд с полосы движения";
|
|
|
|
|
break;
|
|
|
|
|
case "6":
|
|
|
|
|
type = "!!! Лобовое столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "7":
|
|
|
|
|
type = "Скорость превышена";
|
|
|
|
|
break;
|
|
|
|
|
case "8":
|
|
|
|
|
type = "Распознавание номерных знаков";
|
|
|
|
|
break;
|
|
|
|
|
case "9":
|
|
|
|
|
type = "!! Маленькое расстояние спереди";
|
|
|
|
|
break;
|
|
|
|
|
case "10":
|
|
|
|
|
type = "Водитель зевает";
|
|
|
|
|
break;
|
|
|
|
|
case "11":
|
|
|
|
|
type = "!!! Столкновение с пешеходом";
|
|
|
|
|
break;
|
|
|
|
|
case "12":
|
|
|
|
|
type = "Проходы переполнены";
|
|
|
|
|
break;
|
|
|
|
|
case "13":
|
|
|
|
|
type = "!! Посадка/высадка вне остановки";
|
|
|
|
|
break;
|
|
|
|
|
case "14":
|
|
|
|
|
type = "!! Смена полосы с нарушением ПДД";
|
|
|
|
|
break;
|
|
|
|
|
case "15":
|
|
|
|
|
type = "! Включенный телефон у водителя";
|
|
|
|
|
break;
|
|
|
|
|
case "16":
|
|
|
|
|
type = "!!! Ремень безопасности";
|
|
|
|
|
break;
|
|
|
|
|
case "17":
|
|
|
|
|
type = "Проверка не удалась";
|
|
|
|
|
break;
|
|
|
|
|
case "18":
|
|
|
|
|
type = "Слепые зоны справа";
|
|
|
|
|
break;
|
|
|
|
|
case "19":
|
|
|
|
|
type = "!!! Заднее столкновение";
|
|
|
|
|
break;
|
|
|
|
|
case "20":
|
|
|
|
|
type = "!!! Управление без рук";
|
|
|
|
|
break;
|
|
|
|
|
case "21":
|
|
|
|
|
type = "!! Управление одной рукой";
|
|
|
|
|
break;
|
|
|
|
|
case "22":
|
|
|
|
|
type = "Очки, блокирующие инфракрасное излучение";
|
|
|
|
|
break;
|
|
|
|
|
case "23":
|
|
|
|
|
type = "Слепые зоны слева";
|
|
|
|
|
break;
|
|
|
|
|
case "24":
|
|
|
|
|
type = "Помехи для пассажиров";
|
|
|
|
|
break;
|
|
|
|
|
case "25":
|
|
|
|
|
type = "На перекрестке ограничена скорость";
|
|
|
|
|
break;
|
|
|
|
|
case "26":
|
|
|
|
|
type = "Обнаружен перекресток";
|
|
|
|
|
break;
|
|
|
|
|
case "27":
|
|
|
|
|
type = "Пешеходы на переходе";
|
|
|
|
|
break;
|
|
|
|
|
case "28":
|
|
|
|
|
type = "! Неучтивое отношение к пешеходам";
|
|
|
|
|
break;
|
|
|
|
|
case "29":
|
|
|
|
|
type = "Обнаружен пешеходный переход";
|
|
|
|
|
break;
|
|
|
|
|
case "30":
|
|
|
|
|
type = "Водитель матерится";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
type = "Неизвестный тип";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var actualSpeed;
|
|
|
|
|
if (alarm.speed > 150) {
|
|
|
|
|
actualSpeed = alarm.speed / 100
|
|
|
|
|
} else {
|
|
|
|
|
actualSpeed = alarm.speed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
templateData.Type = type;
|
|
|
|
|
templateData.Speed = actualSpeed;
|
|
|
|
|
templateData.Date = formatDate(alarm.time);
|
|
|
|
|
templateData.Serial = alarm.serial;
|
|
|
|
|
templateData.Geo = alarm.latitude + "," + alarm.longitude;
|
|
|
|
|
templateData.Latitude = alarm.latitude
|
|
|
|
|
templateData.Longitude = alarm.longitude
|
|
|
|
|
|
|
|
|
|
templateData.DriverName = alarm.name + " " + alarm.surname;
|
|
|
|
|
templateData.DriverPhone = alarm.phone;
|
|
|
|
|
templateData.DriverEmail = alarm.email;
|
|
|
|
|
templateData.DriverLicense = alarm.card;
|
|
|
|
|
|
|
|
|
|
templateData.PrevLatitude = alarm.prev_latitude;
|
|
|
|
|
templateData.PrevLongitude = alarm.prev_longitude;
|
|
|
|
|
templateData.NextLatitude = alarm.next_latitude;
|
|
|
|
|
templateData.NextLongitude = alarm.next_longitude;
|
|
|
|
|
|
|
|
|
|
templateData.Speeds = alarm.nearest_speeds
|
|
|
|
|
templateData.Speeds = templateData.Speeds.map(speed => {
|
|
|
|
|
if (speed > 150) {
|
|
|
|
|
return speed / 100;
|
|
|
|
|
} else {
|
|
|
|
|
return speed;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let data = {
|
|
|
|
|
Id: templateData.Id,
|
|
|
|
|
Organisation: templateData.Organisation,
|
|
|
|
|
Type: templateData.Type,
|
|
|
|
|
Speed: templateData.Speed,
|
|
|
|
|
Date: templateData.Date,
|
|
|
|
|
Serial: templateData.Serial,
|
|
|
|
|
Geo: templateData.Geo,
|
|
|
|
|
PrevLongitude: templateData.PrevLongitude,
|
|
|
|
|
PrevLatitude: templateData.PrevLatitude,
|
|
|
|
|
NextLongitude: templateData.NextLongitude,
|
|
|
|
|
NextLatitude: templateData.NextLatitude,
|
|
|
|
|
Speeds: templateData.Speeds,
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const source = fs.readFileSync("static/templates/reports/pdf.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/reports/pdf.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(data);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
2023-09-06 19:07:19 +00:00
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
async function devices(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
|
|
|
|
|
let userInfo;
|
2023-07-18 01:32:15 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
Organisation: '',
|
|
|
|
|
User: '',
|
|
|
|
|
UserInfo: '',
|
2023-09-11 09:57:10 +00:00
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-07-18 01:32:15 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: [],
|
2023-09-04 09:11:22 +00:00
|
|
|
|
Groups: [],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
GroupsList: [],
|
2023-09-18 01:58:49 +00:00
|
|
|
|
EditTransport: false,
|
|
|
|
|
DeleteTransport: false,
|
|
|
|
|
Update: false,
|
2023-07-18 01:32:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
try {
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
2023-09-14 02:40:03 +00:00
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const minuteInMillis = 90 * 1000;
|
|
|
|
|
|
2023-08-01 12:35:10 +00:00
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-18 01:58:49 +00:00
|
|
|
|
FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''}
|
2023-07-16 16:09:25 +00:00
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrarsResult = await client.query(queryRegistrars, templateData.isAdmin ? [] : [serialValues]);
|
2023-08-01 12:35:10 +00:00
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
2023-09-14 02:40:03 +00:00
|
|
|
|
|
|
|
|
|
const groupedRegistrars = {};
|
2023-09-19 13:31:40 +00:00
|
|
|
|
const groupedNumbers = {};
|
2023-09-14 02:40:03 +00:00
|
|
|
|
allRegistrars.forEach((registrar) => {
|
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName] = [];
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
groupedRegistrars[groupName].push(registrar.serial);
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName].push(registrar.number);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
userInfo = await getUserInfo(req.session.userId);
|
|
|
|
|
|
|
|
|
|
templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
2023-09-18 01:58:49 +00:00
|
|
|
|
EditTransport: userInfo.EditTransport,
|
|
|
|
|
DeleteTransport: userInfo.DeleteTransport,
|
|
|
|
|
Update: userInfo.Update,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: allRegistrars.map((registrar) => ({
|
2023-07-18 01:32:15 +00:00
|
|
|
|
id: registrar.id,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: registrar.number,
|
2023-07-18 01:32:15 +00:00
|
|
|
|
serial: registrar.serial,
|
2023-08-01 12:35:10 +00:00
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
2023-07-18 01:32:15 +00:00
|
|
|
|
name: registrar.name,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
2023-07-18 01:32:15 +00:00
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
})),
|
|
|
|
|
Groups: Object.keys(groupedRegistrars).map((groupName) => ({
|
|
|
|
|
name: groupName,
|
|
|
|
|
serials: groupedRegistrars[groupName],
|
2023-09-19 13:31:40 +00:00
|
|
|
|
numbers: groupedNumbers[groupName],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
})),
|
|
|
|
|
GroupsList: groupsResult.rows,
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
2023-08-01 12:35:10 +00:00
|
|
|
|
const source = fs.readFileSync("static/templates/devices/index.html", "utf8");
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
client.release();
|
2023-09-14 02:40:03 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
if (templateData) {
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/devices/index.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function groups(req, res) {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-09-18 01:58:49 +00:00
|
|
|
|
if (!userInfo.EditTransport) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
ifDBError: false,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
|
|
|
|
Groups: [],
|
2023-09-18 01:58:49 +00:00
|
|
|
|
EditTransport: userInfo.EditTransport,
|
|
|
|
|
DeleteTransport: userInfo.DeleteTransport,
|
|
|
|
|
Update: userInfo.Update,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
const result = await client.query('SELECT id, name FROM groups');
|
|
|
|
|
const groups = result.rows;
|
|
|
|
|
client.release();
|
|
|
|
|
|
|
|
|
|
templateData.Groups = groups;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/devices/groups.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-18 01:32:15 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
2023-09-14 02:40:03 +00:00
|
|
|
|
"static/templates/devices/groups.html",
|
2023-07-18 01:32:15 +00:00
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
app.post('/update-group', async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const { groupId, newName } = req.body;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const query = 'UPDATE groups SET name = $1 WHERE id = $2';
|
|
|
|
|
const values = [newName, groupId];
|
|
|
|
|
|
|
|
|
|
await pool.query(query, values);
|
|
|
|
|
|
|
|
|
|
res.status(200).json({ message: 'Данные группы обновлены успешно' });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Ошибка при обновлении данных группы:', error);
|
|
|
|
|
res.status(500).json({ error: 'Внутренняя ошибка сервера' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
async function getParameters(serial) {
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const requestResponse = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/request?serial=${serial}`, {
|
2023-09-04 09:11:22 +00:00
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
2023-09-21 05:54:26 +00:00
|
|
|
|
data: JSON.stringify({
|
|
|
|
|
"FIELDS": [
|
|
|
|
|
"DOSD"
|
|
|
|
|
]
|
|
|
|
|
}),
|
2023-09-04 09:11:22 +00:00
|
|
|
|
});
|
2023-09-21 05:54:26 +00:00
|
|
|
|
|
|
|
|
|
const requestResponse2 = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/request?serial=${serial}`, {
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
data: JSON.stringify({
|
|
|
|
|
"FIELDS": [
|
|
|
|
|
"GSP"
|
|
|
|
|
]
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const requestResponse3 = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/request?serial=${serial}`, {
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
data: JSON.stringify({
|
|
|
|
|
"FIELDS": [
|
|
|
|
|
"TIMEP"
|
|
|
|
|
]
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const requestResponse4 = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/request?serial=${serial}`, {
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
data: JSON.stringify({
|
|
|
|
|
"FIELDS": [
|
|
|
|
|
"SUBSTRNET"
|
|
|
|
|
]
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const requestResponse5 = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/request?serial=${serial}`, {
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
data: JSON.stringify({
|
|
|
|
|
"FIELDS": [
|
|
|
|
|
"AR"
|
|
|
|
|
]
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// console.log(requestResponse.data);
|
2023-09-04 09:20:56 +00:00
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const getResponse = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/get?serial=${serial}`);
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// console.log(getResponse.data);
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
return getResponse.data;
|
2023-09-04 09:11:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app.post('/device-parameters', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-04 09:11:22 +00:00
|
|
|
|
try {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const { serial } = req.body;
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Используем асинхронный цикл для выполнения GET-запросов по очереди
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const responseData = await getParameters(serial);
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res.json(responseData);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
res.status(500).json({ error: 'Internal server error' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.put('/device-parameters', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// Получаем данные из PUT запроса
|
|
|
|
|
const requestData = req.body;
|
|
|
|
|
const { serial } = req.query;
|
|
|
|
|
|
|
|
|
|
// Извлекаем необходимые параметры
|
|
|
|
|
const {
|
|
|
|
|
DATEMOD,
|
|
|
|
|
TIMEFORMAT,
|
|
|
|
|
LANGUAGE,
|
|
|
|
|
VIDEOFORMAT,
|
|
|
|
|
GEOMOD,
|
|
|
|
|
SUBSTREAMMODE,
|
2023-09-21 05:54:26 +00:00
|
|
|
|
TIMEZ,
|
2023-09-04 09:11:22 +00:00
|
|
|
|
NE,
|
|
|
|
|
TE,
|
|
|
|
|
VE,
|
|
|
|
|
SE,
|
|
|
|
|
GE
|
|
|
|
|
} = requestData;
|
|
|
|
|
|
|
|
|
|
// Создаем JSON для GET запроса
|
|
|
|
|
const requestBody = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
"TIMEP": {
|
|
|
|
|
"DATEM": parseInt(DATEMOD, 10) || 1,
|
|
|
|
|
"TIMEM": parseInt(TIMEFORMAT, 10) || 0,
|
|
|
|
|
"TIMEZ": TIMEZ || "180C"
|
2023-09-04 09:11:22 +00:00
|
|
|
|
},
|
2023-09-21 05:54:26 +00:00
|
|
|
|
"GSP": {
|
|
|
|
|
"LANT": parseInt(LANGUAGE, 10) || 12,
|
|
|
|
|
"VGA": parseInt(VIDEOFORMAT, 10) || 0,
|
|
|
|
|
"GM": parseInt(GEOMOD, 10) || 0
|
2023-09-04 09:11:22 +00:00
|
|
|
|
},
|
2023-09-21 05:54:26 +00:00
|
|
|
|
"SUBSTRNET": {
|
|
|
|
|
"SM": parseInt(SUBSTREAMMODE, 10) || 1
|
2023-09-04 09:11:22 +00:00
|
|
|
|
},
|
2023-09-21 05:54:26 +00:00
|
|
|
|
"DOSD": {
|
|
|
|
|
"NE": parseInt(NE, 10) || 1,
|
|
|
|
|
"TE": parseInt(TE, 10) || 1,
|
|
|
|
|
"VE": parseInt(VE, 10) || 0,
|
|
|
|
|
"SE": parseInt(SE, 10) || 0,
|
|
|
|
|
"GE": parseInt(GE, 10) || 0
|
2023-09-04 09:11:22 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-21 05:54:26 +00:00
|
|
|
|
|
|
|
|
|
// Отправляем GET запрос с JSON BODY
|
|
|
|
|
try {
|
|
|
|
|
const response = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/set?serial=${serial}`, {
|
|
|
|
|
data: JSON.stringify(requestBody),
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
res.status(response.status).send(response.data);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
res.status(500).send('Произошла ошибка при отправке GET запроса.');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.put('/camera-parameters', async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
// Получаем данные из PUT запроса
|
|
|
|
|
const camerasData = req.body;
|
|
|
|
|
const { serial } = req.query;
|
|
|
|
|
|
|
|
|
|
// Создаем JSON для GET запроса
|
|
|
|
|
const requestBody = {
|
|
|
|
|
"AR": camerasData
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// Отправляем GET запрос с JSON BODY
|
|
|
|
|
try {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const response = await axios.get(`http://${process.env.SERVER_IP}:8080/http/parameters/set?serial=${serial}`, {
|
2023-09-04 09:11:22 +00:00
|
|
|
|
data: JSON.stringify(requestBody),
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
res.status(response.status).send(response.data);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
res.status(500).send('Произошла ошибка при отправке GET запроса.');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
app.post("/devicedata", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
2023-07-18 01:32:15 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const client = await pool.connect();
|
2023-07-18 01:32:15 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
try {
|
|
|
|
|
const query = "SELECT * FROM registrars WHERE id = $1;";
|
|
|
|
|
const devicedata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
const response = devicedata.rows[0];
|
|
|
|
|
res.json(response);
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/updatedevice", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
var {
|
|
|
|
|
serialNumber,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
deviceNumber,
|
|
|
|
|
plateNumber,
|
2023-07-16 16:09:25 +00:00
|
|
|
|
channelsAmount,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
plateColor,
|
2023-07-16 16:09:25 +00:00
|
|
|
|
IPAddress,
|
|
|
|
|
serverPort,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
deviceGroup,
|
|
|
|
|
connectionProtocol,
|
2023-07-16 16:09:25 +00:00
|
|
|
|
sumNumber,
|
|
|
|
|
simIMEI,
|
|
|
|
|
simIMSI,
|
|
|
|
|
simModule,
|
|
|
|
|
transportType,
|
|
|
|
|
transportFactory,
|
|
|
|
|
transportStrength,
|
|
|
|
|
transportEngine,
|
|
|
|
|
transportStanina,
|
|
|
|
|
transportFuel,
|
|
|
|
|
transportCertificate,
|
|
|
|
|
transportCategory,
|
|
|
|
|
transportExpire,
|
|
|
|
|
transportConsumption,
|
|
|
|
|
transportProvince,
|
|
|
|
|
transportCity,
|
|
|
|
|
equipmentName,
|
|
|
|
|
equipmentPassword,
|
|
|
|
|
equipmentNumber,
|
|
|
|
|
equipmentReleased,
|
|
|
|
|
equipmentInstaller,
|
|
|
|
|
equipmentInstalled,
|
|
|
|
|
equipmentDescription,
|
|
|
|
|
} = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
2023-08-13 17:52:23 +00:00
|
|
|
|
|
2023-07-16 16:09:25 +00:00
|
|
|
|
const query = `
|
|
|
|
|
UPDATE registrars
|
|
|
|
|
SET
|
|
|
|
|
plate = $1,
|
|
|
|
|
plate_color = $2,
|
|
|
|
|
channels = $3,
|
|
|
|
|
protocol = $4,
|
|
|
|
|
ip = $5,
|
|
|
|
|
"group" = $6,
|
|
|
|
|
port = $7,
|
|
|
|
|
sim = $8,
|
|
|
|
|
imei = $9,
|
|
|
|
|
imsi = $10,
|
|
|
|
|
module = $11,
|
|
|
|
|
auto = $12,
|
|
|
|
|
factory = $13,
|
|
|
|
|
capacity = $14,
|
|
|
|
|
engine = $15,
|
|
|
|
|
stanina = $16,
|
|
|
|
|
fuel = $17,
|
|
|
|
|
certificate = $18,
|
|
|
|
|
category = $19,
|
|
|
|
|
certificate_exp = $20,
|
|
|
|
|
consumption = $21,
|
|
|
|
|
region = $22,
|
|
|
|
|
city = $23,
|
|
|
|
|
name = $24,
|
|
|
|
|
password = $25,
|
|
|
|
|
batch = $26,
|
|
|
|
|
release = $27,
|
|
|
|
|
installer = $28,
|
|
|
|
|
installation = $29,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
description = $30,
|
|
|
|
|
number = $31
|
|
|
|
|
WHERE serial = $32
|
2023-07-16 16:09:25 +00:00
|
|
|
|
RETURNING *;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const values = [
|
|
|
|
|
plateNumber,
|
|
|
|
|
plateColor,
|
|
|
|
|
channelsAmount,
|
|
|
|
|
connectionProtocol,
|
|
|
|
|
IPAddress,
|
|
|
|
|
deviceGroup,
|
|
|
|
|
serverPort,
|
|
|
|
|
sumNumber,
|
|
|
|
|
simIMEI,
|
|
|
|
|
simIMSI,
|
|
|
|
|
simModule,
|
|
|
|
|
transportType,
|
|
|
|
|
transportFactory,
|
|
|
|
|
transportStrength,
|
|
|
|
|
transportEngine,
|
|
|
|
|
transportStanina,
|
|
|
|
|
transportFuel,
|
|
|
|
|
transportCertificate,
|
|
|
|
|
transportCategory,
|
|
|
|
|
transportExpire,
|
|
|
|
|
transportConsumption,
|
|
|
|
|
transportProvince,
|
|
|
|
|
transportCity,
|
|
|
|
|
equipmentName,
|
|
|
|
|
equipmentPassword,
|
|
|
|
|
equipmentNumber,
|
|
|
|
|
equipmentReleased,
|
|
|
|
|
equipmentInstaller,
|
|
|
|
|
equipmentInstalled,
|
|
|
|
|
equipmentDescription,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
deviceNumber,
|
2023-07-16 16:09:25 +00:00
|
|
|
|
serialNumber,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, values);
|
|
|
|
|
|
|
|
|
|
const updatedRow = result.rows[0];
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log("Updated row:", updatedRow);
|
2023-07-16 16:09:25 +00:00
|
|
|
|
|
|
|
|
|
res.send("Data updated successfully");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error updating data:", error);
|
|
|
|
|
res.status(500).send("An error occurred while updating data");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
app.post("/updatedriver", upload.single("upload-file"), async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
var {
|
|
|
|
|
driverName,
|
|
|
|
|
driverSurname,
|
|
|
|
|
driverCard,
|
|
|
|
|
driverGender,
|
|
|
|
|
driverLicense,
|
|
|
|
|
driverPassport,
|
|
|
|
|
driverPhone,
|
|
|
|
|
driverEmail,
|
|
|
|
|
driverTransport,
|
|
|
|
|
driverDescription,
|
|
|
|
|
driverID,
|
|
|
|
|
} = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Вставка новой строки в таблицу drivers
|
|
|
|
|
const query = `
|
|
|
|
|
UPDATE drivers
|
|
|
|
|
SET name = $1,
|
|
|
|
|
surname = $2,
|
|
|
|
|
card = $3,
|
|
|
|
|
gender = $4,
|
|
|
|
|
license = $5,
|
|
|
|
|
passport = $6,
|
|
|
|
|
phone = $7,
|
|
|
|
|
email = $8,
|
|
|
|
|
transport = $9,
|
|
|
|
|
description = $10
|
|
|
|
|
WHERE id = $11
|
|
|
|
|
RETURNING *;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const values = [
|
|
|
|
|
driverName,
|
|
|
|
|
driverSurname,
|
|
|
|
|
driverCard,
|
|
|
|
|
driverGender,
|
|
|
|
|
driverLicense,
|
|
|
|
|
driverPassport,
|
|
|
|
|
driverPhone,
|
|
|
|
|
driverEmail,
|
|
|
|
|
driverTransport,
|
|
|
|
|
driverDescription,
|
|
|
|
|
driverID,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, values);
|
|
|
|
|
|
|
|
|
|
const newRow = result.rows[0];
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log("New driver added:", newRow);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
res.send("Data added successfully");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error adding data:", error);
|
|
|
|
|
res.status(500).send("An error occurred while adding data");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/adddriver", upload.single("upload-file"), async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
var {
|
|
|
|
|
driverName,
|
|
|
|
|
driverSurname,
|
|
|
|
|
driverCard,
|
|
|
|
|
driverGender,
|
|
|
|
|
driverLicense,
|
|
|
|
|
driverPassport,
|
|
|
|
|
driverPhone,
|
|
|
|
|
driverEmail,
|
|
|
|
|
driverTransport,
|
|
|
|
|
driverDescription,
|
|
|
|
|
} = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Вставка новой строки в таблицу drivers
|
|
|
|
|
const query = `
|
|
|
|
|
INSERT INTO drivers (
|
|
|
|
|
name,
|
|
|
|
|
surname,
|
|
|
|
|
card,
|
|
|
|
|
gender,
|
|
|
|
|
license,
|
|
|
|
|
passport,
|
|
|
|
|
phone,
|
|
|
|
|
email,
|
|
|
|
|
transport,
|
|
|
|
|
description
|
|
|
|
|
)
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
|
|
|
RETURNING *;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const values = [
|
|
|
|
|
driverName,
|
|
|
|
|
driverSurname,
|
|
|
|
|
driverCard,
|
|
|
|
|
driverGender,
|
|
|
|
|
driverLicense,
|
|
|
|
|
driverPassport,
|
|
|
|
|
driverPhone,
|
|
|
|
|
driverEmail,
|
|
|
|
|
driverTransport,
|
|
|
|
|
driverDescription,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, values);
|
|
|
|
|
|
|
|
|
|
const newRow = result.rows[0];
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log("New driver added:", newRow);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
res.send("Data added successfully");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error adding data:", error);
|
|
|
|
|
res.status(500).send("An error occurred while adding data");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/driverdata", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "SELECT * FROM drivers WHERE id = $1;";
|
|
|
|
|
const driverdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
const response = driverdata.rows[0];
|
|
|
|
|
res.json(response);
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-11 05:59:00 +00:00
|
|
|
|
app.post("/userdata", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-11 05:59:00 +00:00
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "SELECT * FROM users WHERE id = $1;";
|
|
|
|
|
const userdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
const response = userdata.rows[0];
|
|
|
|
|
res.json(response);
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
app.post("/groupdata", async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "SELECT * FROM groups WHERE id = $1;";
|
|
|
|
|
const userdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
const response = userdata.rows[0];
|
|
|
|
|
res.json(response);
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
app.post("/deletedriver", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "DELETE FROM drivers WHERE id = $1;";
|
|
|
|
|
const driverdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
res.send("Data deleted successfully");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-11 05:59:00 +00:00
|
|
|
|
app.post("/deleteuser", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-11 05:59:00 +00:00
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "DELETE FROM users WHERE id = $1;";
|
|
|
|
|
const userdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
res.send("Data deleted successfully");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
app.post("/deletegroup", async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const id = req.body.id;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Выполняем запрос и получаем результат
|
|
|
|
|
const query = "DELETE FROM groups WHERE id = $1;";
|
|
|
|
|
const userdata = await client.query(query, [id]);
|
|
|
|
|
|
|
|
|
|
// Формирование и отправка ответа
|
|
|
|
|
res.send("Data deleted successfully");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/add-group", async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const { name } = req.body;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
const query = `
|
|
|
|
|
INSERT INTO groups (name)
|
|
|
|
|
VALUES ($1)
|
|
|
|
|
RETURNING id
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, [name]);
|
|
|
|
|
|
|
|
|
|
// Освобождение клиента
|
|
|
|
|
client.release();
|
|
|
|
|
|
|
|
|
|
console.log("Группа успешно добавлена");
|
|
|
|
|
res.json({ message: "Группа успешно добавлена" });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error("Ошибка при вставке данных в базу данных:", err);
|
|
|
|
|
res.status(500).json({ error: "Ошибка при добавлении пользователя" });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-07-24 04:53:11 +00:00
|
|
|
|
async function drivers(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-07-24 04:53:11 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Drivers: [],
|
|
|
|
|
Registrars: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
// Выполняем запрос для объединения данных из таблиц drivers и registrars
|
|
|
|
|
const queryDrivers = `
|
|
|
|
|
SELECT d.id, d.name, d.surname, d.transport, d.phone, d.email, d.card, r.connected
|
|
|
|
|
FROM drivers d
|
|
|
|
|
LEFT JOIN registrars r ON d.transport = r.serial
|
|
|
|
|
ORDER BY r.connected DESC NULLS LAST, CASE WHEN r.connected = true THEN 0 ELSE 1 END, d.id
|
|
|
|
|
`;
|
|
|
|
|
const driversResult = await client.query(queryDrivers);
|
|
|
|
|
|
|
|
|
|
templateData.Drivers = driversResult.rows.map((driver) => ({
|
|
|
|
|
id: driver.id,
|
|
|
|
|
name: driver.name,
|
|
|
|
|
surname: driver.surname,
|
|
|
|
|
transport: driver.transport,
|
|
|
|
|
phone: driver.phone,
|
|
|
|
|
email: driver.email,
|
|
|
|
|
card: driver.card,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const queryRegistrars = `
|
|
|
|
|
SELECT serial
|
|
|
|
|
FROM registrars
|
|
|
|
|
`;
|
|
|
|
|
const registrarsResult = await client.query(queryRegistrars);
|
|
|
|
|
|
|
|
|
|
templateData.Registrars = registrarsResult.rows.map(
|
|
|
|
|
(registrar) => registrar.serial
|
|
|
|
|
);
|
|
|
|
|
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log(templateData);
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/devices/drivers.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/devices/drivers.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
}
|
2023-07-24 04:53:11 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
async function update(req, res) {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-09-18 01:58:49 +00:00
|
|
|
|
if (!userInfo.Update) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-11 09:57:10 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
ifDBError: false,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-09-18 01:58:49 +00:00
|
|
|
|
EditTransport: userInfo.EditTransport,
|
|
|
|
|
DeleteTransport: userInfo.DeleteTransport,
|
|
|
|
|
Update: userInfo.Update,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const source = fs.readFileSync("static/templates/devices/update.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/devices/update.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
2023-07-18 01:32:15 +00:00
|
|
|
|
}
|
2023-07-03 22:31:18 +00:00
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
async function settings(req, res) {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
ifDBError: false,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const source = fs.readFileSync("static/templates/settings.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/settings.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
2023-08-28 04:40:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
async function organisation(req, res) {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
ifDBError: false,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const source = fs.readFileSync("static/templates/admin/organisation.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/admin/organisation.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app.post('/update-organisation', async (req, res) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const { name } = req.body;
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
await client.query('UPDATE main SET organisation = $1 WHERE id = 1', [name]);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
|
|
|
|
|
res.status(200).json({ message: 'Значение успешно обновлено' });
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
res.status(500).json({ error: 'Произошла ошибка при обновлении значения' });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-11 05:59:00 +00:00
|
|
|
|
async function adminPanel(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-09-11 05:59:00 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
2023-09-11 05:59:00 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Users: [],
|
2023-09-11 09:57:10 +00:00
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-09-11 05:59:00 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
const queryUsers = `
|
|
|
|
|
SELECT id, name, surname, email, phone, added
|
|
|
|
|
FROM users
|
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
|
|
|
|
const usersResult = await client.query(queryUsers);
|
|
|
|
|
const allUsers = usersResult.rows;
|
|
|
|
|
|
|
|
|
|
templateData.Users = allUsers.map((user) => ({
|
|
|
|
|
id: user.id,
|
|
|
|
|
name: user.name,
|
|
|
|
|
surname: user.surname,
|
|
|
|
|
email: user.email,
|
|
|
|
|
phone: user.phone,
|
|
|
|
|
added: new Date(user.added).toLocaleDateString('ru-RU', {
|
|
|
|
|
year: 'numeric',
|
|
|
|
|
month: '2-digit',
|
|
|
|
|
day: '2-digit',
|
|
|
|
|
hour: '2-digit',
|
|
|
|
|
minute: '2-digit'
|
|
|
|
|
}),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// console.log(templateData);
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/admin/index.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/admin/index.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Обработка POST-запроса для добавления пользователя
|
|
|
|
|
app.post("/add-user", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-11 05:59:00 +00:00
|
|
|
|
const { name, surname, email, phone, password } = req.body;
|
|
|
|
|
|
2023-09-18 02:03:16 +00:00
|
|
|
|
// console.log(name, surname, email, phone, password)
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
const query = `
|
|
|
|
|
INSERT INTO users (name, surname, email, phone, password, added)
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5, NOW())
|
|
|
|
|
RETURNING id
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, [name, surname, email, phone, password]);
|
|
|
|
|
|
|
|
|
|
// Освобождение клиента
|
|
|
|
|
client.release();
|
|
|
|
|
|
|
|
|
|
console.log("Пользователь успешно добавлен");
|
|
|
|
|
res.json({ message: "Пользователь успешно добавлен" });
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error("Ошибка при вставке данных в базу данных:", err);
|
|
|
|
|
res.status(500).json({ error: "Ошибка при добавлении пользователя" });
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.get('/admin/user/:id', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-09-11 05:59:00 +00:00
|
|
|
|
const id = req.params.id;
|
|
|
|
|
|
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-09-11 05:59:00 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Id: id,
|
|
|
|
|
Name: "",
|
|
|
|
|
Surname: "",
|
|
|
|
|
Email: "",
|
|
|
|
|
Phone: "",
|
|
|
|
|
Password: "",
|
|
|
|
|
Devices: [],
|
|
|
|
|
EditTransport: false,
|
|
|
|
|
DeleteTransport: false,
|
|
|
|
|
Update: false,
|
|
|
|
|
|
|
|
|
|
Groups: [],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const minuteInMillis = 90 * 1000;
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-14 02:40:03 +00:00
|
|
|
|
FROM registrars
|
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
|
|
|
|
const registrarsResult = await client.query(queryRegistrars);
|
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
|
|
|
|
|
|
|
|
|
const groupedRegistrars = {};
|
2023-09-19 13:31:40 +00:00
|
|
|
|
const groupedNumbers = {};
|
2023-09-14 02:40:03 +00:00
|
|
|
|
allRegistrars.forEach((registrar) => {
|
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName] = [];
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}
|
|
|
|
|
groupedRegistrars[groupName].push({
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
checked: false,
|
|
|
|
|
});
|
2023-09-19 13:31:40 +00:00
|
|
|
|
groupedNumbers[groupName].push(registrar.number);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
});
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const query = "SELECT * FROM users WHERE id = $1;";
|
|
|
|
|
const userdata = await client.query(query, [id]);
|
|
|
|
|
const response = userdata.rows[0];
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
if (response.devices && response.devices.length > 0) {
|
|
|
|
|
for (const groupName in groupedRegistrars) {
|
|
|
|
|
groupedRegistrars[groupName].forEach((serialObj) => {
|
|
|
|
|
serialObj.checked = response.devices.includes(serialObj.serial);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
templateData.Name = response.name;
|
|
|
|
|
templateData.Surname = response.surname;
|
|
|
|
|
templateData.Email = response.email;
|
|
|
|
|
templateData.Phone = response.phone;
|
|
|
|
|
templateData.Password = response.password;
|
|
|
|
|
templateData.Devices = response.devices;
|
|
|
|
|
templateData.DeleteTransport = response.deletetransport;
|
|
|
|
|
templateData.EditTransport = response.edittransport;
|
|
|
|
|
templateData.Update = response.update;
|
|
|
|
|
|
|
|
|
|
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
|
|
|
|
|
name: groupName,
|
|
|
|
|
serials: groupedRegistrars[groupName],
|
2023-09-19 13:31:40 +00:00
|
|
|
|
numbers: groupedNumbers[groupName],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}));
|
2023-09-11 05:59:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/admin/user.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync(
|
|
|
|
|
"static/templates/admin/user.html",
|
|
|
|
|
"utf8"
|
|
|
|
|
);
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/updateuser/:id", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
if (req.session.userId != "admin") {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-09-11 05:59:00 +00:00
|
|
|
|
const id = req.params.id;
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
|
|
|
|
var {
|
|
|
|
|
name,
|
|
|
|
|
surname,
|
|
|
|
|
email,
|
|
|
|
|
phone,
|
|
|
|
|
password,
|
|
|
|
|
EditTransport,
|
|
|
|
|
DeleteTransport,
|
|
|
|
|
Update,
|
|
|
|
|
} = req.body.formData;
|
|
|
|
|
|
|
|
|
|
var devices = req.body.devices
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
const query = `
|
|
|
|
|
UPDATE users
|
|
|
|
|
SET
|
|
|
|
|
name = $2,
|
|
|
|
|
surname = $3,
|
|
|
|
|
email = $4,
|
|
|
|
|
phone = $5,
|
|
|
|
|
password = $6,
|
|
|
|
|
editTransport = $7,
|
|
|
|
|
deleteTransport = $8,
|
|
|
|
|
update = $9,
|
|
|
|
|
devices = $10
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
RETURNING *;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const values = [
|
|
|
|
|
id,
|
|
|
|
|
name,
|
|
|
|
|
surname,
|
|
|
|
|
email,
|
|
|
|
|
phone,
|
|
|
|
|
password,
|
|
|
|
|
EditTransport,
|
|
|
|
|
DeleteTransport,
|
|
|
|
|
Update,
|
|
|
|
|
devices,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const result = await client.query(query, values);
|
|
|
|
|
|
|
|
|
|
const updatedRow = result.rows[0];
|
|
|
|
|
// console.log("Updated row:", updatedRow);
|
|
|
|
|
|
|
|
|
|
res.send("Data updated successfully");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error updating data:", error);
|
|
|
|
|
res.status(500).send("An error occurred while updating data");
|
|
|
|
|
} finally {
|
|
|
|
|
client.release();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-08-21 03:28:58 +00:00
|
|
|
|
async function videos(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-08-21 03:28:58 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-08-21 03:28:58 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: [],
|
2023-09-04 09:11:22 +00:00
|
|
|
|
Groups: [],
|
2023-08-21 03:28:58 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-21 03:28:58 +00:00
|
|
|
|
const minuteInMillis = 60 * 1000;
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
// Получаем список групп и их идентификаторов из таблицы groups
|
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
|
|
|
|
|
2023-09-04 09:11:22 +00:00
|
|
|
|
// Выполняем запрос, чтобы получить все данные из таблицы registrars
|
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-18 01:58:49 +00:00
|
|
|
|
FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''}
|
2023-09-04 09:11:22 +00:00
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrarsResult = await client.query(queryRegistrars, templateData.isAdmin ? [] : [serialValues]);
|
2023-09-04 09:11:22 +00:00
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
|
|
|
|
|
|
|
|
|
const groupedRegistrars = {};
|
|
|
|
|
allRegistrars.forEach((registrar) => {
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
2023-09-04 09:11:22 +00:00
|
|
|
|
}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
groupedRegistrars[groupName].push({
|
2023-09-04 09:11:22 +00:00
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
2023-09-14 02:40:03 +00:00
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
2023-09-04 09:11:22 +00:00
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: registrar.number,
|
2023-09-04 09:11:22 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
templateData.Registrars = allRegistrars.map((registrar) => ({
|
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
|
2023-09-04 09:11:22 +00:00
|
|
|
|
name: groupName,
|
|
|
|
|
devices: groupedRegistrars[groupName],
|
2023-09-14 02:40:03 +00:00
|
|
|
|
}));
|
2023-09-04 09:11:22 +00:00
|
|
|
|
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log(templateData);
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
2023-08-28 04:40:58 +00:00
|
|
|
|
const source = fs.readFileSync("static/templates/videos/playback.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultHTML = template(templateData);
|
|
|
|
|
res.send(resultHTML);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/videos/playback.html", "utf8");
|
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function videoExport(req, res) {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
const userInfo = await getUserInfo(req.session.userId);
|
2023-08-28 04:40:58 +00:00
|
|
|
|
let templateData = {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
SERVER_IP: process.env.SERVER_IP,
|
2023-09-11 09:57:10 +00:00
|
|
|
|
Organisation: userInfo.Organisation,
|
|
|
|
|
User: userInfo.User,
|
|
|
|
|
UserInfo: userInfo.Users,
|
|
|
|
|
isAdmin: req.session.userId === 'admin',
|
2023-08-28 04:40:58 +00:00
|
|
|
|
ifDBError: false,
|
|
|
|
|
Registrars: [],
|
2023-09-04 09:11:22 +00:00
|
|
|
|
Groups: [],
|
2023-08-28 04:40:58 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
|
|
|
|
|
2023-09-18 01:58:49 +00:00
|
|
|
|
let serialValues = [];
|
|
|
|
|
if (!templateData.isAdmin) {
|
|
|
|
|
const userDevicesQuery = `
|
|
|
|
|
SELECT devices
|
|
|
|
|
FROM users
|
|
|
|
|
WHERE id = $1
|
|
|
|
|
`;
|
|
|
|
|
const userDevicesResult = await client.query(userDevicesQuery, [req.session.userId]);
|
|
|
|
|
|
2023-09-22 07:55:07 +00:00
|
|
|
|
if (userDevicesResult.rows[0].devices.length > 0) {
|
2023-09-18 01:58:49 +00:00
|
|
|
|
serialValues = userDevicesResult.rows[0].devices;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-28 04:40:58 +00:00
|
|
|
|
const minuteInMillis = 60 * 1000;
|
|
|
|
|
|
2023-09-14 02:40:03 +00:00
|
|
|
|
// Получаем список групп и их идентификаторов из таблицы groups
|
|
|
|
|
const groupsQuery = "SELECT id, name FROM groups";
|
|
|
|
|
const groupsResult = await client.query(groupsQuery);
|
|
|
|
|
const groupsMap = {};
|
|
|
|
|
groupsResult.rows.forEach((group) => {
|
|
|
|
|
groupsMap[group.id] = group.name;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Выполняем запрос, чтобы получить все данные из таблицы registrars
|
|
|
|
|
const queryRegistrars = `
|
2023-09-19 13:31:40 +00:00
|
|
|
|
SELECT id, serial, channels, lastkeepalive, "group", name, plate, sim, ip, port, number
|
2023-09-18 01:58:49 +00:00
|
|
|
|
FROM registrars ${!templateData.isAdmin ? 'WHERE serial = ANY($1)' : ''}
|
2023-09-14 02:40:03 +00:00
|
|
|
|
ORDER BY id
|
|
|
|
|
`;
|
2023-09-18 01:58:49 +00:00
|
|
|
|
const registrarsResult = await client.query(queryRegistrars, templateData.isAdmin ? [] : [serialValues]);
|
2023-09-14 02:40:03 +00:00
|
|
|
|
const allRegistrars = registrarsResult.rows;
|
|
|
|
|
|
|
|
|
|
const groupedRegistrars = {};
|
|
|
|
|
allRegistrars.forEach((registrar) => {
|
|
|
|
|
const groupName = groupsMap[registrar.group] || "Другое"; // Используем "Другое", если группа неизвестна
|
|
|
|
|
if (!groupedRegistrars[groupName]) {
|
|
|
|
|
groupedRegistrars[groupName] = [];
|
|
|
|
|
}
|
|
|
|
|
groupedRegistrars[groupName].push({
|
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
2023-09-19 13:31:40 +00:00
|
|
|
|
number: registrar.number
|
2023-09-14 02:40:03 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
templateData.Registrars = allRegistrars.map((registrar) => ({
|
|
|
|
|
id: registrar.id,
|
|
|
|
|
serial: registrar.serial,
|
|
|
|
|
channels: registrar.channels,
|
|
|
|
|
status: Date.now() - Date.parse(registrar.lastkeepalive) <= minuteInMillis,
|
|
|
|
|
name: registrar.name,
|
|
|
|
|
group: groupsMap[registrar.group] || "Другое",
|
|
|
|
|
plate: registrar.plate,
|
|
|
|
|
sim: registrar.sim,
|
|
|
|
|
ip: registrar.ip,
|
|
|
|
|
port: registrar.port,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
templateData.Groups = Object.keys(groupedRegistrars).map((groupName) => ({
|
|
|
|
|
name: groupName,
|
|
|
|
|
devices: groupedRegistrars[groupName],
|
|
|
|
|
}));
|
2023-08-28 06:20:23 +00:00
|
|
|
|
// console.log(templateData);
|
2023-08-28 04:40:58 +00:00
|
|
|
|
|
|
|
|
|
const source = fs.readFileSync("static/templates/videos/export.html", "utf8");
|
2023-08-21 03:28:58 +00:00
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultHTML = template(templateData);
|
|
|
|
|
res.send(resultHTML);
|
|
|
|
|
|
|
|
|
|
client.release();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
templateData.ifDBError = true;
|
|
|
|
|
|
2023-08-28 04:40:58 +00:00
|
|
|
|
const source = fs.readFileSync("static/templates/videos/export.html", "utf8");
|
2023-08-21 03:28:58 +00:00
|
|
|
|
const template = handlebars.compile(source);
|
|
|
|
|
const resultT = template(templateData);
|
|
|
|
|
res.send(resultT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-28 11:25:45 +00:00
|
|
|
|
app.get('/getData', async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-08-28 11:25:45 +00:00
|
|
|
|
const selectedSerial = req.query.serial;
|
|
|
|
|
const selectedDate = req.query.selectedDate;
|
|
|
|
|
const selectedTime = req.query.selectedTime;
|
|
|
|
|
const selectedChannel = req.query.selectedChannel;
|
|
|
|
|
|
|
|
|
|
try {
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const successResponse = await axios.get(`http://${process.env.SERVER_IP}:8080/http/filelist/request?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`);
|
2023-08-28 11:25:45 +00:00
|
|
|
|
if (successResponse.data.SUCCESS) {
|
2023-09-17 12:22:14 +00:00
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 7000));
|
2023-09-21 05:54:26 +00:00
|
|
|
|
const dataResponse = await axios.get(`http://${process.env.SERVER_IP}:8080/http/filelist/get?serial=${selectedSerial}&querytime=${selectedDate}&channel=${selectedChannel}`);
|
2023-08-28 11:25:45 +00:00
|
|
|
|
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: 'Ошибка при отправке запроса' });
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-08-21 03:28:58 +00:00
|
|
|
|
|
|
|
|
|
app.post("/getspeedarchive", async (req, res) => {
|
2023-09-11 09:57:10 +00:00
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
2023-08-21 03:28:58 +00:00
|
|
|
|
const { serial, datetime } = req.body;
|
|
|
|
|
|
|
|
|
|
const formattedDateTime = new Date(datetime).toISOString();
|
|
|
|
|
const pool = new Pool({
|
|
|
|
|
user: DB_User,
|
|
|
|
|
host: DB_Host,
|
|
|
|
|
database: DB_Name,
|
|
|
|
|
password: DB_Password,
|
|
|
|
|
port: DB_Port,
|
|
|
|
|
});
|
|
|
|
|
const client = await pool.connect();
|
2023-09-17 12:22:14 +00:00
|
|
|
|
|
|
|
|
|
// Запрос для получения первой и последней временных отметок
|
|
|
|
|
const timeRangeQuery = `
|
|
|
|
|
SELECT MIN(time) as min_time, MAX(time) as max_time
|
2023-08-21 03:28:58 +00:00
|
|
|
|
FROM geo
|
|
|
|
|
WHERE serial = $1
|
|
|
|
|
AND time >= $2
|
2023-09-17 12:22:14 +00:00
|
|
|
|
AND time <= $3;
|
2023-08-21 03:28:58 +00:00
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const startTime = new Date(formattedDateTime);
|
|
|
|
|
startTime.setMinutes(0, 0, 0); // Округление до начала часа
|
|
|
|
|
const endTime = new Date(startTime);
|
|
|
|
|
endTime.setHours(endTime.getHours() + 1);
|
|
|
|
|
|
2023-09-17 12:22:14 +00:00
|
|
|
|
// Первый запрос для получения временных отметок
|
|
|
|
|
pool.query(timeRangeQuery, [serial, startTime, endTime], (error, timeResults) => {
|
2023-08-21 03:28:58 +00:00
|
|
|
|
if (error) {
|
|
|
|
|
console.error("Ошибка при выполнении SQL-запроса:", error);
|
|
|
|
|
res.status(500).json({ error: "Ошибка на сервере" });
|
|
|
|
|
} else {
|
2023-09-17 12:22:14 +00:00
|
|
|
|
const { min_time, max_time } = timeResults.rows[0];
|
|
|
|
|
|
|
|
|
|
// Запрос для получения данных скорости и геолокации
|
|
|
|
|
const sqlQuery = `
|
|
|
|
|
SELECT speed, latitude, longitude, time
|
|
|
|
|
FROM geo
|
|
|
|
|
WHERE serial = $1
|
|
|
|
|
AND time >= $2
|
|
|
|
|
AND time <= $3;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
pool.query(sqlQuery, [serial, startTime, endTime], (error, results) => {
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error("Ошибка при выполнении SQL-запроса:", error);
|
|
|
|
|
res.status(500).json({ error: "Ошибка на сервере" });
|
2023-08-21 03:28:58 +00:00
|
|
|
|
} else {
|
2023-09-17 12:22:14 +00:00
|
|
|
|
const data = results.rows.map((row) => ({
|
|
|
|
|
speed: row.speed > 150 ? row.speed / 100 : row.speed,
|
|
|
|
|
geo: {
|
|
|
|
|
latitude: row.latitude,
|
|
|
|
|
longitude: row.longitude,
|
|
|
|
|
},
|
|
|
|
|
time: row.time.toLocaleTimeString("ru-RU", {
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
hour12: false,
|
|
|
|
|
}),
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// Функция для сравнения времени в формате "час:минута"
|
|
|
|
|
function compareTime(a, b) {
|
|
|
|
|
return new Date('1970-01-01 ' + a.time) - new Date('1970-01-01 ' + b.time);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Сортируем массив данных
|
|
|
|
|
data.sort(compareTime);
|
|
|
|
|
|
|
|
|
|
// Разделяем отсортированный массив обратно на отдельные массивы
|
|
|
|
|
const transformedSpeeds = data.map((item) => item.speed);
|
|
|
|
|
const geoData = data.map((item) => item.geo);
|
|
|
|
|
const names = data.map((item) => item.time);
|
|
|
|
|
|
|
|
|
|
res.json({ speeds: transformedSpeeds, geo: geoData, names });
|
2023-08-21 03:28:58 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-17 12:22:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-03 22:31:18 +00:00
|
|
|
|
const port = 8081;
|
|
|
|
|
app.listen(port, () => {
|
|
|
|
|
console.log(`Server is running on port ${port}`);
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-11 09:57:10 +00:00
|
|
|
|
app.use((req, res, next) => {
|
|
|
|
|
if (req.session.userId === undefined) {
|
|
|
|
|
return res.redirect("/signin");
|
|
|
|
|
}
|
|
|
|
|
res.sendFile(path.join(__dirname, "static/templates/404.html"));
|
|
|
|
|
});
|