From 8d6f07e25568a1ee8d2a19d18a044b546d78dddb Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 12 Dec 2024 22:08:02 -0800 Subject: [PATCH] duo updater --- css/styles.css | 28 ++++++++++++++++ js/ChromalinkPanel.js | 76 ++++++++++++++++++++++++++++++++++++++++--- js/VortexPort.js | 5 ++- 3 files changed, 103 insertions(+), 6 deletions(-) diff --git a/css/styles.css b/css/styles.css index ef193fe..078f699 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1933,3 +1933,31 @@ i { } + + +.device-info { + display: flex; + align-items: center; + margin-bottom: 10px; +} + +.device-info img { + width: 50px; + height: 50px; + margin-right: 10px; +} + +#firmwareProgress { + margin-top: 10px; + height: 20px; + background-color: #e0e0e0; + border-radius: 10px; + overflow: hidden; +} + +#firmwareProgressBar { + height: 100%; + background-color: #007bff; + width: 0; + transition: width 0.3s ease; +} diff --git a/js/ChromalinkPanel.js b/js/ChromalinkPanel.js index 3db5628..50f1f03 100644 --- a/js/ChromalinkPanel.js +++ b/js/ChromalinkPanel.js @@ -5,7 +5,21 @@ export default class ChromalinkPanel extends Panel { constructor(editor, modesPanel) { const content = `
- +
+ + +
+ + +
+
+
+
+
@@ -19,9 +33,14 @@ export default class ChromalinkPanel extends Panel { initialize() { const connectButton = document.getElementById('chromalinkConnect'); - const flashButton = document.getElementById('chromalinkFlash'); const panelElement = document.getElementById('chromalinkPanel'); const firmwareFileInput = document.getElementById('firmwareFileInput'); + const flashButton = document.getElementById('chromalinkFlash'); + const updateButton = document.getElementById('chromalinkUpdate'); + + updateButton.addEventListener('click', async () => { + await this.updateFirmware(); + }); // Connect button logic connectButton.addEventListener('click', async () => { @@ -54,7 +73,7 @@ export default class ChromalinkPanel extends Panel { await this.vortexPort.flashFirmware(this.modesPanel.lightshow.vortexLib, firmwareData, (chunk, totalChunks) => { // Update progress const progress = Math.round((chunk / totalChunks) * 100); - Notification.success(`Writing firmware: ${progress}%...`); + progressBar.style.width = `${progress}%`; }); // Call the vortexPort flash method Notification.success('Firmware flashed successfully.'); @@ -71,6 +90,37 @@ export default class ChromalinkPanel extends Panel { this.hide(); } + async updateFirmware() { + const progressBar = document.getElementById('firmwareProgressBar'); + try { + Notification.success('Fetching latest firmware...'); + // Fetch the firmware metadata + const apiResponse = await fetch('https://vortex.community/downloads/json/duo'); + if (!apiResponse.ok) { + throw new Error('Failed to fetch firmware metadata'); + } + const responseData = await apiResponse.json(); + const firmwareUrl = responseData.firmware?.fileUrl; + const firmwareResponse = await fetch(firmwareUrl); + if (!firmwareResponse.ok) { + throw new Error('Failed to fetch firmware file.'); + } + const firmwareData = new Uint8Array(await firmwareResponse.arrayBuffer()); + Notification.success('Flashing firmware...'); + await this.vortexPort.flashFirmware( + this.modesPanel.lightshow.vortexLib, + firmwareData, + (chunk, totalChunks) => { + const progress = Math.round((chunk / totalChunks) * 100); + progressBar.style.width = `${progress}%`; + } + ); + Notification.success('Firmware updated successfully.'); + } catch (error) { + Notification.failure('Firmware update failed: ' + error.message); + } + } + async connect() { try { // Use the connect function from VortexPort @@ -78,7 +128,7 @@ export default class ChromalinkPanel extends Panel { if (!this.duoHeader) { throw new Error('Failed to read Duo save header'); } - await this.modesPanel.checkVersion('Duo', this.duoHeader.version); + //await this.modesPanel.checkVersion('Duo', this.duoHeader.version); const connectButton = document.getElementById('chromalinkConnect'); connectButton.innerHTML = 'Disconnect Duo' this.isConnected = true; @@ -89,8 +139,18 @@ export default class ChromalinkPanel extends Panel { this.modesPanel.lightshow.vortex.clearModes(); this.modesPanel.lightshow.setLedCount(2); this.modesPanel.updateSelectedDevice('Duo', true); - this.modesPanel.renderLedIndicators('Duo'); + //this.modesPanel.renderLedIndicators('Duo'); this.modesPanel.selectAllLeds(); + // update ui + document.getElementById('duoIcon').style.display = 'block'; + document.getElementById('duoInfo').style.display = 'block'; + document.getElementById('duoVersion').textContent = this.duoHeader.version; + document.getElementById('duoModes').textContent = this.duoHeader.numModes; + const flashButton = document.getElementById('chromalinkFlash'); + const updateButton = document.getElementById('chromalinkUpdate'); + flashButton.disabled = false; + updateButton.disabled = false; + // give a notification Notification.success('Successfully Chromalinked Duo v' + this.duoHeader.version); } catch (error) { Notification.failure('Failed to connect: ' + error.message); @@ -112,6 +172,12 @@ export default class ChromalinkPanel extends Panel { this.modesPanel.updateSelectedDevice('Chromadeck', true); this.modesPanel.renderLedIndicators('Chromadeck'); this.modesPanel.selectAllLeds(); + const flashButton = document.getElementById('chromalinkFlash'); + const updateButton = document.getElementById('chromalinkUpdate'); + flashButton.disabled = true; + updateButton.disabled = true; + document.getElementById('duoIcon').style.display = 'none'; + document.getElementById('duoInfo').style.display = 'none'; Notification.success('Successfully Disconnected Chromalink'); } catch (error) { Notification.failure('Failed to connect: ' + error.message); diff --git a/js/VortexPort.js b/js/VortexPort.js index 9c534c8..530b0d2 100644 --- a/js/VortexPort.js +++ b/js/VortexPort.js @@ -549,7 +549,6 @@ export default class VortexPort { // Call the Wasm function let headerStream = new vortexLib.ByteStream(); vortexLib.createByteStreamFromRawData(header, headerStream); - // TODO: big header is 15 not 5 if (!headerStream.checkCRC() || headerStream.size() < 5) { throw new Error('Bad CRC or size: ' + headerStream.size()); } @@ -561,6 +560,10 @@ export default class VortexPort { duoHeader.flags = headerData[2]; duoHeader.brightness = headerData[3]; duoHeader.numModes = headerData[4]; + if (headerStream.size() > 5) { + duoHeader.vBuild = headerData[5]; + } + console.log(JSON.stringify(headerData)); // construct a full version string duoHeader.version = duoHeader.vMajor + '.' + duoHeader.vMinor + '.' + duoHeader.vBuild; duoHeader.rawData = headerData;