tasmota-esp-web-tools 12.2.1 → 12.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flash.d.ts +29 -1
- package/dist/flash.js +64 -19
- package/dist/install-dialog.d.ts +7 -0
- package/dist/install-dialog.js +54 -6
- package/dist/web/install-button.js +1 -1
- package/dist/web/{install-dialog-C3uI77Wb.js → install-dialog-HBW3T1yn.js} +41 -39
- package/js/modules/install-button.js +1 -1
- package/js/modules/{install-dialog-C3uI77Wb.js → install-dialog-HBW3T1yn.js} +41 -39
- package/package.json +1 -1
package/dist/flash.d.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
import { Logger } from "tasmota-webserial-esptool";
|
|
2
|
-
import { FlashState } from "./const";
|
|
2
|
+
import { Build, FlashState, Manifest } from "./const";
|
|
3
|
+
/**
|
|
4
|
+
* Parse flash size string (e.g., "4MB", "8MB", "16MB") to megabytes number
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseFlashSizeToMB(flashSize: string): number | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Extract the most relevant firmware filename from a build's parts.
|
|
9
|
+
* Prefers parts with "factory" in the name.
|
|
10
|
+
* Ignores parts with "bootloader" or "partition" in the name.
|
|
11
|
+
* Returns just the basename (no path prefix).
|
|
12
|
+
*/
|
|
13
|
+
export declare function getFirmwareFileName(build: Build): string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Find the best matching build for a given chip configuration.
|
|
16
|
+
* This is the single source of truth for build selection used by both
|
|
17
|
+
* the flash routine and the install dialog UI.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findMatchingBuild(manifest: Manifest, chipFamily: string, chipVariant: string | null, flashSizeMB: number | undefined, usbInterface: "UART" | "CDC" | undefined): Build | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Detect the matching build for the currently connected device.
|
|
22
|
+
* Extracts chip info directly from the esploader instance.
|
|
23
|
+
*
|
|
24
|
+
* @param manifest - The loaded firmware manifest
|
|
25
|
+
* @param esploader - ESPLoader instance (or stub) with chip info
|
|
26
|
+
* @param flashSize - Detected flash size string (e.g. "4MB"), or undefined
|
|
27
|
+
* @param isUsbJtagOrOtg - Whether the device uses native USB (CDC) instead of external serial
|
|
28
|
+
* @param improvChipFamily - Optional chipFamily from Improv Serial info (takes precedence)
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectMatchingBuild(manifest: Manifest, esploader: any, flashSize: string | undefined, isUsbJtagOrOtg: boolean, improvChipFamily?: string): Build | undefined;
|
|
3
31
|
export declare const flash: (onEvent: (state: FlashState) => void, esploader: any, // ESPLoader instance from tasmota-webserial-esptool
|
|
4
32
|
logger: Logger, manifestPath: string, eraseFirst: boolean, firmwareBuffer: Uint8Array, _baudRate?: number) => Promise<void>;
|
package/dist/flash.js
CHANGED
|
@@ -4,7 +4,7 @@ import { corsProxyFetch } from "./util/cors-proxy";
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse flash size string (e.g., "4MB", "8MB", "16MB") to megabytes number
|
|
6
6
|
*/
|
|
7
|
-
function parseFlashSizeToMB(flashSize) {
|
|
7
|
+
export function parseFlashSizeToMB(flashSize) {
|
|
8
8
|
if (!flashSize)
|
|
9
9
|
return undefined;
|
|
10
10
|
const match = flashSize.match(/^(\d+)(MB|GB)$/);
|
|
@@ -66,9 +66,71 @@ function selectBestBuild(builds, detectedFlashSizeMB, detectedUsbInterface) {
|
|
|
66
66
|
}
|
|
67
67
|
return bestScore >= 0 ? bestBuild : undefined;
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract the most relevant firmware filename from a build's parts.
|
|
71
|
+
* Prefers parts with "factory" in the name.
|
|
72
|
+
* Ignores parts with "bootloader" or "partition" in the name.
|
|
73
|
+
* Returns just the basename (no path prefix).
|
|
74
|
+
*/
|
|
75
|
+
export function getFirmwareFileName(build) {
|
|
76
|
+
const candidates = build.parts
|
|
77
|
+
.map((p) => p.path)
|
|
78
|
+
.filter((path) => {
|
|
79
|
+
const lower = path.toLowerCase();
|
|
80
|
+
return !lower.includes("bootloader") && !lower.includes("partition");
|
|
81
|
+
});
|
|
82
|
+
if (candidates.length === 0)
|
|
83
|
+
return undefined;
|
|
84
|
+
const factory = candidates.find((p) => p.toLowerCase().includes("factory"));
|
|
85
|
+
const chosen = factory !== null && factory !== void 0 ? factory : candidates[0];
|
|
86
|
+
// Return only the basename
|
|
87
|
+
return chosen.split("/").pop().split("\\").pop();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find the best matching build for a given chip configuration.
|
|
91
|
+
* This is the single source of truth for build selection used by both
|
|
92
|
+
* the flash routine and the install dialog UI.
|
|
93
|
+
*/
|
|
94
|
+
export function findMatchingBuild(manifest, chipFamily, chipVariant, flashSizeMB, usbInterface) {
|
|
95
|
+
const compatible = manifest.builds.filter((b) => {
|
|
96
|
+
if (b.chipFamily !== chipFamily)
|
|
97
|
+
return false;
|
|
98
|
+
if (b.chipVariant && b.chipVariant !== chipVariant)
|
|
99
|
+
return false;
|
|
100
|
+
return true;
|
|
101
|
+
});
|
|
102
|
+
const exactVariant = compatible.filter((b) => b.chipVariant !== undefined && b.chipVariant === chipVariant);
|
|
103
|
+
const variantAgnostic = compatible.filter((b) => b.chipVariant === undefined);
|
|
104
|
+
return (selectBestBuild(exactVariant, flashSizeMB, usbInterface) ||
|
|
105
|
+
selectBestBuild(variantAgnostic, flashSizeMB, usbInterface));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Detect the matching build for the currently connected device.
|
|
109
|
+
* Extracts chip info directly from the esploader instance.
|
|
110
|
+
*
|
|
111
|
+
* @param manifest - The loaded firmware manifest
|
|
112
|
+
* @param esploader - ESPLoader instance (or stub) with chip info
|
|
113
|
+
* @param flashSize - Detected flash size string (e.g. "4MB"), or undefined
|
|
114
|
+
* @param isUsbJtagOrOtg - Whether the device uses native USB (CDC) instead of external serial
|
|
115
|
+
* @param improvChipFamily - Optional chipFamily from Improv Serial info (takes precedence)
|
|
116
|
+
*/
|
|
117
|
+
export function detectMatchingBuild(manifest, esploader, flashSize, isUsbJtagOrOtg, improvChipFamily) {
|
|
118
|
+
var _a;
|
|
119
|
+
const chipFamily = improvChipFamily ||
|
|
120
|
+
(esploader.chipFamily ? getChipFamilyName(esploader) : null);
|
|
121
|
+
if (!chipFamily)
|
|
122
|
+
return undefined;
|
|
123
|
+
const chipVariant = (_a = esploader.chipVariant) !== null && _a !== void 0 ? _a : null;
|
|
124
|
+
const flashSizeMB = flashSize ? parseFlashSizeToMB(flashSize) : undefined;
|
|
125
|
+
const usbInterface = isUsbJtagOrOtg
|
|
126
|
+
? "CDC"
|
|
127
|
+
: "UART";
|
|
128
|
+
return findMatchingBuild(manifest, chipFamily, chipVariant, flashSizeMB, usbInterface);
|
|
129
|
+
}
|
|
69
130
|
export const flash = async (onEvent, esploader, // ESPLoader instance from tasmota-webserial-esptool
|
|
70
131
|
logger, manifestPath, eraseFirst, firmwareBuffer, _baudRate) => {
|
|
71
132
|
let manifest;
|
|
133
|
+
// eslint-disable-next-line prefer-const
|
|
72
134
|
let build;
|
|
73
135
|
// eslint-disable-next-line prefer-const
|
|
74
136
|
let chipFamily;
|
|
@@ -167,24 +229,7 @@ logger, manifestPath, eraseFirst, firmwareBuffer, _baudRate) => {
|
|
|
167
229
|
await esploader.disconnect();
|
|
168
230
|
return;
|
|
169
231
|
}
|
|
170
|
-
|
|
171
|
-
const compatibleBuilds = manifest.builds.filter((b) => {
|
|
172
|
-
if (b.chipFamily !== chipFamily) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
if (b.chipVariant && b.chipVariant !== chipVariant) {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
return true;
|
|
179
|
-
});
|
|
180
|
-
// Select the best build using most-specific-matching algorithm
|
|
181
|
-
// Prefer builds with more matching qualifiers (flashSizeMB)
|
|
182
|
-
const exactVariantBuilds = compatibleBuilds.filter((b) => b.chipVariant !== undefined && b.chipVariant === chipVariant);
|
|
183
|
-
const variantAgnosticBuilds = compatibleBuilds.filter((b) => b.chipVariant === undefined);
|
|
184
|
-
build = selectBestBuild(exactVariantBuilds, flashSizeMB, detectedUsbInterface);
|
|
185
|
-
if (!build) {
|
|
186
|
-
build = selectBestBuild(variantAgnosticBuilds, flashSizeMB, detectedUsbInterface);
|
|
187
|
-
}
|
|
232
|
+
build = findMatchingBuild(manifest, chipFamily, chipVariant, flashSizeMB, detectedUsbInterface);
|
|
188
233
|
if (!build) {
|
|
189
234
|
fireStateEvent({
|
|
190
235
|
state: "error" /* FlashStateType.ERROR */,
|
package/dist/install-dialog.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export declare class EwtInstallDialog extends LitElement {
|
|
|
46
46
|
private _improvSupported;
|
|
47
47
|
private _isUsbJtagOrOtgDevice;
|
|
48
48
|
private _flashSize?;
|
|
49
|
+
private _detectedBuild?;
|
|
49
50
|
private _openConsoleAfterReconnect;
|
|
50
51
|
private _visitDeviceAfterReconnect;
|
|
51
52
|
private _addToHAAfterReconnect;
|
|
@@ -100,6 +101,12 @@ export declare class EwtInstallDialog extends LitElement {
|
|
|
100
101
|
private _preventDefault;
|
|
101
102
|
private _closeDialog;
|
|
102
103
|
private _handleClose;
|
|
104
|
+
/**
|
|
105
|
+
* Return a human-readable label for the differentiating properties of a build.
|
|
106
|
+
* Shows the firmware filename from parts (factory preferred, no bootloader/partition).
|
|
107
|
+
* Falls back to chipVariant/flashSizeMB/usbInterface if no filename found.
|
|
108
|
+
*/
|
|
109
|
+
private _buildVariantLabel;
|
|
103
110
|
/**
|
|
104
111
|
* Return if the device runs same firmware as manifest.
|
|
105
112
|
*/
|
package/dist/install-dialog.js
CHANGED
|
@@ -18,7 +18,7 @@ import "./pages/ew-page-message";
|
|
|
18
18
|
import { closeIcon, warningIcon, checkCircleIcon, listItemInstallIcon, listItemWifi, listItemConsole, listItemVisitDevice, listItemHomeAssistant, listItemEraseUserData, listItemFundDevelopment, firmwareIcon, downloadIcon, } from "./components/svg";
|
|
19
19
|
import { ImprovSerial } from "improv-wifi-serial-sdk/dist/serial";
|
|
20
20
|
import { ImprovSerialCurrentState, } from "improv-wifi-serial-sdk/dist/const";
|
|
21
|
-
import { flash } from "./flash";
|
|
21
|
+
import { flash, detectMatchingBuild, getFirmwareFileName } from "./flash";
|
|
22
22
|
import { textDownload } from "./util/file-download";
|
|
23
23
|
import { fireEvent } from "./util/fire-event";
|
|
24
24
|
import { sleep } from "./util/sleep";
|
|
@@ -57,8 +57,9 @@ export class EwtInstallDialog extends LitElement {
|
|
|
57
57
|
this._handleDisconnect = () => {
|
|
58
58
|
this._state = "ERROR";
|
|
59
59
|
this._error = "Disconnected";
|
|
60
|
-
// Reset flash size when device is actually disconnected
|
|
60
|
+
// Reset flash size and detected build when device is actually disconnected
|
|
61
61
|
this._flashSize = undefined;
|
|
62
|
+
this._detectedBuild = undefined;
|
|
62
63
|
};
|
|
63
64
|
}
|
|
64
65
|
// Ensure stub is initialized (called before any operation that needs it)
|
|
@@ -144,6 +145,7 @@ export class EwtInstallDialog extends LitElement {
|
|
|
144
145
|
}
|
|
145
146
|
// Helper to probe flash size from a running stub (only available after stub)
|
|
146
147
|
async _probeFlashSize(espStub) {
|
|
148
|
+
var _a;
|
|
147
149
|
if (espStub.detectFlashSize && !this._flashSize) {
|
|
148
150
|
try {
|
|
149
151
|
await espStub.detectFlashSize();
|
|
@@ -154,6 +156,7 @@ export class EwtInstallDialog extends LitElement {
|
|
|
154
156
|
this.logger.debug("Failed to detect flash size:", err);
|
|
155
157
|
}
|
|
156
158
|
}
|
|
159
|
+
this._detectedBuild = detectMatchingBuild(this._manifest, espStub, this._flashSize, this._isUsbJtagOrOtgDevice, (_a = this._info) === null || _a === void 0 ? void 0 : _a.chipFamily);
|
|
157
160
|
}
|
|
158
161
|
// Helper to check if device is using USB-JTAG or USB-OTG (not external serial chip)
|
|
159
162
|
async _isUsbJtagOrOtg() {
|
|
@@ -557,6 +560,14 @@ export class EwtInstallDialog extends LitElement {
|
|
|
557
560
|
? `Install ${this._manifest.name}`
|
|
558
561
|
: `Update ${this._manifest.name}`}
|
|
559
562
|
</div>
|
|
563
|
+
${(() => {
|
|
564
|
+
const label = this._detectedBuild
|
|
565
|
+
? this._buildVariantLabel(this._detectedBuild)
|
|
566
|
+
: undefined;
|
|
567
|
+
return label
|
|
568
|
+
? html `<div slot="supporting-text">Variant: ${label}</div>`
|
|
569
|
+
: "";
|
|
570
|
+
})()}
|
|
560
571
|
</ew-list-item>
|
|
561
572
|
`
|
|
562
573
|
: ""}
|
|
@@ -879,6 +890,14 @@ export class EwtInstallDialog extends LitElement {
|
|
|
879
890
|
>
|
|
880
891
|
${listItemInstallIcon}
|
|
881
892
|
<div slot="headline">Install ${this._manifest.name}</div>
|
|
893
|
+
${(() => {
|
|
894
|
+
const label = this._detectedBuild
|
|
895
|
+
? this._buildVariantLabel(this._detectedBuild)
|
|
896
|
+
: undefined;
|
|
897
|
+
return label
|
|
898
|
+
? html `<div slot="supporting-text">Variant: ${label}</div>`
|
|
899
|
+
: "";
|
|
900
|
+
})()}
|
|
882
901
|
</ew-list-item>
|
|
883
902
|
|
|
884
903
|
${!this._isUsbJtagOrOtgDevice
|
|
@@ -1251,7 +1270,7 @@ export class EwtInstallDialog extends LitElement {
|
|
|
1251
1270
|
return [heading, content];
|
|
1252
1271
|
}
|
|
1253
1272
|
_renderInstall() {
|
|
1254
|
-
var _a, _b, _c;
|
|
1273
|
+
var _a, _b, _c, _d, _e;
|
|
1255
1274
|
let heading;
|
|
1256
1275
|
let content;
|
|
1257
1276
|
let hideActions = false;
|
|
@@ -1286,6 +1305,10 @@ export class EwtInstallDialog extends LitElement {
|
|
|
1286
1305
|
? `, ${this._flashSize}`
|
|
1287
1306
|
: this._flashSize})`
|
|
1288
1307
|
: "";
|
|
1308
|
+
const variantBuild = (_d = (_c = this._installState) === null || _c === void 0 ? void 0 : _c.build) !== null && _d !== void 0 ? _d : this._detectedBuild;
|
|
1309
|
+
const variantLabel = variantBuild
|
|
1310
|
+
? this._buildVariantLabel(variantBuild)
|
|
1311
|
+
: undefined;
|
|
1289
1312
|
content = html `
|
|
1290
1313
|
${isUpdate
|
|
1291
1314
|
? html `Your device is running
|
|
@@ -1295,7 +1318,9 @@ export class EwtInstallDialog extends LitElement {
|
|
|
1295
1318
|
? html `Device detected: ${deviceInfo}<br /><br />`
|
|
1296
1319
|
: ""}
|
|
1297
1320
|
Do you want to ${action}
|
|
1298
|
-
${this._manifest.name} ${this._manifest.version}
|
|
1321
|
+
${this._manifest.name} ${this._manifest.version}${variantLabel
|
|
1322
|
+
? html ` <em>(${variantLabel})</em>`
|
|
1323
|
+
: ""}?
|
|
1299
1324
|
${this._installErase
|
|
1300
1325
|
? html `<br /><br />All data on the device will be erased.`
|
|
1301
1326
|
: ""}
|
|
@@ -1317,7 +1342,7 @@ export class EwtInstallDialog extends LitElement {
|
|
|
1317
1342
|
this._installState.state === "preparing" /* FlashStateType.PREPARING */) {
|
|
1318
1343
|
heading = "Installing";
|
|
1319
1344
|
// Show flash size in preparing message if available
|
|
1320
|
-
const preparingMsg = ((
|
|
1345
|
+
const preparingMsg = ((_e = this._installState) === null || _e === void 0 ? void 0 : _e.flashSize)
|
|
1321
1346
|
? `Preparing installation (${this._installState.flashSize})`
|
|
1322
1347
|
: "Preparing installation";
|
|
1323
1348
|
content = this._renderProgress(preparingMsg);
|
|
@@ -2562,11 +2587,31 @@ export class EwtInstallDialog extends LitElement {
|
|
|
2562
2587
|
await this._closeClientWithoutEvents(this._client);
|
|
2563
2588
|
}
|
|
2564
2589
|
document.body.style.overflow = (_a = this._bodyOverflow) !== null && _a !== void 0 ? _a : "";
|
|
2565
|
-
// Reset flash size when dialog is closed
|
|
2590
|
+
// Reset flash size and detected build when dialog is closed
|
|
2566
2591
|
this._flashSize = undefined;
|
|
2592
|
+
this._detectedBuild = undefined;
|
|
2567
2593
|
fireEvent(this, "closed");
|
|
2568
2594
|
this.parentNode.removeChild(this);
|
|
2569
2595
|
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Return a human-readable label for the differentiating properties of a build.
|
|
2598
|
+
* Shows the firmware filename from parts (factory preferred, no bootloader/partition).
|
|
2599
|
+
* Falls back to chipVariant/flashSizeMB/usbInterface if no filename found.
|
|
2600
|
+
*/
|
|
2601
|
+
_buildVariantLabel(build) {
|
|
2602
|
+
const filename = getFirmwareFileName(build);
|
|
2603
|
+
if (filename)
|
|
2604
|
+
return filename;
|
|
2605
|
+
// Fallback: structural qualifiers
|
|
2606
|
+
const parts = [];
|
|
2607
|
+
if (build.chipVariant)
|
|
2608
|
+
parts.push(build.chipVariant);
|
|
2609
|
+
if (build.flashSizeMB)
|
|
2610
|
+
parts.push(`${build.flashSizeMB} MB`);
|
|
2611
|
+
if (build.usbInterface)
|
|
2612
|
+
parts.push(build.usbInterface);
|
|
2613
|
+
return parts.length > 0 ? parts.join(", ") : undefined;
|
|
2614
|
+
}
|
|
2570
2615
|
/**
|
|
2571
2616
|
* Return if the device runs same firmware as manifest.
|
|
2572
2617
|
*/
|
|
@@ -2756,4 +2801,7 @@ __decorate([
|
|
|
2756
2801
|
__decorate([
|
|
2757
2802
|
state()
|
|
2758
2803
|
], EwtInstallDialog.prototype, "_flashSize", void 0);
|
|
2804
|
+
__decorate([
|
|
2805
|
+
state()
|
|
2806
|
+
], EwtInstallDialog.prototype, "_detectedBuild", void 0);
|
|
2759
2807
|
customElements.define("ewt-install-dialog", EwtInstallDialog);
|