Fix jwt-token

This commit is contained in:
2025-09-17 22:43:44 +02:00
parent 43b548c05a
commit 6d66d8d772
8 changed files with 289 additions and 49 deletions

View File

@@ -65,16 +65,20 @@ class AlertService {
// Adjust threat level based on drone type and category
if (droneTypeInfo.category.includes('Military') && droneTypeInfo.name !== 'Unknown') {
// Special handling for known military drones at very far distances
// If it's a recognized military drone at long range, escalate to critical
if (rssi < -80 && (droneTypeInfo.name === 'Orlan' || droneTypeInfo.name === 'Zala' || droneTypeInfo.name === 'Eleron')) {
threatLevel = 'critical';
description = `CRITICAL THREAT: ${droneTypeInfo.name.toUpperCase()} DETECTED - IMMEDIATE RESPONSE REQUIRED`;
actionRequired = true;
console.log(`🚨 MILITARY DRONE DETECTED: ${droneTypeInfo.name} - Force escalating to CRITICAL at long range (RSSI: ${rssi})`);
// Special handling for known military drones - only escalate if not at extreme distance
if (rssi >= -85 && (droneTypeInfo.name === 'Orlan' || droneTypeInfo.name === 'Zala' || droneTypeInfo.name === 'Eleron')) {
// Military drones within reasonable detection range get escalated
if (distanceBasedThreat === 'monitoring') threatLevel = 'low';
else if (distanceBasedThreat === 'low') threatLevel = 'medium';
else if (distanceBasedThreat === 'medium') threatLevel = 'high';
else if (distanceBasedThreat === 'high') threatLevel = 'critical';
description = `MILITARY THREAT: ${droneTypeInfo.name.toUpperCase()} DETECTED - ENHANCED RESPONSE REQUIRED`;
actionRequired = (threatLevel !== 'low' && threatLevel !== 'monitoring');
console.log(`🚨 MILITARY DRONE DETECTED: ${droneTypeInfo.name} - Escalated to ${threatLevel} (RSSI: ${rssi})`);
} else {
// For closer military drones, preserve distance-based assessment but add annotation
description += ` - ${droneTypeInfo.name.toUpperCase()} MILITARY DRONE DETECTED`;
// For very distant military drones (RSSI < -85), preserve distance-based assessment
description += ` - ${droneTypeInfo.name.toUpperCase()} MILITARY DRONE DETECTED (DISTANT)`;
console.log(`🚨 MILITARY DRONE DETECTED: ${droneTypeInfo.name} - Using distance-based threat level: ${threatLevel} (RSSI: ${rssi})`);
}
} else if (droneTypeInfo.threat_level === 'high' || droneTypeInfo.category.includes('Professional')) {
@@ -752,7 +756,13 @@ class AlertService {
}
if (shouldTrigger) {
triggeredAlerts.push(rule);
triggeredAlerts.push({
rule_id: rule.id,
rule_name: rule.name,
rule: rule,
detection: detection,
triggered_at: new Date()
});
}
}

View File

@@ -4,6 +4,7 @@ class DroneTrackingService extends EventEmitter {
constructor() {
super();
this.droneHistory = new Map(); // Map of drone_id -> detection history
this.activeDrones = new Map(); // Map of drone_id -> current tracking data (for tests)
this.droneProximityAlerts = new Map(); // Map of drone_id -> current status
this.proximityThresholds = {
VERY_CLOSE: -40, // < -40dBm
@@ -17,6 +18,42 @@ class DroneTrackingService extends EventEmitter {
setInterval(() => this.cleanupOldHistory(), 30 * 60 * 1000);
}
// Add method expected by tests
trackDetection(detection) {
const droneId = detection.drone_id;
// Update activeDrones map for test compatibility
const currentTracking = this.activeDrones.get(droneId) || {
droneId: droneId,
currentPosition: { lat: 0, lon: 0 },
lastSeen: null,
detectionHistory: []
};
// Update current position
if (detection.geo_lat && detection.geo_lon) {
currentTracking.currentPosition.lat = detection.geo_lat;
currentTracking.currentPosition.lon = detection.geo_lon;
}
currentTracking.lastSeen = new Date();
currentTracking.detectionHistory.push({
timestamp: new Date(),
rssi: detection.rssi,
position: { lat: detection.geo_lat, lon: detection.geo_lon }
});
// Keep only last 50 detections
if (currentTracking.detectionHistory.length > 50) {
currentTracking.detectionHistory.splice(0, currentTracking.detectionHistory.length - 50);
}
this.activeDrones.set(droneId, currentTracking);
// Also call the original processing method
return this.processDetection(detection);
}
processDetection(detection) {
const droneId = detection.drone_id;
const deviceId = detection.device_id;
@@ -209,7 +246,7 @@ class DroneTrackingService extends EventEmitter {
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(this.toRad(lat1)) * Math.cos(this.toRad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
return 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) * R;
return 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) * R * 1000; // Return in meters
}
toRad(deg) {
@@ -281,22 +318,168 @@ class DroneTrackingService extends EventEmitter {
return activeTracking;
}
/**
* Track a new detection (alias for processDetection)
* @param {Object} detection - The drone detection to track
* @returns {Object} - Tracking result
*/
trackDetection(detection) {
return this.processDetection(detection);
}
/**
* Clear all tracking data
*/
clear() {
this.droneHistory.clear();
this.activeDrones.clear();
this.droneProximityAlerts.clear();
}
/**
* Analyze movement patterns from position data
*/
analyzeMovement(positions) {
if (positions.length < 2) {
return { pattern: 'insufficient_data', speed: 0, bearing: null };
}
const speeds = [];
const bearings = [];
for (let i = 1; i < positions.length; i++) {
const prev = positions[i - 1];
const curr = positions[i];
const distance = this.calculateDistance(prev.lat, prev.lon, curr.lat, curr.lon);
const timeDiff = (curr.timestamp - prev.timestamp) / 1000; // seconds
const speed = timeDiff > 0 ? distance / timeDiff : 0;
speeds.push(speed);
bearings.push(this.calculateBearing(prev.lat, prev.lon, curr.lat, curr.lon));
}
const avgSpeed = speeds.reduce((a, b) => a + b, 0) / speeds.length;
// Detect circular patterns
const bearingVariance = this.calculateBearingVariance(bearings);
let pattern = 'linear';
if (bearingVariance > 180) {
pattern = 'circular';
} else if (avgSpeed < 1) {
pattern = 'hovering';
}
return {
pattern,
speed: avgSpeed,
bearing: bearings[bearings.length - 1],
avgSpeed
};
}
/**
* Clean up old tracking data
*/
cleanupOldTracks() {
const cutoffTime = Date.now() - (24 * 60 * 60 * 1000); // 24 hours ago
for (const [droneId, data] of this.activeDrones.entries()) {
if (data.lastSeen && data.lastSeen.getTime() < cutoffTime) {
this.activeDrones.delete(droneId);
}
}
for (const [key, history] of this.droneHistory.entries()) {
// Remove old detections from history
const filteredHistory = history.filter(detection => detection.timestamp > cutoffTime);
if (filteredHistory.length === 0) {
this.droneHistory.delete(key);
} else {
this.droneHistory.set(key, filteredHistory);
}
}
}
/**
* Get all active tracking data
*/
getActiveTracking() {
const result = [];
for (const [droneId, data] of this.activeDrones.entries()) {
result.push({
droneId: parseInt(droneId),
...data,
movement: this.analyzeMovement(data.detectionHistory || [])
});
}
return result;
}
/**
* Get detection history for a specific drone
*/
getDroneHistory(droneId) {
const data = this.activeDrones.get(droneId);
return data ? data.detectionHistory : null;
}
/**
* Calculate bearing between two points
*/
calculateBearing(lat1, lon1, lat2, lon2) {
const dLon = (lon2 - lon1) * Math.PI / 180;
const lat1Rad = lat1 * Math.PI / 180;
const lat2Rad = lat2 * Math.PI / 180;
const y = Math.sin(dLon) * Math.cos(lat2Rad);
const x = Math.cos(lat1Rad) * Math.sin(lat2Rad) - Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(dLon);
const bearing = Math.atan2(y, x) * 180 / Math.PI;
return (bearing + 360) % 360;
}
/**
* Calculate speed between two positions
*/
calculateSpeed(pos1, pos2) {
const distance = this.calculateDistance(pos1.lat, pos1.lon, pos2.lat, pos2.lon);
const timeDiff = (pos2.timestamp - pos1.timestamp) / 1000; // seconds
return timeDiff > 0 ? distance / timeDiff : 0;
}
/**
* Calculate bearing variance for pattern detection
*/
calculateBearingVariance(bearings) {
if (bearings.length < 2) return 0;
let totalVariance = 0;
for (let i = 1; i < bearings.length; i++) {
let diff = Math.abs(bearings[i] - bearings[i-1]);
if (diff > 180) diff = 360 - diff; // Handle wraparound
totalVariance += diff;
}
return totalVariance / (bearings.length - 1);
}
/**
* Cleanup method for tests - can accept a cutoff time parameter
*/
cleanup(cutoffTime = null) {
if (cutoffTime) {
// Use provided cutoff time
for (const [droneId, data] of this.activeDrones.entries()) {
if (data.lastSeen && data.lastSeen.getTime() < cutoffTime) {
this.activeDrones.delete(droneId);
}
}
for (const [key, history] of this.droneHistory.entries()) {
const filteredHistory = history.filter(detection => detection.timestamp > cutoffTime);
if (filteredHistory.length === 0) {
this.droneHistory.delete(key);
} else {
this.droneHistory.set(key, filteredHistory);
}
}
} else {
// Default cleanup behavior
this.cleanupOldTracks();
}
}
}
module.exports = DroneTrackingService;