import {ESPLoader,Transport} from "https://cdn.jsdelivr.net/npm/esptool-js@0.2.1/bundle.js"; /** * write all messages to the console */ class ConsoleOutputHandler{ clean() { } writeLine(data) { console.log("ESPInstaller:",data); } write(data) { console.log(data); } } /** * write messages to an instance of xterm * to use this, include in your html * and create a div element
* provide the id of this div to the constructor */ class XtermOutputHandler { constructor(termId) { let termElement = document.getElementById(termId); if (termElement) { this.term = new Terminal({ cols: 120, rows: 40 , convertEol: true }); this.term.open(termElement); } this.clean=this.clean.bind(this); this.writeLine=this.writeLine.bind(this); this.write=this.write.bind(this); } clean() { if (!this.term) return; this.term.clear(); } writeLine(data) { if (!this.term) { console.log("TERM:", data); return; }; this.term.writeln(data); } write(data) { if (!this.term) { console.log("TERM:", data); return; }; this.term.write(data) } }; class ESPInstaller{ constructor(outputHandler){ this.espLoaderTerminal=outputHandler|| new ConsoleOutputHandler(); this.transport=undefined; this.esploader=undefined; this.chipFamily=undefined; this.base=import.meta.url.replace(/[^/]*$/,"install.php"); this.consoleDevice=undefined; this.consoleReader=undefined; } /** * get an URL query parameter * @param key * @returns */ static getParam(key){ let value=RegExp(""+key+"[^&]+").exec(window.location.search); // Return the unescaped value minus everything starting from the equals sign or an empty string return decodeURIComponent(!!value ? value.toString().replace(/^[^=]+./,"") : ""); }; /** * add an HTML element * @param {*} type * @param {*} clazz * @param {*} parent * @param {*} text * @returns */ static addEl(type, clazz, parent, text) { let el = document.createElement(type); if (clazz) { if (!(clazz instanceof Array)) { clazz = clazz.split(/ */); } clazz.forEach(function (ce) { el.classList.add(ce); }); } if (text) el.textContent = text; if (parent) parent.appendChild(el); return el; } /** * call a function for each matching element * @param {*} selector * @param {*} cb */ static forEachEl(selector,cb){ let arr=document.querySelectorAll(selector); for (let i=0;i resolve(reader.result)); reader.readAsBinaryString(blob); }); this.espLoaderTerminal.writeLine(`successfully loaded ${data.length} bytes`); return data; } /** * handle the click of an install button * @param {*} isFull * @param {*} user * @param {*} repo * @param {*} version * @param {*} address * @param {*} assetName the name of the asset file. * can be a function - will be called with the chip family * and must return the asset file name * @returns */ async installClicked(isFull, user, repo, version, address, assetName) { try { await this.connect(); let assetFileName = assetName; if (typeof (assetName) === 'function') { assetFileName = assetName(this.getChipFamily()); } let imageData = await this.getReleaseAsset(user, repo, version, assetFileName); if (!imageData || imageData.length == 0) { throw new Error(`no image data fetched`); } let fileList = [ { data: imageData, address: address } ]; let txt = isFull ? "baseImage (all data will be erased)" : "update"; if (!confirm(`ready to install ${version}\n${txt}`)) { this.espLoaderTerminal.writeLine("aborted by user..."); await this.disconnect(); return; } await this.writeFlash(fileList); await this.disconnect(); } catch (e) { this.espLoaderTerminal.writeLine(`Error: ${e}`); alert(`Error: ${e}`); } } /** * fetch the release info from the github API * @param {*} user * @param {*} repo * @returns */ async getReleaseInfo(user,repo){ let url=this.base+"?api=1&user="+encodeURIComponent(user)+"&repo="+encodeURIComponent(repo) let resp=await fetch(url); if (! resp.ok){ throw new Error(`unable to query release info from ${url}: ${resp.status}`); } return await resp.json(); } /** * get the release info in a parsed form * @param {*} user * @param {*} repo * @returns an object: {version:nnn, assets:[name1,name2,...]} */ async getParsedReleaseInfo(user,repo){ let raw=await this.getReleaseInfo(user,repo); let rt={ version:raw.name, assets:[] }; if (! raw.assets) return rt; raw.assets.forEach((asset)=>{ rt.assets.push(asset.name); }) return rt; } }; export {ConsoleOutputHandler, XtermOutputHandler}; export default ESPInstaller;