WillemVH commited on
Commit
1a7c3fd
·
verified ·
1 Parent(s): 941e798

Create templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +309 -0
templates/index.html ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Servo Web Controller</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ background: #1e1e2e;
11
+ color: #dcdcdc;
12
+ margin: 0;
13
+ padding: 20px;
14
+ text-align: center;
15
+ }
16
+
17
+ .container {
18
+ max-width: 600px;
19
+ margin: 0 auto;
20
+ background: #262626;
21
+ padding: 20px;
22
+ border-radius: 10px;
23
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
24
+ }
25
+
26
+ h1 {
27
+ color: #ffffff;
28
+ margin-bottom: 20px;
29
+ }
30
+
31
+ .ip-section {
32
+ margin: 20px 0;
33
+ padding: 15px;
34
+ background: #2d2d2d;
35
+ border-radius: 5px;
36
+ }
37
+
38
+ input[type="text"] {
39
+ padding: 10px;
40
+ width: 200px;
41
+ border: 1px solid #555;
42
+ background: #1a1a1a;
43
+ color: white;
44
+ border-radius: 3px;
45
+ }
46
+
47
+ button {
48
+ padding: 10px 20px;
49
+ margin: 5px;
50
+ border: none;
51
+ border-radius: 5px;
52
+ cursor: pointer;
53
+ font-weight: bold;
54
+ transition: background 0.3s;
55
+ }
56
+
57
+ .start-btn {
58
+ background: #00ff64;
59
+ color: black;
60
+ }
61
+
62
+ .start-btn:hover {
63
+ background: #00cc50;
64
+ }
65
+
66
+ .stop-btn {
67
+ background: #ff5050;
68
+ color: white;
69
+ }
70
+
71
+ .stop-btn:hover {
72
+ background: #cc4040;
73
+ }
74
+
75
+ .reset-btn {
76
+ background: #5050ff;
77
+ color: white;
78
+ }
79
+
80
+ .reset-btn:hover {
81
+ background: #4040cc;
82
+ }
83
+
84
+ .status {
85
+ margin: 20px 0;
86
+ padding: 15px;
87
+ border-radius: 5px;
88
+ background: #2d2d2d;
89
+ }
90
+
91
+ .rotating {
92
+ background: #00ff64;
93
+ color: black;
94
+ font-weight: bold;
95
+ padding: 10px;
96
+ border-radius: 5px;
97
+ }
98
+
99
+ .stopped {
100
+ background: #ff5050;
101
+ color: white;
102
+ font-weight: bold;
103
+ padding: 10px;
104
+ border-radius: 5px;
105
+ }
106
+
107
+ .angles {
108
+ font-size: 18px;
109
+ margin: 15px 0;
110
+ }
111
+
112
+ .manual-control {
113
+ margin: 20px 0;
114
+ padding: 15px;
115
+ background: #2d2d2d;
116
+ border-radius: 5px;
117
+ }
118
+
119
+ .servo-control {
120
+ margin: 10px 0;
121
+ }
122
+
123
+ input[type="range"] {
124
+ width: 80%;
125
+ margin: 0 10px;
126
+ }
127
+ </style>
128
+ </head>
129
+ <body>
130
+ <div class="container">
131
+ <h1>Servo Web Controller</h1>
132
+
133
+ <div class="ip-section">
134
+ <h3>Set ESP32 IP Address</h3>
135
+ <input type="text" id="ipInput" placeholder="192.168.1.100">
136
+ <button onclick="setIP()">Set IP</button>
137
+ <div id="ipStatus"></div>
138
+ </div>
139
+
140
+ <div class="status">
141
+ <h3>Status</h3>
142
+ <div id="rotationStatus" class="stopped">STOPPED</div>
143
+ <div class="angles" id="anglesDisplay">Angles: 0°, 0°, 0°</div>
144
+ <div id="currentIP">ESP32 IP: Not set</div>
145
+ </div>
146
+
147
+ <div class="controls">
148
+ <button class="start-btn" onclick="startRotation()">Hold A (Start Rotation)</button>
149
+ <button class="stop-btn" onclick="stopRotation()">Release A (Emergency Stop)</button>
150
+ <button class="reset-btn" onclick="resetServos()">Press R (Reset to 0°)</button>
151
+ </div>
152
+
153
+ <div class="manual-control">
154
+ <h3>Manual Servo Control</h3>
155
+ <div class="servo-control">
156
+ Servo 1: <input type="range" id="servo1" min="0" max="180" value="0" onchange="setServoAngle(1, this.value)">
157
+ <span id="servo1Value">0°</span>
158
+ </div>
159
+ <div class="servo-control">
160
+ Servo 2: <input type="range" id="servo2" min="0" max="180" value="0" onchange="setServoAngle(2, this.value)">
161
+ <span id="servo2Value">0°</span>
162
+ </div>
163
+ <div class="servo-control">
164
+ Servo 3: <input type="range" id="servo3" min="0" max="180" value="0" onchange="setServoAngle(3, this.value)">
165
+ <span id="servo3Value">0°</span>
166
+ </div>
167
+ </div>
168
+
169
+ <div id="message" style="margin-top: 20px; min-height: 40px;"></div>
170
+ </div>
171
+
172
+ <script>
173
+ let currentIP = null;
174
+
175
+ function updateStatus() {
176
+ fetch('/get_status')
177
+ .then(response => response.json())
178
+ .then(data => {
179
+ document.getElementById('anglesDisplay').textContent =
180
+ `Angles: ${data.current_angles[0]}°, ${data.current_angles[1]}°, ${data.current_angles[2]}°`;
181
+
182
+ const statusElement = document.getElementById('rotationStatus');
183
+ if (data.rotation_active) {
184
+ statusElement.textContent = 'ROTATING';
185
+ statusElement.className = 'rotating';
186
+ } else {
187
+ statusElement.textContent = 'STOPPED';
188
+ statusElement.className = 'stopped';
189
+ }
190
+
191
+ if (data.esp_ip) {
192
+ currentIP = data.esp_ip;
193
+ document.getElementById('currentIP').textContent = `ESP32 IP: ${data.esp_ip}`;
194
+ }
195
+
196
+ // Update sliders
197
+ document.getElementById('servo1').value = data.current_angles[0];
198
+ document.getElementById('servo2').value = data.current_angles[1];
199
+ document.getElementById('servo3').value = data.current_angles[2];
200
+ document.getElementById('servo1Value').textContent = data.current_angles[0] + '°';
201
+ document.getElementById('servo2Value').textContent = data.current_angles[1] + '°';
202
+ document.getElementById('servo3Value').textContent = data.current_angles[2] + '°';
203
+ })
204
+ .catch(error => console.error('Error:', error));
205
+ }
206
+
207
+ function setIP() {
208
+ const ip = document.getElementById('ipInput').value;
209
+ if (!ip) {
210
+ showMessage('Please enter an IP address', 'error');
211
+ return;
212
+ }
213
+
214
+ fetch('/set_ip', {
215
+ method: 'POST',
216
+ headers: {
217
+ 'Content-Type': 'application/json',
218
+ },
219
+ body: JSON.stringify({ip: ip})
220
+ })
221
+ .then(response => response.json())
222
+ .then(data => {
223
+ showMessage(data.message, data.status);
224
+ updateStatus();
225
+ })
226
+ .catch(error => {
227
+ showMessage('Error setting IP: ' + error, 'error');
228
+ });
229
+ }
230
+
231
+ function startRotation() {
232
+ fetch('/start_rotation', {
233
+ method: 'POST'
234
+ })
235
+ .then(response => response.json())
236
+ .then(data => {
237
+ showMessage(data.message, data.status);
238
+ updateStatus();
239
+ })
240
+ .catch(error => {
241
+ showMessage('Error starting rotation: ' + error, 'error');
242
+ });
243
+ }
244
+
245
+ function stopRotation() {
246
+ fetch('/stop_rotation', {
247
+ method: 'POST'
248
+ })
249
+ .then(response => response.json())
250
+ .then(data => {
251
+ showMessage(data.message + ' - ' + data.stop_message, data.status);
252
+ updateStatus();
253
+ })
254
+ .catch(error => {
255
+ showMessage('Error stopping rotation: ' + error, 'error');
256
+ });
257
+ }
258
+
259
+ function resetServos() {
260
+ fetch('/reset_servos', {
261
+ method: 'POST'
262
+ })
263
+ .then(response => response.json())
264
+ .then(data => {
265
+ showMessage(data.message, data.status);
266
+ updateStatus();
267
+ })
268
+ .catch(error => {
269
+ showMessage('Error resetting servos: ' + error, 'error');
270
+ });
271
+ }
272
+
273
+ function setServoAngle(servoNum, angle) {
274
+ document.getElementById(`servo${servoNum}Value`).textContent = angle + '°';
275
+
276
+ fetch('/set_angle', {
277
+ method: 'POST',
278
+ headers: {
279
+ 'Content-Type': 'application/json',
280
+ },
281
+ body: JSON.stringify({servo: servoNum, angle: parseInt(angle)})
282
+ })
283
+ .then(response => response.json())
284
+ .then(data => {
285
+ if (data.status === 'success') {
286
+ updateStatus();
287
+ } else {
288
+ showMessage(data.message, 'error');
289
+ }
290
+ })
291
+ .catch(error => {
292
+ showMessage('Error setting angle: ' + error, 'error');
293
+ });
294
+ }
295
+
296
+ function showMessage(message, type) {
297
+ const messageElement = document.getElementById('message');
298
+ messageElement.textContent = message;
299
+ messageElement.style.color = type === 'error' ? '#ff5050' : '#00ff64';
300
+ }
301
+
302
+ // Update status every second
303
+ setInterval(updateStatus, 1000);
304
+
305
+ // Initial status update
306
+ updateStatus();
307
+ </script>
308
+ </body>
309
+ </html>