drbaker171 commited on
Commit
15e8115
·
verified ·
1 Parent(s): 374a766

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +64 -166
index.html CHANGED
@@ -3,6 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
6
  <title>ESP32/Arduino Code Uploader</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs/loader.js"></script>
@@ -68,6 +69,12 @@
68
  max-width: 500px;
69
  width: 90%;
70
  }
 
 
 
 
 
 
71
  </style>
72
  </head>
73
  <body class="bg-gray-50 min-h-screen">
@@ -76,10 +83,13 @@
76
  <div class="permission-content">
77
  <h2 class="text-xl font-bold mb-4">Serial Port Access Required</h2>
78
  <p class="mb-4">To connect to your device, you need to grant permission to access serial ports. Please click the button below and select your device from the browser's prompt.</p>
79
- <div class="flex justify-center">
80
- <button id="requestPermissionBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded-md">
81
  <i class="fas fa-key mr-2"></i> Grant Permission
82
  </button>
 
 
 
83
  </div>
84
  </div>
85
  </div>
@@ -93,6 +103,21 @@
93
  <p class="text-gray-600 mt-2">Upload and manage your sketches for ESP32 and Arduino devices</p>
94
  </header>
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
97
  <!-- Left Column - Connection & Upload -->
98
  <div class="lg:col-span-1 space-y-6">
@@ -143,7 +168,7 @@
143
  </div>
144
 
145
  <div class="pt-2">
146
- <button id="connectBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md flex items-center justify-center">
147
  <i class="fas fa-link mr-2"></i>
148
  Connect
149
  </button>
@@ -350,6 +375,9 @@
350
  let activePorts = [];
351
 
352
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
353
  // Tab switching
354
  const editorTab = document.getElementById('editorTab');
355
  const serialTab = document.getElementById('serialTab');
@@ -579,6 +607,21 @@
579
  const portHelp = document.getElementById('portHelp');
580
  const permissionModal = document.getElementById('permissionModal');
581
  const requestPermissionBtn = document.getElementById('requestPermissionBtn');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
 
583
  // Show permission modal
584
  function showPermissionModal() {
@@ -590,6 +633,11 @@
590
  permissionModal.style.display = 'none';
591
  }
592
 
 
 
 
 
 
593
  // Request permission button handler
594
  requestPermissionBtn.addEventListener('click', async () => {
595
  try {
@@ -609,7 +657,7 @@
609
  } catch (error) {
610
  if (error.name === 'NotFoundError') {
611
  addToOutputConsole('No device was selected', 'info');
612
- portHelp.textContent = 'No device selected';
613
  } else if (error.name === 'SecurityError') {
614
  addToOutputConsole('Permission denied for serial port access', 'error');
615
  portHelp.textContent = 'Permission denied. Please allow serial port access.';
@@ -622,6 +670,8 @@
622
  });
623
 
624
  async function refreshPortList() {
 
 
625
  portSelect.innerHTML = '<option value="">Select a port</option>';
626
  activePorts = [];
627
 
@@ -665,12 +715,15 @@
665
  portHelp.textContent = `Found ${ports.length} serial port(s)`;
666
  addToOutputConsole(`Found ${ports.length} serial port(s)`);
667
  } catch (error) {
668
- addToOutputConsole(`Error accessing serial ports: ${error}`, 'error');
669
- portSelect.innerHTML = '<option value="">Error accessing ports</option>';
670
- portHelp.textContent = 'Error accessing ports. Make sure to grant permission when prompted.';
671
-
672
- // Show permission modal since we got an error
673
- showPermissionModal();
 
 
 
674
  }
675
  }
676
 
@@ -804,160 +857,5 @@
804
  connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
805
  connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
806
 
807
- connectionStatus.classList.remove('bg-green-100', 'text-green-700');
808
- connectionStatus.classList.add('bg-gray-100', 'text-gray-700');
809
- connectionStatus.innerHTML = '<i class="fas fa-circle mr-2 text-gray-400"></i><span>Disconnected</span>';
810
-
811
- addToOutputConsole('Disconnected from device');
812
- uploadBtn.disabled = true;
813
- }
814
-
815
- async function readSerialData() {
816
- while (isReading && port.readable) {
817
- try {
818
- const { value, done } = await reader.read();
819
- if (done) {
820
- reader.releaseLock();
821
- break;
822
- }
823
-
824
- if (value) {
825
- const text = new TextDecoder().decode(value);
826
- addToSerialMonitor(text);
827
- }
828
- } catch (error) {
829
- addToOutputConsole(`Error reading from serial port: ${error}`, 'error');
830
- await disconnectFromPort();
831
- break;
832
- }
833
- }
834
- }
835
-
836
- connectBtn.addEventListener('click', async () => {
837
- if (isConnected) {
838
- await disconnectFromPort();
839
- } else {
840
- await connectToPort();
841
- }
842
- });
843
-
844
- // Upload simulation with board-specific settings
845
- uploadBtn.addEventListener('click', async () => {
846
- if (!isConnected) {
847
- addToOutputConsole('Please connect to a device first', 'error');
848
- return;
849
- }
850
-
851
- const boardType = boardSelect.value;
852
- const config = boardConfigurations[boardType];
853
-
854
- const uploadProgress = document.getElementById('uploadProgress');
855
- const progressBar = document.getElementById('progressBar');
856
- const progressPercent = document.getElementById('progressPercent');
857
-
858
- uploadProgress.classList.remove('hidden');
859
- progressBar.style.width = '0%';
860
- progressPercent.textContent = '0%';
861
-
862
- // Show board-specific settings in output
863
- addToOutputConsole(`Preparing to upload to ${config.name}`);
864
- addToOutputConsole(`Board: ${config.name}`);
865
-
866
- if (boardType.startsWith('esp32') || boardType === 'cyd_esp32') {
867
- addToOutputConsole(`Flash Mode: ${document.getElementById('flashMode')?.value || config.flashMode}`);
868
- addToOutputConsole(`Flash Frequency: ${document.getElementById('flashFreq')?.value || config.flashFreq}`);
869
- addToOutputConsole(`Upload Speed: ${document.getElementById('uploadSpeed')?.value || config.uploadSpeed}`);
870
- } else {
871
- // Arduino settings
872
- addToOutputConsole(`Processor: ${config.processor}`);
873
- addToOutputConsole(`Programmer: ${document.getElementById('programmer')?.value || config.programmer}`);
874
- }
875
-
876
- addToOutputConsole('Compiling sketch...');
877
-
878
- // Simulate compilation and upload
879
- let progress = 0;
880
- const interval = setInterval(() => {
881
- progress += Math.random() * 10;
882
- if (progress > 100) progress = 100;
883
-
884
- progressBar.style.width = `${progress}%`;
885
- progressPercent.textContent = `${Math.floor(progress)}%`;
886
-
887
- if (progress === 100) {
888
- clearInterval(interval);
889
- setTimeout(() => {
890
- uploadProgress.classList.add('hidden');
891
- addToOutputConsole('Upload complete!');
892
- addToSerialMonitor('Sketch uploaded successfully');
893
-
894
- // Board-specific success message
895
- if (boardType === 'cyd_esp32') {
896
- addToOutputConsole('CYD ESP32-2432S028: Touch screen initialized', 'success');
897
- } else if (boardType === 'uno') {
898
- addToOutputConsole('Arduino UNO: Sketch running', 'success');
899
- }
900
- }, 500);
901
- }
902
- }, 200);
903
- });
904
-
905
- // Verify button with board-specific settings
906
- document.getElementById('verifyBtn').addEventListener('click', () => {
907
- const boardType = boardSelect.value;
908
- const config = boardConfigurations[boardType];
909
-
910
- addToOutputConsole(`Verifying sketch for ${config.name}...`);
911
-
912
- setTimeout(() => {
913
- if (boardType.startsWith('esp32') || boardType === 'cyd_esp32') {
914
- addToOutputConsole('Sketch uses ' + Math.floor(Math.random() * 20 + 10) + 'KB (' +
915
- Math.floor(Math.random() * 10 + 5) + '%) of program storage space.');
916
- addToOutputConsole('Global variables use ' + Math.floor(Math.random() * 5 + 1) + 'KB of dynamic memory.');
917
- } else {
918
- // Arduino boards
919
- addToOutputConsole('Sketch uses ' + Math.floor(Math.random() * 30 + 5) + ' bytes (' +
920
- Math.floor(Math.random() * 10 + 2) + '%) of program storage space.');
921
- addToOutputConsole('Global variables use ' + Math.floor(Math.random() * 200 + 50) + ' bytes of dynamic memory.');
922
- }
923
-
924
- addToOutputConsole('Done verifying sketch.', 'success');
925
- }, 1500);
926
- });
927
-
928
- // Output console helper
929
- function addToOutputConsole(text, type = 'info') {
930
- const console = document.getElementById('outputConsole');
931
- const line = document.createElement('p');
932
-
933
- if (type === 'error') {
934
- line.className = 'text-red-400';
935
- line.textContent = '! ' + text;
936
- } else if (type === 'success') {
937
- line.className = 'text-green-400';
938
- line.textContent = '✓ ' + text;
939
- } else {
940
- line.textContent = '> ' + text;
941
- }
942
-
943
- console.appendChild(line);
944
- console.scrollTop = console.scrollHeight;
945
- }
946
-
947
- // Check if Web Serial API is available
948
- if (!('serial' in navigator)) {
949
- addToOutputConsole('Web Serial API not supported in this browser. Try Chrome or Edge.', 'error');
950
- portHelp.textContent = 'Web Serial API not supported. Use Chrome or Edge.';
951
- refreshPorts.disabled = true;
952
- connectBtn.disabled = true;
953
- } else {
954
- // Initial port refresh
955
- refreshPortList();
956
- }
957
-
958
- // Trigger initial board selection
959
- boardSelect.dispatchEvent(new Event('change'));
960
- });
961
- </script>
962
- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=drbaker171/esp" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
963
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="Permissions-Policy" content="serial=(self)">
7
  <title>ESP32/Arduino Code Uploader</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.43.0/min/vs/loader.js"></script>
 
69
  max-width: 500px;
70
  width: 90%;
71
  }
72
+ .browser-warning {
73
+ background-color: #fef3c7;
74
+ border-left: 4px solid #f59e0b;
75
+ padding: 1rem;
76
+ margin-bottom: 1rem;
77
+ }
78
  </style>
79
  </head>
80
  <body class="bg-gray-50 min-h-screen">
 
83
  <div class="permission-content">
84
  <h2 class="text-xl font-bold mb-4">Serial Port Access Required</h2>
85
  <p class="mb-4">To connect to your device, you need to grant permission to access serial ports. Please click the button below and select your device from the browser's prompt.</p>
86
+ <div class="flex flex-col space-y-4">
87
+ <button id="requestPermissionBtn" class="bg-blue-600 hover:bg-blue-700 text-white py-2 px-6 rounded-md flex items-center justify-center">
88
  <i class="fas fa-key mr-2"></i> Grant Permission
89
  </button>
90
+ <button id="learnMoreBtn" class="text-blue-600 hover:text-blue-800 py-2 px-6 rounded-md flex items-center justify-center">
91
+ <i class="fas fa-info-circle mr-2"></i> Learn More About Serial Access
92
+ </button>
93
  </div>
94
  </div>
95
  </div>
 
103
  <p class="text-gray-600 mt-2">Upload and manage your sketches for ESP32 and Arduino devices</p>
104
  </header>
105
 
106
+ <!-- Browser Warning (hidden by default) -->
107
+ <div id="browserWarning" class="browser-warning hidden">
108
+ <div class="flex items-start">
109
+ <div class="flex-shrink-0">
110
+ <i class="fas fa-exclamation-triangle text-yellow-600"></i>
111
+ </div>
112
+ <div class="ml-3">
113
+ <h3 class="text-sm font-medium text-yellow-800">Browser Compatibility Notice</h3>
114
+ <div class="mt-2 text-sm text-yellow-700">
115
+ <p>This application requires the Web Serial API which is currently only supported in Chrome/Edge 89+ and Opera 76+.</p>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ </div>
120
+
121
  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
122
  <!-- Left Column - Connection & Upload -->
123
  <div class="lg:col-span-1 space-y-6">
 
168
  </div>
169
 
170
  <div class="pt-2">
171
+ <button id="connectBtn" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md flex items-center justify-center disabled:opacity-50 disabled:cursor-not-allowed">
172
  <i class="fas fa-link mr-2"></i>
173
  Connect
174
  </button>
 
375
  let activePorts = [];
376
 
377
  document.addEventListener('DOMContentLoaded', function() {
378
+ // Check browser compatibility first
379
+ checkBrowserCompatibility();
380
+
381
  // Tab switching
382
  const editorTab = document.getElementById('editorTab');
383
  const serialTab = document.getElementById('serialTab');
 
607
  const portHelp = document.getElementById('portHelp');
608
  const permissionModal = document.getElementById('permissionModal');
609
  const requestPermissionBtn = document.getElementById('requestPermissionBtn');
610
+ const learnMoreBtn = document.getElementById('learnMoreBtn');
611
+ const browserWarning = document.getElementById('browserWarning');
612
+
613
+ // Check browser compatibility
614
+ function checkBrowserCompatibility() {
615
+ if (!('serial' in navigator)) {
616
+ browserWarning.classList.remove('hidden');
617
+ refreshPorts.disabled = true;
618
+ connectBtn.disabled = true;
619
+ portHelp.textContent = 'Web Serial API not supported in this browser. Use Chrome/Edge 89+ or Opera 76+.';
620
+ addToOutputConsole('Web Serial API not supported in this browser. Try Chrome/Edge 89+ or Opera 76+.', 'error');
621
+ return false;
622
+ }
623
+ return true;
624
+ }
625
 
626
  // Show permission modal
627
  function showPermissionModal() {
 
633
  permissionModal.style.display = 'none';
634
  }
635
 
636
+ // Learn more button handler
637
+ learnMoreBtn.addEventListener('click', () => {
638
+ window.open('https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API', '_blank');
639
+ });
640
+
641
  // Request permission button handler
642
  requestPermissionBtn.addEventListener('click', async () => {
643
  try {
 
657
  } catch (error) {
658
  if (error.name === 'NotFoundError') {
659
  addToOutputConsole('No device was selected', 'info');
660
+ portHelp.textContent = 'No device selected. Make sure your device is connected.';
661
  } else if (error.name === 'SecurityError') {
662
  addToOutputConsole('Permission denied for serial port access', 'error');
663
  portHelp.textContent = 'Permission denied. Please allow serial port access.';
 
670
  });
671
 
672
  async function refreshPortList() {
673
+ if (!checkBrowserCompatibility()) return;
674
+
675
  portSelect.innerHTML = '<option value="">Select a port</option>';
676
  activePorts = [];
677
 
 
715
  portHelp.textContent = `Found ${ports.length} serial port(s)`;
716
  addToOutputConsole(`Found ${ports.length} serial port(s)`);
717
  } catch (error) {
718
+ if (error.name === 'SecurityError') {
719
+ addToOutputConsole('Permission denied for serial port access. Please grant permission.', 'error');
720
+ portHelp.textContent = 'Permission denied. Please allow serial port access.';
721
+ showPermissionModal();
722
+ } else {
723
+ addToOutputConsole(`Error accessing serial ports: ${error}`, 'error');
724
+ portSelect.innerHTML = '<option value="">Error accessing ports</option>';
725
+ portHelp.textContent = 'Error accessing ports. Please try again.';
726
+ }
727
  }
728
  }
729
 
 
857
  connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
858
  connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
859
 
860
+ connectionStatus
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861
  </html>