-
-
Save nuta/2c70ba8855f50c536a51f0c5993c1e4c to your computer and use it in GitHub Desktop.
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>esptool.js</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/xterm.min.js" integrity="sha256-8rsVcpCnO6HdeJL84i0VdubjM42fjSmO8aONghdq3gc=" crossorigin="anonymous"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/2.9.2/xterm.min.css" integrity="sha256-w69o8Y6P5VZjfYFmn2KlqMU7TUi2I+oWObi8FLlVZZg=" crossorigin="anonymous" /> | |
</head> | |
<body> | |
<h1>esptool.js</h1> | |
<button id="flash-button" style="padding: 30px; font-size: 40px">Flash</button> | |
<div id="serial"></div> | |
<script src="esptool.js"></script> | |
<script> | |
const term = new Terminal() | |
term.open(document.querySelector("#serial")) | |
document.querySelector("#flash-button").addEventListener("click", () => { | |
const esp = new Esptool() | |
esp.connect().then(() => { | |
const receive = () => { | |
esp.serial.read().then(data => { | |
const s = String.fromCharCode.apply(null, new Uint8Array(data)) | |
term.write(s) | |
receive() | |
}) | |
} | |
receive() | |
}) | |
}) | |
</script> | |
</body> | |
</html> |
const { Serial } = require("./serial") | |
class Esptool { | |
constructor() { | |
this.serial = new Serial() | |
} | |
connect() { | |
return this.serial.connect().then(() => { | |
return this.serial.initialize() | |
}) | |
} | |
async flash() { | |
} | |
} | |
if (window) { | |
// Web browser | |
window.Esptool = Esptool; | |
} |
{ | |
"name": "esptool.js", | |
"version": "0.0.1", | |
"description": "Esptool implemented for Node.js and web browsers.", | |
"main": "lib/index.js", | |
"repository": "https://github.com/seiyanuta/esptool.js", | |
"author": "Seiya Nuta <[email protected]>", | |
"license": "(CC0-1.0 OR MIT)", | |
"devDependencies": { | |
"copy-webpack-plugin": "^4.3.1", | |
"webpack": "^3.10.0", | |
"webpack-dev-server": "^2.11.1" | |
} | |
} |
class Serial { | |
constructor() { | |
this.usb = null | |
} | |
connect() { | |
const filters = [ | |
{ 'vendorId': 0x10c4, 'productId': 0xea60 } | |
] | |
return navigator.usb.getDevices().then(devices => { | |
if (devices.length > 0) { | |
const usb = devices[0] | |
this.usb = usb | |
return usb | |
} else { | |
return navigator.usb.requestDevice({ filters }).then(usb => { | |
this.usb = usb | |
return usb | |
}) | |
} | |
}) | |
} | |
initialize() { | |
return this.usb.open() | |
.then(() => { | |
return this.usb.selectConfiguration(1) | |
}) | |
.then(() => { | |
console.log(this.usb) | |
return this.usb.claimInterface(0) | |
}) | |
.then(() => { | |
return this.usb.controlTransferOut({ | |
requestType: 'vendor', | |
recipient: 'device', | |
request: 0x00, | |
index: 0x00, | |
value: 0x01 | |
}) | |
}) | |
.then(() => { | |
return this.usb.controlTransferOut({ | |
requestType: 'vendor', | |
recipient: 'device', | |
request: 0x07, | |
index: 0x00, | |
value: 0x03 | 0x0100 | 0x0200 | |
}) | |
}) | |
.then(() => { | |
return this.usb.controlTransferOut({ | |
requestType: 'vendor', | |
recipient: 'device', | |
request: 0x01, | |
index: 0x00, | |
value: 0x384000 / 115200 | |
}) | |
}) | |
} | |
async read() { | |
const r = await this.usb.transferIn(1, 64) | |
return new Uint8Array(r.data.buffer) | |
} | |
async write(data) { | |
await this.usb.transferIn(1, data) | |
} | |
} | |
module.exports = { Serial } |
const path = require("path") | |
module.exports = { | |
entry: { | |
app: ["./index.js"] | |
}, | |
output: { | |
path: __dirname, | |
publicPath: "/", | |
filename: "esptool.js" | |
} | |
}; |
@FeedDahBirds IIRC I read its Linux device driver. Maybe this would be helpful: https://github.com/torvalds/linux/blob/master/drivers/usb/serial/cp210x.c
Your sharing is great and this will make ESP32 programming so interesting with Web. Unfortunately I cannot make it working, Chrome does not detect any device when I click Flash button even though the ESP32 DevKit is connected. Any tip to debug?
Could you, please, explain in a couple of words, what is the purpose of this index.html?
@vanminh0910 I've tried just now but it doesn't work for me. I'd recommend to use Serial API instead. It's way better than this gist.
@vanminh0910 If you want to flash a firmware, in addition to the serial device driver like this, you'll need to implement esptool protocol. ESP32 programming on the web sounds really exciting to me, but unfortunately I have no time to work on it for now.
@AlexFundorin It seems it no longer work though, index.html instantiates xterm.js (for printing colored device messages) and writes received data into it.
@seiyanuta this - https://github.com/scottchiefbaker/ESP-WebOTA
Thank you for sharing! It looks interesting :)
I'm already using it in my project. Well, it's working, yet I'm still updating firmware directly from VSCode, using OTA.
This device (https://yolostem.com) using esp32 supports web programming using webusb API which is available on Chrome already, but not Serial API. Here is its programming page https://lab.yolostem.com. Sadly the homepage is mainly in Vietnamese.
I'm mostly interested in uploading firmware to a second Arduino board via ESP32.
Don't see much point in the actual programming, using webusb.
@vanminh0910 looks to me that the device is using an atmega chip inside that translates the webusb, I looked at the files and found this https://lab.yolostem.com/assets/webusb.js, inside the vendorID is 0x2341 which corresponds to the arduino.
Hey,
Thank you for this GIST! It helped me through a big blocker.
Quick question if you have the time:
Where/how did you learn the setup for the series of control transfer out calls to get it all working?
Would love to learn any debug tips or tricks with this stuff!
Thank you,
FeedDahBirds