theta_rho_controller.html 8.3 KB

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