diff --git a/routes/_swaggerRoutes.js b/routes/_swaggerRoutes.js deleted file mode 100644 index 2d8058c..0000000 --- a/routes/_swaggerRoutes.js +++ /dev/null @@ -1,620 +0,0 @@ -// Routes SWAGGER - Documentation API -// Documentation: https://swagger.io/docs/specification/2-0/basic-structure/ -// Les documentations sont volontairement séparées du code source pour des raisons de lisibilité et de maintenabilité. - -/** - * @swagger - * /projects/{id}: - * delete: - * summary: Supprimer un projet par son ID - * description: Supprime un projet spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID du projet - * responses: - * 200: - * description: Projet supprimé avec succès. - * 400: - * description: ID de projet invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /projects: - * get: - * summary: Récupérer tous les projets - * description: Récupère tous les projets disponibles. - * responses: - * 200: - * description: Une liste de projets. - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /projects/{id}: - * get: - * summary: Récupérer un projet par ID - * description: Récupère un projet spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID du projet - * responses: - * 200: - * description: Un projet. - * content: - * application/json: - * schema: - * type: object - * 400: - * description: ID de projet invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /projects/{id}/videos: - * get: - * summary: Récupérer les vidéos d'un projet par ID - * description: Récupère les vidéos associées à un projet spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID du projet - * responses: - * 200: - * description: Une liste de vidéos. - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * 400: - * description: ID de projet invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /projects/{id}/measurements: - * get: - * summary: Récupérer les mesures d'un projet par ID - * description: Récupère les mesures associées à un projet spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID du projet - * responses: - * 200: - * description: Une liste de mesures. - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * 400: - * description: ID de projet invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /projects: - * post: - * summary: Ajouter un nouveau projet - * description: Ajoute un nouveau projet à la base de données. - * requestBody: - * required: true - * content: - * application/json: - * schema: - * type: object - * properties: - * name: - * type: string - * description: - * type: string - * responses: - * 201: - * description: Projet ajouté avec succès. - * 400: - * description: Le nom et la description sont requis. - * 500: - * description: Erreur serveur. - */ - -/** - * @swagger - * /smile: - * get: - * summary: Retrieve a smile image - * responses: - * 200: - * description: A smile image - * content: - * image/jpeg: - * schema: - * type: string - * format: binary - * 404: - * description: Image not found - */ - -/** - * @swagger - * /images/{projectId}/{orderId}: - * get: - * summary: Retrieve an image by project and order ID - * parameters: - * - in: path - * name: projectId - * required: true - * schema: - * type: string - * description: The project ID - * - in: path - * name: orderId - * required: true - * schema: - * type: string - * description: The order ID - * responses: - * 200: - * description: An image file - * content: - * application/octet-stream: - * schema: - * type: string - * format: binary - * 404: - * description: Image not found - */ -/** - * @swagger - * /images/{measurementId}: - * get: - * summary: Retrieve an image by measurement ID - * parameters: - * - in: path - * name: measurementId - * required: true - * schema: - * type: string - * description: The measurement ID - * responses: - * 200: - * description: An image file - * content: - * application/octet-stream: - * schema: - * type: string - * format: binary - * 404: - * description: Image not found - */ -/** - * @swagger - * /preview/{projectId}/{orderId}: - * get: - * summary: Retrieve a preview of an image by project and order ID - * parameters: - * - in: path - * name: projectId - * required: true - * schema: - * type: string - * description: The project ID - * - in: path - * name: orderId - * required: true - * schema: - * type: string - * description: The order ID - * responses: - * 200: - * description: A resized preview of the image - * content: - * image/jpeg: - * schema: - * type: string - * format: binary - * 404: - * description: Image not found - * 500: - * description: Internal Server Error - */ -/** - * @swagger - * /measurements: - * get: - * summary: Récupérer toutes les mesures - * description: Récupère toutes les mesures de la base de données. - * responses: - * 200: - * description: Une liste de mesures. - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: integer - * project_id: - * type: integer - * timestamp: - * type: string - * format: date-time - * image_path: - * type: string - * temperature: - * type: number - * humidity: - * type: number - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /measurements/{id}: - * get: - * summary: Récupérer une mesure par ID - * description: Récupère une mesure spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID de la mesure - * responses: - * 200: - * description: Une mesure. - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * project_id: - * type: integer - * timestamp: - * type: string - * format: date-time - * image_path: - * type: string - * temperature: - * type: number - * humidity: - * type: number - * 400: - * description: ID de mesure invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /measurements/{projectId}/{orderId}: - * get: - * summary: Récupérer une mesure par project ID et order ID - * description: Récupère une mesure spécifique en utilisant le project ID et order ID. - * parameters: - * - in: path - * name: projectId - * schema: - * type: integer - * required: true - * description: ID du projet - * - in: path - * name: orderId - * schema: - * type: integer - * required: true - * description: ID de la commande - * responses: - * 200: - * description: Une mesure. - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * project_id: - * type: integer - * timestamp: - * type: string - * format: date-time - * image_path: - * type: string - * temperature: - * type: number - * humidity: - * type: number - * 400: - * description: ID de projet ou de commande invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /measurements/{id}: - * delete: - * summary: Supprimer une mesure par ID - * description: Supprime une mesure spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID de la mesure - * responses: - * 200: - * description: Mesure supprimée avec succès. - * 400: - * description: ID de mesure invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /measurements/{projectId}/{orderId}: - * delete: - * summary: Supprimer une mesure par project ID et order ID - * description: Supprime une mesure spécifique en utilisant le project ID et order ID. - * parameters: - * - in: path - * name: projectId - * schema: - * type: integer - * required: true - * description: ID du projet - * - in: path - * name: orderId - * schema: - * type: integer - * required: true - * description: ID de la commande - * responses: - * 200: - * description: Mesure supprimée avec succès. - * 400: - * description: ID de projet ou de commande invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /videos: - * get: - * summary: Récupérer toutes les vidéos - * description: Récupère toutes les vidéos de la base de données. - * responses: - * 200: - * description: Une liste de vidéos. - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: integer - * project_id: - * type: integer - * measurement_ids: - * type: string - * video_path: - * type: string - * start_timestamp: - * type: string - * end_timestamp: - * type: string - * image_count: - * type: integer - * resolution: - * type: string - * duration: - * type: number - * fps: - * type: number - * status: - * type: integer - * name: - * type: string - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /videos/{id}: - * get: - * summary: Récupérer une vidéo par ID - * description: Récupère une vidéo spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID de la vidéo - * responses: - * 200: - * description: Une vidéo. - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * project_id: - * type: integer - * measurement_ids: - * type: string - * video_path: - * type: string - * start_timestamp: - * type: string - * end_timestamp: - * type: string - * image_count: - * type: integer - * resolution: - * type: string - * duration: - * type: number - * fps: - * type: number - * status: - * type: integer - * name: - * type: string - * 400: - * description: ID de vidéo invalide. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /videos: - * post: - * summary: Créer une nouvelle vidéo - * description: Crée une nouvelle vidéo avec les informations fournies. - * requestBody: - * required: true - * content: - * application/json: - * schema: - * type: object - * properties: - * project_id: - * type: integer - * measurement_ids: - * type: string - * name: - * type: string - * resolution: - * type: string - * duration: - * type: number - * responses: - * 200: - * description: Vidéo créée avec succès. - * content: - * application/json: - * schema: - * type: object - * properties: - * message: - * type: string - * video: - * type: object - * properties: - * project_id: - * type: integer - * measurement_ids: - * type: string - * name: - * type: string - * resolution: - * type: string - * duration: - * type: number - * 400: - * description: Tous les champs sont requis. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /videos/{id}: - * delete: - * summary: Supprimer une vidéo par ID - * description: Supprime une vidéo spécifique en utilisant son ID. - * parameters: - * - in: path - * name: id - * schema: - * type: integer - * required: true - * description: ID de la vidéo - * responses: - * 200: - * description: Vidéo supprimée avec succès. - * 400: - * description: ID de vidéo invalide. - * 404: - * description: Aucune vidéo trouvée avec cet ID. - * 500: - * description: Erreur serveur. - */ -/** - * @swagger - * /videos/file/{video_id}: - * get: - * summary: Retrieve a video by video ID - * parameters: - * - in: path - * name: video_id - * required: true - * schema: - * type: string - * description: The video ID - * responses: - * 200: - * description: A video file - * content: - * application/octet-stream: - * schema: - * type: string - * format: binary - * 404: - * description: Video not found - * 400: - * description: Video not yet produced - */ -/** - * @swagger - * /cat: - * get: - * summary: Retrieve a cat video - * responses: - * 200: - * description: A cat video - * content: - * application/octet-stream: - * schema: - * type: string - * format: binary - * 404: - * description: Video not found - */ diff --git a/routes/capture_system.js b/routes/capture_system.js deleted file mode 100644 index 1c5962a..0000000 --- a/routes/capture_system.js +++ /dev/null @@ -1,260 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const serverError = require('../utils/serverError'); -const database_manager = require('../src/database/database_manager'); - -const defaultSettings = { - id: 1, - interval: null, - nb_images: null, - maintenance: false, - stop_flag: false, - idle: true -}; - -async function camera_initialization() { - // si capture.get_camera est vide ou undefined, on l'initialise - let current_camera = await database_manager.capture.get_camera(); - if (!current_camera || current_camera === undefined) { - console.log("Initializing camera..."); - current_camera = await database_manager.capture.init_camera( - defaultSettings.id, - defaultSettings.interval, - defaultSettings.nb_images, - defaultSettings.maintenance, - defaultSettings.stop_flag, - defaultSettings.idle - ); - console.log("Camera initialized:", current_camera); - } - else { - console.log("Camera already initialized:", current_camera); - } -} - -camera_initialization() - -async function get_camera_settings() { - const settings = await database_manager.capture.get_camera(); - if (!settings) { - // balancer une erreur si la caméra n'est pas initialisée - throw new Error("Camera settings not found in the database."); - } - return settings; -} - -router.get('/camera/status', async (req, res) => { - try { - const settings = await get_camera_settings(); - res.json(settings); - } catch (error) { - serverError.sendError('Error getting camera status:', res, error, 500); - } -}); - -async function stop_procedure() { // côté serveur - let new_settings = { - stop_flag: true, - } - await database_manager.capture.edit_camera(1, new_settings); - console.log("Stopping camera... en attente de confirmation de la caméra..."); -} - -async function confirm_stop_procedure() { // côté caméra - let new_settings = { - interval: null, - nb_images: null, - stop_flag: false, - idle: true, - } - await database_manager.capture.edit_camera(1, new_settings); - let project_settings = { - status: 0, - } - let current_project = await database_manager.project.find_current_rendering_project(); - if (current_project) { - await database_manager.project.edit_project_by_id(current_project.id, project_settings); - console.log("Project : " + current_project.id + " stopped."); - } else { - console.log("No project to stop."); - } - console.log("Camera stopped."); -} - -async function start_procedure(project_id, interval, nb_images) { - let new_settings = { - interval: interval, - nb_images: nb_images, - stop_flag: false, - idle: false, - } - console.log("Starting Procedure with settings:", new_settings); - await database_manager.capture.edit_camera(1, new_settings); - let project_settings = { - status: 1, - } - let existing_project = await database_manager.project.find_current_rendering_project(); - if (existing_project) { - throw new Error("A project is already being rendered. Please stop it before starting a new one."); - } else { - await database_manager.project.edit_project_by_id(project_id, project_settings); - console.log("Project : " + project_id + " started."); - } - console.log("Camera started."); -} - -async function activate_maintenance() { - let new_settings = { - maintenance: true, - } - await database_manager.capture.edit_camera(1, new_settings); - console.log("Camera in maintenance mode."); -} - -async function deactivate_maintenance() { - let new_settings = { - maintenance: false, - } - await database_manager.capture.edit_camera(1, new_settings); - console.log("Camera out of maintenance mode."); -} - -router.post('/procedure/start', async (req, res) => { - const { project_id, interval, nb_images } = req.body; - if (!interval || !nb_images) { - return res.status(400).json({ error: 'Interval and number of images are required' }); - } - try { - await start_procedure(project_id, interval, nb_images); - res.json({ message: 'Camera started successfully', settings: { interval, nb_images } }); - } catch (error) { - serverError.sendError('Error starting camera procedure:', res, error, 500); - } -}); - -router.post('/procedure/stop', async (req, res) => { - try { - await stop_procedure(); - res.json({ message: 'Camera stop procedure initiated successfully' }); - } catch (error) { - serverError.sendError('Error stopping camera procedure:', res, error, 500); - } -}); - -router.post('/camera/stop', async (req, res) => { - try { - await confirm_stop_procedure(); - res.json({ message: 'Camera stopped successfully' }); - } catch (error) { - serverError.sendError('Error stopping camera:', res, error, 500); - } -}); - -/** - * @swagger - * /camera/status: - * get: - * summary: Get the current camera settings - * responses: - * 200: - * description: Successfully retrieved camera settings - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * interval: - * type: integer - * nb_images: - * type: integer - * maintenance: - * type: boolean - * stop_flag: - * type: boolean - * idle: - * type: boolean - * 500: - * description: Error retrieving camera settings - * - * /procedure/start: - * post: - * summary: Start the camera procedure - * requestBody: - * required: true - * content: - * application/json: - * schema: - * type: object - * properties: - * project_id: - * type: integer - * interval: - * type: integer - * nb_images: - * type: integer - * responses: - * 200: - * description: Camera started successfully - * 400: - * description: Interval and number of images are required - * 500: - * description: Error starting camera procedure - * - * /procedure/stop: - * post: - * summary: Initiate the camera stop procedure - * responses: - * 200: - * description: Camera stop procedure initiated successfully - * 500: - * description: Error stopping camera procedure - * - * /camera/stop: - * post: - * summary: Confirm the camera stop procedure - * responses: - * 200: - * description: Camera stopped successfully - * 500: - * description: Error stopping camera - * - * /camera/maintenance: - * post: - * summary: Activate maintenance mode for the camera - * responses: - * 200: - * description: Camera in maintenance mode - * 500: - * description: Error activating maintenance mode - * - * /camera/maintenance/deactivate: - * post: - * summary: Deactivate maintenance mode for the camera - * responses: - * 200: - * description: Camera out of maintenance mode - * 500: - * description: Error deactivating maintenance mode - */ -router.post('/camera/maintenance', async (req, res) => { - try { - await activate_maintenance(); - res.json({ message: 'Camera in maintenance mode' }); - } catch (error) { - serverError.sendError('Error activating maintenance mode:', res, error, 500); - } -} -); - -router.post('/camera/maintenance/deactivate', async (req, res) => { - try { - await deactivate_maintenance(); - res.json({ message: 'Camera out of maintenance mode' }); - } catch (error) { - serverError.sendError('Error deactivating maintenance mode:', res, error, 500); - } -}); - -module.exports = router; \ No newline at end of file diff --git a/routes/imageRoutes.js b/routes/imageRoutes.js deleted file mode 100644 index 6c6c151..0000000 --- a/routes/imageRoutes.js +++ /dev/null @@ -1,115 +0,0 @@ -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'); - -router.get('/smile', (req, res) => { - const imagePath = dbTester.getSmileImage(); - fs.access(imagePath, fs.constants.F_OK, (err) => { - if (err) { - console.error('Image not found:', err); - return res.status(404).json({ error: 'Image not found' }); - } - res.sendFile(imagePath); - }); -}); - -router.get('/images/:projectId/:orderId', (req, res) => { - const projectId = req.params.projectId; - const orderId = req.params.orderId; - const query = 'SELECT path FROM public.measurements WHERE project_id = $1 AND order_id = $2'; - db.query(query, [projectId, orderId], (err, results) => { - if (err) { - return serverError.sendError('Error getting image:', res, err, 500); - } - if (results.rows.length === 0) { - return res.status(404).json({ error: 'Image not found' }); - } - const imagePath = results.rows[0].path; - fs.access(imagePath, fs.constants.F_OK, (err) => { - if (err) { - console.error('Image not found:', err); - return res.status(404).json({ error: 'Image not found' }); - } - res.download(imagePath); - }); - }); -}); - - -router.get('/images/:measurementId', (req, res) => { - const measurementId = req.params.measurementId; - const query = 'SELECT path FROM public.measurements WHERE id = $1'; - db.query(query, [measurementId], (err, results) => { - if (err) { - return serverError.sendError('Error getting image:', res, err, 500); - } - if (results.rows.length === 0) { - return res.status(404).json({ error: 'Image not found' }); - } - const imagePath = results.rows[0].path; - fs.access(imagePath, fs.constants.F_OK, (err) => { - if (err) { - console.error('Image not found:', err); - return res.status(404).json({ error: 'Image not found' }); - } - res.download(imagePath); - }); - }); -}); - -const getImagePath = async (projectId, orderId) => { - const query = 'SELECT path FROM public.measurements WHERE project_id = $1 AND order_id = $2'; - const result = await db.query(query, [projectId, orderId]); - if (result.rows.length === 0) { - throw new Error('Image not found'); - } - return result.rows[0].path; -}; - -const checkImageExists = (imagePath) => { - return new Promise((resolve, reject) => { - fs.access(imagePath, fs.constants.F_OK, (err) => { - if (err) { - reject(new Error('Image not found')); - } else { - resolve(); - } - }); - }); -}; - -const resizeImage = async (imagePath) => { - const metadata = await sharp(imagePath).metadata(); - const width = Math.floor(metadata.width / 7); - const height = Math.floor(metadata.height / 7); - return sharp(imagePath) - .resize(width, height) - .jpeg({ quality: 65 }) - .toBuffer(); -}; - -router.get('/preview/:projectId/:orderId', async (req, res) => { - const projectId = req.params.projectId; - const orderId = req.params.orderId; - - try { - const imagePath = await getImagePath(projectId, orderId); - await checkImageExists(imagePath); - const resizedImage = await resizeImage(imagePath); - - res.set('Content-Type', 'image/jpeg'); - res.send(resizedImage); - } catch (err) { - console.error('Error getting image preview:', err); - if (err.message === 'Image not found') { - return res.status(404).json({ error: 'Image not found' }); - } - return res.status(500).json({ error: 'Internal Server Error' }); - } -}); - -module.exports = router; diff --git a/routes/measurementRoutes.js b/routes/measurementRoutes.js deleted file mode 100644 index 13b9f8e..0000000 --- a/routes/measurementRoutes.js +++ /dev/null @@ -1,45 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const database_manager = require('../src/database/database_manager'); - -router.get('/measurements', async (req, res) => { - const measurements = await database_manager.measurement.get_all_measurements(); - if (!measurements) { - return res.status(404).json({ error: 'No measurements found' }); - } - res.json(measurements); -}); - -router.get('/measurements/:id', async (req, res) => { - const measurement = await database_manager.measurement.get_measurement_by_id(req.params.id); - if (!measurement) { - return res.status(404).json({ error: 'Measurement not found' }); - } - res.json(measurement); -}); - -router.get('/measurements/:projectId/:orderId', async (req, res) => { - const measurement = await database_manager.measurement.get_measurement_by_project_and_order_id(req.params.projectId, req.params.orderId); - if (!measurement) { - return res.status(404).json({ error: 'Measurement not found' }); - } - res.json(measurement); -}); - -router.delete('/measurements/:id', async (req, res) => { - const measurement = await database_manager.measurement.delete_measurement_by_id(req.params.id); - if (!measurement) { - return res.status(404).json({ error: 'Measurement not found' }); - } - res.json({ message: 'Measurement deleted successfully', id: measurement.id }); -}); - -router.delete('/measurements/:projectId/:orderId', async (req, res) => { - const measurement = await database_manager.measurement.delete_measurement_by_project_and_order_id(req.params.projectId, req.params.orderId); - if (!measurement) { - return res.status(404).json({ error: 'Measurement not found' }); - } - res.json({ message: 'Measurement deleted successfully', id: measurement.id }); -}); - -module.exports = router; diff --git a/routes/projectRoutes.js b/routes/projectRoutes.js deleted file mode 100644 index f646186..0000000 --- a/routes/projectRoutes.js +++ /dev/null @@ -1,91 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const serverError = require('../utils/serverError'); -const database_manager = require('../src/database/database_manager'); -const storage_manager = require('../src/data/storage_manager'); - -router.get('/projects', async (req, res) => { - try { - const projects = await database_manager.project.get_all_projects(); - res.json(projects); - } catch (error) { - serverError.sendError('Error getting all projects:', res, error, 500); - } -}); - -router.get('/projects/:id', async (req, res) => { - const projectId = req.params.id; - if (!projectId || isNaN(projectId)) { - return res.status(400).json({ error: 'Invalid project ID' }); - } - try { - const project = await database_manager.project.get_project_by_id(projectId); - res.json(project); - } catch (error) { - serverError.sendError('Error getting project by ID:', res, error, 500); - } -}); - -router.get('/projects/:id/videos', async (req, res) => { - const projectId = req.params.id; - if (!projectId || isNaN(projectId)) { - return res.status(400).json({ error: 'Invalid project ID' }); - } - try { - const videos = await database_manager.video.get_videos_by_project_id(projectId); - if (videos.length === 0) { - return res.status(404).json({ error: 'No videos found for this project' }); - } - res.json(videos); - } catch (error) { - serverError.sendError('Error getting videos by project ID:', res, error, 500); - } -}); - -router.get('/projects/:id/measurements', async (req, res) => { - const projectId = req.params.id; - if (!projectId || isNaN(projectId)) { - return res.status(400).json({ error: 'Invalid project ID' }); - } - try { - const measurements = await database_manager.measurement.get_measurements_by_project_id(projectId); - if (measurements.length === 0) { - return res.status(404).json({ error: 'No measurements found for this project' }); - } - res.json(measurements); - } catch (error) { - serverError.sendError('Error getting measurements by project ID:', res, error, 500); - } -}); - -router.post('/projects', async (req, res) => { - const { name, description } = req.body; - if (!name || !description) { - return res.status(400).json({ error: 'Name and description are required' }); - } - try { - const date = new Date(); - const default_status = 0; - const project = await database_manager.project.create_project(name, description, date, default_status); - storage_manager.project.createProjectDirectory(project.id); - res.status(201).json({ message: 'Project added successfully', id: project.id }); - } catch (error) { - serverError.sendError('Error creating project:', res, error, 500); - } -}); - -router.delete('/projects/:id', async (req, res) => { - const projectId = req.params.id; - if (!projectId || isNaN(projectId)) { - return res.status(400).json({ error: 'Invalid project ID' }); - } - try { - storage_manager.project.deleteProjectDirectory(projectId); - await database_manager.project.delete_project_by_id(projectId); - res.status(200).json({ message: 'Project deleted successfully', id: projectId }); - } catch (error) { - serverError.sendError('Error deleting project:', res, error, 500); - } -}); - -module.exports = router; diff --git a/routes/uploadRoutes.js b/routes/uploadRoutes.js deleted file mode 100644 index a6c2ee3..0000000 --- a/routes/uploadRoutes.js +++ /dev/null @@ -1,96 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const multer = require('multer'); -const database_manager = require('../src/database/database_manager'); -const storage_manager = require('../src/data/storage_manager'); -const serverError = require('../utils/serverError'); - -const upload = multer({ storage: multer.memoryStorage() }); - -/** - * @swagger - * /camera/upload: - * post: - * summary: Télécharger une mesure avec une image - * description: Télécharge une mesure avec une image pour un projet spécifique. - * requestBody: - * content: - * multipart/form-data: - * schema: - * type: object - * properties: - * image: - * type: string - * format: binary - * description: Fichier image à télécharger - * projectId: - * type: integer - * description: ID du projet - * timestamp: - * type: string - * format: date-time - * description: Horodatage de la mesure - * temperature: - * type: number - * description: Température mesurée - * humidity: - * type: number - * description: Humidité mesurée - * responses: - * 200: - * description: Mesure téléchargée avec succès. - * content: - * application/json: - * schema: - * type: object - * properties: - * message: - * type: string - * path: - * type: string - * id: - * type: integer - * 400: - * description: Tous les champs sont requis. - * 500: - * description: Erreur serveur. - */ -router.post('/camera/upload', upload.single('image'), async (req, res) => { - //afficher le body de la requête - console.log(req.body); - const { projectId, timestamp, temperature, humidity } = req.body; - const image = req.file; - - if (!image || !projectId || !timestamp || !temperature || !humidity) { - return res.status(400).json({ error: 'All fields are required' }); - } - - try { - const nextOrderId = await database_manager.measurement.get_next_order_id(projectId); - if (nextOrderId === null) { - return res.status(404).json({ error: 'Project not found' }); - } - - // Log types for debugging - console.log('Types:', { - image: typeof image, - projectId: typeof projectId, - nextOrderId: typeof nextOrderId - }); - - const imagePath = await storage_manager.measurement.upload_measurement_image(image, projectId, nextOrderId); - if (!imagePath) { - return res.status(500).json({ error: 'Failed to upload image' }); - } - const measurement = await database_manager.measurement.create_measurement(projectId, timestamp, imagePath, temperature, humidity, nextOrderId); - if (!measurement) { - return res.status(500).json({ error: 'Failed to create measurement' }); - } - res.json({ message: 'Measurement uploaded successfully', path: imagePath, id: measurement.id }); - } catch (error) { - serverError.sendError('Error uploading measurement:', res, error, 500); - } -}); - - -module.exports = router; diff --git a/routes/videoRoutes.js b/routes/videoRoutes.js deleted file mode 100644 index 022fccb..0000000 --- a/routes/videoRoutes.js +++ /dev/null @@ -1,271 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const db = require('../db'); -const fs = require('fs'); -const rangeParser = require('range-parser'); -const serverError = require('../utils/serverError'); -const videoManager = require('../src/video/videoManager'); -const database_manager = require('../src/database/database_manager'); -const storage_manager = require('../src/data/storage_manager'); -const dbTester = require('../test/tester'); - -router.get('/videos', (req, res) => { - const query = 'SELECT * FROM public.videos'; - db.query(query, (err, results) => { - if (err) { - serverError.sendError('Erreur lors de la récupération des vidéos:', res, err, 500); - } - res.json(results.rows); - }); -}); - -router.get('/videos/:id', (req, res) => { - const videoId = req.params.id; - if (!videoId || isNaN(videoId)) { - return res.status(400).json({ error: 'Invalid video ID' }); - } - const query = 'SELECT * FROM public.videos WHERE id = $1'; - db.query(query, [videoId], (err, results) => { - if (err) { - serverError.sendError('Erreur lors de la récupération de la vidéo:', res, err, 500); - } - res.json(results.rows); - }); -}); - -router.post('/videos', async (req, res) => { - const { project_id, measurement_ids, name, resolution, duration } = req.body; - console.log('Creating video:', req.body); - if (!project_id || !measurement_ids || !name || !resolution || !duration) { - return res.status(400).json({ error: 'Tous les champs sont requis.' }); - } - - console.log('Creating video with measurements:', measurement_ids); - - try { - const query = await database_manager.video.create_video(project_id, measurement_ids, name, resolution, duration); - const videoId = query.id; - if (!videoId) { - return res.status(500).json({ error: 'Erreur lors de la création de la vidéo' }); - } - console.log('Vidéo créée avec succès:', videoId); - - // Start rendering the video immediately after creation - // const result = await db.query( - // 'SELECT measurement_ids, project_id, duration FROM public.videos WHERE id = $1', - // [videoId] - // ); - - // if (result.rows.length === 0) { - // return res.status(404).json({ error: 'Vidéo non trouvée' }); - // } - - // récupérer les informations de la vidéo - const result = await database_manager.video.get_video_by_id(videoId); - - if (!result) { - return res.status(404).json({ error: 'Vidéo non trouvée' }); - } - - const videoDuration = result.duration; - const videoMeasurementIds = result.measurement_ids; - const videoProjectId = result.project_id; - - const pathList = await storage_manager.measurement.get_path_list(videoMeasurementIds, project_id); - if (!pathList || pathList.length === 0) { - return res.status(404).json({ error: 'Aucun chemin trouvé pour les mesures' }); - } - - // parser la résolution (ex: 1920x1080) - const [res_width, res_height] = resolution.split('x').map(Number); - if (isNaN(res_width) || isNaN(res_height)) { - return res.status(400).json({ error: 'Invalid resolution format. Use WIDTHxHEIGHT (e.g., 1920x1080)' }); - } - - // Start background processing - videoManager.createVideoWithList(videoProjectId, pathList, videoDuration, videoId, res_width, res_height) - .then(videoFile => { - console.log('Rendu vidéo terminé:', videoFile); - return database_manager.video.update_video_file_path_by_id(videoId, videoFile); - }) - .catch(error => { - console.error('Échec du rendu vidéo:', error); - }); - - // Immediate response - res.json({ - message: 'Vidéo créée avec succès et le rendu a démarré', - id: videoId - }); - - } catch (err) { - console.error('Erreur lors de la création de la vidéo:', err); - res.status(500).json({ error: 'Erreur lors de la création de la vidéo' }); - } -}); - - -router.delete('/videos/:id', (req, res) => { - const videoId = req.params.id; - if (!videoId || isNaN(videoId)) { - return res.status(400).json({ error: 'Invalid video ID' }); - } - - const query = 'SELECT video_file FROM public.videos WHERE id = $1'; - db.query(query, [videoId], (err, results) => { - if (err) { - return serverError.sendError('Error getting video:', res, err, 500); - } - if (results.rows.length === 0) { - return res.status(404).json({ error: 'Video not found' }); - } - - const videoFile = results.rows[0].video_file; - console.log('Deleting video file:', videoFile); - - if(videoFile==null){ - console.log('No video file to delete'); - database_manager.video.delete_video_by_id(videoId).then(() => { - res.json({ message: 'Vidéo supprimée avec succès' }); - }).catch(err => { - console.error('Erreur lors de la suppression de la vidéo:', err); - res.status(500).json({ error: 'Erreur lors de la suppression de la vidéo' }); - }); - - } else { - fs.unlink(videoFile, (err) => { - if (err) { - console.error('Error deleting video file:', err); - return res.status(500).json({ error: 'Error deleting video file' }); - } - database_manager.video.delete_video_by_id(videoId).then(() => { - res.json({ message: 'Vidéo supprimée avec succès' }); - }).catch(err => { - console.error('Erreur lors de la suppression de la vidéo:', err); - res.status(500).json({ error: 'Erreur lors de la suppression de la vidéo' }); - }); - }); - } - }); -}); - -router.get('/videos/file/:video_id', (req, res) => { - const videoId = req.params.video_id; - const query = 'SELECT video_file, status FROM public.videos WHERE id = $1'; - - db.query(query, [videoId], (err, results) => { - if (err) { - console.error('Error getting video:', err); - return serveFallbackVideo(res); - } - if (results.rows.length === 0) { - console.error('Video not found'); - return serveFallbackVideo(res); - } - - const video = results.rows[0]; - if (video.status === 0) { - return res.status(400).json({ error: 'Video not yet produced' }); - } - - let videoPath = video.video_file; - - if (!videoPath) { - console.error('Video file path is null or undefined'); - videoPath = dbTester.getCatVideo(); - } - - // Check if the video file exists - fs.access(videoPath, fs.constants.F_OK, (err) => { - if (err) { - console.error('Video file not found:', err); - videoPath = dbTester.getCatVideo(); - } - - const stat = fs.statSync(videoPath); - const fileSize = stat.size; - const range = req.headers.range; - - if (range) { - const parts = rangeParser(fileSize, range); - const start = parts[0].start; - const end = parts[0].end; - const chunksize = (end - start) + 1; - const file = fs.createReadStream(videoPath, { start, end }); - const head = { - 'Content-Range': `bytes ${start}-${end}/${fileSize}`, - 'Accept-Ranges': 'bytes', - 'Content-Length': chunksize, - 'Content-Type': 'video/mp4', - }; - res.writeHead(206, head); - file.pipe(res); - } else { - const head = { - 'Content-Length': fileSize, - 'Content-Type': 'video/mp4', - }; - res.writeHead(200, head); - fs.createReadStream(videoPath).pipe(res); - } - }); - }); -}); - -function serveFallbackVideo() { - return dbTester.getCatVideo(); -} - -router.get('/videos/progress/:video_id', async (req, res) => { - try { - const result = await db.query(` - SELECT - progress, - EXTRACT(EPOCH FROM (NOW() - started_at)) as elapsed, - eta, - status - FROM public.videos - WHERE id = $1 - `, [req.params.video_id]); - - if (result.rows.length === 0) { - return res.status(404).json({ error: 'Vidéo non trouvée' }); - } - - const video = result.rows[0]; - res.json({ - progress: video.progress, - elapsed: video.elapsed, - eta: video.eta, - status: this.getStatusLabel(video.status) - }); - - } catch (error) { - console.error(error); - res.status(500).json({ error: 'Erreur de récupération' }); - } -}); - -// function getStatusLabel(status) { -// const statusMap = { -// 0: 'En attente', -// 1: 'Terminé', -// 2: 'Échec', -// 3: 'En cours' -// }; -// return statusMap[status] || 'Inconnu'; -// } - - -router.get('/cat', (_, res) => { - const videoPath = dbTester.getCatVideo(); - fs.access(videoPath, fs.constants.F_OK, (err) => { - if (err) { - console.error('Video not found:', err); - return res.status(404).json({ error: 'Video not found' }); - } - res.download(videoPath); - }); -}); - -module.exports = router;