#!/usr/bin/env python3 """ Orlan Detection Test Script Tests the critical alert system for Orlan military drones by simulating a long-distance approach from undetectable range to directly overhead. Test Scenario: - Starts 50km away (beyond detection range) - Slowly approaches target device - Triggers critical alerts as it enters detection range - Ends with drone hovering directly above target """ import requests import json import time import math from datetime import datetime # Configuration API_BASE_URL = "http://selfservice.cqers.com/drones/api" # Detection range parameters (approximate) MAX_DETECTION_RANGE_KM = 25.0 # Maximum range for drone detection MIN_RSSI_THRESHOLD = -95 # Minimum RSSI for detection def haversine_distance(lat1, lon1, lat2, lon2): """Calculate distance between two points in kilometers""" R = 6371 # Earth's radius in kilometers dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = (math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) return R * c def rssi_from_distance(distance_km): """Calculate RSSI based on distance for Orlan drone""" # Orlan drones have powerful military-grade transmission systems # Base RSSI at 1km = -55 dBm (stronger than civilian drones) base_rssi = -55 path_loss_exponent = 2.3 # Lower path loss due to military equipment if distance_km < 0.001: # Less than 1 meter return -25 rssi = base_rssi - (20 * path_loss_exponent * math.log10(distance_km)) return max(rssi, -100) # Cap at -100 dBm def is_detectable(distance_km): """Check if drone is within detectable range""" rssi = rssi_from_distance(distance_km) return distance_km <= MAX_DETECTION_RANGE_KM and rssi >= MIN_RSSI_THRESHOLD def fetch_devices(): """Fetch devices from API""" try: response = requests.get(f"{API_BASE_URL}/devices/map") if response.status_code == 200: data = response.json() return data.get('data', []) except Exception as e: print(f"Error fetching devices: {e}") return [] def send_detection(device, drone_lat, drone_lon, distance_km, step, total_steps): """Send a detection to the API using EXACT standard payload format""" rssi = rssi_from_distance(distance_km) # Use the EXACT standard payload format - NEVER change this! detection_data = { "device_id": device["id"], "geo_lat": drone_lat, "geo_lon": drone_lon, "device_timestamp": int(time.time() * 1000), # Current timestamp in milliseconds "drone_type": 1, # Orlan/Military type "rssi": int(rssi), "freq": 24, # Orlan operates on 2.4 GHz (24 = 2400 MHz) "drone_id": 2000 + step # Unique drone ID for tracking } try: response = requests.post(f"{API_BASE_URL}/detections", json=detection_data) if response.status_code == 201: status = "🚨 CRITICAL ALERT" if distance_km <= 5 else "āš ļø DETECTED" if is_detectable(distance_km) else "šŸ“” MONITORING" print(f"{status} - Step {step}/{total_steps}: Distance={distance_km:.1f}km, RSSI={rssi:.0f}dBm") return True else: print(f"Failed to send detection: {response.status_code}") return False except Exception as e: print(f"Error sending detection: {e}") return False def calculate_position_along_path(start_lat, start_lon, end_lat, end_lon, progress): """Calculate position along great circle path""" # Simple linear interpolation for this test lat = start_lat + (end_lat - start_lat) * progress lon = start_lon + (end_lon - start_lon) * progress return lat, lon def run_orlan_detection_test(): """Run the comprehensive Orlan detection test""" print("=" * 70) print("🚨 ORLAN MILITARY DRONE DETECTION TEST") print("=" * 70) print("Test Scenario:") print("• Starting position: 50km away (undetectable)") print("• Approach pattern: Straight line to target") print("• Detection threshold: ~25km range") print("• Critical alerts: <5km from target") print("• End position: Directly overhead (0m)") print("=" * 70) # Fetch devices devices = fetch_devices() if not devices: print("āŒ No devices found!") return # Use the first device as target target_device = devices[0] print(f"šŸŽÆ Target Device: {target_device['name']}") print(f"šŸ“ Target Location: {target_device['geo_lat']:.6f}, {target_device['geo_lon']:.6f}") # Calculate starting position 50km away (due north for simplicity) start_distance = 50.0 # km # Move 50km north of target start_lat = target_device['geo_lat'] + (start_distance / 111.0) # ~111km per degree latitude start_lon = target_device['geo_lon'] # Same longitude print(f"šŸ›« Orlan Starting Position: {start_lat:.6f}, {start_lon:.6f}") print(f"šŸ“ Initial Distance: {start_distance:.1f}km") # Verify starting position is undetectable if is_detectable(start_distance): print("āš ļø WARNING: Starting position is within detection range!") else: print("āœ… Starting position confirmed undetectable") print("\n" + "=" * 70) print("STARTING ORLAN APPROACH SIMULATION") print("=" * 70) # Simulation parameters total_steps = 50 # More steps for gradual approach final_distance = 0.0 # Directly overhead detection_started = False critical_alerts_started = False for step in range(1, total_steps + 1): # Calculate current distance using exponential approach for realistic acceleration progress = step / total_steps # Use exponential curve for realistic approach - slower at distance, faster when close distance_km = start_distance * (1 - progress) ** 1.8 + final_distance * progress ** 1.8 # Calculate current position current_lat, current_lon = calculate_position_along_path( start_lat, start_lon, target_device['geo_lat'], target_device['geo_lon'], progress ) # Check detection status detectable = is_detectable(distance_km) # Send detection only if within detectable range if detectable: if not detection_started: print(f"\nšŸ” FIRST DETECTION at {distance_km:.1f}km - Orlan has entered detection range!") detection_started = True success = send_detection(target_device, current_lat, current_lon, distance_km, step, total_steps) if not success: print(f"āŒ Failed to send detection at step {step}") continue # Show escalation messages if distance_km <= 5 and not critical_alerts_started: print(f"🚨 CRITICAL ALERT THRESHOLD REACHED at {distance_km:.1f}km!") critical_alerts_started = True elif distance_km <= 1: print(f"šŸ”„ IMMEDIATE THREAT: Orlan within {distance_km:.1f}km!") elif distance_km <= 0.1: print(f"šŸ’„ DIRECTLY OVERHEAD: Orlan at {distance_km*1000:.0f}m altitude!") else: # Outside detection range print(f"šŸ“” Step {step}/{total_steps}: Distance={distance_km:.1f}km (undetectable, RSSI={rssi_from_distance(distance_km):.0f}dBm)") # Variable delay based on distance if distance_km > 30: delay = 2.0 # 2 seconds for very long range elif distance_km > 15: delay = 1.5 # 1.5 seconds for long range elif distance_km > 5: delay = 1.0 # 1 second for medium range else: delay = 0.8 # Faster updates for critical proximity time.sleep(delay) print("\n" + "=" * 70) print("🚨 ORLAN DETECTION TEST COMPLETED") print("=" * 70) print("Test Summary:") print(f"• Starting distance: {start_distance:.1f}km (undetectable)") print(f"• Detection range entered: ~{MAX_DETECTION_RANGE_KM:.1f}km") print(f"• Critical alerts triggered: <5km") print(f"• Final position: Directly overhead") print(f"• Target device: {target_device['name']}") print(f"• Total simulation steps: {total_steps}") print("") print("Expected Results:") print("āœ… No detections sent while >25km away") print("āœ… First detection when entering ~25km range") print("āœ… Critical alerts triggered for Orlan type (drone_type=1)") print("āœ… All alerts escalated regardless of distance/RSSI") print("āœ… Real-time tracking visible on dashboard") print("=" * 70) if __name__ == "__main__": try: run_orlan_detection_test() except KeyboardInterrupt: print("\n\nāš ļø Orlan detection test interrupted by user") except Exception as e: print(f"\nāŒ Error during Orlan detection test: {e}")