Merge branch 'main' of NabuCasa/esp-web-flasher
commit
7729ef1a05
@ -0,0 +1,10 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@ -0,0 +1,9 @@
|
||||
categories:
|
||||
- title: "⬆️ Dependencies"
|
||||
collapse-after: 1
|
||||
labels:
|
||||
- "dependencies"
|
||||
template: |
|
||||
## What's Changed
|
||||
|
||||
$CHANGES
|
||||
@ -0,0 +1,26 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- run: npm ci
|
||||
- run: script/build
|
||||
- run: npm exec -- prettier --check src
|
||||
@ -0,0 +1,22 @@
|
||||
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
||||
|
||||
name: Node.js Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish-npm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
@ -0,0 +1,14 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@ -1 +1,3 @@
|
||||
*.DS_Store
|
||||
dist
|
||||
node_modules
|
||||
|
||||
@ -0,0 +1 @@
|
||||
src/stubs
|
||||
@ -1,5 +1,26 @@
|
||||
# Adafruit ESPTool
|
||||
# This package is deprecated. Use [esptool-js](https://github.com/espressif/esptool-js/) instead.
|
||||
|
||||
A Web Serial tool for updating your ESP bootloader. Please submit any new issues or pull requests to https://github.com/NabuCasa/esp-web-flasher.
|
||||
# ESP Web Flasher
|
||||
|
||||
A live copy of the tool is hosted here: https://nabucasa.github.io/esp-web-flasher/
|
||||
JavaScript package to install firmware on ESP devices via the browser using WebSerial.
|
||||
|
||||
_This project is a collaboration between [Adafruit](https://www.adafruit.com/) and [Nabu Casa](https://www.nabucasa.com/)._
|
||||
|
||||
## Used by
|
||||
|
||||
- [Adafruit WipperSnapper](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper)
|
||||
- [ESP Web Tools](https://github.com/esphome/esp-web-tools), the one click button to install your ESP devices via the browser.
|
||||
|
||||
## Local development
|
||||
|
||||
- Clone this repository.
|
||||
- Install dependencies with `npm`
|
||||
- Run `script/develop`
|
||||
- Open http://localhost:5004/
|
||||
|
||||
## Origin
|
||||
|
||||
This project was originally written by [Melissa LeBlanc-Williams](https://github.com/makermelissa). [Nabu Casa](https://www.nabucasa.com) ported the code over to TypeScript and in March 2022 took over maintenance from Adafruit. In July 2022, the Nabucasa stopped maintaining the project in favor of an official, but very early release of Espressif's [esptool-js](https://github.com/espressif/esptool-js/). Due to the instability of the tool, Adafruit updated their fork with Nabucasa's changes and took over maintenance once again.
|
||||
|
||||
|
||||
A live copy of the tool is hosted here: https://adafruit.github.io/Adafruit_WebSerial_ESPTool/
|
||||
@ -1,6 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="40" viewBox="0 0 115 40">
|
||||
<g fill="#FFF" fill-rule="evenodd">
|
||||
<path d="M33.793 27.417c.52-.533 1.13-.75 2.304-.75h4.728c1.317 0 2.093.24 2.565.75.588.602.777 1.306.777 3.556v9.002h-3.6v-1.523C39.016 39.758 38.452 40 37.299 40h-1.765c-1.152 0-1.763-.147-2.281-.676-.447-.462-.752-1.236-.752-2.977 0-1.646.235-2.663.8-3.244.587-.605 1.34-.896 3.668-.896 1.248 0 2.54.147 3.6.389v-1.187c0-1.308-.072-1.573-.236-1.766-.166-.148-.4-.196-.94-.196h-1.81c-.496 0-.755.048-.896.196-.187.193-.212.458-.26 1.258h-3.408c.022-2.225.234-2.953.775-3.484zm6.775 9.242v-2.226h-2.375c-1.366 0-1.694.097-1.93.338-.234.243-.282.534-.282 1.138 0 .68.048 1.04.235 1.235.189.192.447.217.917.217h1.012c.752 0 1.247-.071 2.423-.702zM54.568 39.974v-1.76C52.87 39.701 52.28 40 51.171 40h-1.426c-1.427 0-2.19-.248-2.78-.843-.81-.82-1.132-2.012-1.132-6.006 0-4.018.392-5.158 1.231-6.003.59-.594 1.377-.842 2.73-.842h1.475c1.133 0 1.749.248 3.3 1.562v-6.201h3.764v18.307h-3.765zm0-3.597V29.88c-.79-.372-1.354-.546-1.968-.546h-1.353c-.69 0-1.011.1-1.232.321-.344.323-.442.895-.442 3.497 0 2.605.098 3.153.442 3.5.22.222.542.298 1.232.298h1.229c.64 0 1.255-.175 2.092-.572zM60.46 27.417c.518-.533 1.13-.75 2.305-.75h4.728c1.316 0 2.093.24 2.564.75.587.602.776 1.306.776 3.556v9.002h-3.599v-1.523C65.682 39.758 65.117 40 63.965 40h-1.762c-1.154 0-1.767-.147-2.283-.676-.447-.462-.753-1.236-.753-2.977 0-1.646.235-2.663.8-3.244.588-.605 1.34-.896 3.668-.896 1.248 0 2.541.147 3.6.389v-1.187c0-1.308-.072-1.573-.235-1.766-.164-.148-.401-.196-.942-.196h-1.81c-.495 0-.753.048-.894.196-.188.193-.212.458-.26 1.258h-3.41c.024-2.225.236-2.953.776-3.484zm6.774 9.242v-2.226H64.86c-1.365 0-1.694.097-1.93.338-.234.243-.282.534-.282 1.138 0 .68.048 1.04.236 1.235.188.192.445.217.916.217h1.01c.754 0 1.248-.071 2.424-.702zM72.5 40V25.692c0-1.715.227-2.61.803-3.18.577-.572 1.228-.845 2.706-.845h3.158v2.88H77.31c-.5 0-.65.05-.8.175-.127.15-.176.42-.176 1.093v.548h2.833v2.955h-2.808V40H72.5M80.833 40V26.69h3.727v2.033c1.39-1.429 2.096-2.056 3.169-2.056h1.438v3.653h-1.73c-1.024 0-1.804.096-2.877.532V40h-3.727M101.667 26.667v13.308h-3.63V38.21c-1.65 1.523-2.191 1.79-3.37 1.79h-1.58c-1.131 0-1.84-.242-2.332-.751-.52-.556-.755-1.258-.755-3.194v-9.388h3.63v8.977c0 .555.07.871.282 1.09.212.216.424.29 1.062.29h1.037c.612 0 1.155-.146 2.027-.533v-9.824h3.629M103.333 21.667h3.334v2.78h-3.334v-2.78zm0 4.67h3.334V40h-3.334V26.338zM115 36.84h-1.648c-.626 0-.874-.052-.998-.15-.126-.152-.176-.351-.176-.955v-6.648H115v-3.011h-2.822v-1.91h-3.845v12.599c0 1.404.175 2.031.625 2.483.475.478 1.173.752 2.472.752 1.023 0 2.047-.15 2.645-.301l.925-.24v-2.62"/>
|
||||
<path d="M39.974 17.619c-.131-.82-.575-1.054-1.647-1.398-.815-.261-6.272-2-6.272-2s-3.802-1.436-6.622.595c-.38.275-.773.586-1.169.92.333-.396.644-.79.917-1.17 2.026-2.824.583-6.626.583-6.626s-1.747-5.455-2.01-6.27c-.346-1.072-.58-1.516-1.4-1.644-.82-.13-1.179.22-1.837 1.135-.5.693-3.84 5.348-3.84 5.348s-2.54 3.173-1.48 6.484c.143.446.318.916.513 1.395-.274-.439-.552-.856-.83-1.233-2.059-2.8-6.118-2.603-6.118-2.603s-5.727-.022-6.584-.024c-1.125-.003-1.62.084-1.995.822-.377.74-.154 1.191.51 2.098.506.691 3.9 5.307 3.9 5.307s2.233 3.398 5.707 3.412c.467.002.967-.019 1.482-.057-.501.126-.983.262-1.426.408-3.298 1.094-4.365 5.017-4.365 5.017L3.933 33.79c-.35 1.07-.421 1.567.166 2.153.587.587 1.083.515 2.153.162.813-.267 6.25-2.07 6.25-2.07s3.92-1.073 5.007-4.375c.146-.443.28-.924.404-1.424-.035.514-.055 1.013-.053 1.48.021 3.475 3.422 5.703 3.422 5.703l5.31 3.89c.91.663 1.36.885 2.1.507.738-.377.823-.872.818-1.998-.003-.855-.036-6.584-.036-6.584s.19-4.061-2.612-6.116c-.377-.276-.793-.553-1.232-.826.479.194.948.367 1.393.508 3.31 1.056 6.48-1.49 6.48-1.49s4.646-3.35 5.34-3.852c.912-.66 1.26-1.02 1.13-1.84zM20.249 13.4c.624.099.934 1.428.692 2.968-.243 1.541-.946 2.71-1.57 2.612-.626-.098-.936-1.427-.693-2.967.243-1.541.946-2.711 1.57-2.613zm-8 4.087c.286-.564 1.645-.448 3.035.26 1.39.705 2.285 1.736 1.999 2.3-.288.564-1.646.447-3.036-.258-1.39-.708-2.285-1.738-1.998-2.302zm4.218 7.684c-1.102 1.104-2.358 1.637-2.806 1.19-.447-.448.084-1.705 1.185-2.81 1.102-1.103 2.358-1.635 2.806-1.188.447.447-.083 1.704-1.185 2.808zm6.068 2.587c-.563.288-1.594-.605-2.303-1.994-.71-1.39-.828-2.75-.265-3.037.563-.287 1.595.605 2.304 1.994.71 1.389.828 2.75.264 3.037zm1.463-6.434c-1.54.245-2.87-.062-2.97-.687-.097-.625 1.07-1.33 2.61-1.575 1.54-.245 2.87.061 2.968.686.1.624-1.068 1.33-2.608 1.576z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.4 KiB |
@ -1,16 +1,212 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Redirecting to NabuCasa ESP Web Flasher</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>ESP Web Flasher</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<script>
|
||||
// Redirect to HTTPS if HTTP is requested.
|
||||
window.location.href = 'https://nabucasa.github.io/esp-web-flasher/';
|
||||
if (
|
||||
window.location.hostname !== "localhost" &&
|
||||
window.location.protocol === "http:"
|
||||
) {
|
||||
window.location.href = "https:" + window.location.href.substring(5);
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- import the web page's stylesheets along with the themes -->
|
||||
<link rel="stylesheet" href="https://use.typekit.net/qtk5kiq.css" />
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="css/light.css"
|
||||
id="light"
|
||||
class="alternate"
|
||||
disabled
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="css/dark.css"
|
||||
id="dark"
|
||||
class="alternate"
|
||||
disabled
|
||||
/>
|
||||
|
||||
<!-- import the webpage's javascript file -->
|
||||
<script module>
|
||||
window.esptoolPackage = import(
|
||||
// In development we import locally.
|
||||
window.location.hostname === "localhost"
|
||||
? "/dist/web/index.js"
|
||||
: "https://unpkg.com/esp-web-flasher@5.1.4/dist/web/index.js?module"
|
||||
);
|
||||
</script>
|
||||
<script src="js/script.js" module defer></script>
|
||||
</head>
|
||||
<body>
|
||||
Please use <a href="https://nabucasa.github.io/esp-web-flasher/">https://nabucasa.github.io/esp-web-flasher/</a> to flash your ESP boards.
|
||||
<header class="header">
|
||||
<div class="left"></div>
|
||||
<div class="right">
|
||||
<select id="baudRate"></select>
|
||||
<button id="butConnect" type="button">Connect</button>
|
||||
</div>
|
||||
</header>
|
||||
<main class="main">
|
||||
<div class="notSupported">
|
||||
This website is no longer maintained.
|
||||
<a href="https://espressif.github.io/esptool-js/"
|
||||
>Use esptool-js instead.</a
|
||||
>
|
||||
</div>
|
||||
<div id="notSupported" class="notSupported">
|
||||
Sorry, <b>Web Serial</b> is not supported on this device, make sure
|
||||
you're running Chrome 89 or later.
|
||||
</div>
|
||||
<div class="subheader">
|
||||
<div class="title left">ESP Web Flasher</div>
|
||||
<div class="right">
|
||||
<label for="darkmode"> Dark Mode </label>
|
||||
<div class="onoffswitch">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="darkmode"
|
||||
class="onoffswitch-checkbox"
|
||||
id="darkmode"
|
||||
/>
|
||||
<label class="onoffswitch-label" for="darkmode">
|
||||
<span class="onoffswitch-inner"></span>
|
||||
<span class="onoffswitch-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="app">
|
||||
<div id="commands">
|
||||
<div class="upload">
|
||||
<label
|
||||
>Offset: 0x
|
||||
<input class="offset" type="text" value="0" />
|
||||
</label>
|
||||
<label class="firmware">
|
||||
<input type="file" accept=".bin" />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="17"
|
||||
viewbox="0 0 20 17"
|
||||
>
|
||||
<path
|
||||
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Choose a file…</span>
|
||||
</label>
|
||||
<div class="progress-bar hidden"><div></div></div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<label
|
||||
>Offset: 0x
|
||||
<input class="offset" type="text" value="0" />
|
||||
</label>
|
||||
<label class="firmware">
|
||||
<input type="file" accept=".bin" />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="17"
|
||||
viewbox="0 0 20 17"
|
||||
>
|
||||
<path
|
||||
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Choose a file…</span>
|
||||
</label>
|
||||
<div class="progress-bar hidden"><div></div></div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<label
|
||||
>Offset: 0x
|
||||
<input class="offset" type="text" value="0" />
|
||||
</label>
|
||||
<label class="firmware">
|
||||
<input type="file" accept=".bin" />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="17"
|
||||
viewbox="0 0 20 17"
|
||||
>
|
||||
<path
|
||||
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Choose a file…</span>
|
||||
</label>
|
||||
<div class="progress-bar hidden"><div></div></div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<label
|
||||
>Offset: 0x
|
||||
<input class="offset" type="text" value="0" />
|
||||
</label>
|
||||
<label class="firmware">
|
||||
<input type="file" accept=".bin" />
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
height="17"
|
||||
viewbox="0 0 20 17"
|
||||
>
|
||||
<path
|
||||
d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Choose a file…</span>
|
||||
</label>
|
||||
<div class="progress-bar hidden"><div></div></div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button id="butErase" type="button" disabled="disabled">
|
||||
Erase
|
||||
</button>
|
||||
<button id="butProgram" type="button" disabled="disabled">
|
||||
Program
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="log"></div>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="footer">
|
||||
<div class="justify controls">
|
||||
<div>
|
||||
<label for="autoscroll">Autoscroll </label>
|
||||
<div class="onoffswitch">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="autoscroll"
|
||||
class="onoffswitch-checkbox"
|
||||
id="autoscroll"
|
||||
/>
|
||||
<label class="onoffswitch-label" for="autoscroll">
|
||||
<span class="onoffswitch-inner"></span>
|
||||
<span class="onoffswitch-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button id="butClear" type="button">Clear Text</button>
|
||||
</div>
|
||||
<div class="center">
|
||||
Maintained by <a href="https://www.nabucasa.com">Nabu Casa</a>. Derived
|
||||
from
|
||||
<a href="https://github.com/adafruit/Adafruit_WebSerial_ESPTool"
|
||||
>Adafruit WebSerial ESPTool</a
|
||||
>
|
||||
by
|
||||
<a href="https://github.com/makermelissa">Melissa LeBlanc-Williams</a>.
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "esp-web-flasher",
|
||||
"version": "5.1.5",
|
||||
"description": "Flash ESP devices using WebSerial",
|
||||
"main": "dist/index.js",
|
||||
"repository": "https://github.com/nabucasa/ESP-Web-flasher",
|
||||
"author": "Nabu Casa",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"prepublishOnly": "script/build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.0",
|
||||
"@rollup/plugin-typescript": "^8.2.1",
|
||||
"@types/pako": "^2.0.0",
|
||||
"@types/w3c-web-serial": "^1.0.1",
|
||||
"prettier": "^2.3.0",
|
||||
"rollup": "^2.48.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"serve": "^13.0.2",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"pako": "^2.0.3",
|
||||
"tslib": "^2.2.0"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
||||
import json from "@rollup/plugin-json";
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
|
||||
const config = {
|
||||
input: "dist/index.js",
|
||||
output: {
|
||||
dir: "dist/web",
|
||||
format: "module",
|
||||
},
|
||||
// preserveEntrySignatures: false,
|
||||
plugins: [nodeResolve(), json()],
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
config.plugins.push(
|
||||
terser({
|
||||
ecma: 2019,
|
||||
toplevel: true,
|
||||
output: {
|
||||
comments: false,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export default config;
|
||||
@ -0,0 +1,8 @@
|
||||
# Stop on errors
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
rm -rf dist
|
||||
NODE_ENV=production npm exec -- tsc
|
||||
NODE_ENV=production npm exec -- rollup -c
|
||||
@ -0,0 +1,17 @@
|
||||
# Stop on errors
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
rm -rf dist
|
||||
|
||||
# Quit all background tasks when script exits
|
||||
trap "kill 0" EXIT
|
||||
|
||||
# Run tsc once as rollup expects those files
|
||||
npm exec -- tsc || true
|
||||
|
||||
npm exec -- serve -p 5004 &
|
||||
npm exec -- tsc --watch &
|
||||
npm exec -- rollup -c --watch &
|
||||
wait
|
||||
@ -0,0 +1,303 @@
|
||||
import { toByteArray } from "./util";
|
||||
|
||||
export interface Logger {
|
||||
log(msg: string, ...args: any[]): void;
|
||||
error(msg: string, ...args: any[]): void;
|
||||
debug(msg: string, ...args: any[]): void;
|
||||
}
|
||||
|
||||
export const baudRates = [
|
||||
115200, 128000, 153600, 230400, 460800, 921600, 1500000, 2000000,
|
||||
];
|
||||
export const FLASH_SIZES = {
|
||||
"512KB": 0x00,
|
||||
"256KB": 0x10,
|
||||
"1MB": 0x20,
|
||||
"2MB": 0x30,
|
||||
"4MB": 0x40,
|
||||
"2MB-c1": 0x50,
|
||||
"4MB-c1": 0x60,
|
||||
"8MB": 0x80,
|
||||
"16MB": 0x90,
|
||||
};
|
||||
|
||||
export const ESP32_FLASH_SIZES = {
|
||||
"1MB": 0x00,
|
||||
"2MB": 0x10,
|
||||
"4MB": 0x20,
|
||||
"8MB": 0x30,
|
||||
"16MB": 0x40,
|
||||
"32MB": 0x50,
|
||||
"64MB": 0x60,
|
||||
"128MB": 0x70,
|
||||
};
|
||||
|
||||
export const DETECTED_FLASH_SIZES = {
|
||||
0x12: "256KB",
|
||||
0x13: "512KB",
|
||||
0x14: "1MB",
|
||||
0x15: "2MB",
|
||||
0x16: "4MB",
|
||||
0x17: "8MB",
|
||||
0x18: "16MB",
|
||||
0x19: "32MB",
|
||||
0x1a: "64MB",
|
||||
};
|
||||
|
||||
export const FLASH_WRITE_SIZE = 0x400;
|
||||
export const STUB_FLASH_WRITE_SIZE = 0x4000;
|
||||
export const FLASH_SECTOR_SIZE = 0x1000; // Flash sector size, minimum unit of erase.
|
||||
export const ESP_ROM_BAUD = 115200;
|
||||
|
||||
export const ESP8266_SPI_REG_BASE = 0x60000200;
|
||||
export const ESP8266_BASEFUSEADDR = 0x3ff00050;
|
||||
export const ESP8266_MACFUSEADDR = 0x3ff00050;
|
||||
export const ESP8266_SPI_USR_OFFS = 0x1c;
|
||||
export const ESP8266_SPI_USR1_OFFS = 0x20;
|
||||
export const ESP8266_SPI_USR2_OFFS = 0x24;
|
||||
export const ESP8266_SPI_MOSI_DLEN_OFFS = -1;
|
||||
export const ESP8266_SPI_MISO_DLEN_OFFS = -1;
|
||||
export const ESP8266_SPI_W0_OFFS = 0x40;
|
||||
export const ESP8266_UART_DATE_REG_ADDR = 0x60000078;
|
||||
export const ESP8266_BOOTLOADER_FLASH_OFFSET = 0x0;
|
||||
|
||||
export const ESP32_SPI_REG_BASE = 0x3ff42000;
|
||||
export const ESP32_BASEFUSEADDR = 0x3ff5a000;
|
||||
export const ESP32_MACFUSEADDR = 0x3ff5a000;
|
||||
export const ESP32_SPI_USR_OFFS = 0x1c;
|
||||
export const ESP32_SPI_USR1_OFFS = 0x20;
|
||||
export const ESP32_SPI_USR2_OFFS = 0x24;
|
||||
export const ESP32_SPI_MOSI_DLEN_OFFS = 0x28;
|
||||
export const ESP32_SPI_MISO_DLEN_OFFS = 0x2c;
|
||||
export const ESP32_SPI_W0_OFFS = 0x80;
|
||||
export const ESP32_UART_DATE_REG_ADDR = 0x60000078;
|
||||
export const ESP32_BOOTLOADER_FLASH_OFFSET = 0x1000;
|
||||
|
||||
export const ESP32S2_SPI_REG_BASE = 0x3f402000;
|
||||
export const ESP32S2_BASEFUSEADDR = 0x3f41a000;
|
||||
export const ESP32S2_MACFUSEADDR = 0x3f41a044;
|
||||
export const ESP32S2_SPI_USR_OFFS = 0x18;
|
||||
export const ESP32S2_SPI_USR1_OFFS = 0x1c;
|
||||
export const ESP32S2_SPI_USR2_OFFS = 0x20;
|
||||
export const ESP32S2_SPI_MOSI_DLEN_OFFS = 0x24;
|
||||
export const ESP32S2_SPI_MISO_DLEN_OFFS = 0x28;
|
||||
export const ESP32S2_SPI_W0_OFFS = 0x58;
|
||||
export const ESP32S2_UART_DATE_REG_ADDR = 0x60000078;
|
||||
export const ESP32S2_BOOTLOADER_FLASH_OFFSET = 0x1000;
|
||||
|
||||
export const ESP32S3_SPI_REG_BASE = 0x60002000;
|
||||
export const ESP32S3_BASEFUSEADDR = 0x60007000;
|
||||
export const ESP32S3_MACFUSEADDR = 0x60007000 + 0x044;
|
||||
export const ESP32S3_SPI_USR_OFFS = 0x18;
|
||||
export const ESP32S3_SPI_USR1_OFFS = 0x1c;
|
||||
export const ESP32S3_SPI_USR2_OFFS = 0x20;
|
||||
export const ESP32S3_SPI_MOSI_DLEN_OFFS = 0x24;
|
||||
export const ESP32S3_SPI_MISO_DLEN_OFFS = 0x28;
|
||||
export const ESP32S3_SPI_W0_OFFS = 0x58;
|
||||
export const ESP32S3_UART_DATE_REG_ADDR = 0x60000080;
|
||||
export const ESP32S3_BOOTLOADER_FLASH_OFFSET = 0x0;
|
||||
|
||||
export const ESP32C3_SPI_REG_BASE = 0x60002000;
|
||||
export const ESP32C3_BASEFUSEADDR = 0x60008800;
|
||||
export const ESP32C3_MACFUSEADDR = 0x60008800 + 0x044;
|
||||
export const ESP32C3_SPI_USR_OFFS = 0x18;
|
||||
export const ESP32C3_SPI_USR1_OFFS = 0x1c;
|
||||
export const ESP32C3_SPI_USR2_OFFS = 0x20;
|
||||
export const ESP32C3_SPI_MOSI_DLEN_OFFS = 0x24;
|
||||
export const ESP32C3_SPI_MISO_DLEN_OFFS = 0x28;
|
||||
export const ESP32C3_SPI_W0_OFFS = 0x58;
|
||||
export const ESP32C3_UART_DATE_REG_ADDR = 0x6000007c;
|
||||
export const ESP32C3_BOOTLOADER_FLASH_OFFSET = 0x0;
|
||||
|
||||
export interface SpiFlashAddresses {
|
||||
regBase: number;
|
||||
baseFuse: number;
|
||||
macFuse: number;
|
||||
usrOffs: number;
|
||||
usr1Offs: number;
|
||||
usr2Offs: number;
|
||||
mosiDlenOffs: number;
|
||||
misoDlenOffs: number;
|
||||
w0Offs: number;
|
||||
uartDateReg: number;
|
||||
flashOffs: number;
|
||||
}
|
||||
|
||||
export const SYNC_PACKET = toByteArray(
|
||||
"\x07\x07\x12 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"
|
||||
);
|
||||
export const CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000;
|
||||
// These values for the families are made up; nothing that esptool uses.
|
||||
export const CHIP_FAMILY_ESP8266 = 0x8266;
|
||||
export const CHIP_FAMILY_ESP32 = 0x32;
|
||||
export const CHIP_FAMILY_ESP32S2 = 0x3252;
|
||||
export const CHIP_FAMILY_ESP32S3 = 0x3253;
|
||||
export const CHIP_FAMILY_ESP32C3 = 0x32c3;
|
||||
export const CHIP_FAMILY_ESP32C6 = 0x32c6;
|
||||
export const CHIP_FAMILY_ESP32H2 = 0x3272;
|
||||
export type ChipFamily =
|
||||
| typeof CHIP_FAMILY_ESP8266
|
||||
| typeof CHIP_FAMILY_ESP32
|
||||
| typeof CHIP_FAMILY_ESP32S2
|
||||
| typeof CHIP_FAMILY_ESP32S3
|
||||
| typeof CHIP_FAMILY_ESP32C3
|
||||
| typeof CHIP_FAMILY_ESP32C6
|
||||
| typeof CHIP_FAMILY_ESP32H2;
|
||||
|
||||
export const CHIP_DETECT_MAGIC_VALUES = {
|
||||
0xfff0c101: { name: "ESP8266", family: CHIP_FAMILY_ESP8266 },
|
||||
0x00f01d83: { name: "ESP32", family: CHIP_FAMILY_ESP32 },
|
||||
0x000007c6: { name: "ESP32-S2", family: CHIP_FAMILY_ESP32S2 },
|
||||
0x9: { name: "ESP32-S3", family: CHIP_FAMILY_ESP32S3 },
|
||||
0xeb004136: { name: "ESP32-S3(beta2)", family: CHIP_FAMILY_ESP32S3 },
|
||||
0x6921506f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
||||
0x1b31506f: { name: "ESP32-C3", family: CHIP_FAMILY_ESP32C3 },
|
||||
0xca26cc22: { name: "ESP32-H2", family: CHIP_FAMILY_ESP32H2 },
|
||||
0x0da1806f: { name: "ESP32-C6(beta)", family: CHIP_FAMILY_ESP32C6 },
|
||||
};
|
||||
|
||||
// Commands supported by ESP8266 ROM bootloader
|
||||
export const ESP_FLASH_BEGIN = 0x02;
|
||||
export const ESP_FLASH_DATA = 0x03;
|
||||
export const ESP_FLASH_END = 0x04;
|
||||
export const ESP_MEM_BEGIN = 0x05;
|
||||
export const ESP_MEM_END = 0x06;
|
||||
export const ESP_MEM_DATA = 0x07;
|
||||
export const ESP_SYNC = 0x08;
|
||||
export const ESP_WRITE_REG = 0x09;
|
||||
export const ESP_READ_REG = 0x0a;
|
||||
|
||||
export const ESP_ERASE_FLASH = 0xd0;
|
||||
export const ESP_ERASE_REGION = 0xd1;
|
||||
|
||||
export const ESP_SPI_SET_PARAMS = 0x0b;
|
||||
export const ESP_SPI_ATTACH = 0x0d;
|
||||
export const ESP_CHANGE_BAUDRATE = 0x0f;
|
||||
export const ESP_SPI_FLASH_MD5 = 0x13;
|
||||
export const ESP_CHECKSUM_MAGIC = 0xef;
|
||||
export const ESP_FLASH_DEFL_BEGIN = 0x10;
|
||||
export const ESP_FLASH_DEFL_DATA = 0x11;
|
||||
export const ESP_FLASH_DEFL_END = 0x12;
|
||||
|
||||
export const ROM_INVALID_RECV_MSG = 0x05;
|
||||
|
||||
export const USB_RAM_BLOCK = 0x800;
|
||||
export const ESP_RAM_BLOCK = 0x1800;
|
||||
|
||||
// Timeouts
|
||||
export const DEFAULT_TIMEOUT = 3000;
|
||||
export const CHIP_ERASE_TIMEOUT = 600000; // timeout for full chip erase in ms
|
||||
export const MAX_TIMEOUT = CHIP_ERASE_TIMEOUT * 2; // longest any command can run in ms
|
||||
export const SYNC_TIMEOUT = 100; // timeout for syncing with bootloader in ms
|
||||
export const ERASE_REGION_TIMEOUT_PER_MB = 30000; // timeout (per megabyte) for erasing a region in ms
|
||||
export const MEM_END_ROM_TIMEOUT = 500;
|
||||
|
||||
/**
|
||||
* @name timeoutPerMb
|
||||
* Scales timeouts which are size-specific
|
||||
*/
|
||||
export const timeoutPerMb = (secondsPerMb: number, sizeBytes: number) => {
|
||||
let result = Math.floor(secondsPerMb * (sizeBytes / 0x1e6));
|
||||
if (result < DEFAULT_TIMEOUT) {
|
||||
return DEFAULT_TIMEOUT;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const getSpiFlashAddresses = (
|
||||
chipFamily: ChipFamily
|
||||
): SpiFlashAddresses => {
|
||||
switch (chipFamily) {
|
||||
case CHIP_FAMILY_ESP32:
|
||||
return {
|
||||
regBase: ESP32_SPI_REG_BASE,
|
||||
baseFuse: ESP32_BASEFUSEADDR,
|
||||
macFuse: ESP32_MACFUSEADDR,
|
||||
usrOffs: ESP32_SPI_USR_OFFS,
|
||||
usr1Offs: ESP32_SPI_USR1_OFFS,
|
||||
usr2Offs: ESP32_SPI_USR2_OFFS,
|
||||
mosiDlenOffs: ESP32_SPI_MOSI_DLEN_OFFS,
|
||||
misoDlenOffs: ESP32_SPI_MISO_DLEN_OFFS,
|
||||
w0Offs: ESP32_SPI_W0_OFFS,
|
||||
uartDateReg: ESP32_UART_DATE_REG_ADDR,
|
||||
flashOffs: ESP32_BOOTLOADER_FLASH_OFFSET,
|
||||
};
|
||||
case CHIP_FAMILY_ESP32S2:
|
||||
return {
|
||||
regBase: ESP32S2_SPI_REG_BASE,
|
||||
baseFuse: ESP32S2_BASEFUSEADDR,
|
||||
macFuse: ESP32S2_MACFUSEADDR,
|
||||
usrOffs: ESP32S2_SPI_USR_OFFS,
|
||||
usr1Offs: ESP32S2_SPI_USR1_OFFS,
|
||||
usr2Offs: ESP32S2_SPI_USR2_OFFS,
|
||||
mosiDlenOffs: ESP32S2_SPI_MOSI_DLEN_OFFS,
|
||||
misoDlenOffs: ESP32S2_SPI_MISO_DLEN_OFFS,
|
||||
w0Offs: ESP32S2_SPI_W0_OFFS,
|
||||
uartDateReg: ESP32S2_UART_DATE_REG_ADDR,
|
||||
flashOffs: ESP32S2_BOOTLOADER_FLASH_OFFSET,
|
||||
};
|
||||
case CHIP_FAMILY_ESP32S3:
|
||||
return {
|
||||
regBase: ESP32S3_SPI_REG_BASE,
|
||||
usrOffs: ESP32S3_SPI_USR_OFFS,
|
||||
baseFuse: ESP32S3_BASEFUSEADDR,
|
||||
macFuse: ESP32S3_MACFUSEADDR,
|
||||
usr1Offs: ESP32S3_SPI_USR1_OFFS,
|
||||
usr2Offs: ESP32S3_SPI_USR2_OFFS,
|
||||
mosiDlenOffs: ESP32S3_SPI_MOSI_DLEN_OFFS,
|
||||
misoDlenOffs: ESP32S3_SPI_MISO_DLEN_OFFS,
|
||||
w0Offs: ESP32S3_SPI_W0_OFFS,
|
||||
uartDateReg: ESP32S3_UART_DATE_REG_ADDR,
|
||||
flashOffs: ESP32S3_BOOTLOADER_FLASH_OFFSET,
|
||||
};
|
||||
case CHIP_FAMILY_ESP8266:
|
||||
return {
|
||||
regBase: ESP8266_SPI_REG_BASE,
|
||||
usrOffs: ESP8266_SPI_USR_OFFS,
|
||||
baseFuse: ESP8266_BASEFUSEADDR,
|
||||
macFuse: ESP8266_MACFUSEADDR,
|
||||
usr1Offs: ESP8266_SPI_USR1_OFFS,
|
||||
usr2Offs: ESP8266_SPI_USR2_OFFS,
|
||||
mosiDlenOffs: ESP8266_SPI_MOSI_DLEN_OFFS,
|
||||
misoDlenOffs: ESP8266_SPI_MISO_DLEN_OFFS,
|
||||
w0Offs: ESP8266_SPI_W0_OFFS,
|
||||
uartDateReg: ESP8266_UART_DATE_REG_ADDR,
|
||||
flashOffs: ESP8266_BOOTLOADER_FLASH_OFFSET,
|
||||
};
|
||||
case CHIP_FAMILY_ESP32C3:
|
||||
return {
|
||||
regBase: ESP32C3_SPI_REG_BASE,
|
||||
baseFuse: ESP32C3_BASEFUSEADDR,
|
||||
macFuse: ESP32C3_MACFUSEADDR,
|
||||
usrOffs: ESP32C3_SPI_USR_OFFS,
|
||||
usr1Offs: ESP32C3_SPI_USR1_OFFS,
|
||||
usr2Offs: ESP32C3_SPI_USR2_OFFS,
|
||||
mosiDlenOffs: ESP32C3_SPI_MOSI_DLEN_OFFS,
|
||||
misoDlenOffs: ESP32C3_SPI_MISO_DLEN_OFFS,
|
||||
w0Offs: ESP32C3_SPI_W0_OFFS,
|
||||
uartDateReg: ESP32C3_UART_DATE_REG_ADDR,
|
||||
flashOffs: ESP32C3_BOOTLOADER_FLASH_OFFSET,
|
||||
};
|
||||
default:
|
||||
return {
|
||||
regBase: -1,
|
||||
baseFuse: -1,
|
||||
macFuse: -1,
|
||||
usrOffs: -1,
|
||||
usr1Offs: -1,
|
||||
usr2Offs: -1,
|
||||
mosiDlenOffs: -1,
|
||||
misoDlenOffs: -1,
|
||||
w0Offs: -1,
|
||||
uartDateReg: -1,
|
||||
flashOffs: -1,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export class SlipReadError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = "SlipReadError";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,27 @@
|
||||
import { ESP_ROM_BAUD, Logger } from "./const";
|
||||
import { ESPLoader } from "./esp_loader";
|
||||
|
||||
export type { Logger } from "./const";
|
||||
export { ESPLoader } from "./esp_loader";
|
||||
|
||||
export {
|
||||
CHIP_FAMILY_ESP32,
|
||||
CHIP_FAMILY_ESP32S2,
|
||||
CHIP_FAMILY_ESP32S3,
|
||||
CHIP_FAMILY_ESP8266,
|
||||
CHIP_FAMILY_ESP32C3,
|
||||
CHIP_FAMILY_ESP32C6,
|
||||
CHIP_FAMILY_ESP32H2,
|
||||
} from "./const";
|
||||
|
||||
export const connect = async (logger: Logger) => {
|
||||
// - Request a port and open a connection.
|
||||
const port = await navigator.serial.requestPort();
|
||||
|
||||
logger.log("Connecting...");
|
||||
await port.open({ baudRate: ESP_ROM_BAUD });
|
||||
|
||||
logger.log("Connected successfully.");
|
||||
|
||||
return new ESPLoader(port, logger);
|
||||
};
|
||||
@ -0,0 +1,108 @@
|
||||
const lut = {
|
||||
b: { u: DataView.prototype.getInt8, p: DataView.prototype.setInt8, bytes: 1 },
|
||||
B: {
|
||||
u: DataView.prototype.getUint8,
|
||||
p: DataView.prototype.setUint8,
|
||||
bytes: 1,
|
||||
},
|
||||
h: {
|
||||
u: DataView.prototype.getInt16,
|
||||
p: DataView.prototype.setInt16,
|
||||
bytes: 2,
|
||||
},
|
||||
H: {
|
||||
u: DataView.prototype.getUint16,
|
||||
p: DataView.prototype.setUint16,
|
||||
bytes: 2,
|
||||
},
|
||||
i: {
|
||||
u: DataView.prototype.getInt32,
|
||||
p: DataView.prototype.setInt32,
|
||||
bytes: 4,
|
||||
},
|
||||
I: {
|
||||
u: DataView.prototype.getUint32,
|
||||
p: DataView.prototype.setUint32,
|
||||
bytes: 4,
|
||||
},
|
||||
q: {
|
||||
// @ts-ignore
|
||||
u: DataView.prototype.getInt64,
|
||||
// @ts-ignore
|
||||
p: DataView.prototype.setInt64,
|
||||
bytes: 8,
|
||||
},
|
||||
Q: {
|
||||
// @ts-ignore
|
||||
u: DataView.prototype.getUint64,
|
||||
// @ts-ignore
|
||||
p: DataView.prototype.setUint64,
|
||||
bytes: 8,
|
||||
},
|
||||
};
|
||||
|
||||
export const pack = (format: string, ...data: number[]) => {
|
||||
let pointer = 0;
|
||||
if (format.replace(/[<>]/, "").length != data.length) {
|
||||
throw "Pack format to Argument count mismatch";
|
||||
}
|
||||
let bytes: number[] = [];
|
||||
let littleEndian = true;
|
||||
for (let i = 0; i < format.length; i++) {
|
||||
if (format[i] == "<") {
|
||||
littleEndian = true;
|
||||
} else if (format[i] == ">") {
|
||||
littleEndian = false;
|
||||
} else {
|
||||
pushBytes(format[i], data[pointer]);
|
||||
pointer++;
|
||||
}
|
||||
}
|
||||
|
||||
function pushBytes(formatChar: string, value: number) {
|
||||
if (!(formatChar in lut)) {
|
||||
throw "Unhandled character '" + formatChar + "' in pack format";
|
||||
}
|
||||
let dataSize = lut[formatChar].bytes;
|
||||
let view = new DataView(new ArrayBuffer(dataSize));
|
||||
let dataViewFn = lut[formatChar].p.bind(view);
|
||||
dataViewFn(0, value, littleEndian);
|
||||
for (let i = 0; i < dataSize; i++) {
|
||||
bytes.push(view.getUint8(i));
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
};
|
||||
|
||||
export const unpack = (format: string, bytes: number[]) => {
|
||||
let pointer = 0;
|
||||
let data: number[] = [];
|
||||
let littleEndian = true;
|
||||
|
||||
for (let c of format) {
|
||||
if (c == "<") {
|
||||
littleEndian = true;
|
||||
} else if (c == ">") {
|
||||
littleEndian = false;
|
||||
} else {
|
||||
pushData(c);
|
||||
}
|
||||
}
|
||||
|
||||
function pushData(formatChar: string) {
|
||||
if (!(formatChar in lut)) {
|
||||
throw "Unhandled character '" + formatChar + "' in unpack format";
|
||||
}
|
||||
let dataSize = lut[formatChar].bytes;
|
||||
let view = new DataView(new ArrayBuffer(dataSize));
|
||||
for (let i = 0; i < dataSize; i++) {
|
||||
view.setUint8(i, bytes[pointer + i] & 0xff);
|
||||
}
|
||||
let dataViewFn = lut[formatChar].u.bind(view);
|
||||
data.push(dataViewFn(0, littleEndian));
|
||||
pointer += dataSize;
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
{"text": "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", "text_start": 1077411840, "entry": 1077413328, "data": "DEDKPw==", "data_start": 1070295976}
|
||||
@ -0,0 +1 @@
|
||||
{"text": "QREixCbCBsa3NwRgEUfYyzc0BGC3RMg/XECRi5HnskAiRJJEQQGCgAhAg6cEABN19Q+Cl9W3ARG3BwBgSsgDqYcAJspOxlLEBs4izLcEAGD9WTdKyD/ATBN09D8N4PJAYkQjqCQBsknSREJJIkoFYYKAiECDJwoAE3X1D4KXfRTjGTT/yb83JwBgfEudi/X/NzcAYHxLnYv1/4KAQREGxt03tycAYCOmBwI3BwAImMOYQ33/yFeyQBNF9f8FiUEBgoBBEQbG2T993TcHAEC3JwBgmMM3JwBgHEP9/7JAQQGCgEERIsQ3RMk/kwfECZxLBsYmwqHPXTcxyRMExAkYSL1HgURj1ucABES9iJO0FABNP5U/HEQ3BwABE5bHAGN/5gC3BoAAmeC3BgABNycAYFDDFMO3JgBgmEJ9/0FHkeAFRxRIupccxJmOFMiyQCJEkkRBAYKAEwcADJxBYxvlAIHnhUecwSGoI6AFAPlXPoWCgAVHY4fnAIlGY43XAP1X/beTFwUBEwewDcGH4xHl/olHyb+TB8ANYxb1AJjBkwcADPG3kwbQDf1X4xLV/JjBkwewDW2/t0XJP0ERk4VFCQbGUT9jSQUGt0fJP5OHxwCDpgcIA9dHCBN19Q9CB0GDEwYXAEIGQYIjkscINpcjAKcAA9dHCJFnk4cHBEIHQYNjHvcCN8fIPxMHxwChZ7qXA6YHCLcGyT+3R8k/k4fHAJOGxgRjH+YAI6bHCCOg1wgjkgcIIaD5V+MG9fyyQEEBgoAjptcII6DnCN23QREGxpcAyP/ngADmA0WFAbJAdRUTNRUAQQGCgEERBsbFNxHBDUWyQEEBFwPI/2cAo+BBEQbGlwDI/+eAYN7JNwHFskBBAdm/skBBAYKAQREGxhMHAAxjGuUAEwWwDdE/EwXADbJAQQHptxMHsA3jG+X+wTcTBdAN9bdBESLEJsIGxiqEswS1AGMXlACyQCJEkkRBAYKAA0UEAAUETT/ttxMFAAx5twERIsw3RMk/kwfECSbKxEcGzkrITsYTBMQJY/OVAK6EucADKUQAqokmmRNZyQAcSGNV8AAcRGNf+QKFO33dSEAmhs6FlwDI/+eAYN8TdfUPAcWTB0AMXMhcQKaXXMBcRLOEl0BExPJAYkTSREJJskkFYYKAtTtlvwERBs4izBk7NwTOP2wAEwVE/5cAyP/ngADehUcV5bJHk/cHID7GDTs3JwBgHEe3BkAAEwVE/9WPHMeyRZcAyP/ngKDbszegAPJAYkQ+hQVhgoBBEbdHyT8FRwbGI47nCJOHxwkT18UAmMcFZ30XzMPIx/mNOpWqlbGBjMsjqgcAQTcZwRMFUAyyQEEBgoB1cUrBfXMFaSLFJsPO3tLc1toGx310GpGTBwkHipcTBIT6PpSqiSKFroSXAMj/54AgH5MHCQcFaoqXs4pHQbngBWeTBwcHfXSTBYT6ipcTBIT5PpSTBwcHipe+lSKFlwDI/+eAYBwihcFFlTUBRQVjGpG6QCpEmkQKSfZZZlrWWklhgoAmiWNzmgAFaUqG1oVOhZcAyP/ngGDKE3X1DwHtSobWhSKFlwDI/+eAoBfKmbOEJEFptxMFMAZVvzFxfXNW01rRXs9izQbfIt0m20rZTtdS1WbLasluxwVnGpE2jBMHBwcUCDaX/Xe6lz7GI6oH+KqKLouyi7E7kwcAAhnBtwcCAD6FlwDI/+eAoBCFZ2PjdxWFZBgIfXSThwQHupcTBIT6M4mHAEqFlwDI/+eAIA99ehgIk4cEB7qXkww6+b6ck4cEBxMNivm6l4FJPp2FZ5OHBwcYCLqXM4RHAYMtRPlj9m0LY/G5A1WgYTOmhSKFsTtBMyaGooVKhZcAyP/ngEAKppqmmWP2aQOzh7lBY/KHA7MHO0HehGPzdwG+hCaGooVWhZcAyP/ngCC5E3X1D03dhWeThwcHGAi6lzOERwEjLAT4gUSNTaMJBPhmhZcAyP/ngICqffkDRTT56oW9PmNABQLj4p3+hWcYCJOHBwe6lzOHlwBSlyMKp/iFBOm3+VfjE/X8EUfjg+T0BWcUCJMHBwd9dLaXkwWE+hMEhPk+lJMHBwe2l76VIoWXAMj/54Bg/305wUUihUk5XTkRObcHAgAZ4ZMHAAI+hZcAyP/ngGD8BWMakfpQalTaVEpZulkqWppaClv6S2pM2kxKTbpNKWGCgLdXQUkZcZOH94QBRT7Oht6i3KbaytjO1tLU1tLa0N7O4szmyurI7saXAMj/54BAordHyD83d8k/k4cHABMHh7pj6ucUJTmRRWgIMTEFObfHyD+Th8cAIWc+lyMg9wi3BzhAN0rIP5OHZxsjIPoAt0rJP602k4rKABMKCgBjAAUStycMYEVHuNeFRUVFlwDI/+eAQO63BThAAUaThQUARUWXAMj/54BA7zc3BGAcSzcFAgCT50cAHMuXAMj/54BA7pcAyP/ngMD+t0cAYJxfEeUT9ccBYRUTNRUAgUWXAMj/54CAocFnN0vJP/0XEwcAEIVmQWa3BQABAUWTCcsJjWs3TMg/lwDI/+eAAJzOm5MMzACDp8oI9d+DpMoIhUcjpgoIIwLxAoPHFAAJRyMT4QKjAvECAtRNR2OF5whRR2OD5wgpR2Oe5wCDxzQAA8ckAKIH2Y8RR2OV5wCcRJxDPtQxPqFFSBDFPAPHNACDxyQAkWYiB12Pk4cGAWP45wQTBbANcTQTBcANWTQTBeAOQTT1NEG3I6AHAJEHXbW3BThAAUaThWUDFUWXAMj/54DA3jcHAGBcRxMFAAKT5xcQXMflvclHIxPxAmG/g8cUADVGY43HLGNu9g4ZRmOMxzZjYvYIDUZjgscYY2z2BAlGY47HJgFJEwTwDxN19A89NBN1+Q8lNKU84xYE8IPHFAA9R2OJ50Rja/c2EUdjgudUGUdjgOdWDUfjlufug8U0AIPHJAAThYQBogXdjcEVmTTRvZFGY4bXJJVG45XX+sFHBUVjEvcQnETYSCMk+gAjIuoAZaKlRmOO1yRj7PYCnUZjitcooUbjn9f2kwdAAmMR9x4C1B1EAUVhMgFFRTLFOv0yoUVIEH0UwTJ19AFJAUSpv6lGY47XJK1G45XX9OFHYxv3HtxMmEzUSJBIzESIRJcAyP/ngGCAKokzNaAAKoQtt9FGY4DXDmPt9gTFRmOG1whj6vYCvUZjidcWwUbjk9fwBURjH/cMnEgRZ2Ns9ybARMxIiEQzhIcCkTQjrAkAI6SLsPmgyUZjjNcWzUbjm9fswUcFRGMW9wrMRIhEsTxNqJMGIA1jidcSY+D2ApMGAA1jitcIkwYQDeOV1+qhR2MM9wgFRSqEraiTBjANY4/XQpMGQA3jl9fog0fLCWOABxqcREEXA6RJAWOE5wATBAAMgUeTBvAOY83nDgPHVACDx0QAAUkiB12Pg8dkAMIHXY+Dx3QA4gfZj+OI9uQTBBAMobUFRBHvcBCBRQFFl7DM/+eA4PoR5dFFaBDv8N+IAUQBSR21BURt/5fwx//ngIBtMzSgAPW3A62EAMBEs2eNABOXRwE5/xEyKf1BaSKdfRn9fTMFjUAZ6AFFqbcxgZfwx//ngKBqFf1ulOW3s3clAfX3QWkzBY1AY26JAH15MwWNQHnYMYGX8Mf/54AgaBH5SpT1t0GBl/DH/+eA4GbjEgXwMwQkQfm3oUfjAPfkAUkTBAAMUbvBR82/wUcFROMR9/acSGPv9g7MSIhEwTiNtzOG9AADRoYBhQexju29g0fLCa3Pg6fJAO3jIw4LCAOkSQE9twFJBUUVtZFHBUXjE/fqiESBRZfwx//ngOBjqbeTd/cAyf8TXUcAE4SEAAFJ/V3jdKndSESX8Mf/54CAUBxEWEAUQH2PY4e3AZBCk8f3//GPXY+YwgUJQQTZv5FHqb+DJUoAQReR5QHPAUkTBGAM3bGDJ4oAY+XnBpN3NwCd/wMoigABRoFHMwX4QLOG9QBj6ecA4wIG1iMi2gAjJKoAobszhvQAEE6RB5DCBUbpv6FHBUXjH/feAySKABnAEwSADCMkCgAjIgoAMzWAANWzAUkTBCAMQbEBSRMEgAyluQFJEwSQDIW5SUdjieccY2L3BEVH457ntoPHNAADxyQAE4SEAaIH2Y+TjQf/BUmDp8kAY4UNAJnDY0QgEWNXCRgTB3AMI6rpAOOUB7STB5AMWaITByANY4vnDBMHQA3jmeeyA8Q0AIPHJAAiBF2Ml/DH/+eAgEsDqckAQRRjcyQBIonjBwmwA6RJAEqUMYCDpwkBY1bwAIOniQBjUPQK7/DPwHXdA6VJAEqGk4WEAZfwx//ngABHCcWTB0AMI6r5AIOnSQDKlyOi+QCDp8kAM4knQSOmKQGX8Mf/54BARU28CWUTBQVxA6nEAIBEl/DH/+eAIDe3BwBg2Eu3BgABwRaTV0cBEgd1j72L2Y+zhycDAUWz1YcCl/DH/+eAADgTBYA+l/DH/+eAwDOdtNRIkEjMRIhE7/Dv+KG87/Bvu4G/t3bJPwOnhrq3x8g/k4fHAJmPPtaDp4uwN33JP27QEw3NCZOEhroFSGPz/QANSELGOsTv8O+3IkcySDdFyT+ihXwQkwbMABAQEwVFC5fwx//ngGA3glcDJ42wjECzjf1AHY8+lLJXIyTtsCqJvpWMwJMHzACdjQHFoWfjmvXmZoXv8A/UI6CUAZ214x8J5uOBB5yTB4AMI6r5AF26nETjmQea7/BPyQllEwUFcZfwx//ngCAnl/DH/+eAoCpRusBE4wgEmO/wL8cTBYA+l/DH/+eAICUClK269lBmVNZURlm2WSZalloGW/ZLZkzWTEZNtk0JYYKA", "text_start": 1077411840, "entry": 1077413488, "data": "DEDIPw==", "data_start": 1070164904}
|
||||
@ -0,0 +1 @@
|
||||
{"text": "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", "text_start": 1077411840, "entry": 1077413328, "data": "DEDIPw==", "data_start": 1070164904}
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,48 @@
|
||||
import {
|
||||
ChipFamily,
|
||||
CHIP_FAMILY_ESP32,
|
||||
CHIP_FAMILY_ESP32S2,
|
||||
CHIP_FAMILY_ESP32S3,
|
||||
CHIP_FAMILY_ESP8266,
|
||||
CHIP_FAMILY_ESP32C3
|
||||
} from "../const";
|
||||
import { toByteArray } from "../util";
|
||||
|
||||
interface LoadedStub {
|
||||
text: string;
|
||||
data: string;
|
||||
text_start: number;
|
||||
entry: number;
|
||||
data_start: number;
|
||||
}
|
||||
|
||||
interface Stub {
|
||||
text: number[];
|
||||
data: number[];
|
||||
text_start: number;
|
||||
entry: number;
|
||||
data_start: number;
|
||||
}
|
||||
|
||||
export const getStubCode = async (chipFamily: ChipFamily): Promise<Stub> => {
|
||||
let stubcode!: LoadedStub;
|
||||
|
||||
if (chipFamily == CHIP_FAMILY_ESP32) {
|
||||
stubcode = await import("./esp32.json");
|
||||
} else if (chipFamily == CHIP_FAMILY_ESP32S2) {
|
||||
stubcode = await import("./esp32s2.json");
|
||||
} else if (chipFamily == CHIP_FAMILY_ESP32S3) {
|
||||
stubcode = await import("./esp32s3.json");
|
||||
} else if (chipFamily == CHIP_FAMILY_ESP8266) {
|
||||
stubcode = await import("./esp8266.json");
|
||||
} else if (chipFamily == CHIP_FAMILY_ESP32C3) {
|
||||
stubcode = await import("./esp32c3.json");
|
||||
}
|
||||
|
||||
// Base64 decode the text and data
|
||||
return {
|
||||
...stubcode,
|
||||
text: toByteArray(atob(stubcode.text)),
|
||||
data: toByteArray(atob(stubcode.data)),
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @name slipEncode
|
||||
* Take an array buffer and return back a new array where
|
||||
* 0xdb is replaced with 0xdb 0xdd and 0xc0 is replaced with 0xdb 0xdc
|
||||
*/
|
||||
export const slipEncode = (buffer: number[]): number[] => {
|
||||
let encoded = [0xc0];
|
||||
for (let byte of buffer) {
|
||||
if (byte == 0xdb) {
|
||||
encoded = encoded.concat([0xdb, 0xdd]);
|
||||
} else if (byte == 0xc0) {
|
||||
encoded = encoded.concat([0xdb, 0xdc]);
|
||||
} else {
|
||||
encoded.push(byte);
|
||||
}
|
||||
}
|
||||
encoded.push(0xc0);
|
||||
return encoded;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name toByteArray
|
||||
* Convert a string to a byte array
|
||||
*/
|
||||
export const toByteArray = (str: string): number[] => {
|
||||
let byteArray: number[] = [];
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let charcode = str.charCodeAt(i);
|
||||
if (charcode <= 0xff) {
|
||||
byteArray.push(charcode);
|
||||
}
|
||||
}
|
||||
return byteArray;
|
||||
};
|
||||
|
||||
export const hexFormatter = (bytes: number[]) =>
|
||||
"[" + bytes.map((value) => toHex(value)).join(", ") + "]";
|
||||
|
||||
export const toHex = (value: number, size = 2) => {
|
||||
let hex = value.toString(16).toUpperCase();
|
||||
if (hex.startsWith("-")) {
|
||||
return "-0x" + hex.substring(1).padStart(size, "0");
|
||||
} else {
|
||||
return "0x" + hex.padStart(size, "0");
|
||||
}
|
||||
};
|
||||
|
||||
export const sleep = (ms: number) =>
|
||||
new Promise((resolve) => setTimeout(resolve, ms));
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2019", "dom"],
|
||||
"target": "es2019",
|
||||
"module": "es2020",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"importHelpers": true
|
||||
},
|
||||
"include": ["src/*"]
|
||||
}
|
||||
Loading…
Reference in New Issue