DroneAgent / chatbot.html
zok213
Initial commit
8579cdc
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🚁 DroneAgent Chatbot</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.chat-container {
width: 90%;
max-width: 800px;
height: 80vh;
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-header {
background: linear-gradient(135deg, #4CAF50, #45a049);
color: white;
padding: 20px;
text-align: center;
font-size: 1.2em;
font-weight: bold;
}
.chat-messages {
flex: 1;
padding: 20px;
overflow-y: auto;
background: #f8f9fa;
}
.message {
margin-bottom: 15px;
padding: 12px 16px;
border-radius: 18px;
max-width: 80%;
word-wrap: break-word;
white-space: pre-wrap;
}
.user-message {
background: #007bff;
color: white;
margin-left: auto;
text-align: right;
}
.bot-message {
background: #e9ecef;
color: #333;
margin-right: auto;
}
.chat-input-container {
padding: 20px;
background: white;
border-top: 1px solid #dee2e6;
display: flex;
gap: 10px;
}
.chat-input {
flex: 1;
padding: 12px 16px;
border: 2px solid #dee2e6;
border-radius: 25px;
outline: none;
font-size: 14px;
transition: border-color 0.3s;
}
.chat-input:focus {
border-color: #007bff;
}
.send-button {
padding: 12px 24px;
background: #007bff;
color: white;
border: none;
border-radius: 25px;
cursor: pointer;
font-weight: bold;
transition: background 0.3s;
}
.send-button:hover {
background: #0056b3;
}
.send-button:disabled {
background: #6c757d;
cursor: not-allowed;
}
.examples {
margin-bottom: 20px;
padding: 15px;
background: #fff3cd;
border-radius: 10px;
border-left: 4px solid #ffc107;
}
.examples h3 {
margin-bottom: 10px;
color: #856404;
}
.example-button {
display: inline-block;
margin: 5px;
padding: 8px 12px;
background: #fff;
border: 1px solid #ffc107;
border-radius: 15px;
cursor: pointer;
font-size: 12px;
transition: all 0.3s;
}
.example-button:hover {
background: #ffc107;
color: white;
}
.loading {
text-align: center;
color: #6c757d;
font-style: italic;
padding: 10px;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">
🚁 DroneAgent - AI Mission Planner
</div>
<div class="chat-messages" id="chatMessages">
<div class="examples">
<h3>🎯 Try these examples:</h3>
<div class="example-button" onclick="sendExample('Go straight 100m from 16.047, 108.206')">
Go straight 100m from 16.047, 108.206
</div>
<div class="example-button" onclick="sendExample('Survey mission at 16.047, 108.206')">
Survey mission at 16.047, 108.206
</div>
<div class="example-button" onclick="sendExample('Patrol route at 16.047, 108.206 at 80m altitude')">
Patrol route at 16.047, 108.206 at 80m altitude
</div>
<div class="example-button" onclick="sendExample('Photography flight at 16.047, 108.206')">
Photography flight at 16.047, 108.206
</div>
<div class="example-button" onclick="sendExample('Hi, I want to take photos of my building')">
Hi, I want to take photos of my building
</div>
</div>
</div>
<div class="chat-input-container">
<input type="text" class="chat-input" id="chatInput" placeholder="Type your message... (e.g., 'Survey mission at 16.047, 108.206')" onkeypress="handleKeyPress(event)">
<button class="send-button" id="sendButton" onclick="sendMessage()">Send</button>
<button class="send-button" style="background: #28a745;" onclick="getLatestMission()">📁 Latest</button>
<button class="send-button" style="background: #17a2b8;" onclick="getDroneStatus()">🚁 Drone</button>
</div>
</div>
<script>
const chatMessages = document.getElementById('chatMessages');
const chatInput = document.getElementById('chatInput');
const sendButton = document.getElementById('sendButton');
// Add welcome message
addBotMessage("👋 Hi! I'm DroneBot, your friendly AI assistant for drone mission planning!\n\n🚁 I can help you create professional drone missions. Try one of the examples above or ask me anything about drone missions!");
function handleKeyPress(event) {
if (event.key === 'Enter') {
sendMessage();
}
}
function sendExample(text) {
chatInput.value = text;
sendMessage();
}
async function sendMessage() {
const message = chatInput.value.trim();
if (!message) return;
// Add user message
addUserMessage(message);
chatInput.value = '';
// Disable input
sendButton.disabled = true;
chatInput.disabled = true;
// Add loading message
const loadingElement = addLoadingMessage();
try {
const response = await fetch('http://localhost:8000/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message: message })
});
const data = await response.json();
// Remove loading message
loadingElement.remove();
// Add bot response
let botResponse = data.ai_response || 'Sorry, I had trouble processing that request.';
// Add comprehensive status information
if (data.mission_file) {
botResponse += `\n\n📁 Mission file: ${data.mission_file}`;
}
addBotMessage(botResponse);
} catch (error) {
loadingElement.remove();
addBotMessage('❌ Error: Could not connect to DroneAgent server. Make sure the server is running on http://localhost:8000');
}
// Re-enable input
sendButton.disabled = false;
chatInput.disabled = false;
chatInput.focus();
}
function addUserMessage(message) {
const messageDiv = document.createElement('div');
messageDiv.className = 'message user-message';
messageDiv.textContent = message;
chatMessages.appendChild(messageDiv);
scrollToBottom();
}
function addBotMessage(message) {
const messageDiv = document.createElement('div');
messageDiv.className = 'message bot-message';
messageDiv.textContent = message;
chatMessages.appendChild(messageDiv);
scrollToBottom();
}
function addLoadingMessage() {
const loadingDiv = document.createElement('div');
loadingDiv.className = 'loading';
loadingDiv.textContent = '🤖 DroneBot is thinking...';
chatMessages.appendChild(loadingDiv);
scrollToBottom();
return loadingDiv;
}
async function getLatestMission() {
try {
const loadingElement = addLoadingMessage();
const response = await fetch('http://localhost:8000/api/latest-mission');
const data = await response.json();
loadingElement.remove();
if (data.status === 'success') {
let message = `📁 **Latest Mission Retrieved**\n\n`;
message += `**File:** ${data.filename}\n`;
message += `**Created:** ${new Date(data.created_at).toLocaleString()}\n`;
message += `**Size:** ${data.file_size} bytes\n\n`;
message += `✅ Mission plan ready for QGroundControl!`;
addBotMessage(message);
} else {
addBotMessage(`📁 ${data.message}`);
}
} catch (error) {
addBotMessage('❌ Error retrieving latest mission. Make sure the server is running.');
}
}
async function getDroneStatus() {
try {
const loadingElement = addLoadingMessage();
const response = await fetch('http://localhost:8000/drone/status');
const data = await response.json();
loadingElement.remove();
if (data.status === 'success') {
const status = data.drone_status;
const rec = data.mission_recommendations;
let message = `🚁 **Drone Status**\n\n`;
message += `🔋 Battery: ${status.batteryRemaining}% (${status.voltage.toFixed(1)}V)\n`;
message += `📡 GPS: ${status.satelite} satellites\n`;
message += `📍 Location: ${status.latitude.toFixed(4)}, ${status.longitude.toFixed(4)}\n`;
message += `🛩️ Mode: ${status.mode} | Altitude: ${status.altitude.toFixed(0)}m\n\n`;
message += `**Mission Recommendations:**\n`;
message += `• Optimal Altitude: ${rec.optimal_altitude}\n`;
message += `• Max Distance: ${rec.max_mission_distance}\n`;
message += `• Flight Time: ${rec.estimated_flight_time}\n`;
message += `• Ready: ${rec.ready_for_mission ? '✅ Yes' : '❌ No'}`;
addBotMessage(message);
} else {
addBotMessage('❌ Could not retrieve drone status.');
}
} catch (error) {
addBotMessage('❌ Error retrieving drone status. Make sure the server is running.');
}
}
function scrollToBottom() {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// Focus input on load
chatInput.focus();
</script>
</body>
</html>