Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>PV Plant Surveillance Drone Control</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> | |
| <style> | |
| #map { height: 100%; width: 100%; } | |
| .waypoint-marker { background-color: #3b82f6; width: 12px; height: 12px; border-radius: 50%; border: 2px solid white; } | |
| .home-marker { background-color: #ef4444; width: 14px; height: 14px; border-radius: 50%; border: 2px solid white; } | |
| .drone-marker { background-color: #10b981; width: 16px; height: 16px; border-radius: 50%; border: 2px solid white; } | |
| .custom-scrollbar::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .custom-scrollbar::-webkit-scrollbar-track { | |
| background: #f1f1f1; | |
| } | |
| .custom-scrollbar::-webkit-scrollbar-thumb { | |
| background: #888; | |
| border-radius: 3px; | |
| } | |
| .custom-scrollbar::-webkit-scrollbar-thumb:hover { | |
| background: #555; | |
| } | |
| .telemetry-value { | |
| font-family: 'Courier New', monospace; | |
| font-size: 0.9rem; | |
| } | |
| .gauge { | |
| width: 100%; | |
| height: 8px; | |
| background: #e5e7eb; | |
| border-radius: 4px; | |
| overflow: hidden; | |
| } | |
| .gauge-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, #10b981, #3b82f6); | |
| border-radius: 4px; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-100 text-gray-800 h-screen flex flex-col"> | |
| <!-- Header --> | |
| <header class="bg-blue-600 text-white p-4 shadow-md"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <div class="flex items-center space-x-3"> | |
| <i class="fas fa-solar-panel text-2xl"></i> | |
| <h1 class="text-xl font-bold">PV Plant Surveillance Drone Control</h1> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <div class="flex items-center space-x-2"> | |
| <div class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div> | |
| <span class="text-sm">MAVLINK Connected</span> | |
| </div> | |
| <button class="bg-red-500 hover:bg-red-600 px-3 py-1 rounded text-sm"> | |
| <i class="fas fa-power-off mr-1"></i> Emergency Stop | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Main Content --> | |
| <div class="flex flex-1 overflow-hidden"> | |
| <!-- Sidebar --> | |
| <div class="w-80 bg-white border-r border-gray-200 flex flex-col"> | |
| <!-- Connection Panel --> | |
| <div class="p-4 border-b border-gray-200"> | |
| <h2 class="font-semibold text-lg mb-3 flex items-center"> | |
| <i class="fas fa-plug mr-2 text-blue-500"></i> Connection | |
| </h2> | |
| <div class="space-y-3"> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Connection Type</label> | |
| <select class="w-full p-2 border border-gray-300 rounded"> | |
| <option>UDP</option> | |
| <option>TCP</option> | |
| <option>Serial</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Address</label> | |
| <input type="text" class="w-full p-2 border border-gray-300 rounded" value="192.168.1.100"> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium text-gray-700 mb-1">Port</label> | |
| <input type="text" class="w-full p-2 border border-gray-300 rounded" value="14550"> | |
| </div> | |
| <button class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded flex items-center justify-center"> | |
| <i class="fas fa-link mr-2"></i> Connect | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Telemetry Panel --> | |
| <div class="p-4 border-b border-gray-200 flex-1 overflow-y-auto custom-scrollbar"> | |
| <h2 class="font-semibold text-lg mb-3 flex items-center"> | |
| <i class="fas fa-chart-line mr-2 text-green-500"></i> Telemetry | |
| </h2> | |
| <div class="space-y-4"> | |
| <div class="bg-gray-50 p-3 rounded"> | |
| <div class="flex justify-between items-center mb-1"> | |
| <span class="text-sm font-medium">Battery</span> | |
| <span class="text-sm font-bold">78%</span> | |
| </div> | |
| <div class="gauge"> | |
| <div class="gauge-fill" style="width: 78%"></div> | |
| </div> | |
| </div> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">Altitude</div> | |
| <div class="telemetry-value">120.5 m</div> | |
| </div> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">Speed</div> | |
| <div class="telemetry-value">8.2 m/s</div> | |
| </div> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">Satellites</div> | |
| <div class="telemetry-value">12</div> | |
| </div> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">HDOP</div> | |
| <div class="telemetry-value">1.2</div> | |
| </div> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">Latitude</div> | |
| <div class="telemetry-value">48.8566°</div> | |
| </div> | |
| <div class="bg-gray-50 p-2 rounded"> | |
| <div class="text-xs text-gray-500">Longitude</div> | |
| <div class="telemetry-value">2.3522°</div> | |
| </div> | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-sm mb-2">Flight Mode</h3> | |
| <div class="flex space-x-2"> | |
| <button class="px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-xs">GUIDED</button> | |
| <button class="px-3 py-1 bg-gray-100 text-gray-800 rounded-full text-xs">AUTO</button> | |
| <button class="px-3 py-1 bg-gray-100 text-gray-800 rounded-full text-xs">RTL</button> | |
| <button class="px-3 py-1 bg-gray-100 text-gray-800 rounded-full text-xs">LOITER</button> | |
| </div> | |
| </div> | |
| <div> | |
| <h3 class="font-medium text-sm mb-2">Camera Control</h3> | |
| <div class="grid grid-cols-3 gap-2"> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-camera"></i> | |
| </button> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-video"></i> | |
| </button> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-expand"></i> | |
| </button> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-arrow-up"></i> | |
| </button> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-arrow-down"></i> | |
| </button> | |
| <button class="p-2 bg-gray-100 rounded hover:bg-gray-200"> | |
| <i class="fas fa-thermometer-half"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Mission Control --> | |
| <div class="p-4 border-b border-gray-200"> | |
| <h2 class="font-semibold text-lg mb-3 flex items-center"> | |
| <i class="fas fa-map-marked-alt mr-2 text-purple-500"></i> Mission Control | |
| </h2> | |
| <div class="space-y-3"> | |
| <button class="w-full bg-green-600 hover:bg-green-700 text-white py-2 rounded flex items-center justify-center"> | |
| <i class="fas fa-play mr-2"></i> Start Mission | |
| </button> | |
| <button class="w-full bg-yellow-500 hover:bg-yellow-600 text-white py-2 rounded flex items-center justify-center"> | |
| <i class="fas fa-pause mr-2"></i> Pause Mission | |
| </button> | |
| <button class="w-full bg-red-500 hover:bg-red-600 text-white py-2 rounded flex items-center justify-center"> | |
| <i class="fas fa-undo mr-2"></i> Return to Launch | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Main Map Area --> | |
| <div class="flex-1 flex flex-col"> | |
| <!-- Map Tabs --> | |
| <div class="bg-white border-b border-gray-200"> | |
| <div class="flex"> | |
| <button class="px-4 py-2 border-b-2 border-blue-500 text-blue-600 font-medium">Google Earth</button> | |
| <button class="px-4 py-2 text-gray-600 hover:text-gray-800">Satellite</button> | |
| <button class="px-4 py-2 text-gray-600 hover:text-gray-800">Topographic</button> | |
| <button class="px-4 py-2 text-gray-600 hover:text-gray-800">PV Layout</button> | |
| </div> | |
| </div> | |
| <!-- Map Container --> | |
| <div id="map" class="flex-1"></div> | |
| <!-- Mission Planning Panel --> | |
| <div class="bg-white border-t border-gray-200 p-4"> | |
| <div class="flex justify-between items-center mb-3"> | |
| <h2 class="font-semibold text-lg flex items-center"> | |
| <i class="fas fa-route mr-2 text-purple-500"></i> Mission Planning | |
| </h2> | |
| <div class="flex space-x-2"> | |
| <button class="px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm flex items-center"> | |
| <i class="fas fa-plus mr-1"></i> Add Waypoint | |
| </button> | |
| <button class="px-3 py-1 bg-green-100 text-green-800 rounded-full text-sm flex items-center"> | |
| <i class="fas fa-save mr-1"></i> Save Mission | |
| </button> | |
| <button class="px-3 py-1 bg-gray-100 text-gray-800 rounded-full text-sm flex items-center"> | |
| <i class="fas fa-trash mr-1"></i> Clear | |
| </button> | |
| </div> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="min-w-full divide-y divide-gray-200"> | |
| <thead class="bg-gray-50"> | |
| <tr> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">#</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Latitude</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Longitude</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Altitude</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Speed</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase">Action</th> | |
| <th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase"></th> | |
| </tr> | |
| </thead> | |
| <tbody class="bg-white divide-y divide-gray-200"> | |
| <tr> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">1</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">48.856612</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2.352222</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="100"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="5"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <select class="p-1 border border-gray-300 rounded text-xs"> | |
| <option>Waypoint</option> | |
| <option>Take Photo</option> | |
| <option>Start Video</option> | |
| <option>Thermal Scan</option> | |
| </select> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <button class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">2</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">48.856712</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2.353222</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="100"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="5"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <select class="p-1 border border-gray-300 rounded text-xs"> | |
| <option>Waypoint</option> | |
| <option selected>Take Photo</option> | |
| <option>Start Video</option> | |
| <option>Thermal Scan</option> | |
| </select> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <button class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| <tr> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">3</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">48.857612</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">2.354222</td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="100"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <input type="number" class="w-20 p-1 border border-gray-300 rounded" value="5"> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <select class="p-1 border border-gray-300 rounded text-xs"> | |
| <option>Waypoint</option> | |
| <option>Take Photo</option> | |
| <option>Start Video</option> | |
| <option selected>Thermal Scan</option> | |
| </select> | |
| </td> | |
| <td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500"> | |
| <button class="text-red-500 hover:text-red-700"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <div class="mt-4 flex justify-between"> | |
| <div class="flex items-center space-x-2"> | |
| <button class="px-3 py-1 bg-blue-600 text-white rounded text-sm"> | |
| <i class="fas fa-upload mr-1"></i> Import Mission | |
| </button> | |
| <button class="px-3 py-1 bg-gray-200 text-gray-800 rounded text-sm"> | |
| <i class="fas fa-download mr-1"></i> Export Mission | |
| </button> | |
| </div> | |
| <div class="text-sm text-gray-600"> | |
| Total Distance: 1.2 km | Estimated Duration: 8 min 24 sec | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Status Bar --> | |
| <footer class="bg-gray-800 text-white p-2 text-sm"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <div class="flex items-center space-x-4"> | |
| <span><i class="fas fa-satellite-dish mr-1 text-green-400"></i> GPS: 12 satellites</span> | |
| <span><i class="fas fa-battery-three-quarters mr-1 text-yellow-400"></i> Battery: 78% (24.3V)</span> | |
| <span><i class="fas fa-signal mr-1 text-blue-400"></i> RSSI: -65dBm</span> | |
| </div> | |
| <div> | |
| <span><i class="fas fa-clock mr-1"></i> Flight Time: 00:12:45</span> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| // Initialize the map | |
| const map = L.map('map').setView([48.8566, 2.3522], 15); | |
| // Add Google Earth layer (this is a placeholder - in reality you'd need Google Earth API) | |
| L.tileLayer('https://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', { | |
| maxZoom: 20, | |
| subdomains: ['mt0', 'mt1', 'mt2', 'mt3'], | |
| attribution: 'Google Earth' | |
| }).addTo(map); | |
| // Add PV plant area (polygon) | |
| const pvPlant = L.polygon([ | |
| [48.8560, 2.3515], | |
| [48.8560, 2.3535], | |
| [48.8575, 2.3535], | |
| [48.8575, 2.3515] | |
| ], {color: '#3b82f6', fillOpacity: 0.2}).addTo(map); | |
| pvPlant.bindPopup("PV Plant Area"); | |
| // Add home position | |
| const home = L.marker([48.8566, 2.3522], { | |
| icon: L.divIcon({className: 'home-marker', html: ''}) | |
| }).addTo(map); | |
| home.bindPopup("Home Position"); | |
| // Add drone position (would update in real application) | |
| const drone = L.marker([48.8566, 2.3522], { | |
| icon: L.divIcon({className: 'drone-marker', html: ''}) | |
| }).addTo(map); | |
| drone.bindPopup("Drone Position"); | |
| // Add waypoints | |
| const waypoints = [ | |
| {lat: 48.856612, lng: 2.352222, alt: 100}, | |
| {lat: 48.856712, lng: 2.353222, alt: 100}, | |
| {lat: 48.857612, lng: 2.354222, alt: 100} | |
| ]; | |
| const waypointMarkers = []; | |
| waypoints.forEach((wp, i) => { | |
| const marker = L.marker([wp.lat, wp.lng], { | |
| icon: L.divIcon({className: 'waypoint-marker', html: ''}) | |
| }).addTo(map); | |
| marker.bindPopup(`Waypoint ${i+1}<br>Altitude: ${wp.alt}m`); | |
| waypointMarkers.push(marker); | |
| }); | |
| // Draw lines between waypoints | |
| const waypointLine = L.polyline( | |
| waypoints.map(wp => [wp.lat, wp.lng]), | |
| {color: '#3b82f6', dashArray: '5,5'} | |
| ).addTo(map); | |
| // Simulate drone movement (for demo purposes) | |
| let currentWp = 0; | |
| function simulateDroneMovement() { | |
| if (currentWp >= waypoints.length) { | |
| currentWp = 0; | |
| } | |
| const target = waypoints[currentWp]; | |
| const currentPos = drone.getLatLng(); | |
| // Move drone slightly toward target | |
| const newLat = currentPos.lat + (target.lat - currentPos.lat) * 0.1; | |
| const newLng = currentPos.lng + (target.lng - currentPos.lng) * 0.1; | |
| drone.setLatLng([newLat, newLng]); | |
| // If close to waypoint, move to next | |
| if (Math.abs(newLat - target.lat) < 0.0001 && Math.abs(newLng - target.lng) < 0.0001) { | |
| currentWp++; | |
| } | |
| setTimeout(simulateDroneMovement, 500); | |
| } | |
| // Start simulation | |
| simulateDroneMovement(); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=nkellil/kellil-uav1" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |