Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibiity With Electron #113

Open
conalllaverty opened this issue Oct 8, 2023 · 4 comments
Open

Compatibiity With Electron #113

conalllaverty opened this issue Oct 8, 2023 · 4 comments

Comments

@conalllaverty
Copy link

conalllaverty commented Oct 8, 2023

Hi,
Does anyone have an example project of being able to flash an ESP32 using esptool-js from an Electron app?

I'm currently getting this error.

Error: TypeError: Cannot read properties of undefined (reading 'get_info')
    at new ESPLoader (esploader.js:124:1)
    at HTMLButtonElement.<anonymous> (renderer.js:73:27)
// renderer.js

const { SerialPort } = require('serialport');
const requireESM = require('esm')(module);
const esptool = requireESM('esptool-js');
const fs = require('fs');
const axios = require('axios');

const dropdown = document.getElementById('serial-dropdown');
const status = document.getElementById('status');

let selectedPort;

function updateStatus(text) {
    status.innerHTML = text;
}

// Consts
const REMOTE_FIRMWARE_URL = "";
const REMOTE_BOOTLOADER_URL = "";
const REMOTE_PARTITIONS_URL = "";

async function listSerialPorts() {
    try {
        const ports = await SerialPort.list();
        
        // Clear the dropdown
        dropdown.innerHTML = '';

        if (ports.length > 0) {
            selectedPort = ports[0].path;
        }
        ports.forEach(port => {
            const option = document.createElement('option');
            option.value = port.path;
            option.text = port.path + (port.manufacturer ? ` (${port.manufacturer})` : '');
            dropdown.appendChild(option);
        });
    } catch (error) {
        console.error('Error listing serial ports:', error);
    }
}

listSerialPorts();

dropdown.addEventListener('change', (e) => {
    console.log(`Selected serial port: ${e.target.value}`);
    selectedPort = e.target.value;
});

document.getElementById('refreshButton').addEventListener('click', async () => {
    listSerialPorts();
});

// Flashing
async function downloadFile(url, outputPath) {
    const response = await axios({
        method: 'get',
        url: url,
        responseType: 'arraybuffer'
    });
    fs.writeFileSync(outputPath, new Uint8Array(response.data));
}

document.getElementById('flashButton').addEventListener('click', async () => {
    updateStatus('Flashing...');
    try {
        const espLoader = new esptool.ESPLoader({
            port: selectedPort,
            chip: 'esp32',
            logLevel: 'debug'
        });
        
        updateStatus('Erasing flash...');

        // Erase the flash first.
        await espLoader.eraseFlash();

        updateStatus('Downloading files...');

        // Download the necessary files
        await downloadFile(REMOTE_FIRMWARE_URL, './tempFirmware.bin');
        await downloadFile(REMOTE_BOOTLOADER_URL, './tempBootloader.bin');
        await downloadFile(REMOTE_PARTITIONS_URL, './tempPartitions.bin');

        updateStatus('Flashing bootloader...');

        // Flash the bootloader.
        const bootloader = await espLoader.readFirmware('./tempBootloader.bin');
        await espLoader.flashFirmware(bootloader, 0x10000);

        updateStatus('Flashing firmware...');

        // Flash the firmware.
        const firmware = await espLoader.readFirmware('./tempFirmware.bin');
        await espLoader.flashFirmware(firmware, 0x1000);

        updateStatus('Flashing partition...');

        // Flash the partitions.
        const partitions = await espLoader.readPartitions('./tempPartitions.bin');
        await espLoader.flashPartitions(partitions, 0x8000);

        await espLoader.close();

        updateStatus('Cleanup...');

        // Clean up the temporary files
        fs.unlinkSync('./tempFirmware.bin');
        fs.unlinkSync('./tempBootloader.bin');
        fs.unlinkSync('./tempPartitions.bin');

        console.log('Flashing complete');
        updateStatus('Flashing completed successfully!');
    } catch (error) {
        console.error('Error:', error);
        updateStatus(error.toString());
    }
});
@ruigouveiamaciel
Copy link

esptool-js will not work on electron because it requires the window.navigator.serial API which is not supported on whatever browser electron uses. Since you're already using Electron you could package your app with the python version of esptool which is more supported and works better.

@sahilrastogi94
Copy link

esptool-js will not work on electron because it requires the window.navigator.serial API which is not supported on whatever browser electron uses. Since you're already using Electron you could package your app with the python version of esptool which is more supported and works better.

esptool-js uses the Web Serial API which is supported in electron. Electron uses chromium browser which supports both Web Serial and Web Bluetooth APIs.
Documentation for the same can be found here - https://www.electronjs.org/docs/latest/tutorial/devices#web-serial-api

@ruigouveiamaciel
Copy link

I'm sorry, I completely missed that page. It seems electron has a couple extra steps to work with web serial so that might be why esptool-js doesn't work out of the box.

@sahilrastogi94
Copy link

I don't have an example code but esptool-js should work with electron. Just try using the Web Serial API instead of the serialport package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants