theta_rho_controller.html 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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>Theta-Rho Controller</title>
  7. <style>
  8. #theta_rho_files li {
  9. cursor: pointer;
  10. }
  11. #theta_rho_files li.selected {
  12. font-weight: bold;
  13. color: green;
  14. }
  15. .status {
  16. margin-top: 1em;
  17. font-weight: bold;
  18. }
  19. #serial_status {
  20. color: blue;
  21. }
  22. </style>
  23. </head>
  24. <body>
  25. <h1>Theta-Rho Controller</h1>
  26. <h2>Serial Connection</h2>
  27. <label for="serial_ports">Available Ports:</label>
  28. <select id="serial_ports"></select>
  29. <button onclick="connectSerial()">Connect</button>
  30. <button onclick="disconnectSerial()">Disconnect</button>
  31. <button onclick="restartSerial()">Restart</button>
  32. <p id="serial_status" class="status">Status: Not connected</p>
  33. <h2>Theta-Rho Files</h2>
  34. <ul id="theta_rho_files"></ul>
  35. <input type="file" id="upload_file">
  36. <button onclick="uploadThetaRho()">Upload</button>
  37. <h2>Run Theta-Rho</h2>
  38. <button id="run_button" disabled>Run Selected File</button>
  39. <button onclick="stopExecution()">Stop</button>
  40. <h2>Quick Actions</h2>
  41. <button onclick="sendHomeCommand()">Home Device</button>
  42. <button onclick="runClearIn()">Clear from in</button>
  43. <button onclick="runClearOut()">Clear from out</button>
  44. <script>
  45. let selectedFile = null;
  46. async function loadSerialPorts() {
  47. const response = await fetch('/list_serial_ports');
  48. const ports = await response.json();
  49. const select = document.getElementById('serial_ports');
  50. select.innerHTML = '';
  51. ports.forEach(port => {
  52. const option = document.createElement('option');
  53. option.value = port;
  54. option.textContent = port;
  55. select.appendChild(option);
  56. });
  57. }
  58. async function connectSerial() {
  59. const port = document.getElementById('serial_ports').value;
  60. const response = await fetch('/connect_serial', {
  61. method: 'POST',
  62. headers: { 'Content-Type': 'application/json' },
  63. body: JSON.stringify({ port })
  64. });
  65. const result = await response.json();
  66. if (result.success) {
  67. document.getElementById('serial_status').textContent = `Status: Connected to ${port}`;
  68. alert('Connected to serial port!');
  69. } else {
  70. alert(`Error connecting to serial port: ${result.error}`);
  71. }
  72. }
  73. async function disconnectSerial() {
  74. const response = await fetch('/disconnect_serial', { method: 'POST' });
  75. const result = await response.json();
  76. if (result.success) {
  77. document.getElementById('serial_status').textContent = 'Status: Disconnected';
  78. alert('Serial port disconnected!');
  79. } else {
  80. alert(`Error disconnecting: ${result.error}`);
  81. }
  82. }
  83. async function restartSerial() {
  84. const port = document.getElementById('serial_ports').value;
  85. const response = await fetch('/restart_serial', {
  86. method: 'POST',
  87. headers: { 'Content-Type': 'application/json' },
  88. body: JSON.stringify({ port })
  89. });
  90. const result = await response.json();
  91. if (result.success) {
  92. document.getElementById('serial_status').textContent = `Status: Restarted connection to ${port}`;
  93. alert('Serial connection restarted!');
  94. } else {
  95. alert(`Error restarting serial connection: ${result.error}`);
  96. }
  97. }
  98. async function loadThetaRhoFiles() {
  99. const response = await fetch('/list_theta_rho_files');
  100. const files = await response.json();
  101. const ul = document.getElementById('theta_rho_files');
  102. ul.innerHTML = '';
  103. files.forEach(file => {
  104. const li = document.createElement('li');
  105. li.textContent = file;
  106. li.onclick = () => selectFile(file, li);
  107. ul.appendChild(li);
  108. });
  109. }
  110. function selectFile(file, listItem) {
  111. selectedFile = file;
  112. document.querySelectorAll('#theta_rho_files li').forEach(li => li.classList.remove('selected'));
  113. listItem.classList.add('selected');
  114. document.getElementById('run_button').disabled = false;
  115. }
  116. async function uploadThetaRho() {
  117. const fileInput = document.getElementById('upload_file');
  118. const file = fileInput.files[0];
  119. const formData = new FormData();
  120. formData.append('file', file);
  121. const response = await fetch('/upload_theta_rho', {
  122. method: 'POST',
  123. body: formData
  124. });
  125. const result = await response.json();
  126. if (result.success) {
  127. alert('File uploaded successfully!');
  128. loadThetaRhoFiles();
  129. } else {
  130. alert('Failed to upload file.');
  131. }
  132. }
  133. async function runThetaRho() {
  134. if (!selectedFile) return;
  135. const response = await fetch('/run_theta_rho', {
  136. method: 'POST',
  137. headers: { 'Content-Type': 'application/json' },
  138. body: JSON.stringify({ file_name: selectedFile })
  139. });
  140. const result = await response.json();
  141. if (result.success) {
  142. alert(`Running Theta-Rho file: ${selectedFile}`);
  143. } else {
  144. alert(`Error starting Theta-Rho execution: ${result.error}`);
  145. }
  146. }
  147. async function stopExecution() {
  148. const response = await fetch('/stop_execution', { method: 'POST' });
  149. const result = await response.json();
  150. if (result.success) {
  151. alert('Execution stopped.');
  152. } else {
  153. alert('Failed to stop execution.');
  154. }
  155. }
  156. async function sendHomeCommand() {
  157. const response = await fetch('/send_home', { method: 'POST' });
  158. const result = await response.json();
  159. if (result.success) {
  160. alert('HOME command sent successfully!');
  161. } else {
  162. alert('Failed to send HOME command.');
  163. }
  164. }
  165. async function runClearIn() {
  166. await runFile('clear_from_in.thr');
  167. }
  168. async function runClearOut() {
  169. await runFile('clear_from_out.thr');
  170. }
  171. async function runFile(fileName) {
  172. const response = await fetch(`/run_theta_rho_file/${fileName}`, { method: 'POST' });
  173. const result = await response.json();
  174. if (result.success) {
  175. alert(`Running file: ${fileName}`);
  176. } else {
  177. alert(`Failed to run file: ${fileName}`);
  178. }
  179. }
  180. // Initial load of serial ports and Theta-Rho files
  181. loadSerialPorts();
  182. loadThetaRhoFiles();
  183. // Attach runThetaRho function to the Run button
  184. document.getElementById('run_button').onclick = runThetaRho;
  185. </script>
  186. </body>
  187. </html>