From 5919794408c3dc08e96eddcf1f1189289d2e9a21 Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Thu, 28 Aug 2025 11:40:04 +0200 Subject: [PATCH] Fix jwt-token --- server/routes/detections.js | 21 +++- server/routes/detectors.js | 7 +- server/routes/droneTypes.js | 160 +++++++++++++++++++++++ server/routes/index.js | 3 + server/services/alertService.js | 34 +++-- server/utils/droneTypes.js | 217 ++++++++++++++++++++++++++++++++ 6 files changed, 421 insertions(+), 21 deletions(-) create mode 100644 server/routes/droneTypes.js create mode 100644 server/utils/droneTypes.js diff --git a/server/routes/detections.js b/server/routes/detections.js index 72730c8..e168303 100644 --- a/server/routes/detections.js +++ b/server/routes/detections.js @@ -2,6 +2,7 @@ const express = require('express'); const DroneDetection = require('../models/DroneDetection'); const Device = require('../models/Device'); const { authenticateToken } = require('../middleware/auth'); +const { getDroneTypeInfo } = require('../utils/droneTypes'); const router = express.Router(); /** @@ -66,8 +67,17 @@ router.get('/', authenticateToken, async (req, res) => { const hasNextPage = parseInt(page) < totalPages; const hasPrevPage = parseInt(page) > 1; + // Enhance detections with drone type information + const enhancedDetections = detections.map(detection => { + const droneTypeInfo = getDroneTypeInfo(detection.drone_type); + return { + ...detection.toJSON(), + drone_type_info: droneTypeInfo + }; + }); + res.json({ - detections, + detections: enhancedDetections, pagination: { currentPage: parseInt(page), totalPages, @@ -107,7 +117,14 @@ router.get('/:id', authenticateToken, async (req, res) => { return res.status(404).json({ error: 'Detection not found' }); } - res.json(detection); + // Enhance detection with drone type information + const droneTypeInfo = getDroneTypeInfo(detection.drone_type); + const enhancedDetection = { + ...detection.toJSON(), + drone_type_info: droneTypeInfo + }; + + res.json(enhancedDetection); } catch (error) { console.error('Error fetching detection:', error); diff --git a/server/routes/detectors.js b/server/routes/detectors.js index 55a4957..c72e2c5 100644 --- a/server/routes/detectors.js +++ b/server/routes/detectors.js @@ -5,6 +5,7 @@ const { validateRequest } = require('../middleware/validation'); const { Heartbeat, Device, DroneDetection } = require('../models'); const AlertService = require('../services/alertService'); const DroneTrackingService = require('../services/droneTrackingService'); +const { getDroneTypeInfo, getDroneTypeName } = require('../utils/droneTypes'); // Initialize services const alertService = new AlertService(); @@ -191,7 +192,11 @@ async function handleHeartbeat(req, res) { async function handleDetection(req, res) { const detectionData = req.body; - console.log(`🚁 Drone detection received from device ${detectionData.device_id}: drone_id=${detectionData.drone_id}, type=${detectionData.drone_type}, rssi=${detectionData.rssi}`); + // Get drone type information + const droneTypeInfo = getDroneTypeInfo(detectionData.drone_type); + + console.log(`🚁 Drone detection received from device ${detectionData.device_id}: drone_id=${detectionData.drone_id}, type=${detectionData.drone_type} (${droneTypeInfo.name}), rssi=${detectionData.rssi}`); + console.log(`🎯 Drone Type Details: ${droneTypeInfo.category} | Threat: ${droneTypeInfo.threat_level} | ${droneTypeInfo.description}`); console.log('🔍 Complete detection data:', JSON.stringify(detectionData, null, 2)); // Check if device exists and is approved diff --git a/server/routes/droneTypes.js b/server/routes/droneTypes.js new file mode 100644 index 0000000..9128bf9 --- /dev/null +++ b/server/routes/droneTypes.js @@ -0,0 +1,160 @@ +const express = require('express'); +const router = express.Router(); +const { + getAllDroneTypes, + getDroneTypesByCategory, + getDroneTypesByThreatLevel, + getDroneTypeInfo +} = require('../utils/droneTypes'); + +/** + * GET /api/drone-types + * Get all available drone types + */ +router.get('/', (req, res) => { + try { + const droneTypes = getAllDroneTypes(); + + // Convert to array format with IDs + const droneTypesArray = Object.entries(droneTypes).map(([id, info]) => ({ + id: parseInt(id), + ...info + })); + + res.json({ + success: true, + data: droneTypesArray, + total: droneTypesArray.length + }); + } catch (error) { + console.error('Error fetching drone types:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone types', + details: error.message + }); + } +}); + +/** + * GET /api/drone-types/:id + * Get specific drone type by ID + */ +router.get('/:id', (req, res) => { + try { + const { id } = req.params; + const droneTypeInfo = getDroneTypeInfo(parseInt(id)); + + res.json({ + success: true, + data: droneTypeInfo + }); + } catch (error) { + console.error('Error fetching drone type:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone type', + details: error.message + }); + } +}); + +/** + * GET /api/drone-types/category/:category + * Get drone types by category + */ +router.get('/category/:category', (req, res) => { + try { + const { category } = req.params; + const droneTypes = getDroneTypesByCategory(category); + + res.json({ + success: true, + data: droneTypes, + category: category, + total: droneTypes.length + }); + } catch (error) { + console.error('Error fetching drone types by category:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone types by category', + details: error.message + }); + } +}); + +/** + * GET /api/drone-types/threat/:threatLevel + * Get drone types by threat level + */ +router.get('/threat/:threatLevel', (req, res) => { + try { + const { threatLevel } = req.params; + const droneTypes = getDroneTypesByThreatLevel(threatLevel); + + res.json({ + success: true, + data: droneTypes, + threat_level: threatLevel, + total: droneTypes.length + }); + } catch (error) { + console.error('Error fetching drone types by threat level:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone types by threat level', + details: error.message + }); + } +}); + +/** + * GET /api/drone-types/categories + * Get all available categories + */ +router.get('/meta/categories', (req, res) => { + try { + const droneTypes = getAllDroneTypes(); + const categories = [...new Set(Object.values(droneTypes).map(type => type.category))]; + + res.json({ + success: true, + data: categories, + total: categories.length + }); + } catch (error) { + console.error('Error fetching drone type categories:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone type categories', + details: error.message + }); + } +}); + +/** + * GET /api/drone-types/threat-levels + * Get all available threat levels + */ +router.get('/meta/threat-levels', (req, res) => { + try { + const droneTypes = getAllDroneTypes(); + const threatLevels = [...new Set(Object.values(droneTypes).map(type => type.threat_level))]; + + res.json({ + success: true, + data: threatLevels, + total: threatLevels.length + }); + } catch (error) { + console.error('Error fetching drone type threat levels:', error); + res.status(500).json({ + success: false, + error: 'Failed to fetch drone type threat levels', + details: error.message + }); + } +}); + +module.exports = router; diff --git a/server/routes/index.js b/server/routes/index.js index 7114146..1a93ecc 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -10,6 +10,7 @@ const healthRoutes = require('./health'); const debugRoutes = require('./debug'); const detectorsRoutes = require('./detectors'); const detectionsRoutes = require('./detections'); +const droneTypesRoutes = require('./droneTypes'); // API versioning router.use('/v1/devices', deviceRoutes); @@ -19,6 +20,7 @@ router.use('/v1/dashboard', dashboardRoutes); router.use('/v1/health', healthRoutes); router.use('/v1/detectors', detectorsRoutes); router.use('/v1/detections', detectionsRoutes); +router.use('/v1/drone-types', droneTypesRoutes); // Default routes (no version prefix for backward compatibility) router.use('/devices', deviceRoutes); @@ -29,6 +31,7 @@ router.use('/health', healthRoutes); router.use('/debug', debugRoutes); router.use('/detectors', detectorsRoutes); router.use('/detections', detectionsRoutes); +router.use('/drone-types', droneTypesRoutes); // API documentation endpoint router.get('/', (req, res) => { diff --git a/server/services/alertService.js b/server/services/alertService.js index 07db392..7c16482 100644 --- a/server/services/alertService.js +++ b/server/services/alertService.js @@ -1,6 +1,7 @@ const twilio = require('twilio'); const { AlertRule, AlertLog, User, Device, DroneDetection } = require('../models'); const { Op } = require('sequelize'); +const { getDroneTypeInfo } = require('../utils/droneTypes'); class AlertService { constructor() { @@ -56,33 +57,28 @@ class AlertService { actionRequired = false; } - // Adjust threat level based on drone type (if classified) - const droneTypes = { - 0: 'Consumer/Hobby', - 1: 'Orlan/Military', // Orlan drones - highest threat - 2: 'Professional/Commercial', - 3: 'Racing/High-speed', - 4: 'Unknown/Custom' - }; + // Get drone type information using our comprehensive mapping + const droneTypeInfo = getDroneTypeInfo(droneType); - // CRITICAL: Orlan drones (type 1) - ALWAYS CRITICAL regardless of distance - if (droneType === 1) { + // Adjust threat level based on drone type and category + if (droneTypeInfo.threat_level === 'critical' || droneTypeInfo.category.includes('Military')) { + // Military/Combat drones - ALWAYS CRITICAL regardless of distance threatLevel = 'critical'; - description = 'CRITICAL THREAT: ORLAN MILITARY DRONE DETECTED - IMMEDIATE RESPONSE REQUIRED'; + description = `CRITICAL THREAT: ${droneTypeInfo.name.toUpperCase()} DETECTED - IMMEDIATE RESPONSE REQUIRED`; actionRequired = true; - console.log(`🚨 ORLAN DRONE DETECTED - Force escalating to CRITICAL threat level (RSSI: ${rssi})`); - } else if (droneType === 2) { - // Professional/Commercial drone - escalate threat + console.log(`🚨 MILITARY DRONE DETECTED: ${droneTypeInfo.name} - Force escalating to CRITICAL threat level (RSSI: ${rssi})`); + } else if (droneTypeInfo.threat_level === 'high' || droneTypeInfo.category.includes('Professional')) { + // Professional/Commercial drone - escalate threat one level if (threatLevel === 'low') threatLevel = 'medium'; if (threatLevel === 'medium') threatLevel = 'high'; if (threatLevel === 'high') threatLevel = 'critical'; - description += ' - PROFESSIONAL/COMMERCIAL DRONE DETECTED'; + description += ` - ${droneTypeInfo.name.toUpperCase()} DETECTED`; actionRequired = true; - } else if (droneType === 3) { + } else if (droneTypeInfo.category.includes('Racing')) { // Racing/Fast drone - escalate if close if (rssi >= -55 && threatLevel !== 'critical') { threatLevel = 'high'; - description += ' - HIGH-SPEED DRONE DETECTED'; + description += ` - HIGH-SPEED ${droneTypeInfo.name.toUpperCase()} DETECTED`; actionRequired = true; } } @@ -91,7 +87,9 @@ class AlertService { level: threatLevel, estimatedDistance: Math.round(estimatedDistance), rssi, - droneType: droneTypes[droneType] || 'Unknown', + droneType: droneTypeInfo.name, + droneCategory: droneTypeInfo.category, + threatLevel: droneTypeInfo.threat_level, description, requiresImmediateAction: actionRequired, priority: threatLevel === 'critical' ? 1 : threatLevel === 'high' ? 2 : threatLevel === 'medium' ? 3 : 4 diff --git a/server/utils/droneTypes.js b/server/utils/droneTypes.js new file mode 100644 index 0000000..25389bf --- /dev/null +++ b/server/utils/droneTypes.js @@ -0,0 +1,217 @@ +/** + * Drone Type Mappings + * Maps integer drone_type values to human-readable names and categories + */ + +const DRONE_TYPES = { + // Military/Combat Drones + 0: { + name: "Russian Orlan", + category: "Military/Reconnaissance", + threat_level: "high", + description: "Russian military reconnaissance drone" + }, + 1: { + name: "Bayraktar TB2", + category: "Military/Combat", + threat_level: "critical", + description: "Turkish military combat drone" + }, + 2: { + name: "MQ-9 Reaper", + category: "Military/Combat", + threat_level: "critical", + description: "US military combat drone" + }, + 3: { + name: "Iranian Shahed", + category: "Military/Kamikaze", + threat_level: "critical", + description: "Iranian kamikaze/suicide drone" + }, + 4: { + name: "Chinese Wing Loong", + category: "Military/Combat", + threat_level: "critical", + description: "Chinese military combat drone" + }, + 5: { + name: "Israeli Hermes", + category: "Military/Reconnaissance", + threat_level: "high", + description: "Israeli military reconnaissance drone" + }, + + // Commercial/Professional Drones + 10: { + name: "DJI Mavic", + category: "Commercial/Professional", + threat_level: "medium", + description: "DJI professional quadcopter" + }, + 11: { + name: "DJI Phantom", + category: "Commercial/Professional", + threat_level: "medium", + description: "DJI professional quadcopter" + }, + 12: { + name: "DJI Inspire", + category: "Commercial/Professional", + threat_level: "medium", + description: "DJI professional cinematography drone" + }, + 13: { + name: "Autel EVO", + category: "Commercial/Professional", + threat_level: "medium", + description: "Autel professional quadcopter" + }, + 14: { + name: "Parrot Anafi", + category: "Commercial/Professional", + threat_level: "medium", + description: "Parrot professional quadcopter" + }, + + // Consumer/Hobby Drones + 20: { + name: "DJI Mini", + category: "Consumer/Hobby", + threat_level: "low", + description: "DJI consumer mini drone" + }, + 21: { + name: "DJI Spark", + category: "Consumer/Hobby", + threat_level: "low", + description: "DJI consumer compact drone" + }, + 22: { + name: "Ryze Tello", + category: "Consumer/Hobby", + threat_level: "low", + description: "Consumer toy/education drone" + }, + 23: { + name: "Holy Stone", + category: "Consumer/Hobby", + threat_level: "low", + description: "Consumer hobby quadcopter" + }, + 24: { + name: "Syma X5C", + category: "Consumer/Hobby", + threat_level: "low", + description: "Consumer toy quadcopter" + }, + + // Racing/FPV Drones + 30: { + name: "Racing Quadcopter", + category: "Racing/FPV", + threat_level: "low", + description: "Custom racing/FPV quadcopter" + }, + 31: { + name: "TinyHawk", + category: "Racing/FPV", + threat_level: "low", + description: "Micro racing quadcopter" + }, + + // Fixed-Wing Drones + 40: { + name: "Fixed-Wing Surveillance", + category: "Fixed-Wing/Surveillance", + threat_level: "medium", + description: "Fixed-wing surveillance aircraft" + }, + 41: { + name: "Fixed-Wing Cargo", + category: "Fixed-Wing/Commercial", + threat_level: "medium", + description: "Fixed-wing cargo/delivery aircraft" + }, + + // Unknown/Unclassified + 99: { + name: "Unknown Drone", + category: "Unknown/Unclassified", + threat_level: "medium", + description: "Unidentified or unclassified drone" + } +}; + +/** + * Get drone type information by ID + * @param {number} droneTypeId - The integer drone type ID + * @returns {object} Drone type information or default for unknown types + */ +function getDroneTypeInfo(droneTypeId) { + const typeInfo = DRONE_TYPES[droneTypeId]; + + if (typeInfo) { + return { + id: droneTypeId, + ...typeInfo + }; + } + + // Return default for unknown types + return { + id: droneTypeId, + name: `Unknown Type ${droneTypeId}`, + category: "Unknown/Unclassified", + threat_level: "medium", + description: `Unrecognized drone type ID: ${droneTypeId}` + }; +} + +/** + * Get just the drone name by ID + * @param {number} droneTypeId - The integer drone type ID + * @returns {string} Drone name + */ +function getDroneTypeName(droneTypeId) { + return getDroneTypeInfo(droneTypeId).name; +} + +/** + * Get all available drone types + * @returns {object} All drone type mappings + */ +function getAllDroneTypes() { + return DRONE_TYPES; +} + +/** + * Get drone types by category + * @param {string} category - The category to filter by + * @returns {array} Array of drone types in the category + */ +function getDroneTypesByCategory(category) { + return Object.entries(DRONE_TYPES) + .filter(([id, info]) => info.category === category) + .map(([id, info]) => ({ id: parseInt(id), ...info })); +} + +/** + * Get drone types by threat level + * @param {string} threatLevel - The threat level to filter by + * @returns {array} Array of drone types with the threat level + */ +function getDroneTypesByThreatLevel(threatLevel) { + return Object.entries(DRONE_TYPES) + .filter(([id, info]) => info.threat_level === threatLevel) + .map(([id, info]) => ({ id: parseInt(id), ...info })); +} + +module.exports = { + DRONE_TYPES, + getDroneTypeInfo, + getDroneTypeName, + getAllDroneTypes, + getDroneTypesByCategory, + getDroneTypesByThreatLevel +};