RushiMane2003 commited on
Commit
77d5f23
·
verified ·
1 Parent(s): 14cd95a

Update templates/predict.html

Browse files
Files changed (1) hide show
  1. templates/predict.html +66 -101
templates/predict.html CHANGED
@@ -1,25 +1,28 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6
  <title>Prediction Results</title>
7
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"/>
8
  <style>
9
- /* (same styles as before, trimmed here for brevity) */
10
- body { background-color: #f4f8f4; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
11
- .header { background-color: #28a745; color: white; padding: 20px; text-align: center; font-weight: bold; }
12
- .container { margin-top: 30px; padding: 20px; background-color: white; border-radius: 15px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); opacity: 0; transition: opacity 0.5s ease-in-out; }
13
- .form-control[readonly] { font-size: 1.2rem; text-align: center; font-weight: bold; color: #28a745; background-color: #e9f5e9; border: 2px solid #28a745; }
14
- .btn-start-motor { background-color: #28a745; color: white; font-size: 1.2rem; padding: 12px 25px; font-weight: bold; border-radius: 8px; transition: background-color 0.3s; }
15
- .camera-container { margin-top: 20px; display: none; flex-direction: column; align-items: center; gap: 20px; }
16
- video { width: 100%; max-width: 720px; height: auto; border-radius: 10px; border: 2px solid #ddd; background-color: #000; }
17
- .timer { font-size: 2rem; color: white; background-color: #28a745; font-weight: bold; padding: 10px 25px; border-radius: 10px; display: inline-block; min-width: 120px; text-align: center; }
18
- .timer-finished { font-size: 1.5rem; padding: 15px 40px; background-color: #28a745; }
19
- .alert-message { font-size: 1.2rem; font-weight: bold; margin-top: 10px; text-align: center; }
 
 
20
  </style>
21
  </head>
22
  <body>
 
23
  <div class="header">
24
  <h1>Water Requirement Prediction Results</h1>
25
  </div>
@@ -39,9 +42,8 @@
39
  </div>
40
 
41
  <div class="info-card">
42
- <h4>Want to automatically inspect your irrigation process?</h4>
43
- <p class="mt-3">We will start the camera & monitoring when you reply <strong>1</strong> on WhatsApp. Reply <strong>0</strong> to cancel.</p>
44
- <p>Make sure to reply to the WhatsApp message we sent earlier. (If you didn't receive it, check your phone number or resubmit prediction.)</p>
45
  </div>
46
 
47
  <div class="camera-container" id="cameraContainer">
@@ -49,119 +51,83 @@
49
  <video id="videoElement" autoplay playsinline></video>
50
  <div class="timer" id="timer"></div>
51
  </div>
52
-
53
- <div class="alert-message" id="alertMessage"></div>
54
  </div>
55
-
56
- <!-- Modal that appears after prediction, instructing the user to reply '1' on WhatsApp -->
57
- <div class="modal fade" id="whatsappModal" tabindex="-1" aria-labelledby="whatsappModalLabel" aria-hidden="true">
58
- <div class="modal-dialog modal-dialog-centered">
59
- <div class="modal-content">
60
- <div class="modal-header" style="background-color:#28a745;color:white;">
61
- <h5 class="modal-title" id="whatsappModalLabel">Start Monitoring</h5>
62
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
63
- </div>
64
- <div class="modal-body">
65
- <p>To start live monitoring (camera + motor), please reply <strong>1</strong> on WhatsApp to the message we just sent you. Reply <strong>0</strong> to cancel.</p>
66
- <p class="mb-0">This page will start the camera automatically when your WhatsApp reply is received.</p>
67
- </div>
68
- <div class="modal-footer">
69
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Ok, got it</button>
70
- </div>
71
- </div>
72
- </div>
73
- </div>
74
-
75
- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
76
  <script>
77
- // Variables
78
- const estimatedTime = parseFloat("{{ estimated_time_duration }}");
79
- const timeUnit = "{{ time_unit }}";
80
- const estimatedTimeSecondsFromServer = timeUnit === "minutes" ? estimatedTime * 60 : estimatedTime;
81
  let clientTimerInterval = null;
82
  let cameraStream = null;
83
- let pollingInterval = null;
84
- let currentlyMonitoring = false;
85
 
86
- // Show container and modal on load
87
  window.onload = function() {
88
- document.querySelector('.container').style.opacity = 1;
89
- // Show the WhatsApp instruction modal
90
- var whatsappModalEl = document.getElementById('whatsappModal');
91
- var bsModal = new bootstrap.Modal(whatsappModalEl, { backdrop: 'static', keyboard: false });
92
- bsModal.show();
93
-
94
- // start polling for monitor status
95
- pollingInterval = setInterval(checkMonitorStatus, 2000);
96
- // check once immediately
97
- checkMonitorStatus();
98
  };
99
-
 
100
  function checkMonitorStatus() {
101
- fetch('/monitor_status')
102
  .then(resp => resp.json())
103
  .then(data => {
104
- const isMon = data.monitoring === true;
105
- if (isMon && !currentlyMonitoring) {
106
- // transition to monitoring ON
107
- currentlyMonitoring = true;
108
- startCameraAndTimer(data.time_remaining ?? Math.floor(estimatedTimeSecondsFromServer));
109
- document.getElementById('alertMessage').textContent = "Monitoring started (triggered by WhatsApp).";
110
- } else if (!isMon && currentlyMonitoring) {
111
- // transition to monitoring OFF
112
- currentlyMonitoring = false;
 
 
113
  stopCameraAndTimer();
114
- document.getElementById('alertMessage').textContent = "Monitoring stopped.";
115
- } else {
116
- // no change - optionally update time remaining
117
- if (isMon && data.time_remaining != null) {
118
- // update timer display if running
119
- const t = data.time_remaining;
120
- document.getElementById('timer').textContent = t + "s";
121
- }
122
  }
123
  })
124
  .catch(err => {
125
- console.error('monitor_status error', err);
 
 
126
  });
127
  }
128
 
129
- function startCameraAndTimer(timeRemainingSec) {
130
- // Start camera
131
- const cameraContainer = document.getElementById('cameraContainer');
132
- cameraContainer.style.display = 'flex';
133
- const videoElem = document.getElementById('videoElement');
134
-
135
  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
136
  navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false })
137
  .then(function(stream) {
138
  cameraStream = stream;
139
- videoElem.srcObject = stream;
140
  })
141
  .catch(function(err) {
142
- console.error("Camera Error: " + err);
143
  alert("Could not access the camera. Please ensure you have given permission.");
144
  });
145
  } else {
146
  alert("Camera API not supported in this browser.");
147
  }
148
 
149
- // Client countdown (best-effort; server controls final stop)
150
- clearInterval(clientTimerInterval);
151
- let timeRemaining = Math.max(0, Math.floor(timeRemainingSec));
152
- const timerElem = document.getElementById('timer');
153
  timerElem.classList.remove('timer-finished');
154
 
 
155
  clientTimerInterval = setInterval(function() {
156
  if (timeRemaining <= 0) {
157
  clearInterval(clientTimerInterval);
158
  timerElem.textContent = "Finished";
159
  timerElem.classList.add('timer-finished');
160
- try {
161
- const beep = new Audio('/static/alarn_tune.mp3');
162
- beep.play().catch(()=>{});
163
- } catch(e) {}
164
- document.getElementById('alertMessage').textContent = "Irrigation time is over. Motor is off automatically.";
165
  } else {
166
  timerElem.textContent = timeRemaining + "s";
167
  }
@@ -169,20 +135,19 @@
169
  }, 1000);
170
  }
171
 
 
172
  function stopCameraAndTimer() {
173
- // Stop client timer
174
  clearInterval(clientTimerInterval);
175
- const timerElem = document.getElementById('timer');
176
- timerElem.textContent = "";
177
- timerElem.classList.remove('timer-finished');
178
 
179
- // Stop camera stream
180
  if (cameraStream) {
181
  cameraStream.getTracks().forEach(track => track.stop());
182
  cameraStream = null;
183
  }
184
- document.getElementById('cameraContainer').style.display = 'none';
 
 
185
  }
186
  </script>
187
  </body>
188
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Prediction Results</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
8
  <style>
9
+ body { background-color: #f4f8f4; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
10
+ .header { background-color: #28a745; color: white; padding: 20px; text-align: center; font-weight: bold; }
11
+ .container { margin-top: 30px; padding: 20px; background-color: white; border-radius: 15px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
12
+ .result-label { font-weight: bold; color: #555; }
13
+ .form-control[readonly] { font-size: 1.2rem; text-align: center; font-weight: bold; color: #28a745; background-color: #e9f5e9; border: 2px solid #28a745; }
14
+ .gauge-container { margin-top: 20px; text-align: center; }
15
+ .info-card { background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 10px; padding: 25px; margin-top: 40px; text-align: center; }
16
+ .camera-container { margin-top: 20px; display: none; flex-direction: column; align-items: center; gap: 20px; }
17
+ video { width: 100%; max-width: 720px; height: auto; border-radius: 10px; border: 2px solid #ddd; background-color: #000; }
18
+ .timer { font-size: 2rem; color: white; background-color: #28a745; font-weight: bold; padding: 10px 25px; border-radius: 10px; display: inline-block; min-width: 120px; text-align: center; }
19
+ .timer-finished { font-size: 1.5rem; padding: 15px 40px; background-color: #dc3545; }
20
+ .alert-message { font-size: 1.2rem; font-weight: bold; margin-top: 20px; text-align: center; }
21
+ .modal-header { background-color: #28a745; color: white; }
22
  </style>
23
  </head>
24
  <body>
25
+
26
  <div class="header">
27
  <h1>Water Requirement Prediction Results</h1>
28
  </div>
 
42
  </div>
43
 
44
  <div class="info-card">
45
+ <h4>AI-Driven Irrigation Monitoring</h4>
46
+ <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>
 
47
  </div>
48
 
49
  <div class="camera-container" id="cameraContainer">
 
51
  <video id="videoElement" autoplay playsinline></video>
52
  <div class="timer" id="timer"></div>
53
  </div>
54
+
55
+ <div class="alert-message text-success" id="alertMessage">Waiting for WhatsApp confirmation...</div>
56
  </div>
57
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  <script>
59
+ // --- GLOBAL VARIABLES ---
60
+ let pollingInterval = null;
 
 
61
  let clientTimerInterval = null;
62
  let cameraStream = null;
63
+ let isMonitoringActive = false;
 
64
 
65
+ // --- MAIN FUNCTION TO START POLLING ---
66
  window.onload = function() {
67
+ // Start polling the server for status updates every 3 seconds
68
+ pollingInterval = setInterval(checkMonitorStatus, 3000);
69
+ checkMonitorStatus(); // Check immediately on load
 
 
 
 
 
 
 
70
  };
71
+
72
+ // --- FUNCTION TO CHECK STATUS WITH THE SERVER ---
73
  function checkMonitorStatus() {
74
+ fetch('/monitoring_status')
75
  .then(resp => resp.json())
76
  .then(data => {
77
+ if (data.monitoring && !isMonitoringActive) {
78
+ // --- START MONITORING ---
79
+ isMonitoringActive = true;
80
+ console.log("Server indicated to start monitoring.");
81
+ document.getElementById('alertMessage').textContent = "✅ Monitoring started via WhatsApp confirmation!";
82
+ startCameraAndTimer(data.time_remaining);
83
+ } else if (!data.monitoring && isMonitoringActive) {
84
+ // --- STOP MONITORING (e.g., if task is canceled or completed on server) ---
85
+ isMonitoringActive = false;
86
+ console.log("Server indicated to stop monitoring.");
87
+ document.getElementById('alertMessage').textContent = "Monitoring has been stopped or completed.";
88
  stopCameraAndTimer();
 
 
 
 
 
 
 
 
89
  }
90
  })
91
  .catch(err => {
92
+ console.error('Error polling for status:', err);
93
+ // Stop polling if there is an error to avoid spamming the console
94
+ clearInterval(pollingInterval);
95
  });
96
  }
97
 
98
+ // --- FUNCTION TO ACTIVATE CAMERA AND VISUAL TIMER ---
99
+ function startCameraAndTimer(timeRemainingSeconds) {
100
+ // Show camera container
101
+ document.getElementById('cameraContainer').style.display = 'flex';
102
+
103
+ // Start Camera
104
  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
105
  navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' }, audio: false })
106
  .then(function(stream) {
107
  cameraStream = stream;
108
+ document.getElementById('videoElement').srcObject = stream;
109
  })
110
  .catch(function(err) {
111
+ console.error("Camera Error: ", err);
112
  alert("Could not access the camera. Please ensure you have given permission.");
113
  });
114
  } else {
115
  alert("Camera API not supported in this browser.");
116
  }
117
 
118
+ // Start client-side visual countdown timer
119
+ let timeRemaining = Math.floor(timeRemainingSeconds);
120
+ let timerElem = document.getElementById('timer');
 
121
  timerElem.classList.remove('timer-finished');
122
 
123
+ clearInterval(clientTimerInterval); // Clear any existing timer
124
  clientTimerInterval = setInterval(function() {
125
  if (timeRemaining <= 0) {
126
  clearInterval(clientTimerInterval);
127
  timerElem.textContent = "Finished";
128
  timerElem.classList.add('timer-finished');
129
+ document.getElementById('alertMessage').textContent = "Irrigation time is over. The motor has stopped automatically.";
130
+ stopCameraAndTimer(); // Also stop camera stream
 
 
 
131
  } else {
132
  timerElem.textContent = timeRemaining + "s";
133
  }
 
135
  }, 1000);
136
  }
137
 
138
+ // --- FUNCTION TO STOP CAMERA AND TIMER ---
139
  function stopCameraAndTimer() {
 
140
  clearInterval(clientTimerInterval);
141
+ clearInterval(pollingInterval); // Stop polling once task is over
 
 
142
 
 
143
  if (cameraStream) {
144
  cameraStream.getTracks().forEach(track => track.stop());
145
  cameraStream = null;
146
  }
147
+
148
+ // We can hide the camera container or leave it visible with a "Finished" message
149
+ // document.getElementById('cameraContainer').style.display = 'none';
150
  }
151
  </script>
152
  </body>
153
+ </html>