Ajout de la gestion des routes pour le système de capture, mise à jour des chemins de fichiers et amélioration de la logique de gestion des mesures et vidéos.
This commit is contained in:
2
api.js
2
api.js
@@ -5,7 +5,6 @@ const projectRoutes = require('./routes/projectRoutes');
|
||||
const measurementRoutes = require('./routes/measurementRoutes');
|
||||
const videoRoutes = require('./routes/videoRoutes');
|
||||
const imageRoutes = require('./routes/imageRoutes');
|
||||
const cameraRoutes = require('./routes/cameraRoutes');
|
||||
const uploadRoutes = require('./routes/uploadRoutes');
|
||||
const FileWatcher = require('./src/data/filewatcher');
|
||||
const database_manager = require('./src/database/database_manager');
|
||||
@@ -22,6 +21,5 @@ router.use('/', measurementRoutes);
|
||||
router.use('/', videoRoutes);
|
||||
router.use('/', imageRoutes);
|
||||
router.use('/', uploadRoutes);
|
||||
router.use('/', cameraRoutes);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -1,359 +0,0 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const db = require('../db');
|
||||
const serverError = require('../utils/serverError');
|
||||
const { start } = require('repl');
|
||||
|
||||
//const minInterval = 3; // Minutes
|
||||
//const maxInterval = 60; // Minutes
|
||||
|
||||
var defaultCaptureInterval = 5; // minutes
|
||||
var defaultMaintenance = 0;
|
||||
var defaultActive = 0; // 0 = pas de capture, 1 = capture en cours
|
||||
|
||||
async function initCamera() {
|
||||
const query = 'SELECT * FROM public.camera WHERE id = $1';
|
||||
const values = [1];
|
||||
|
||||
db.query(query, values, (err, result) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la vérification de l\'entrée caméra:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
const insertQuery = `
|
||||
INSERT INTO public.camera (id, interval, maintenance, active)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
`;
|
||||
const insertValues = [1, defaultCaptureInterval, defaultMaintenance, defaultActive];
|
||||
|
||||
db.query(insertQuery, insertValues, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de l\'initialisation de la caméra:', err);
|
||||
} else {
|
||||
console.log('Caméra initialisée avec les valeurs par défaut.');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('L\'entrée caméra avec l\'ID 1 existe déjà. Aucune initialisation nécessaire.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getCamera() {
|
||||
// retourner l'état de la caméra
|
||||
const query = 'SELECT * FROM public.camera WHERE id = $1';
|
||||
const values = [1];
|
||||
|
||||
try {
|
||||
const result = await db.query(query, values);
|
||||
if (result.rows.length === 0) {
|
||||
console.log('Aucune entrée caméra trouvée.');
|
||||
return null;
|
||||
} else {
|
||||
const camera = result.rows[0];
|
||||
console.log('État de la caméra récupéré avec succès:', camera);
|
||||
return {
|
||||
captureInterval: camera.interval,
|
||||
captureProjectID: camera.active,
|
||||
captureStatus: camera.active,
|
||||
maintenance: camera.maintenance
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Erreur lors de la récupération de l\'état de la caméra:', err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function printCameraStatus() {
|
||||
let camera = await getCamera();
|
||||
console.log('Statut de la caméra:');
|
||||
console.log('Intervalle de capture:', camera.captureInterval, 'minutes');
|
||||
console.log('Maintenance:', camera.maintenance === 1 ? 'En cours' : 'Aucune');
|
||||
console.log('Statut de la capture:', camera.active === 1 ? 'En cours' : 'Arrêté');
|
||||
console.log('-----------------------------------');
|
||||
}
|
||||
|
||||
async function isCameraOccupied() {
|
||||
try {
|
||||
const query = 'SELECT id FROM public.projects WHERE status = $1 LIMIT 1';
|
||||
const values = [1];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
db.query(query, values, (err, result) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la vérification de l\'occupation de la caméra:', err);
|
||||
reject(err);
|
||||
} else {
|
||||
const isOccupied = result.rows.length > 0 ? result.rows[0].id : null;
|
||||
resolve(isOccupied);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erreur inattendue lors de la vérification de l\'occupation de la caméra:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function getCurrentProject() {
|
||||
try {
|
||||
const query = 'SELECT * FROM public.projects WHERE status = $1 LIMIT 1';
|
||||
const values = [1];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
db.query(query, values, (err, result) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la récupération du projet en cours:', err);
|
||||
reject(err);
|
||||
} else if (result.rows.length === 0) {
|
||||
console.log('Aucun projet en cours trouvé.');
|
||||
resolve(null);
|
||||
} else {
|
||||
const currentProject = result.rows[0];
|
||||
console.log('Projet en cours récupéré avec succès:', currentProject);
|
||||
resolve(currentProject);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Erreur inattendue lors de la récupération du projet en cours:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function resetProjectStatus() {
|
||||
const query = 'UPDATE public.projects SET status = $1 WHERE status = $2';
|
||||
const values = [2, 1];
|
||||
|
||||
db.query(query, values, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la réinitialisation du statut des projets:', err);
|
||||
} else {
|
||||
console.log('Statut des projets réinitialisé avec succès.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function activateCamera() {
|
||||
const query = 'UPDATE public.camera SET active = $1 WHERE id = $2';
|
||||
const values = [1, 1];
|
||||
|
||||
db.query(query, values, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de l\'activation de la caméra:', err);
|
||||
} else {
|
||||
console.log('Caméra activée avec succès.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function deactivateCamera() {
|
||||
const query = 'UPDATE public.camera SET active = $1 WHERE id = $2';
|
||||
const values = [0, 1];
|
||||
|
||||
db.query(query, values, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la désactivation de la caméra:', err);
|
||||
} else {
|
||||
console.log('Caméra désactivée avec succès.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function changeProjectStatus(projectId, status) {
|
||||
try {
|
||||
const query = 'UPDATE public.projects SET status = $1 WHERE id = $2';
|
||||
const values = [status, projectId];
|
||||
|
||||
await db.query(query, values);
|
||||
console.log(`Statut du projet ID ${projectId} modifié avec succès à ${status}.`);
|
||||
} catch (err) {
|
||||
console.error('Une erreur inattendue s\'est produite lors de la modification du statut du projet:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function startup() {
|
||||
await initCamera();
|
||||
await printCameraStatus();
|
||||
}
|
||||
|
||||
startup()
|
||||
.catch(err => {
|
||||
console.error('Erreur lors de l\'initialisation de la caméra:', err);
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /camera/status:
|
||||
* get:
|
||||
* summary: Get the current status of the camera
|
||||
* tags:
|
||||
* - Camera
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Successfully retrieved the camera status
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* captureInterval:
|
||||
* type: integer
|
||||
* description: Capture interval in minutes
|
||||
* captureProjectID:
|
||||
* type: integer
|
||||
* description: ID of the project currently being captured
|
||||
* captureStatus:
|
||||
* type: integer
|
||||
* description: Capture status (0 = stopped, 1 = ongoing)
|
||||
* maintenance:
|
||||
* type: integer
|
||||
* description: Maintenance status (0 = none, 1 = ongoing)
|
||||
* 500:
|
||||
* description: Internal server error
|
||||
*/
|
||||
router.get('/camera/status', async (req, res) => {
|
||||
try {
|
||||
const cameraStatus = await getCamera();
|
||||
res.status(200).json(cameraStatus);
|
||||
} catch (err) {
|
||||
serverError.sendError('Erreur lors de la récupération de l\'état de la caméra:', res, err, 500);
|
||||
}
|
||||
});
|
||||
|
||||
async function setCameraSettings(interval, maintenance) {
|
||||
try {
|
||||
const query = `
|
||||
UPDATE public.camera
|
||||
SET interval = $1, maintenance = $2
|
||||
WHERE id = $3
|
||||
`;
|
||||
const values = [interval, maintenance, 1];
|
||||
|
||||
db.query(query, values, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la mise à jour des paramètres de la caméra:', err);
|
||||
} else {
|
||||
console.log('Paramètres de la caméra mis à jour avec succès.');
|
||||
//captureInterval = interval;
|
||||
//maintenance = maintenance;
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Une erreur inattendue s\'est produite lors de la mise à jour des paramètres de la caméra:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function startProcedure(projectId, interval, maintenance) {
|
||||
if (isNaN(projectId) || isNaN(interval) || isNaN(maintenance)) {
|
||||
return { error: 'Invalid parameters' };
|
||||
}
|
||||
const cameraOccupied = await isCameraOccupied();
|
||||
if (cameraOccupied) {
|
||||
return { error: 'Camera is occupied by another project' };
|
||||
} else {
|
||||
await activateCamera();
|
||||
await setCameraSettings(interval, maintenance);
|
||||
await changeProjectStatus(projectId, 1); // changer le statut du projet en cours à 1 (en cours)
|
||||
console.log('Procédure de capture démarrée avec succès.');
|
||||
return { message: 'Capture procedure started successfully' };
|
||||
}
|
||||
}
|
||||
|
||||
async function stopProcedure() {
|
||||
var project = await getCurrentProject();
|
||||
console.log(project);
|
||||
if (project) {
|
||||
await resetProjectStatus(); // réinitialiser le statut du projet en cours
|
||||
await deactivateCamera(); // désactiver la caméra
|
||||
await changeProjectStatus(project.id, 2); // changer le statut du projet en cours à 2 (terminé)
|
||||
console.log('Procédure de capture arrêtée avec succès.');
|
||||
return { message: 'Capture procedure stopped successfully' };
|
||||
} else {
|
||||
return { error: 'No project is currently being captured' };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /procedure/start/:
|
||||
* post:
|
||||
* summary: Start the capture procedure
|
||||
* tags:
|
||||
* - Procedure
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* projectId:
|
||||
* type: integer
|
||||
* description: ID of the project to start capturing
|
||||
* interval:
|
||||
* type: integer
|
||||
* description: Capture interval in minutes
|
||||
* maintenance:
|
||||
* type: integer
|
||||
* description: Maintenance status (0 = none, 1 = ongoing)
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Successfully started the capture procedure
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* description: Success message
|
||||
* error:
|
||||
* type: string
|
||||
* description: Error message, if any
|
||||
* 500:
|
||||
* description: Internal server error
|
||||
* /procedure/stop/:
|
||||
* post:
|
||||
* summary: Stop the capture procedure
|
||||
* tags:
|
||||
* - Procedure
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Successfully stopped the capture procedure
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* description: Success message
|
||||
* error:
|
||||
* type: string
|
||||
* description: Error message, if any
|
||||
* 500:
|
||||
* description: Internal server error
|
||||
*/
|
||||
router.post('/procedure/start/', async (req, res) => {
|
||||
const { projectId, interval, maintenance } = req.body;
|
||||
try {
|
||||
const result = await startProcedure(projectId, interval, maintenance);
|
||||
res.status(200).json(result);
|
||||
} catch (err) {
|
||||
serverError.sendError('Erreur lors du démarrage de la procédure de capture:', res, err, 500);
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/procedure/stop/', async (req, res) => {
|
||||
try {
|
||||
const result = await stopProcedure();
|
||||
res.status(200).json(result);
|
||||
} catch (err) {
|
||||
serverError.sendError('Erreur lors de l\'arrêt de la procédure de capture:', res, err, 500);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
8
routes/capture_system.js
Normal file
8
routes/capture_system.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const sharp = require('sharp');
|
||||
const fs = require('fs');
|
||||
const dbTester = require('../test/tester');
|
||||
const db = require('../db');
|
||||
const serverError = require('../utils/serverError');
|
||||
|
||||
@@ -34,9 +34,9 @@ router.post('/uploadmeasurement', upload.single('image'), async (req, res) => {
|
||||
if (!imagePath) {
|
||||
return res.status(500).json({ error: 'Failed to upload image' });
|
||||
}
|
||||
const measurement = await database_manager.measurement.add_measurement(projectId, timestamp, imagePath, temperature, humidity, nextOrderId);
|
||||
const measurement = await database_manager.measurement.create_measurement(projectId, timestamp, imagePath, temperature, humidity, nextOrderId);
|
||||
if (!measurement) {
|
||||
return res.status(500).json({ error: 'Failed to add measurement' });
|
||||
return res.status(500).json({ error: 'Failed to create measurement' });
|
||||
}
|
||||
res.json({ message: 'Measurement uploaded successfully', path: imagePath, id: measurement.id });
|
||||
} catch (error) {
|
||||
|
||||
@@ -38,7 +38,7 @@ async function checkAndRemoveInvalidEntries() {
|
||||
|
||||
// Run the check periodically
|
||||
console.log('[INFO] Activation du FileWatcher pour surveiller les fichiers invalides...')
|
||||
setInterval(checkAndRemoveInvalidEntries, 10000); // Every 10 seconds
|
||||
setInterval(checkAndRemoveInvalidEntries, 1000); // Every 10 seconds
|
||||
|
||||
// Initial run
|
||||
checkAndRemoveInvalidEntries();
|
||||
@@ -1,5 +1,6 @@
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { Buffer } = require('buffer');
|
||||
const PROJECTS_DIR = path.join('.');
|
||||
const database_manager = require('../database/database_manager.js');
|
||||
|
||||
@@ -62,7 +63,8 @@ async function scanAllImages(dir = 'storage') {
|
||||
}
|
||||
|
||||
async function saveFile(filePath, content) {
|
||||
let Buffer=Buffer.from(content, 'base64');
|
||||
const dir = path.dirname(filePath);
|
||||
await fs.mkdir(dir, { recursive: true });
|
||||
if (Buffer.isBuffer(content)) {
|
||||
await fs.writeFile(filePath, content);
|
||||
} else {
|
||||
@@ -101,7 +103,7 @@ async function handleFileOperation(operation, ...args) {
|
||||
|
||||
const project = {
|
||||
createProjectDirectory: async function (projectId) {
|
||||
const projectPath = `${projectId}`;
|
||||
const projectPath = path.join(PROJECTS_DIR, 'storage', `${projectId}`);
|
||||
await handleFileOperation(createFolder, projectPath);
|
||||
await handleFileOperation(createFolder, `${projectPath}/images`);
|
||||
await handleFileOperation(createFolder, `${projectPath}/videos`);
|
||||
@@ -109,7 +111,7 @@ const project = {
|
||||
},
|
||||
|
||||
deleteProjectDirectory: async function (projectId) {
|
||||
const projectPath = `${projectId}`;
|
||||
const projectPath = path.join(PROJECTS_DIR, 'storage', `${projectId}`);
|
||||
await handleFileOperation(deleteFolder, projectPath);
|
||||
console.log("[FILE] deleteProjectDirectory : " + projectPath);
|
||||
}
|
||||
@@ -117,15 +119,15 @@ const project = {
|
||||
|
||||
const measurement = {
|
||||
get_measurement_image: async function (projectId, orderId) {
|
||||
const projectPath = `${projectId}`;
|
||||
const imagePath = `${projectPath}/images/${orderId}.jpg`;
|
||||
const projectPath = path.join(PROJECTS_DIR, 'storage', `${projectId}`);
|
||||
const imagePath = path.join(projectPath, 'images', `${orderId}.jpg`);
|
||||
console.log("[FILE] get_measurement_image : " + imagePath);
|
||||
return await handleFileOperation(getFile, imagePath);
|
||||
},
|
||||
|
||||
upload_measurement_image: async function (image, projectId, orderId) {
|
||||
const projectPath = `${projectId}`;
|
||||
const imagePath = `${projectPath}/images/${orderId}.jpg`;
|
||||
const projectPath = path.join(PROJECTS_DIR, 'storage', `${projectId}`);
|
||||
const imagePath = path.join(projectPath, 'images', `${orderId}.jpg`);
|
||||
console.log("[FILE] upload_measurement_image : " + imagePath);
|
||||
await handleFileOperation(saveFile, imagePath, image.buffer);
|
||||
return imagePath;
|
||||
@@ -158,8 +160,8 @@ const measurement = {
|
||||
|
||||
const video = {
|
||||
get_video: async function (projectId, orderId) {
|
||||
const projectPath = `${projectId}`;
|
||||
const videoPath = `${projectPath}/videos/${orderId}.mp4`;
|
||||
const projectPath = path.join(PROJECTS_DIR, `${projectId}`);
|
||||
const videoPath = `/storage/${projectPath}/videos/${orderId}.mp4`;
|
||||
console.log("[FILE] get_video : " + videoPath);
|
||||
return await handleFileOperation(getFile, videoPath);
|
||||
},
|
||||
|
||||
@@ -259,8 +259,8 @@ const video = {
|
||||
|
||||
const camera = {
|
||||
get_camera: handleDatabaseOperation(async () => {
|
||||
const query = `SELECT * FROM camera;`;
|
||||
return (await db.query(query)).rows;
|
||||
const query = `SELECT * FROM camera WHERE id = 1;`;
|
||||
return (await db.query(query)).rows[0];
|
||||
}),
|
||||
|
||||
edit_camera: handleDatabaseOperation(async (id, updates) => {
|
||||
@@ -276,6 +276,12 @@ const camera = {
|
||||
})
|
||||
};
|
||||
|
||||
// zone de test
|
||||
async function test_zone(){
|
||||
}
|
||||
|
||||
test_zone();
|
||||
|
||||
// Export des modules
|
||||
module.exports = {
|
||||
project,
|
||||
|
||||
47
stuff.md
47
stuff.md
@@ -1,30 +1,27 @@
|
||||
Routes :
|
||||
Workflow Caméra
|
||||
|
||||
- /projects = liste des projets
|
||||
- /projects/:id = détail d'un projet
|
||||
- /projects/:id/edit = édition d'un projet
|
||||
- /projects/:id/delete = suppression d'un projet
|
||||
- /projects/new = création d'un projet
|
||||
- /projects/:id/measurements = liste des mesures d'un projet
|
||||
- /projects/:id/measurements/:id = détail d'une mesure
|
||||
- /projects/:id/measurements/:id/edit = édition d'une mesure
|
||||
- /projects/:id/measurements/:id/delete = suppression d'une mesure
|
||||
- /projects/:id/videos = liste des vidéos d'un projet
|
||||
- /projects/:id/videos/:id = détail d'une vidéo
|
||||
Côté Caméra
|
||||
|
||||
/camera/status // récupérer le statut de la caméra (GET)
|
||||
|
||||
- /measurements = liste des mesures
|
||||
- /measurements/:id = détail d'une mesure
|
||||
- /measurements/:id/edit = édition d'une mesure
|
||||
- /measurements/:id/delete = suppression d'une mesure
|
||||
- /measurements/new = création d'une mesure
|
||||
si stop :
|
||||
/camera/stop // arrêter la caméra (POST)
|
||||
|
||||
- /cameras = liste des caméras
|
||||
- /cameras/:id = détail d'une caméra
|
||||
- /cameras/:id/edit = édition d'une caméra
|
||||
- /cameras/:id/delete = suppression d'une caméra
|
||||
- /cameras/new = création d'une caméra
|
||||
si upload :
|
||||
/camera/upload // uploader la vidéo (POST)
|
||||
|
||||
- /data/image/:id = image depuis le pool de stockage
|
||||
- /data/video/:id = vidéo depuis le pool de stockage
|
||||
-
|
||||
Côté Backend
|
||||
|
||||
/procedure/start // démarrer une procédure (POST)
|
||||
/procedure/status // récupérer le statut de la caméra/procédure courante (GET)
|
||||
/procedure/stop // arrêter la procédure courante (POST) (doit attendre la confirmation de /camera/stop)
|
||||
/procedure/delete // supprimer la procédure courante (POST) (doit attendre la confirmation de /camera/delete)
|
||||
|
||||
Modèle de données :
|
||||
|
||||
table camera (paramètres de la caméra et procédure courante)
|
||||
id (int, PK) - Toujours 1
|
||||
interval(int) - Intervalle de la caméra (en minutes), peut être null
|
||||
image
|
||||
maintenance(int) - 1 ou 0, 1 = maintenance, 0 = pas de maintenance (si maintenance, la caméra ne doit pas se redémarrer)
|
||||
status(int) - 1 ou 0, 1 = caméra en cours d'utilisation, 0 = caméra arrêtée (si la caméra est arrêtée, la procédure doit être arrêtée)
|
||||
Reference in New Issue
Block a user