mirror of
https://github.com/esphome/esp-web-tools.git
synced 2025-04-19 21:27:20 +00:00
Compare commits
No commits in common. "main" and "9.2.1" have entirely different histories.
@ -4,9 +4,9 @@
|
||||
"name": "Node.js & TypeScript",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
// Update 'VARIANT' to pick a Node version: 12, 14, 16, 18, 20
|
||||
// Update 'VARIANT' to pick a Node version: 12, 14, 16
|
||||
"args": {
|
||||
"VARIANT": "20"
|
||||
"VARIANT": "16"
|
||||
}
|
||||
},
|
||||
|
||||
|
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -14,13 +14,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install jq tool
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install jq
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- run: npm ci
|
||||
|
4
.github/workflows/npmpublish.yml
vendored
4
.github/workflows/npmpublish.yml
vendored
@ -11,12 +11,12 @@ jobs:
|
||||
publish-npm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install jq tool
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install jq
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
2
.github/workflows/release-drafter.yml
vendored
2
.github/workflows/release-drafter.yml
vendored
@ -9,6 +9,6 @@ jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
201
LICENSE
201
LICENSE
@ -1,201 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -66,5 +66,3 @@ Example manifest:
|
||||
## Development
|
||||
|
||||
Run `script/develop`. This starts a server. Open it on http://localhost:5001.
|
||||
|
||||
[](https://www.openhomefoundation.org/)
|
||||
|
81
index.html
81
index.html
@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@ -79,10 +79,8 @@
|
||||
}
|
||||
.screenshot img {
|
||||
max-width: 100%;
|
||||
box-shadow:
|
||||
rgb(0 0 0 / 20%) 0px 2px 1px -1px,
|
||||
rgb(0 0 0 / 14%) 0px 1px 1px 0px,
|
||||
rgb(0 0 0 / 12%) 0px 1px 3px 0px;
|
||||
box-shadow: rgb(0 0 0 / 20%) 0px 2px 1px -1px,
|
||||
rgb(0 0 0 / 14%) 0px 1px 1px 0px, rgb(0 0 0 / 12%) 0px 1px 3px 0px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.screenshot i {
|
||||
@ -173,9 +171,7 @@
|
||||
<a href="https://esphome.io">ESPHome</a>. To get started, connect an ESP
|
||||
device to your computer and hit the button:
|
||||
</p>
|
||||
<esp-web-install-button
|
||||
manifest="https://firmware.esphome.io/esp-web-tools/manifest.json"
|
||||
>
|
||||
<esp-web-install-button manifest="static/firmware_build/manifest.json">
|
||||
<i slot="unsupported">
|
||||
The demo is not available because your browser does not support Web
|
||||
Serial. Open this page in Google Chrome or Microsoft Edge instead<span
|
||||
@ -249,62 +245,13 @@
|
||||
</div>
|
||||
<div class="name">2Smart</div>
|
||||
</a>
|
||||
<a href="https://clockwise.page" target="_blank" class="project">
|
||||
<div class="logo">
|
||||
<img src="static/logos/clockwise.png" alt="Clockwise logo" />
|
||||
</div>
|
||||
<div class="name">Clockwise</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://sblantipodi.github.io/glow_worm_luciferin"
|
||||
target="_blank"
|
||||
class="project"
|
||||
>
|
||||
<div class="logo">
|
||||
<img
|
||||
src="static/logos/luciferin_logo.png"
|
||||
alt="Firefly Luciferin logo"
|
||||
/>
|
||||
</div>
|
||||
<div class="name">Luciferin</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://install.openepaperlink.de"
|
||||
target="_blank"
|
||||
class="project"
|
||||
>
|
||||
<div class="logo">
|
||||
<img
|
||||
src="static/logos/openepaperlink.png"
|
||||
alt="OpenEpaperLink logo"
|
||||
/>
|
||||
</div>
|
||||
<div class="name">OpenEpaperLink</div>
|
||||
</a>
|
||||
<a href="https://openspool.io" target="_blank" class="project">
|
||||
<div class="logo">
|
||||
<img src="static/logos/openspool.png" alt="OpenSpool logo" />
|
||||
</div>
|
||||
<div class="name">OpenSpool</div>
|
||||
</a>
|
||||
<a href="https://usetrmnl.com/flash" target="_blank" class="project">
|
||||
<div class="logo">
|
||||
<img src="static/logos/trmnl.png" alt="TRMNL logo" />
|
||||
</div>
|
||||
<div class="name">TRMNL</div>
|
||||
</a>
|
||||
<a href="https://nspanelmanager.com" target="_blank" class="project">
|
||||
<div class="logo">
|
||||
<img src="static/logos/nspanelmanager.svg" alt="NSPanelManager logo" />
|
||||
</div>
|
||||
<div class="name">NSPanel Manager</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<h2>How it works</h2>
|
||||
<p>
|
||||
ESP Web Tools works by combining
|
||||
<a href="https://developer.mozilla.org/docs/Web/API/Web_Serial_API"
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API"
|
||||
>Web Serial</a
|
||||
>, <a href="https://www.improv-wifi.com/">Improv Wi-Fi</a> (optional),
|
||||
and a manifest which describes the firmware. ESP Web Tools detects the
|
||||
@ -377,7 +324,7 @@
|
||||
<pre>
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/esp-web-tools@10/dist/web/install-button.js?module"
|
||||
src="https://unpkg.com/esp-web-tools@9/dist/web/install-button.js?module"
|
||||
></script></pre
|
||||
>
|
||||
<p>
|
||||
@ -393,7 +340,7 @@
|
||||
</p>
|
||||
<pre>
|
||||
<esp-web-install-button
|
||||
manifest="https://firmware.esphome.io/esp-web-tools/manifest.json"
|
||||
manifest="/static/firmware_build/manifest.json"
|
||||
></esp-web-install-button></pre
|
||||
>
|
||||
<p>
|
||||
@ -404,7 +351,7 @@
|
||||
<p>
|
||||
If your manifest or the firmware files are hosted on another server,
|
||||
make sure you configure
|
||||
<a href="https://developer.mozilla.org/docs/Web/HTTP/CORS"
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"
|
||||
>the CORS-headers</a
|
||||
>
|
||||
such that your website is allowed to fetch those files by adding the
|
||||
@ -459,8 +406,7 @@ esptool --chip esp32 merge_bin \
|
||||
Manifests describe the firmware that you want to offer the user to
|
||||
install. It allows specifying different builds for the different types
|
||||
of ESP devices. Current supported chip families are
|
||||
<code>ESP8266</code>, <code>ESP32</code>, <code>ESP32-C2</code>,
|
||||
<code>ESP32-C3</code>, <code>ESP32-C6</code>, <code>ESP32-H2</code>,
|
||||
<code>ESP8266</code>, <code>ESP32</code>, <code>ESP32-C3</code>,
|
||||
<code>ESP32-S2</code> and <code>ESP32-S3</code>. The correct build will
|
||||
be automatically selected based on the type of the connected ESP device.
|
||||
</p>
|
||||
@ -554,7 +500,6 @@ button.overrides = {
|
||||
<ul>
|
||||
<li><code>--esp-tools-button-color</code></li>
|
||||
<li><code>--esp-tools-button-text-color</code></li>
|
||||
<li><code>--esp-tools-button-border-radius</code></li>
|
||||
</ul>
|
||||
<p>There are also some attributes that can be used for styling:</p>
|
||||
<table>
|
||||
@ -578,7 +523,7 @@ button.overrides = {
|
||||
</p>
|
||||
<pre>
|
||||
<esp-web-install-button
|
||||
manifest="https://firmware.esphome.io/esp-web-tools/manifest.json"
|
||||
manifest="/static/firmware_build/manifest.json"
|
||||
>
|
||||
<button slot="activate">Custom install button</button>
|
||||
<span slot="unsupported">Ah snap, your browser doesn't work!</span>
|
||||
@ -599,9 +544,7 @@ button.overrides = {
|
||||
<div class="footer">
|
||||
<div class="initiative">
|
||||
ESP Web Tools is a project by
|
||||
<a href="https://esphome.io">ESPHome</a>,
|
||||
<a href="https://www.openhomefoundation.org">Open Home Foundation</a
|
||||
>.<br />
|
||||
<a href="https://esphome.io">ESPHome</a>.<br />
|
||||
Development is funded by
|
||||
<a href="https://www.nabucasa.com">Nabu Casa</a>.
|
||||
</div>
|
||||
|
5628
package-lock.json
generated
5628
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
41
package.json
41
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "esp-web-tools",
|
||||
"version": "10.1.0",
|
||||
"version": "9.2.1",
|
||||
"description": "Web tools for ESP devices",
|
||||
"main": "dist/install-button.js",
|
||||
"repository": "https://github.com/esphome/esp-web-tools",
|
||||
@ -10,25 +10,30 @@
|
||||
"prepublishOnly": "script/build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "^28.0.2",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@types/w3c-web-serial": "^1.0.7",
|
||||
"prettier": "^3.4.2",
|
||||
"rollup": "^4.29.1",
|
||||
"serve": "^14.2.4",
|
||||
"typescript": "^5.7.2"
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@rollup/plugin-babel": "^6.0.3",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-typescript": "^11.0.0",
|
||||
"@rollup/plugin-terser": "^0.4.0",
|
||||
"@types/w3c-web-serial": "^1.0.3",
|
||||
"prettier": "^2.8.1",
|
||||
"rollup": "^3.9.1",
|
||||
"serve": "^14.1.2",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@material/web": "^2.2.0",
|
||||
"esptool-js": "^0.5.3",
|
||||
"improv-wifi-serial-sdk": "^2.5.0",
|
||||
"lit": "^3.2.1",
|
||||
"@material/mwc-button": "^0.27.0",
|
||||
"@material/mwc-checkbox": "^0.27.0",
|
||||
"@material/mwc-circular-progress": "^0.27.0",
|
||||
"@material/mwc-dialog": "^0.27.0",
|
||||
"@material/mwc-formfield": "^0.27.0",
|
||||
"@material/mwc-icon-button": "^0.27.0",
|
||||
"@material/mwc-textfield": "^0.27.0",
|
||||
"esptool-js": "^0.2.1",
|
||||
"improv-wifi-serial-sdk": "^2.4.0",
|
||||
"lit": "^2.5.0",
|
||||
"pako": "^2.1.0",
|
||||
"tslib": "^2.8.1"
|
||||
"tslib": "^2.4.1"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import nodeResolve from "@rollup/plugin-node-resolve";
|
||||
import json from "@rollup/plugin-json";
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import babel from "@rollup/plugin-babel";
|
||||
import commonjs from "@rollup/plugin-commonjs";
|
||||
|
||||
const config = {
|
||||
input: "dist/install-button.js",
|
||||
@ -13,24 +12,10 @@ const config = {
|
||||
external: ["https://www.improv-wifi.com/sdk-js/launch-button.js"],
|
||||
preserveEntrySignatures: false,
|
||||
plugins: [
|
||||
commonjs(),
|
||||
nodeResolve({
|
||||
browser: true,
|
||||
preferBuiltins: false,
|
||||
}),
|
||||
nodeResolve(),
|
||||
babel({
|
||||
babelHelpers: "bundled",
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
targets: {
|
||||
// We use unpkg as CDN and it doesn't bundle modern syntax
|
||||
chrome: "84",
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: ["@babel/plugin-proposal-class-properties"],
|
||||
}),
|
||||
json(),
|
||||
],
|
||||
|
@ -1,10 +1,6 @@
|
||||
# Stop on errors
|
||||
set -e
|
||||
|
||||
if [ -z "$PORT" ]; then
|
||||
PORT=5001
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
rm -rf dist
|
||||
@ -13,8 +9,9 @@ rm -rf dist
|
||||
trap "kill 0" EXIT
|
||||
|
||||
# Run tsc once as rollup expects those files
|
||||
npm exec -- tsc || true
|
||||
tsc || true
|
||||
|
||||
npm exec -- serve -p "$PORT" &
|
||||
npm exec -- serve -p 5001 &
|
||||
npm exec -- tsc --watch &
|
||||
npm exec -- rollup -c --watch
|
||||
npm exec -- rollup -c --watch &
|
||||
wait
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { Checkbox } from "@material/web/checkbox/internal/checkbox.js";
|
||||
import { styles } from "@material/web/checkbox/internal/checkbox-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-checkbox": EwCheckbox;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwCheckbox extends Checkbox {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-checkbox", EwCheckbox);
|
@ -1,14 +0,0 @@
|
||||
import { CircularProgress } from "@material/web/progress/internal/circular-progress.js";
|
||||
import { styles } from "@material/web/progress/internal/circular-progress-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-circular-progress": EwCircularProgress;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwCircularProgress extends CircularProgress {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-circular-progress", EwCircularProgress);
|
@ -1,14 +0,0 @@
|
||||
import { Dialog } from "@material/web/dialog/internal/dialog.js";
|
||||
import { styles } from "@material/web/dialog/internal/dialog-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-dialog": EwDialog;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwDialog extends Dialog {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-dialog", EwDialog);
|
@ -1,14 +0,0 @@
|
||||
import { Divider } from "@material/web/divider/internal/divider.js";
|
||||
import { styles } from "@material/web/divider/internal/divider-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-divider": EwDivider;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwDivider extends Divider {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-divider", EwDivider);
|
@ -1,15 +0,0 @@
|
||||
import { FilledSelect } from "@material/web/select/internal/filled-select.js";
|
||||
import { styles } from "@material/web/select/internal/filled-select-styles.js";
|
||||
import { styles as sharedStyles } from "@material/web/select/internal/shared-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-filled-select": EwFilledSelect;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwFilledSelect extends FilledSelect {
|
||||
static override styles = [sharedStyles, styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-filled-select", EwFilledSelect);
|
@ -1,17 +0,0 @@
|
||||
import { styles as filledStyles } from "@material/web/textfield/internal/filled-styles.js";
|
||||
import { FilledTextField } from "@material/web/textfield/internal/filled-text-field.js";
|
||||
import { styles as sharedStyles } from "@material/web/textfield/internal/shared-styles.js";
|
||||
import { literal } from "lit/static-html.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-filled-text-field": EwFilledTextField;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwFilledTextField extends FilledTextField {
|
||||
static override styles = [sharedStyles, filledStyles];
|
||||
protected override readonly fieldTag = literal`md-filled-field`;
|
||||
}
|
||||
|
||||
customElements.define("ew-filled-text-field", EwFilledTextField);
|
@ -1,15 +0,0 @@
|
||||
import { IconButton } from "@material/web/iconbutton/internal/icon-button.js";
|
||||
import { styles as sharedStyles } from "@material/web/iconbutton/internal/shared-styles.js";
|
||||
import { styles } from "@material/web/iconbutton/internal/standard-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-icon-button": EwIconButton;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwIconButton extends IconButton {
|
||||
static override styles = [sharedStyles, styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-icon-button", EwIconButton);
|
@ -1,14 +0,0 @@
|
||||
import { ListItemEl as ListItem } from "@material/web/list/internal/listitem/list-item.js";
|
||||
import { styles } from "@material/web/list/internal/listitem/list-item-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-list-item": EwListItem;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwListItem extends ListItem {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-list-item", EwListItem);
|
@ -1,14 +0,0 @@
|
||||
import { List } from "@material/web/list/internal/list.js";
|
||||
import { styles } from "@material/web/list/internal/list-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-list": EwList;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwList extends List {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-list", EwList);
|
@ -1,14 +0,0 @@
|
||||
import { styles } from "@material/web/menu/internal/menuitem/menu-item-styles.js";
|
||||
import { SelectOptionEl } from "@material/web/select/internal/selectoption/select-option.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-select-option": EwSelectOption;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwSelectOption extends SelectOptionEl {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ew-select-option", EwSelectOption);
|
@ -1,15 +0,0 @@
|
||||
import { styles as sharedStyles } from "@material/web/button/internal/shared-styles.js";
|
||||
import { TextButton } from "@material/web/button/internal/text-button.js";
|
||||
import { styles as textStyles } from "@material/web/button/internal/text-styles.js";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ew-text-button": EwTextButton;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwTextButton extends TextButton {
|
||||
static override styles = [sharedStyles, textStyles];
|
||||
}
|
||||
|
||||
customElements.define("ew-text-button", EwTextButton);
|
25
src/components/ewt-button.ts
Normal file
25
src/components/ewt-button.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { css } from "lit";
|
||||
import { ButtonBase } from "@material/mwc-button/mwc-button-base";
|
||||
import { styles } from "@material/mwc-button/styles.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-button": EwtButton;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtButton extends ButtonBase {
|
||||
static override styles = [
|
||||
styles,
|
||||
css`
|
||||
.mdc-button {
|
||||
min-width: initial;
|
||||
}
|
||||
:host([text-left]) .mdc-button__label {
|
||||
text-align: left;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
customElements.define("ewt-button", EwtButton);
|
14
src/components/ewt-checkbox.ts
Normal file
14
src/components/ewt-checkbox.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { CheckboxBase } from "@material/mwc-checkbox/mwc-checkbox-base";
|
||||
import { styles } from "@material/mwc-checkbox/mwc-checkbox.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-checkbox": EwtCheckbox;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtCheckbox extends CheckboxBase {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ewt-checkbox", EwtCheckbox);
|
14
src/components/ewt-circular-progress.ts
Normal file
14
src/components/ewt-circular-progress.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { CircularProgressBase } from "@material/mwc-circular-progress/mwc-circular-progress-base";
|
||||
import { styles } from "@material/mwc-circular-progress/mwc-circular-progress.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-circular-progress": EwtCircularProgress;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtCircularProgress extends CircularProgressBase {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ewt-circular-progress", EwtCircularProgress);
|
@ -1,7 +1,6 @@
|
||||
import { ColoredConsole, coloredConsoleStyles } from "../util/console-color";
|
||||
import { sleep } from "../util/sleep";
|
||||
import { LineBreakTransformer } from "../util/line-break-transformer";
|
||||
import { TimestampTransformer } from "../util/timestamp-transformer";
|
||||
import { Logger } from "../const";
|
||||
|
||||
export class EwtConsole extends HTMLElement {
|
||||
@ -96,13 +95,12 @@ export class EwtConsole extends HTMLElement {
|
||||
signal: abortSignal,
|
||||
})
|
||||
.pipeThrough(new TransformStream(new LineBreakTransformer()))
|
||||
.pipeThrough(new TransformStream(new TimestampTransformer()))
|
||||
.pipeTo(
|
||||
new WritableStream({
|
||||
write: (chunk) => {
|
||||
this._console!.addLine(chunk.replace("\r", ""));
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
if (!abortSignal.aborted) {
|
||||
this._console!.addLine("");
|
||||
@ -143,17 +141,15 @@ export class EwtConsole extends HTMLElement {
|
||||
}
|
||||
|
||||
public async reset() {
|
||||
this.logger.debug("Triggering reset");
|
||||
this.logger.debug("Triggering reset.");
|
||||
await this.port.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: true,
|
||||
});
|
||||
await sleep(250);
|
||||
await this.port.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: false,
|
||||
});
|
||||
await sleep(250);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}
|
||||
}
|
||||
|
14
src/components/ewt-formfield.ts
Normal file
14
src/components/ewt-formfield.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { FormfieldBase } from "@material/mwc-formfield/mwc-formfield-base";
|
||||
import { styles } from "@material/mwc-formfield/mwc-formfield.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-formfield": EwtFormfield;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtFormfield extends FormfieldBase {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ewt-formfield", EwtFormfield);
|
14
src/components/ewt-icon-button.ts
Normal file
14
src/components/ewt-icon-button.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { IconButtonBase } from "@material/mwc-icon-button/mwc-icon-button-base";
|
||||
import { styles } from "@material/mwc-icon-button/mwc-icon-button.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-icon-button": EwtIconButton;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtIconButton extends IconButtonBase {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ewt-icon-button", EwtIconButton);
|
14
src/components/ewt-list-item.ts
Normal file
14
src/components/ewt-list-item.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { ListItemBase } from "@material/mwc-list/mwc-list-item-base";
|
||||
import { styles } from "@material/mwc-list/mwc-list-item.css";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-list-item": EwtListItem;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtListItem extends ListItemBase {
|
||||
static override styles = [styles];
|
||||
}
|
||||
|
||||
customElements.define("ewt-list-item", EwtListItem);
|
23
src/components/ewt-select.ts
Normal file
23
src/components/ewt-select.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { SelectBase } from "@material/mwc-select/mwc-select-base";
|
||||
import { styles } from "@material/mwc-select/mwc-select.css";
|
||||
import { css } from "lit";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-select": EwtSelect;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtSelect extends SelectBase {
|
||||
static override styles = [
|
||||
styles,
|
||||
// rem -> em conversion
|
||||
css`
|
||||
.mdc-floating-label {
|
||||
line-height: 1.15em;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
customElements.define("ewt-select", EwtSelect);
|
23
src/components/ewt-textfield.ts
Normal file
23
src/components/ewt-textfield.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { TextFieldBase } from "@material/mwc-textfield/mwc-textfield-base";
|
||||
import { styles } from "@material/mwc-textfield/mwc-textfield.css";
|
||||
import { css } from "lit";
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ewt-textfield": EwtTextfield;
|
||||
}
|
||||
}
|
||||
|
||||
export class EwtTextfield extends TextFieldBase {
|
||||
static override styles = [
|
||||
styles,
|
||||
// rem -> em conversion
|
||||
css`
|
||||
.mdc-floating-label {
|
||||
line-height: 1.15em;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
customElements.define("ewt-textfield", EwtTextfield);
|
@ -3,12 +3,29 @@ import { svg } from "lit";
|
||||
export const closeIcon = svg`
|
||||
<svg width="24" height="24" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const firmwareIcon = svg`
|
||||
<svg viewBox="0 0 24 24" title="Software">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M9.5,8.5L11,10L8,13L11,16L9.5,17.5L5,13L9.5,8.5M14.5,17.5L13,16L16,13L13,10L14.5,8.5L19,13L14.5,17.5M21,2H3A2,2 0 0,0 1,4V20A2,2 0 0,0 3,22H21A2,2 0 0,0 23,20V4A2,2 0 0,0 21,2M21,20H3V6H21V20Z"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const chipIcon = svg`
|
||||
<svg viewBox="0 0 24 24" title="Chipset">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M6,4H18V5H21V7H18V9H21V11H18V13H21V15H18V17H21V19H18V20H6V19H3V17H6V15H3V13H6V11H3V9H6V7H3V5H6V4M11,15V18H12V15H11M13,15V18H14V15H13M15,15V18H16V15H15Z"
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const refreshIcon = svg`
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path
|
||||
@ -17,45 +34,3 @@ export const refreshIcon = svg`
|
||||
/>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemInstallIcon = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemWifi = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M12,21L15.6,16.2C14.6,15.45 13.35,15 12,15C10.65,15 9.4,15.45 8.4,16.2L12,21M12,3C7.95,3 4.21,4.34 1.2,6.6L3,9C5.5,7.12 8.62,6 12,6C15.38,6 18.5,7.12 21,9L22.8,6.6C19.79,4.34 16.05,3 12,3M12,9C9.3,9 6.81,9.89 4.8,11.4L6.6,13.8C8.1,12.67 9.97,12 12,12C14.03,12 15.9,12.67 17.4,13.8L19.2,11.4C17.19,9.89 14.7,9 12,9Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemConsole = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M20,19V7H4V19H20M20,3A2,2 0 0,1 22,5V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V5C2,3.89 2.9,3 4,3H20M13,17V15H18V17H13M9.58,13L5.57,9H8.4L11.7,12.3C12.09,12.69 12.09,13.33 11.7,13.72L8.42,17H5.59L9.58,13Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemVisitDevice = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemHomeAssistant = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="m12.151 1.5882c-.3262 0-.6523.1291-.8996.3867l-8.3848 8.7354c-.0619.0644-.1223.1368-.1807.2154-.0588.0789-.1151.1638-.1688.2534-.2593.4325-.4552.9749-.5232 1.4555-.0026.018-.0076.0369-.0094.0548-.0121.0987-.0184.1944-.0184.2857v8.0124a1.2731 1.2731 0 001.2731 1.2731h7.8313l-3.4484-3.593a1.7399 1.7399 0 111.0803-1.125l2.6847 2.7972v-10.248a1.7399 1.7399 0 111.5276-0v7.187l2.6702-2.782a1.7399 1.7399 0 111.0566 1.1505l-3.7269 3.8831v2.7299h8.174a1.2471 1.2471 0 001.2471-1.2471v-8.0375c0-.0912-.0059-.1868-.0184-.2855-.0603-.4935-.2636-1.0617-.5326-1.5105-.0537-.0896-.1101-.1745-.1684-.253-.0588-.079-.1191-.1513-.181-.2158l-8.3848-8.7363c-.2473-.2577-.5735-.3866-.8995-.3864" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemEraseUserData = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M15,14C17.67,14 23,15.33 23,18V20H7V18C7,15.33 12.33,14 15,14M15,12A4,4 0 0,1 11,8A4,4 0 0,1 15,4A4,4 0 0,1 19,8A4,4 0 0,1 15,12M5,9.59L7.12,7.46L8.54,8.88L6.41,11L8.54,13.12L7.12,14.54L5,12.41L2.88,14.54L1.46,13.12L3.59,11L1.46,8.88L2.88,7.46L5,9.59Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
export const listItemFundDevelopment = svg`
|
||||
<svg slot="start" viewBox="0 0 24 24">
|
||||
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
|
||||
</svg>
|
||||
`;
|
||||
|
@ -8,7 +8,7 @@ export const connect = async (button: InstallButton) => {
|
||||
} catch (err: any) {
|
||||
if ((err as DOMException).name === "NotFoundError") {
|
||||
import("./no-port-picked/index").then((mod) =>
|
||||
mod.openNoPortPickedDialog(() => connect(button)),
|
||||
mod.openNoPortPickedDialog(() => connect(button))
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -36,7 +36,7 @@ export const connect = async (button: InstallButton) => {
|
||||
() => {
|
||||
port!.close();
|
||||
},
|
||||
{ once: true },
|
||||
{ once: true }
|
||||
);
|
||||
document.body.appendChild(el);
|
||||
};
|
||||
|
10
src/const.ts
10
src/const.ts
@ -5,15 +5,7 @@ export interface Logger {
|
||||
}
|
||||
|
||||
export interface Build {
|
||||
chipFamily:
|
||||
| "ESP32"
|
||||
| "ESP32-C2"
|
||||
| "ESP32-C3"
|
||||
| "ESP32-C6"
|
||||
| "ESP32-H2"
|
||||
| "ESP32-S2"
|
||||
| "ESP32-S3"
|
||||
| "ESP8266";
|
||||
chipFamily: "ESP32" | "ESP8266" | "ESP32-S2" | "ESP32-S3" | "ESP32-C3";
|
||||
parts: {
|
||||
path: string;
|
||||
offset: number;
|
||||
|
78
src/flash.ts
78
src/flash.ts
@ -6,14 +6,25 @@ import {
|
||||
Manifest,
|
||||
FlashStateType,
|
||||
} from "./const";
|
||||
import { hardReset } from "./util/reset";
|
||||
import { sleep } from "./util/sleep";
|
||||
|
||||
const resetTransport = async (transport: Transport) => {
|
||||
await transport.device.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: true,
|
||||
});
|
||||
await transport.device.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const flash = async (
|
||||
onEvent: (state: FlashState) => void,
|
||||
port: SerialPort,
|
||||
manifestPath: string,
|
||||
manifest: Manifest,
|
||||
eraseFirst: boolean,
|
||||
eraseFirst: boolean
|
||||
) => {
|
||||
let build: Build | undefined;
|
||||
let chipFamily: Build["chipFamily"];
|
||||
@ -27,12 +38,7 @@ export const flash = async (
|
||||
});
|
||||
|
||||
const transport = new Transport(port);
|
||||
const esploader = new ESPLoader({
|
||||
transport,
|
||||
baudrate: 115200,
|
||||
romBaudrate: 115200,
|
||||
enableTracing: false,
|
||||
});
|
||||
const esploader = new ESPLoader(transport, 115200, undefined);
|
||||
|
||||
// For debugging
|
||||
(window as any).esploader = esploader;
|
||||
@ -44,8 +50,8 @@ export const flash = async (
|
||||
});
|
||||
|
||||
try {
|
||||
await esploader.main();
|
||||
await esploader.flashId();
|
||||
await esploader.main_fn();
|
||||
await esploader.flash_id();
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
fireStateEvent({
|
||||
@ -54,14 +60,27 @@ export const flash = async (
|
||||
"Failed to initialize. Try resetting your device or holding the BOOT button while clicking INSTALL.",
|
||||
details: { error: FlashError.FAILED_INITIALIZING, details: err },
|
||||
});
|
||||
|
||||
await hardReset(transport);
|
||||
await resetTransport(transport);
|
||||
await transport.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
chipFamily = esploader.chip.CHIP_NAME as any;
|
||||
|
||||
if (!esploader.chip.ROM_TEXT) {
|
||||
fireStateEvent({
|
||||
state: FlashStateType.ERROR,
|
||||
message: `Chip ${chipFamily} is not supported`,
|
||||
details: {
|
||||
error: FlashError.NOT_SUPPORTED,
|
||||
details: `Chip ${chipFamily} is not supported`,
|
||||
},
|
||||
});
|
||||
await resetTransport(transport);
|
||||
await transport.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
fireStateEvent({
|
||||
state: FlashStateType.INITIALIZING,
|
||||
message: `Initialized. Found ${chipFamily}`,
|
||||
@ -76,7 +95,7 @@ export const flash = async (
|
||||
message: `Your ${chipFamily} board is not supported.`,
|
||||
details: { error: FlashError.NOT_SUPPORTED, details: chipFamily },
|
||||
});
|
||||
await hardReset(transport);
|
||||
await resetTransport(transport);
|
||||
await transport.disconnect();
|
||||
return;
|
||||
}
|
||||
@ -93,7 +112,7 @@ export const flash = async (
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) {
|
||||
throw new Error(
|
||||
`Downlading firmware ${part.path} failed: ${resp.status}`,
|
||||
`Downlading firmware ${part.path} failed: ${resp.status}`
|
||||
);
|
||||
}
|
||||
|
||||
@ -123,7 +142,7 @@ export const flash = async (
|
||||
details: err.message,
|
||||
},
|
||||
});
|
||||
await hardReset(transport);
|
||||
await resetTransport(transport);
|
||||
await transport.disconnect();
|
||||
return;
|
||||
}
|
||||
@ -141,7 +160,7 @@ export const flash = async (
|
||||
message: "Erasing device...",
|
||||
details: { done: false },
|
||||
});
|
||||
await esploader.eraseFlash();
|
||||
await esploader.erase_flash();
|
||||
fireStateEvent({
|
||||
state: FlashStateType.ERASING,
|
||||
message: "Device erased",
|
||||
@ -162,20 +181,20 @@ export const flash = async (
|
||||
let totalWritten = 0;
|
||||
|
||||
try {
|
||||
await esploader.writeFlash({
|
||||
await esploader.write_flash(
|
||||
fileArray,
|
||||
flashSize: "keep",
|
||||
flashMode: "keep",
|
||||
flashFreq: "keep",
|
||||
eraseAll: false,
|
||||
compress: true,
|
||||
"keep",
|
||||
"keep",
|
||||
"keep",
|
||||
false,
|
||||
true,
|
||||
// report progress
|
||||
reportProgress: (fileIndex: number, written: number, total: number) => {
|
||||
(fileIndex: number, written: number, total: number) => {
|
||||
const uncompressedWritten =
|
||||
(written / total) * fileArray[fileIndex].data.length;
|
||||
|
||||
const newPct = Math.floor(
|
||||
((totalWritten + uncompressedWritten) / totalSize) * 100,
|
||||
((totalWritten + uncompressedWritten) / totalSize) * 100
|
||||
);
|
||||
|
||||
// we're done with this file
|
||||
@ -193,15 +212,15 @@ export const flash = async (
|
||||
percentage: newPct,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
} catch (err: any) {
|
||||
fireStateEvent({
|
||||
state: FlashStateType.ERROR,
|
||||
message: err.message,
|
||||
details: { error: FlashError.WRITE_FAILED, details: err },
|
||||
});
|
||||
await hardReset(transport);
|
||||
await resetTransport(transport);
|
||||
await transport.disconnect();
|
||||
return;
|
||||
}
|
||||
@ -216,8 +235,9 @@ export const flash = async (
|
||||
},
|
||||
});
|
||||
|
||||
await hardReset(transport);
|
||||
|
||||
await sleep(100);
|
||||
console.log("HARD RESET");
|
||||
await resetTransport(transport);
|
||||
console.log("DISCONNECT");
|
||||
await transport.disconnect();
|
||||
|
||||
|
@ -12,12 +12,12 @@ export class InstallButton extends HTMLElement {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 10px 24px;
|
||||
padding: 8px 28px;
|
||||
color: var(--esp-tools-button-text-color, #fff);
|
||||
background-color: var(--esp-tools-button-color, #03a9f4);
|
||||
border: none;
|
||||
border-radius: var(--esp-tools-button-border-radius, 9999px);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.12), 0 1px 5px 0 rgba(0,0,0,.2);
|
||||
}
|
||||
button::before {
|
||||
content: " ";
|
||||
@ -27,7 +27,10 @@ export class InstallButton extends HTMLElement {
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0.2;
|
||||
border-radius: var(--esp-tools-button-border-radius, 9999px);
|
||||
border-radius: 4px;
|
||||
}
|
||||
button:hover {
|
||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,.14), 0 1px 7px 0 rgba(0,0,0,.12), 0 3px 1px -1px rgba(0,0,0,.2);
|
||||
}
|
||||
button:hover::before {
|
||||
background-color: rgba(255,255,255,.8);
|
||||
@ -48,6 +51,10 @@ export class InstallButton extends HTMLElement {
|
||||
cursor: unset;
|
||||
pointer-events: none;
|
||||
}
|
||||
improv-wifi-launch-button {
|
||||
display: block;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}`;
|
||||
@ -94,7 +101,7 @@ export class InstallButton extends HTMLElement {
|
||||
|
||||
slot.name = "activate";
|
||||
const button = document.createElement("button");
|
||||
button.innerText = "Connect";
|
||||
button.innerText = "CONNECT";
|
||||
slot.append(button);
|
||||
if (
|
||||
"adoptedStyleSheets" in Document.prototype &&
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
import "./no-port-picked-dialog";
|
||||
|
||||
export const openNoPortPickedDialog = async (
|
||||
doTryAgain?: () => void,
|
||||
doTryAgain?: () => void
|
||||
): Promise<boolean> => {
|
||||
const dialog = document.createElement("ewt-no-port-picked-dialog");
|
||||
dialog.doTryAgain = doTryAgain;
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { LitElement, html, css, svg } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import "../components/ew-dialog";
|
||||
import "../components/ew-text-button";
|
||||
|
||||
import "../components/ewt-dialog";
|
||||
import "../components/ewt-button";
|
||||
import { dialogStyles } from "../styles";
|
||||
import { getOperatingSystem } from "../util/get-operating-system";
|
||||
|
||||
const cloudDownload = svg`
|
||||
<svg
|
||||
@ -32,119 +30,107 @@ class EwtNoPortPickedDialog extends LitElement {
|
||||
public doTryAgain?: () => void;
|
||||
|
||||
public render() {
|
||||
const OS = getOperatingSystem();
|
||||
|
||||
return html`
|
||||
<ew-dialog open @closed=${this._handleClose}>
|
||||
<div slot="headline">No port selected</div>
|
||||
<div slot="content">
|
||||
<div>
|
||||
If you didn't select a port because you didn't see your device
|
||||
listed, try the following steps:
|
||||
</div>
|
||||
<ol>
|
||||
<li>
|
||||
Make sure that the device is connected to this computer (the one
|
||||
that runs the browser that shows this website)
|
||||
</li>
|
||||
<li>
|
||||
Most devices have a tiny light when it is powered on. If yours has
|
||||
one, make sure it is on.
|
||||
</li>
|
||||
<li>
|
||||
Make sure that the USB cable you use can be used for data and is
|
||||
not a power-only cable.
|
||||
</li>
|
||||
${OS === "Linux"
|
||||
? html`
|
||||
<li>
|
||||
If you are using a Linux flavor, make sure that your user is
|
||||
part of the <code>dialout</code> group so it has permission
|
||||
to access the device.
|
||||
<code class="block"
|
||||
>sudo usermod -a -G dialout YourUserName</code
|
||||
>
|
||||
You may need to log out & back in or reboot to activate the
|
||||
new group access.
|
||||
</li>
|
||||
`
|
||||
: ""}
|
||||
<li>
|
||||
Make sure you have the right drivers installed. Below are the
|
||||
drivers for common chips used in ESP devices:
|
||||
<ul>
|
||||
<li>
|
||||
CP2102 drivers:
|
||||
<a
|
||||
href="https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows & Mac</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
CH342, CH343, CH9102 drivers:
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH343SER_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows</a
|
||||
>,
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH34XSER_MAC_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Mac</a
|
||||
>
|
||||
<br />
|
||||
(download via blue button with ${cloudDownload} icon)
|
||||
</li>
|
||||
<li>
|
||||
CH340, CH341 drivers:
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH341SER_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows</a
|
||||
>,
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH341SER_MAC_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Mac</a
|
||||
>
|
||||
<br />
|
||||
(download via blue button with ${cloudDownload} icon)
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
<ewt-dialog
|
||||
open
|
||||
heading="No port selected"
|
||||
scrimClickAction
|
||||
@closed=${this._handleClose}
|
||||
>
|
||||
<div>
|
||||
If you didn't select a port because you didn't see your device listed,
|
||||
try the following steps:
|
||||
</div>
|
||||
<div slot="actions">
|
||||
${this.doTryAgain
|
||||
? html`
|
||||
<ew-text-button @click=${this.close}>Cancel</ew-text-button>
|
||||
<ew-text-button @click=${this.tryAgain}>
|
||||
Try Again
|
||||
</ew-text-button>
|
||||
`
|
||||
: html`
|
||||
<ew-text-button @click=${this.close}>Close</ew-text-button>
|
||||
`}
|
||||
</div>
|
||||
</ew-dialog>
|
||||
<ol>
|
||||
<li>
|
||||
Make sure that the device is connected to this computer (the one
|
||||
that runs the browser that shows this website)
|
||||
</li>
|
||||
<li>
|
||||
Most devices have a tiny light when it is powered on. If yours has
|
||||
one, make sure it is on.
|
||||
</li>
|
||||
<li>
|
||||
Make sure that the USB cable you use can be used for data and is not
|
||||
a power-only cable.
|
||||
</li>
|
||||
<li>
|
||||
Make sure you have the right drivers installed. Below are the
|
||||
drivers for common chips used in ESP devices:
|
||||
<ul>
|
||||
<li>
|
||||
CP2102 drivers:
|
||||
<a
|
||||
href="https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows & Mac</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
CH342, CH343, CH9102 drivers:
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH343SER_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows</a
|
||||
>,
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH34XSER_MAC_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Mac</a
|
||||
>
|
||||
<br />
|
||||
(download via blue button with ${cloudDownload} icon)
|
||||
</li>
|
||||
<li>
|
||||
CH340, CH341 drivers:
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH341SER_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Windows</a
|
||||
>,
|
||||
<a
|
||||
href="https://www.wch.cn/downloads/CH341SER_MAC_ZIP.html"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Mac</a
|
||||
>
|
||||
<br />
|
||||
(download via blue button with ${cloudDownload} icon)
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
${this.doTryAgain
|
||||
? html`
|
||||
<ewt-button
|
||||
slot="primaryAction"
|
||||
dialogAction="close"
|
||||
label="Try Again"
|
||||
@click=${this.doTryAgain}
|
||||
></ewt-button>
|
||||
|
||||
<ewt-button
|
||||
no-attention
|
||||
slot="secondaryAction"
|
||||
dialogAction="close"
|
||||
label="Cancel"
|
||||
></ewt-button>
|
||||
`
|
||||
: html`
|
||||
<ewt-button
|
||||
slot="primaryAction"
|
||||
dialogAction="close"
|
||||
label="Close"
|
||||
></ewt-button>
|
||||
`}
|
||||
</ewt-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private tryAgain() {
|
||||
this.close();
|
||||
this.doTryAgain?.();
|
||||
}
|
||||
|
||||
private close() {
|
||||
this.shadowRoot!.querySelector("ew-dialog")!.close();
|
||||
}
|
||||
|
||||
private async _handleClose() {
|
||||
this.parentNode!.removeChild(this);
|
||||
}
|
||||
@ -161,10 +147,6 @@ class EwtNoPortPickedDialog extends LitElement {
|
||||
margin-bottom: 0;
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
li code.block {
|
||||
display: block;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { LitElement, html, css, TemplateResult } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
import "../components/ewt-circular-progress";
|
||||
|
||||
class EwtPageMessage extends LitElement {
|
||||
@property() icon!: string;
|
||||
@ -24,6 +25,9 @@ class EwtPageMessage extends LitElement {
|
||||
line-height: 80px;
|
||||
color: black;
|
||||
}
|
||||
ewt-circular-progress {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
customElements.define("ewt-page-message", EwtPageMessage);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { LitElement, html, css, TemplateResult } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
import "../components/ew-circular-progress";
|
||||
import "../components/ewt-circular-progress";
|
||||
|
||||
class EwtPageProgress extends LitElement {
|
||||
@property() label!: string | TemplateResult;
|
||||
@ -10,13 +10,14 @@ class EwtPageProgress extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<div>
|
||||
<ew-circular-progress
|
||||
<ewt-circular-progress
|
||||
active
|
||||
?indeterminate=${this.progress === undefined}
|
||||
.value=${this.progress !== undefined
|
||||
.progress=${this.progress !== undefined
|
||||
? this.progress / 100
|
||||
: undefined}
|
||||
></ew-circular-progress>
|
||||
density="8"
|
||||
></ewt-circular-progress>
|
||||
${this.progress !== undefined ? html`<div>${this.progress}%</div>` : ""}
|
||||
</div>
|
||||
${this.label}
|
||||
@ -29,7 +30,7 @@ class EwtPageProgress extends LitElement {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
ew-circular-progress {
|
||||
ewt-circular-progress {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
|
@ -6,26 +6,29 @@ import { css } from "lit";
|
||||
|
||||
export const dialogStyles = css`
|
||||
:host {
|
||||
--roboto-font: Roboto, system-ui;
|
||||
--text-color: rgba(0, 0, 0, 0.6);
|
||||
--danger-color: #db4437;
|
||||
|
||||
--md-sys-color-primary: #03a9f4;
|
||||
--md-sys-color-on-primary: #fff;
|
||||
--md-ref-typeface-brand: var(--roboto-font);
|
||||
--md-ref-typeface-plain: var(--roboto-font);
|
||||
|
||||
--md-sys-color-surface: #fff;
|
||||
--md-sys-color-surface-container: #fff;
|
||||
--md-sys-color-surface-container-high: #fff;
|
||||
--md-sys-color-surface-container-highest: #f5f5f5;
|
||||
--md-sys-color-secondary-container: #e0e0e0;
|
||||
|
||||
--md-sys-typescale-headline-font: var(--roboto-font);
|
||||
--md-sys-typescale-title-font: var(--roboto-font);
|
||||
--mdc-theme-primary: var(--improv-primary-color, #03a9f4);
|
||||
--mdc-theme-on-primary: var(--improv-on-primary-color, #fff);
|
||||
--improv-danger-color: #db4437;
|
||||
--improv-text-color: rgba(0, 0, 0, 0.6);
|
||||
--mdc-theme-text-primary-on-background: var(--improv-text-color);
|
||||
--mdc-dialog-content-ink-color: var(--improv-text-color);
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
--mdc-typography-headline6-font-size: 1.25em;
|
||||
--mdc-typography-headline6-line-height: 2em;
|
||||
--mdc-typography-body1-font-size: 1em;
|
||||
--mdc-typography-body1-line-height: 1.5em;
|
||||
--mdc-typography-button-font-size: 0.875em;
|
||||
--mdc-typography-button-line-height: 2.25em;
|
||||
--mdc-typography-subtitle1-font-size: 1em;
|
||||
--mdc-typography-subtitle1-line-height: 1.75em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--md-sys-color-primary);
|
||||
color: var(--improv-primary-color, #03a9f4);
|
||||
}
|
||||
|
||||
a.button {
|
||||
text-decoration: none;
|
||||
}
|
||||
`;
|
||||
|
@ -28,7 +28,6 @@ export class ColoredConsole {
|
||||
}
|
||||
|
||||
addLine(line: string) {
|
||||
// @ts-expect-error
|
||||
const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g;
|
||||
let i = 0;
|
||||
|
||||
|
@ -7,7 +7,7 @@ export const fireEvent = <Event extends keyof HTMLElementEventMap>(
|
||||
bubbles?: boolean;
|
||||
cancelable?: boolean;
|
||||
composed?: boolean;
|
||||
},
|
||||
}
|
||||
): void => {
|
||||
options = options || {};
|
||||
const event = new CustomEvent(type, {
|
||||
|
@ -1,24 +0,0 @@
|
||||
// From https://stackoverflow.com/a/38241481
|
||||
export const getOperatingSystem = () => {
|
||||
const userAgent = window.navigator.userAgent;
|
||||
const platform =
|
||||
// @ts-expect-error
|
||||
window.navigator?.userAgentData?.platform || window.navigator.platform;
|
||||
const macosPlatforms = ["macOS", "Macintosh", "MacIntel", "MacPPC", "Mac68K"];
|
||||
const windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"];
|
||||
const iosPlatforms = ["iPhone", "iPad", "iPod"];
|
||||
|
||||
if (macosPlatforms.indexOf(platform) !== -1) {
|
||||
return "Mac OS";
|
||||
} else if (iosPlatforms.indexOf(platform) !== -1) {
|
||||
return "iOS";
|
||||
} else if (windowsPlatforms.indexOf(platform) !== -1) {
|
||||
return "Windows";
|
||||
} else if (/Android/.test(userAgent)) {
|
||||
return "Android";
|
||||
} else if (/Linux/.test(platform)) {
|
||||
return "Linux";
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
@ -3,7 +3,7 @@ export class LineBreakTransformer implements Transformer<string, string> {
|
||||
|
||||
transform(
|
||||
chunk: string,
|
||||
controller: TransformStreamDefaultController<string>,
|
||||
controller: TransformStreamDefaultController<string>
|
||||
) {
|
||||
// Append new chunks to existing chunks.
|
||||
this.chunks += chunk;
|
||||
|
@ -7,7 +7,7 @@ export const downloadManifest = async (manifestPath: string) => {
|
||||
|
||||
if ("new_install_skip_erase" in manifest) {
|
||||
console.warn(
|
||||
'Manifest option "new_install_skip_erase" is deprecated. Use "new_install_prompt_erase" instead.',
|
||||
'Manifest option "new_install_skip_erase" is deprecated. Use "new_install_prompt_erase" instead.'
|
||||
);
|
||||
if (manifest.new_install_skip_erase) {
|
||||
manifest.new_install_prompt_erase = true;
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { Transport } from "esptool-js";
|
||||
import { sleep } from "./sleep";
|
||||
|
||||
export const hardReset = async (transport: Transport) => {
|
||||
console.log("Triggering reset");
|
||||
await transport.device.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: true,
|
||||
});
|
||||
await sleep(250);
|
||||
await transport.device.setSignals({
|
||||
dataTerminalReady: false,
|
||||
requestToSend: false,
|
||||
});
|
||||
await sleep(250);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
export class TimestampTransformer implements Transformer<string, string> {
|
||||
transform(
|
||||
chunk: string,
|
||||
controller: TransformStreamDefaultController<string>,
|
||||
) {
|
||||
const date = new Date();
|
||||
const h = date.getHours().toString().padStart(2, "0");
|
||||
const m = date.getMinutes().toString().padStart(2, "0");
|
||||
const s = date.getSeconds().toString().padStart(2, "0");
|
||||
controller.enqueue(`[${h}:${m}:${s}]${chunk}`);
|
||||
}
|
||||
}
|
53
static/firmware_build/manifest.json
Normal file
53
static/firmware_build/manifest.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "ESPHome",
|
||||
"version": "2022.12.8",
|
||||
"home_assistant_domain": "esphome",
|
||||
"funding_url": "https://esphome.io/guides/supporters.html",
|
||||
"builds": [
|
||||
{
|
||||
"chipFamily": "ESP32",
|
||||
"parts": [
|
||||
{
|
||||
"path": "https://firmware.esphome.io/esphome-web-esp32/esphome-web-esp32.bin",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-C3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "https://firmware.esphome.io/esphome-web-esp32c3/esphome-web-esp32c3.bin",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S2",
|
||||
"parts": [
|
||||
{
|
||||
"path": "https://firmware.esphome.io/esphome-web-esp32s2/esphome-web-esp32s2.bin",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP32-S3",
|
||||
"parts": [
|
||||
{
|
||||
"path": "https://firmware.esphome.io/esphome-web-esp32s3/esphome-web-esp32s3.bin",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"chipFamily": "ESP8266",
|
||||
"parts": [
|
||||
{
|
||||
"path": "https://firmware.esphome.io/esphome-web-esp8266/esphome-web-esp8266.bin",
|
||||
"offset": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.2 KiB |
@ -1,156 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="95.541344mm"
|
||||
height="29.999447mm"
|
||||
viewBox="0 0 95.54134 29.999447"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:export-filename="/home/erik/Documents/Projekt/NSPanel Manager/Logos/logo250.png"
|
||||
inkscape:export-xdpi="76.010269"
|
||||
inkscape:export-ydpi="76.010269"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#000000"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.3404872"
|
||||
inkscape:cx="174.5634"
|
||||
inkscape:cy="71.988753"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="704"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer2"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="7"
|
||||
fit-margin-right="7"
|
||||
fit-margin-bottom="5" />
|
||||
<defs
|
||||
id="defs2" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="display:inline"
|
||||
transform="translate(-23.806324,-37.155967)">
|
||||
<rect
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0.264583"
|
||||
id="rect91625"
|
||||
width="16.863066"
|
||||
height="1.0996726"
|
||||
x="30.938616"
|
||||
y="59.758064" />
|
||||
<rect
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0.473039"
|
||||
id="rect91761"
|
||||
width="66.510048"
|
||||
height="0.89121634"
|
||||
x="31.042845"
|
||||
y="42.392487" />
|
||||
<rect
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0.34752"
|
||||
id="rect91763"
|
||||
width="31.46484"
|
||||
height="1.0167363"
|
||||
x="80.709068"
|
||||
y="59.79953" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="Layer 2"
|
||||
style="display:inline"
|
||||
transform="translate(-23.806324,-37.155967)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:10.5833px;line-height:0;font-family:sans-serif;letter-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
|
||||
x="64.189873"
|
||||
y="56.76144"
|
||||
id="text39249"><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.4056px;line-height:0.55;font-family:Hamlin;-inkscape-font-specification:'Hamlin, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583"
|
||||
x="64.189873"
|
||||
y="56.76144"
|
||||
id="tspan62001">NSPANEL</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.93889px;line-height:1.55;font-family:Hamlin;-inkscape-font-specification:'Hamlin Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:center;text-anchor:middle;fill:#000000;stroke-width:0.264583"
|
||||
x="64.189873"
|
||||
y="62.091209"
|
||||
id="tspan73527">MANAGER</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer3"
|
||||
inkscape:label="Layer 3"
|
||||
transform="translate(-23.806324,-37.155967)">
|
||||
<g
|
||||
id="g91894"
|
||||
transform="matrix(0.15910033,0,0,0.15910033,102.25849,44.830316)">
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-1"
|
||||
transform="translate(-30.269979,-9.7200098)"
|
||||
style="display:inline;fill:#ffc101;fill-opacity:1">
|
||||
<path
|
||||
style="fill:#ffc101;fill-opacity:1;stroke-width:0.103892"
|
||||
d="m 55.789326,41.355207 -7.50621,-0.0036 c -8.143469,-0.0039 -15.508914,-0.135689 -16.902471,-0.302478 -0.482408,-0.05774 -0.940146,-0.168019 -1.017198,-0.245069 -0.115522,-0.115523 -0.121188,-0.512246 -0.03231,-2.261925 0.23677,-4.661121 1.011239,-7.815267 2.954845,-12.034057 2.163281,-4.695621 5.19604,-8.340625 9.101253,-10.938592 2.710535,-1.8032 6.982591,-3.536303 9.582241,-3.887359 0.270422,-0.03652 0.543941,-0.129371 0.60782,-0.20634 0.06388,-0.07697 0.286764,-0.168201 0.495299,-0.202735 0.208537,-0.03453 0.449284,-0.09017 0.534995,-0.123628 0.168484,-0.06577 0.381034,-0.08553 1.215776,-0.112981 l 0.540477,-0.01778 0.03093,-0.649326 0.03093,-0.6493272 h 1.610329 1.610329 l 0.03093,0.6493272 0.03093,0.649326 0.540477,0.01778 c 0.834742,0.02745 1.047292,0.04721 1.215776,0.112981 0.08571,0.03346 0.326458,0.08909 0.534995,0.123628 0.208535,0.03453 0.43142,0.125765 0.495299,0.202735 0.06388,0.07697 0.337398,0.169823 0.60782,0.20634 1.199505,0.161981 3.423686,0.820696 4.997483,1.480058 3.507719,1.469604 6.221358,3.303143 8.667596,5.856479 2.140092,2.233788 3.602852,4.416791 5.018415,7.489412 1.943606,4.21879 2.718075,7.372936 2.954845,12.034057 0.08888,1.749679 0.08321,2.146402 -0.03231,2.261925 -0.07705,0.07705 -0.53479,0.187332 -1.017198,0.245069 -1.393557,0.166789 -8.759002,0.298597 -16.902471,0.302478 l -7.50621,0.0036 z"
|
||||
id="path1465"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-xdpi="15.183412"
|
||||
inkscape:export-ydpi="15.183412"
|
||||
sodipodi:nodetypes="csssssssssscccccccccscssssssssccc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:label="Layer 1 copy"
|
||||
id="g2878"
|
||||
transform="translate(-30.269979,-9.7200098)"
|
||||
style="display:inline">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:0.103892"
|
||||
d="m 54.334834,101.13608 c -3.956539,-0.21732 -5.98252,-0.58093 -6.463066,-1.159955 -0.09761,-0.11762 -0.123549,-0.57148 -0.09916,-1.73541 0.02799,-1.33577 0.008,-1.59689 -0.130816,-1.71212 -0.09011,-0.0748 -0.16384,-0.29294 -0.16384,-0.48477 0,-0.30436 0.05486,-0.37678 0.430667,-0.5685 0.694102,-0.3541 2.301256,-0.71174 4.060659,-0.9036 l 1.638312,-0.17866 V 70.783119 c 0,-15.670705 -0.03494,-23.609951 -0.103892,-23.609951 -0.05714,0 -0.103892,-0.0935 -0.103892,-0.207784 0,-0.194592 0.06926,-0.207784 1.090868,-0.207784 0.900399,0 1.090868,-0.02721 1.090868,-0.155839 0,-0.08571 0.04675,-0.155838 0.103892,-0.155838 0.06644,0 0.103892,-3.463072 0.103892,-5.090716 l 2.493412,-2e-6 c 0,1.627644 0.03746,5.090716 0.103892,5.090716 0.05714,0 0.103892,0.07013 0.103892,0.155838 0,0.128629 0.190469,0.155839 1.090868,0.155839 1.021606,0 1.090868,0.01319 1.090868,0.207784 0,0.114281 -0.04675,0.207784 -0.103892,0.207784 -0.06896,0 -0.103892,7.939246 -0.103892,23.609951 v 23.609948 l 1.638312,0.17866 c 1.759403,0.19186 3.366557,0.54949 4.060659,0.9036 0.375812,0.19172 0.430667,0.26413 0.430667,0.5685 0,0.19183 -0.07373,0.40998 -0.16384,0.48476 -0.138668,0.11509 -0.158971,0.37643 -0.132144,1.70097 0.01743,0.86075 -0.0055,1.62411 -0.05099,1.69635 -0.27864,0.442605 -1.632284,0.804945 -3.803075,1.017985 -1.460176,0.14331 -6.726732,0.26812 -8.109225,0.19219 z"
|
||||
id="path2876"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:export-xdpi="15.183412"
|
||||
inkscape:export-ydpi="15.183412"
|
||||
sodipodi:nodetypes="ssssssscssssssccsssssscssssscsss" />
|
||||
</g>
|
||||
<g
|
||||
id="layer3-5"
|
||||
inkscape:label="Layer 3">
|
||||
<circle
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:17.1351;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="path1510"
|
||||
cx="34.837666"
|
||||
cy="55.072739"
|
||||
r="1.2872558" />
|
||||
</g>
|
||||
<g
|
||||
id="layer2-9"
|
||||
inkscape:label="Layer 2">
|
||||
<rect
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;stroke:none;stroke-width:12.8043;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:0;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect1508"
|
||||
width="1.3904994"
|
||||
height="22.681686"
|
||||
x="34.147842"
|
||||
y="31.601988" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 30 KiB |
Binary file not shown.
Before Width: | Height: | Size: 213 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.5 KiB |
@ -13,6 +13,7 @@
|
||||
"noUnusedLocals": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"skipLibCheck": true,
|
||||
"importHelpers": true
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user