Irrigation_Trial / templates /predict.html
krushimitravit's picture
Upload 9 files
f574f17 verified
Raw
History Blame Contribute Delete
11.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prediction Results</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
/* === COLOR SYSTEM === */
:root {
--deep-green: #1a5d3a;
--accent-green: #198754;
--darker-accent: #143d2e;
--background: #f8f9fa;
--surface: #ffffff;
--text-dark: #212529;
--text-muted: #6c757d;
--border: #dee2e6;
}
/* === GLOBAL STYLES === */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color:#f8f9fa;
font-family: 'Outfit', sans-serif;
font-weight: 400;
color: var(--text-dark);
}
/* === HEADER === */
.header {
background-color: var(--deep-green);
color: white;
padding: 2rem;
text-align: center;
}
.header h1 {
font-size: 2rem;
font-weight: 700;
margin: 0;
}
/* === CONTAINER === */
.container {
max-width: 1400px;
margin: 2rem auto;
padding: 0 1rem;
}
/* === CARD STYLES === */
.result-card {
background: var(--surface);
border: none;
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
padding: 2rem;
margin-bottom: 1.5rem;
}
/* === FORM CONTROLS === */
.result-label {
font-weight: 600;
color: var(--text-dark);
margin-bottom: 0.75rem;
font-size: 1.1rem;
}
.form-control[readonly] {
font-size: 1.3rem;
text-align: center;
font-weight: 600;
color: var(--accent-green);
background-color: #f0fff4;
border: 2px solid var(--accent-green);
border-radius: 12px;
padding: 1rem;
}
/* === GAUGE CONTAINER === */
.gauge-container {
margin-top: 1.5rem;
text-align: center;
}
/* === INFO CARD === */
.info-card {
background: linear-gradient(135deg, #f0fff4 0%, #e8f5e9 100%);
border: 2px solid var(--accent-green);
border-radius: 20px;
padding: 2.5rem;
margin-top: 2rem;
text-align: center;
}
.info-card h4 {
color: var(--deep-green);
font-weight: 700;
margin-bottom: 1rem;
}
.info-card p {
color: var(--text-dark);
font-size: 1.05rem;
line-height: 1.6;
}
/* === CAMERA CONTAINER === */
.camera-container {
margin-top: 2rem;
display: none;
flex-direction: column;
align-items: center;
gap: 1.5rem;
background: var(--surface);
border-radius: 20px;
padding: 2rem;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
}
.camera-container h4 {
color: var(--deep-green);
font-weight: 600;
}
video {
width: 100%;
max-width: 720px;
height: auto;
border-radius: 15px;
border: 3px solid var(--border);
background-color: #000;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
}
/* === TIMER === */
.timer {
font-size: 2.5rem;
color: white;
background-color: var(--accent-green);
font-weight: 700;
padding: 1rem 2.5rem;
border-radius: 15px;
display: inline-block;
min-width: 150px;
text-align: center;
box-shadow: 0 5px 15px rgba(25, 135, 84, 0.3);
}
.timer-finished {
font-size: 1.8rem;
padding: 1.25rem 3rem;
background-color: #dc3545;
}
/* === ALERT MESSAGE === */
.alert-message {
font-size: 1.2rem;
font-weight: 600;
margin-top: 1.5rem;
text-align: center;
padding: 1rem;
border-radius: 12px;
background-color: #f0fff4;
color: var(--accent-green);
}
/* === RESPONSIVE === */
@media (max-width: 768px) {
.header h1 {
font-size: 1.5rem;
}
.result-card {
padding: 1.5rem;
}
.timer {
font-size: 2rem;
padding: 0.75rem 2rem;
}
}
</style>
</head>
<body>
<div class="header">
<h1><i class="bi bi-droplet-half"></i> Water Requirement Prediction Results</h1>
</div>
<div class="container">
<div class="row">
<div class="col-md-6 mb-4">
<div class="result-card">
<label for="water_requirement" class="result-label">Predicted Water Requirement (m³/sq.m):</label>
<input type="text" class="form-control" id="water_requirement" value="{{ water_requirement }}" readonly>
<div class="gauge-container">
{% if water_img %}
<img src="{{ water_img }}" alt="Water gauge" class="img-fluid" style="max-height:360px;">
{% else %}
{{ water_gauge|safe }}
{% endif %}
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="result-card">
<label for="estimated_time" class="result-label">Estimated Motor On-Time:</label>
<input type="text" class="form-control" id="estimated_time" value="{{ estimated_time_duration }} {{ time_unit }}" readonly>
<div class="gauge-container">
{% if time_img %}
<img src="{{ time_img }}" alt="Time gauge" class="img-fluid" style="max-height:360px;">
{% else %}
{{ time_gauge|safe }}
{% endif %}
</div>
</div>
</div>
</div>
<div class="info-card">
<h4><i class="bi bi-robot"></i> AI-Driven Irrigation Monitoring</h4>
<p class="mt-3">A message has been sent to your WhatsApp. Please reply <strong>1</strong> to start the motor and activate live monitoring here, or reply <strong>0</strong> to cancel the operation.</p>
</div>
<div class="camera-container" id="cameraContainer">
<h4 class="text-center mb-0"><i class="bi bi-camera-video"></i> Live Irrigation Feed</h4>
<video id="videoElement" autoplay playsinline></video>
<div class="timer" id="timer"></div>
</div>
<div class="alert-message" id="alertMessage">Waiting for WhatsApp confirmation...</div>
</div>
<script>
// --- GLOBAL VARIABLES ---
let pollingInterval = null;
let clientTimerInterval = null;
let cameraStream = null;
let isMonitoringActive = false;
// --- MAIN FUNCTION TO START POLLING ---
window.onload = function() {
// Start polling the server for status updates every 3 seconds
pollingInterval = setInterval(checkMonitorStatus, 3000);
checkMonitorStatus(); // Check immediately on load
};
// --- FUNCTION TO CHECK STATUS WITH THE SERVER ---
function checkMonitorStatus() {
fetch('/monitoring_status')
.then(resp => resp.json())
.then(data => {
if (data.monitoring && !isMonitoringActive) {
// --- START MONITORING ---
isMonitoringActive = true;
console.log("Server indicated to start monitoring.");
document.getElementById('alertMessage').textContent = "✅ Monitoring started via WhatsApp confirmation!";
startCameraAndTimer(data.time_remaining);
} else if (!data.monitoring && isMonitoringActive) {
// --- STOP MONITORING (e.g., if task is canceled or completed on server) ---
isMonitoringActive = false;
console.log("Server indicated to stop monitoring.");
document.getElementById('alertMessage').textContent = "Monitoring has been stopped or completed.";
stopCameraAndTimer();
}
})
.catch(err => {
console.error('Error polling for status:', err);
// Stop polling if there is an error to avoid spamming the console
clearInterval(pollingInterval);
});
}
// --- FUNCTION TO ACTIVATE CAMERA AND VISUAL TIMER ---
function startCameraAndTimer(timeRemainingSeconds) {
// Show camera container
document.getElementById('cameraContainer').style.display = 'flex';
// Start Camera
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false })
.then(function(stream) {
cameraStream = stream;
document.getElementById('videoElement').srcObject = stream;
})
.catch(function(err) {
console.error("Camera Error: ", err);
alert("Could not access the camera. Please ensure you have given permission.");
});
} else {
alert("Camera API not supported in this browser.");
}
// Start client-side visual countdown timer
let timeRemaining = Math.floor(timeRemainingSeconds);
let timerElem = document.getElementById('timer');
timerElem.classList.remove('timer-finished');
clearInterval(clientTimerInterval); // Clear any existing timer
clientTimerInterval = setInterval(function() {
if (timeRemaining <= 0) {
clearInterval(clientTimerInterval);
timerElem.textContent = "Finished";
timerElem.classList.add('timer-finished');
document.getElementById('alertMessage').textContent = "Irrigation time is over. The motor has stopped automatically.";
stopCameraAndTimer(); // Also stop camera stream
} else {
timerElem.textContent = timeRemaining + "s";
}
timeRemaining--;
}, 1000);
}
// --- FUNCTION TO STOP CAMERA AND TIMER ---
function stopCameraAndTimer() {
clearInterval(clientTimerInterval);
clearInterval(pollingInterval); // Stop polling once task is over
if (cameraStream) {
cameraStream.getTracks().forEach(track => track.stop());
cameraStream = null;
}
// We can hide the camera container or leave it visible with a "Finished" message
// document.getElementById('cameraContainer').style.display = 'none';
}
</script>
</body>
</html>