esptool-js-openDTU/index.js

586 lines
15 KiB
JavaScript

const baudrates = document.getElementById('baudrates');
const connectButton = document.getElementById('connectButton');
const disconnectButton = document.getElementById('disconnectButton');
const resetButton = document.getElementById('resetButton');
const consoleStartButton = document.getElementById('consoleStartButton');
const consoleStopButton = document.getElementById('consoleStopButton');
const eraseButton = document.getElementById('eraseButton');
const programButton = document.getElementById('programButton');
const filesDiv = document.getElementById('files');
const terminal = document.getElementById('terminal');
const programDiv = document.getElementById('program');
const consoleDiv = document.getElementById('console');
const lblBaudrate = document.getElementById('lblBaudrate');
const lblConnTo = document.getElementById('lblConnTo');
const table = document.getElementById('fileTable');
const alertDiv = document.getElementById('alertDiv');
// import { Transport } from './cp210x-webusb.js'
import * as esptooljs from "./bundle.js";
const ESPLoader = esptooljs.ESPLoader;
const Transport = esptooljs.Transport;
let term = new Terminal({ cols: 120, rows: 40 });
term.open(terminal);
let device = null;
let transport;
let chip = null;
let esploader;
let file1 = null;
// let temp_bin_file = null;
let connected = false;
disconnectButton.style.display = 'none';
eraseButton.style.display = 'none';
consoleStopButton.style.display = 'none';
filesDiv.style.display = 'none';
function handleFileSelect(evt) {
var file = evt.target.files[0];
if (!file) return;
var reader = new FileReader();
reader.onload = (function (theFile) {
return function (e) {
file1 = e.target.result;
evt.target.data = file1;
};
})(file);
reader.readAsBinaryString(file);
}
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
function SyncFileReader(file) {
let self = this;
let ready = false;
let result = '';
const sleep = function (ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
self.readAsBinaryString = async function() {
while (ready === false) {
await sleep(100);
}
return result;
}
const reader = new FileReader();
reader.onloadend = function(evt) {
result = evt.target.result;
if( result ){
console.log(result);
}
ready = true;
};
reader.readAsBinaryString(file);
}
// function binary_reader_helper(file) {
// var ready = false;
// var result = '';
// var check = function() {
// if (ready === true) {
// // do what you want with the result variable
// return;
// }
// setTimeout(check, 1000);
// }
// check();
// var reader = new FileReader();
// reader.onloadend = function(evt) {
// // file is loaded
// result = evt.target.result;
// ready = true;
// };
// reader.readAsBinaryString(file);
// return (' ' + reader.result).slice(1);
// // let reader = new FileReader();
// // reader.onload = function(evt) {
// // var bin = evt.target.result; //get file content
// // // do sth with text
// // console.log(bin);
// // // temp_bin_file = (' ' + bin).slice(1);
// // // var li = document.createElement("li");
// // // li.innerHTML = name;
// // // ul.appendChild(li);
// // };
// // reader.onloadend = () => {
// // console.log("DONE", reader.readyState); // readyState will be 2
// // };
// }
let espLoaderTerminal = {
clean() {
term.clear();
},
writeLine(data) {
term.writeln(data);
},
write(data) {
term.write(data)
}
}
connectButton.onclick = async () => {
if (device === null) {
device = await navigator.serial.requestPort({});
transport = new Transport(device);
}
try {
esploader = new ESPLoader(transport, baudrates.value, espLoaderTerminal);
connected = true;
chip = await esploader.main_fn();
// Temporarily broken
// await esploader.flash_id();
} catch (e) {
console.error(e);
term.writeln(`Error: ${e.message}`);
}
console.log('Settings done for :' + chip);
lblBaudrate.style.display = 'none';
lblConnTo.innerHTML = 'Connected to device: ' + chip;
lblConnTo.style.display = 'block';
baudrates.style.display = 'none';
connectButton.style.display = 'none';
disconnectButton.style.display = 'initial';
eraseButton.style.display = 'initial';
filesDiv.style.display = 'initial';
consoleDiv.style.display = 'none';
};
resetButton.onclick = async () => {
if (device === null) {
device = await navigator.serial.requestPort({});
transport = new Transport(device);
}
await transport.setDTR(false);
await new Promise((resolve) => setTimeout(resolve, 100));
await transport.setDTR(true);
};
eraseButton.onclick = async () => {
eraseButton.disabled = true;
try {
await esploader.erase_flash();
} catch (e) {
console.error(e);
term.writeln(`Error: ${e.message}`);
} finally {
eraseButton.disabled = false;
}
};
// addFile.onclick = () => {
// var rowCount = table.rows.length;
// var row = table.insertRow(rowCount);
// //Column 1 - Offset
// var cell1 = row.insertCell(0);
// var element1 = document.createElement('input');
// element1.type = 'text';
// element1.id = 'offset' + rowCount;
// element1.value = '0x1000';
// cell1.appendChild(element1);
// // Column 2 - File selector
// var cell2 = row.insertCell(1);
// var element2 = document.createElement('input');
// element2.type = 'file';
// element2.id = 'selectFile' + rowCount;
// element2.name = 'selected_File' + rowCount;
// element2.addEventListener('change', handleFileSelect, false);
// cell2.appendChild(element2);
// // Column 3 - Progress
// var cell3 = row.insertCell(2);
// cell3.classList.add('progress-cell');
// cell3.style.display = 'none';
// cell3.innerHTML = `<progress value="0" max="100"></progress>`;
// // Column 4 - Remove File
// var cell4 = row.insertCell(3);
// cell4.classList.add('action-cell');
// if (rowCount > 1) {
// var element4 = document.createElement('input');
// element4.type = 'button';
// var btnName = 'button' + rowCount;
// element4.name = btnName;
// element4.setAttribute('class', 'btn');
// element4.setAttribute('value', 'Remove'); // or element1.value = "button";
// element4.onclick = function () {
// removeRow(row);
// };
// cell4.appendChild(element4);
// }
// };
// function removeRow(row) {
// const rowIndex = Array.from(table.rows).indexOf(row);
// table.deleteRow(rowIndex);
// }
// to be called on disconnect - remove any stale references of older connections if any
function cleanUp() {
device = null;
transport = null;
chip = null;
}
disconnectButton.onclick = async () => {
if (transport) await transport.disconnect();
term.clear();
connected = false;
baudrates.style.display = 'initial';
connectButton.style.display = 'initial';
disconnectButton.style.display = 'none';
eraseButton.style.display = 'none';
lblConnTo.style.display = 'none';
filesDiv.style.display = 'none';
alertDiv.style.display = 'none';
consoleDiv.style.display = 'initial';
cleanUp();
};
let isConsoleClosed = false;
consoleStartButton.onclick = async () => {
if (device === null) {
device = await navigator.serial.requestPort({});
transport = new Transport(device);
}
lblConsoleFor.style.display = 'block';
consoleStartButton.style.display = 'none';
consoleStopButton.style.display = 'initial';
programDiv.style.display = 'none';
await transport.connect();
isConsoleClosed = false;
while (true && !isConsoleClosed) {
let val = await transport.rawRead();
if (typeof val !== 'undefined') {
term.write(val);
} else {
break;
}
}
console.log('quitting console');
};
consoleStopButton.onclick = async () => {
isConsoleClosed = true;
await transport.disconnect();
await transport.waitForUnlock(1500);
term.clear();
consoleStartButton.style.display = 'initial';
consoleStopButton.style.display = 'none';
programDiv.style.display = 'initial';
};
function validate_program_inputs() {
let offsetArr = [];
var rowCount = table.rows.length;
var row;
let offset = 0;
let fileData = null;
// check for mandatory fields
for (let index = 1; index < rowCount; index++) {
row = table.rows[index];
//offset fields checks
var offSetObj = row.cells[0].childNodes[0];
offset = parseInt(offSetObj.value);
// Non-numeric or blank offset
if (Number.isNaN(offset)) return 'Offset field in row ' + index + ' is not a valid address!';
// Repeated offset used
else if (offsetArr.includes(offset)) return 'Offset field in row ' + index + ' is already in use!';
else offsetArr.push(offset);
var fileObj = row.cells[1].childNodes[0];
fileData = fileObj.data;
if (fileData == null) return 'No file selected for row ' + index + '!';
}
return 'success';
}
programButton.onclick = async () => {
// const alertMsg = document.getElementById('alertmsg');
// const err = validate_program_inputs();
// if (err != 'success') {
// alertMsg.innerHTML = '<strong>' + err + '</strong>';
// alertDiv.style.display = 'block';
// return;
// }
// Hide error message
// alertDiv.style.display = 'none';
let temp_bin_file = null;
const fileArray = [];
// const progressBars = [];
// for (let index = 1; index < table.rows.length; index++) {
// const row = table.rows[index];
// const offSetObj = row.cells[0].childNodes[0];
// const offset = parseInt(offSetObj.value);
// const fileObj = row.cells[1].childNodes[0];
// const progressBar = row.cells[2].childNodes[0];
// progressBar.value = 0;
// progressBars.push(progressBar);
// row.cells[2].style.display = 'initial';
// row.cells[3].style.display = 'none';
// fileArray.push({ data: fileObj.data, address: offset });
// }
// ###################################################################
// ###################################################################
let response = await fetch("/binary_blob/bootloader.bin");
if(response.status != 200) {
throw new Error("Server Error");
}
// read response stream as text
// let text_data = await response.text();
let blob_data = await response.blob();
if(!blob_data) {
throw new Error("Can't read file to flash as blob !")
}
let file = new File( [blob_data], "bootloader.bin", {
type: "text/plain",
});
// let reader = new FileReader();
// reader.onload = (function (theFile) {
// return function (e) {
// file1 = e.target.result;
// };
// })(file);
// reader.onloadend = function (theFile){
// file1 = this.result;
// console.log(this.result);
// };
console.log( file );
let fileReader = new SyncFileReader(file);
temp_bin_file = await fileReader.readAsBinaryString();
if( !temp_bin_file ){
temp_bin_file = await fileReader.readAsBinaryString();
if( temp_bin_file ){
console.log( temp_bin_file );
fileArray.push({ data: (' ' + temp_bin_file).slice(1) , address: 0x1000 });
}
}else{
console.log( temp_bin_file );
fileArray.push({ data: (' ' + temp_bin_file).slice(1) , address: 0x1000 });
}
temp_bin_file = null;
// ###################################################################
// ###################################################################
response = await fetch("/binary_blob/partitions.bin");
if(response.status != 200) {
throw new Error("Server Error");
}
blob_data = await response.blob();
if(!blob_data) {
throw new Error("Can't read file to flash as blob !")
}
file = new File( [blob_data], "partitions.bin", {
type: "text/plain",
});
console.log( file );
fileReader = new SyncFileReader(file);
temp_bin_file = await fileReader.readAsBinaryString();
if( !temp_bin_file ){
temp_bin_file = await fileReader.readAsBinaryString();
if( temp_bin_file ){
console.log( temp_bin_file );
fileArray.push({ data: (' ' + temp_bin_file).slice(1) , address: 0x8000 });
}
}else{
console.log( temp_bin_file );
fileArray.push({ data: (' ' + temp_bin_file).slice(1) , address: 0x8000 });
}
temp_bin_file = null;
// ###################################################################
// ###################################################################
response = await fetch("/binary_blob/boot_app0.bin");
if(response.status != 200) {
throw new Error("Server Error");
}
blob_data = await response.blob();
if(!blob_data) {
throw new Error("Can't read file to flash as blob !")
}
file = new File( [blob_data], "boot_app0.bin", {
type: "text/plain",
});
console.log( file );
fileReader = new SyncFileReader(file);
temp_bin_file = await fileReader.readAsBinaryString();
if( !temp_bin_file ){
temp_bin_file = await fileReader.readAsBinaryString();
if( temp_bin_file ){
console.log( temp_bin_file );
fileArray.push({ data: temp_bin_file , address: 0xe000 });
}
}else{
console.log( temp_bin_file );
fileArray.push({ data: temp_bin_file , address: 0xe000 });
}
temp_bin_file = null;
// ###################################################################
// ###################################################################
response = await fetch("/binary_blob/opendtu-generic.bin");
if(response.status != 200) {
throw new Error("Server Error");
}
blob_data = await response.blob();
if(!blob_data) {
throw new Error("Can't read file to flash as blob !")
}
file = new File( [blob_data], "opendtu-gernic.bin", {
type: "text/plain",
});
console.log( file );
fileReader = new SyncFileReader(file);
temp_bin_file = await fileReader.readAsBinaryString();
if( !temp_bin_file ){
temp_bin_file = await fileReader.readAsBinaryString();
if( temp_bin_file ){
console.log( temp_bin_file );
fileArray.push({ data: temp_bin_file , address: 0x10000 });
}
}else{
console.log( temp_bin_file );
fileArray.push({ data: temp_bin_file , address: 0x10000 });
}
temp_bin_file = null;
sleep(3000)
console.log(fileArray)
try {
await esploader.write_flash(
fileArray,
'keep',
undefined,
undefined,
false,
true,
null,
(image) => CryptoJS.MD5(CryptoJS.enc.Latin1.parse(image)),
);
} catch (e) {
console.error(e);
term.writeln(`Error: ${e.message}`);
} finally {
// Hide progress bars and show erase buttons
// for (let index = 1; index < table.rows.length; index++) {
// table.rows[index].cells[2].style.display = 'none';
// table.rows[index].cells[3].style.display = 'initial';
// }
}
};
// addFile.onclick();