Spaces:
Running
Running
Add 1 files
Browse files- index.html +82 -10
index.html
CHANGED
|
@@ -41,6 +41,14 @@
|
|
| 41 |
from, to { opacity: 1 }
|
| 42 |
50% { opacity: 0.5 }
|
| 43 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
</style>
|
| 45 |
</head>
|
| 46 |
<body class="bg-gray-50 min-h-screen">
|
|
@@ -74,6 +82,7 @@
|
|
| 74 |
<i class="fas fa-sync-alt"></i>
|
| 75 |
</button>
|
| 76 |
</div>
|
|
|
|
| 77 |
</div>
|
| 78 |
|
| 79 |
<div>
|
|
@@ -306,6 +315,7 @@
|
|
| 306 |
let writer = null;
|
| 307 |
let isReading = false;
|
| 308 |
let isConnected = false;
|
|
|
|
| 309 |
|
| 310 |
document.addEventListener('DOMContentLoaded', function() {
|
| 311 |
// Tab switching
|
|
@@ -534,9 +544,11 @@
|
|
| 534 |
const connectBtn = document.getElementById('connectBtn');
|
| 535 |
const connectionStatus = document.getElementById('connectionStatus');
|
| 536 |
const uploadBtn = document.getElementById('uploadBtn');
|
|
|
|
| 537 |
|
| 538 |
async function refreshPortList() {
|
| 539 |
portSelect.innerHTML = '<option value="">Select a port</option>';
|
|
|
|
| 540 |
|
| 541 |
try {
|
| 542 |
// Request permission to access serial ports
|
|
@@ -544,36 +556,70 @@
|
|
| 544 |
|
| 545 |
if (ports.length === 0) {
|
| 546 |
portSelect.innerHTML = '<option value="">No ports found</option>';
|
|
|
|
| 547 |
addToOutputConsole('No serial ports found. Connect a device and click refresh.');
|
| 548 |
return;
|
| 549 |
}
|
| 550 |
|
| 551 |
-
ports
|
|
|
|
|
|
|
|
|
|
| 552 |
const option = document.createElement('option');
|
| 553 |
-
option.value =
|
| 554 |
-
|
| 555 |
-
|
|
|
|
|
|
|
| 556 |
'Serial Port';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
portSelect.appendChild(option);
|
| 558 |
});
|
| 559 |
|
|
|
|
| 560 |
addToOutputConsole(`Found ${ports.length} serial port(s)`);
|
| 561 |
} catch (error) {
|
| 562 |
addToOutputConsole(`Error accessing serial ports: ${error}`, 'error');
|
| 563 |
portSelect.innerHTML = '<option value="">Error accessing ports</option>';
|
|
|
|
| 564 |
}
|
| 565 |
}
|
| 566 |
|
| 567 |
refreshPorts.addEventListener('click', async () => {
|
| 568 |
refreshPorts.classList.add('blink');
|
| 569 |
addToOutputConsole('Searching for serial ports...');
|
|
|
|
| 570 |
|
| 571 |
try {
|
| 572 |
-
// Request permission to access serial ports
|
| 573 |
-
await navigator.serial.requestPort(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 574 |
await refreshPortList();
|
| 575 |
} catch (error) {
|
| 576 |
-
if (error.name
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 577 |
addToOutputConsole(`Error: ${error.message}`, 'error');
|
| 578 |
}
|
| 579 |
} finally {
|
|
@@ -587,10 +633,14 @@
|
|
| 587 |
return;
|
| 588 |
}
|
| 589 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 590 |
try {
|
| 591 |
-
|
| 592 |
-
const ports = await navigator.serial.getPorts();
|
| 593 |
-
port = ports.find(p => p.id === portSelect.value);
|
| 594 |
|
| 595 |
if (!port) {
|
| 596 |
throw new Error('Selected port not found');
|
|
@@ -624,8 +674,17 @@
|
|
| 624 |
addToOutputConsole(`Connected to ${portSelect.options[portSelect.selectedIndex].text} at ${config.baudRate} baud`);
|
| 625 |
uploadBtn.disabled = false;
|
| 626 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
} catch (error) {
|
| 628 |
addToOutputConsole(`Error connecting to port: ${error}`, 'error');
|
|
|
|
|
|
|
| 629 |
if (port) {
|
| 630 |
try {
|
| 631 |
await port.close();
|
|
@@ -634,6 +693,18 @@
|
|
| 634 |
}
|
| 635 |
port = null;
|
| 636 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 637 |
}
|
| 638 |
}
|
| 639 |
|
|
@@ -816,6 +887,7 @@
|
|
| 816 |
// Check if Web Serial API is available
|
| 817 |
if (!('serial' in navigator)) {
|
| 818 |
addToOutputConsole('Web Serial API not supported in this browser. Try Chrome or Edge.', 'error');
|
|
|
|
| 819 |
refreshPorts.disabled = true;
|
| 820 |
connectBtn.disabled = true;
|
| 821 |
} else {
|
|
|
|
| 41 |
from, to { opacity: 1 }
|
| 42 |
50% { opacity: 0.5 }
|
| 43 |
}
|
| 44 |
+
.port-option {
|
| 45 |
+
display: flex;
|
| 46 |
+
align-items: center;
|
| 47 |
+
}
|
| 48 |
+
.port-icon {
|
| 49 |
+
margin-right: 8px;
|
| 50 |
+
color: #4b5563;
|
| 51 |
+
}
|
| 52 |
</style>
|
| 53 |
</head>
|
| 54 |
<body class="bg-gray-50 min-h-screen">
|
|
|
|
| 82 |
<i class="fas fa-sync-alt"></i>
|
| 83 |
</button>
|
| 84 |
</div>
|
| 85 |
+
<p id="portHelp" class="mt-1 text-xs text-gray-500">Connect your device and click refresh</p>
|
| 86 |
</div>
|
| 87 |
|
| 88 |
<div>
|
|
|
|
| 315 |
let writer = null;
|
| 316 |
let isReading = false;
|
| 317 |
let isConnected = false;
|
| 318 |
+
let activePorts = [];
|
| 319 |
|
| 320 |
document.addEventListener('DOMContentLoaded', function() {
|
| 321 |
// Tab switching
|
|
|
|
| 544 |
const connectBtn = document.getElementById('connectBtn');
|
| 545 |
const connectionStatus = document.getElementById('connectionStatus');
|
| 546 |
const uploadBtn = document.getElementById('uploadBtn');
|
| 547 |
+
const portHelp = document.getElementById('portHelp');
|
| 548 |
|
| 549 |
async function refreshPortList() {
|
| 550 |
portSelect.innerHTML = '<option value="">Select a port</option>';
|
| 551 |
+
activePorts = [];
|
| 552 |
|
| 553 |
try {
|
| 554 |
// Request permission to access serial ports
|
|
|
|
| 556 |
|
| 557 |
if (ports.length === 0) {
|
| 558 |
portSelect.innerHTML = '<option value="">No ports found</option>';
|
| 559 |
+
portHelp.textContent = 'No serial ports found. Connect a device and click refresh.';
|
| 560 |
addToOutputConsole('No serial ports found. Connect a device and click refresh.');
|
| 561 |
return;
|
| 562 |
}
|
| 563 |
|
| 564 |
+
// Store ports for later reference
|
| 565 |
+
activePorts = ports;
|
| 566 |
+
|
| 567 |
+
ports.forEach((port, index) => {
|
| 568 |
const option = document.createElement('option');
|
| 569 |
+
option.value = index; // Using index as value since port objects can't be serialized
|
| 570 |
+
|
| 571 |
+
const portInfo = port.getInfo();
|
| 572 |
+
const portName = portInfo.usbVendorId ?
|
| 573 |
+
`Serial Port (Vendor: 0x${portInfo.usbVendorId.toString(16)}, Product: 0x${portInfo.usbProductId.toString(16)})` :
|
| 574 |
'Serial Port';
|
| 575 |
+
|
| 576 |
+
const optionContent = document.createElement('div');
|
| 577 |
+
optionContent.className = 'port-option';
|
| 578 |
+
optionContent.innerHTML = `
|
| 579 |
+
<i class="fas fa-microchip port-icon"></i>
|
| 580 |
+
<span>${portName}</span>
|
| 581 |
+
`;
|
| 582 |
+
|
| 583 |
+
option.textContent = portName;
|
| 584 |
portSelect.appendChild(option);
|
| 585 |
});
|
| 586 |
|
| 587 |
+
portHelp.textContent = `Found ${ports.length} serial port(s)`;
|
| 588 |
addToOutputConsole(`Found ${ports.length} serial port(s)`);
|
| 589 |
} catch (error) {
|
| 590 |
addToOutputConsole(`Error accessing serial ports: ${error}`, 'error');
|
| 591 |
portSelect.innerHTML = '<option value="">Error accessing ports</option>';
|
| 592 |
+
portHelp.textContent = 'Error accessing ports. Make sure to grant permission when prompted.';
|
| 593 |
}
|
| 594 |
}
|
| 595 |
|
| 596 |
refreshPorts.addEventListener('click', async () => {
|
| 597 |
refreshPorts.classList.add('blink');
|
| 598 |
addToOutputConsole('Searching for serial ports...');
|
| 599 |
+
portHelp.textContent = 'Searching for devices...';
|
| 600 |
|
| 601 |
try {
|
| 602 |
+
// Request permission to access serial ports with filters
|
| 603 |
+
const port = await navigator.serial.requestPort({
|
| 604 |
+
filters: [
|
| 605 |
+
{ usbVendorId: 0x2341 }, // Arduino
|
| 606 |
+
{ usbVendorId: 0x2A03 }, // Arduino (alternative)
|
| 607 |
+
{ usbVendorId: 0x10C4 }, // ESP32
|
| 608 |
+
{ usbVendorId: 0x1A86 } // CH340 (common USB-to-serial)
|
| 609 |
+
]
|
| 610 |
+
});
|
| 611 |
+
|
| 612 |
+
// After permission is granted, refresh the list
|
| 613 |
await refreshPortList();
|
| 614 |
} catch (error) {
|
| 615 |
+
if (error.name === 'NotFoundError') {
|
| 616 |
+
portHelp.textContent = 'No device selected';
|
| 617 |
+
addToOutputConsole('No device was selected', 'info');
|
| 618 |
+
} else if (error.name === 'SecurityError') {
|
| 619 |
+
portHelp.textContent = 'Permission denied. Please allow serial port access.';
|
| 620 |
+
addToOutputConsole('Permission denied for serial port access', 'error');
|
| 621 |
+
} else {
|
| 622 |
+
portHelp.textContent = `Error: ${error.message}`;
|
| 623 |
addToOutputConsole(`Error: ${error.message}`, 'error');
|
| 624 |
}
|
| 625 |
} finally {
|
|
|
|
| 633 |
return;
|
| 634 |
}
|
| 635 |
|
| 636 |
+
const portIndex = parseInt(portSelect.value);
|
| 637 |
+
if (isNaN(portIndex) || portIndex < 0 || portIndex >= activePorts.length) {
|
| 638 |
+
addToOutputConsole('Invalid port selection', 'error');
|
| 639 |
+
return;
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
try {
|
| 643 |
+
port = activePorts[portIndex];
|
|
|
|
|
|
|
| 644 |
|
| 645 |
if (!port) {
|
| 646 |
throw new Error('Selected port not found');
|
|
|
|
| 674 |
addToOutputConsole(`Connected to ${portSelect.options[portSelect.selectedIndex].text} at ${config.baudRate} baud`);
|
| 675 |
uploadBtn.disabled = false;
|
| 676 |
|
| 677 |
+
// Send a test message to check connection
|
| 678 |
+
setTimeout(() => {
|
| 679 |
+
if (isConnected) {
|
| 680 |
+
sendSerialData("AT"); // Common test command
|
| 681 |
+
}
|
| 682 |
+
}, 500);
|
| 683 |
+
|
| 684 |
} catch (error) {
|
| 685 |
addToOutputConsole(`Error connecting to port: ${error}`, 'error');
|
| 686 |
+
portHelp.textContent = `Connection failed: ${error.message}`;
|
| 687 |
+
|
| 688 |
if (port) {
|
| 689 |
try {
|
| 690 |
await port.close();
|
|
|
|
| 693 |
}
|
| 694 |
port = null;
|
| 695 |
}
|
| 696 |
+
|
| 697 |
+
// Reset connection state
|
| 698 |
+
isConnected = false;
|
| 699 |
+
connectBtn.innerHTML = '<i class="fas fa-link mr-2"></i> Connect';
|
| 700 |
+
connectBtn.classList.remove('bg-red-600', 'hover:bg-red-700');
|
| 701 |
+
connectBtn.classList.add('bg-blue-600', 'hover:bg-blue-700');
|
| 702 |
+
|
| 703 |
+
connectionStatus.classList.remove('bg-green-100', 'text-green-700');
|
| 704 |
+
connectionStatus.classList.add('bg-gray-100', 'text-gray-700');
|
| 705 |
+
connectionStatus.innerHTML = '<i class="fas fa-circle mr-2 text-gray-400"></i><span>Disconnected</span>';
|
| 706 |
+
|
| 707 |
+
uploadBtn.disabled = true;
|
| 708 |
}
|
| 709 |
}
|
| 710 |
|
|
|
|
| 887 |
// Check if Web Serial API is available
|
| 888 |
if (!('serial' in navigator)) {
|
| 889 |
addToOutputConsole('Web Serial API not supported in this browser. Try Chrome or Edge.', 'error');
|
| 890 |
+
portHelp.textContent = 'Web Serial API not supported. Use Chrome or Edge.';
|
| 891 |
refreshPorts.disabled = true;
|
| 892 |
connectBtn.disabled = true;
|
| 893 |
} else {
|