tasmota-esp-web-tools 12.2.0 → 12.2.1

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/README.md CHANGED
@@ -138,6 +138,38 @@ A device with ESP32-S3 and 16MB flash gets the first build, 4MB gets the second,
138
138
 
139
139
  The `flashSizeMB` field is **optional**. If omitted, the build will match any flash size. Builds with matching `flashSizeMB` are preferred over builds without it (most-specific-matching algorithm).
140
140
 
141
+ ## USB Interface Support (UART vs CDC)
142
+
143
+ For chips that can be connected either through a native USB interface (USB-JTAG/USB-OTG, e.g. ESP32-S2/S3/C3/C6/...) or through an external USB-to-Serial bridge (CP210x, FTDI, CH340, ...), you can ship dedicated firmware variants by specifying `usbInterface`:
144
+
145
+ - `"CDC"` – firmware built for native USB (CDC) console / programming
146
+ - `"UART"` – firmware built for the regular UART console via an external USB-to-Serial chip
147
+
148
+ ```json
149
+ {
150
+ "name": "My Firmware",
151
+ "builds": [
152
+ {
153
+ "chipFamily": "ESP32-S3",
154
+ "usbInterface": "CDC",
155
+ "parts": [{ "path": "s3-cdc.bin", "offset": 0 }]
156
+ },
157
+ {
158
+ "chipFamily": "ESP32-S3",
159
+ "usbInterface": "UART",
160
+ "parts": [{ "path": "s3-uart.bin", "offset": 0 }]
161
+ }
162
+ ]
163
+ }
164
+ ```
165
+
166
+ ESP Web Tools automatically detects how the device is connected:
167
+
168
+ - If the device is reached via native USB (USB-JTAG/USB-OTG) the build with `usbInterface: "CDC"` is selected.
169
+ - Otherwise (external USB-to-Serial bridge) the build with `usbInterface: "UART"` is selected.
170
+
171
+ The `usbInterface` field is **optional**. If omitted, the build will match any USB interface and is used as a fallback. It can also be combined freely with `chipVariant` and `flashSizeMB`.
172
+
141
173
  ## Performance
142
174
 
143
175
  ESP Web Tools supports configurable baud rates for flashing. By default, it uses 115200 baud for maximum compatibility. You can increase the baud rate for significantly faster flashing speeds.
package/dist/const.d.ts CHANGED
@@ -7,6 +7,13 @@ export interface Build {
7
7
  chipFamily: "ESP32" | "ESP8266" | "ESP32-S2" | "ESP32-S3" | "ESP32-C2" | "ESP32-C3" | "ESP32-C5" | "ESP32-C6" | "ESP32-C61" | "ESP32-H2" | "ESP32-P4";
8
8
  chipVariant?: string;
9
9
  flashSizeMB?: number;
10
+ /**
11
+ * Optional USB interface qualifier.
12
+ * - "CDC": native USB CDC (USB-JTAG/USB-OTG, e.g. direct USB on S2/S3/C3/C6/...)
13
+ * - "UART": external USB-to-Serial bridge (CP210x, FTDI, CH340, ...)
14
+ * If omitted, the build will match any USB interface.
15
+ */
16
+ usbInterface?: "UART" | "CDC";
10
17
  parts: {
11
18
  path: string;
12
19
  offset: number;
package/dist/flash.js CHANGED
@@ -18,11 +18,12 @@ function parseFlashSizeToMB(flashSize) {
18
18
  }
19
19
  /**
20
20
  * Select the best build using most-specific-matching algorithm
21
+ * - Builds with matching usbInterface are strongly preferred
21
22
  * - Builds with matching flashSizeMB are preferred
22
23
  * - Among builds with same specificity, first one wins
23
- * - Builds without flashSizeMB are fallback options
24
+ * - Builds without these qualifiers are fallback options
24
25
  */
25
- function selectBestBuild(builds, detectedFlashSizeMB) {
26
+ function selectBestBuild(builds, detectedFlashSizeMB, detectedUsbInterface) {
26
27
  if (builds.length === 0)
27
28
  return undefined;
28
29
  // Score builds: higher score = more specific match
@@ -30,7 +31,19 @@ function selectBestBuild(builds, detectedFlashSizeMB) {
30
31
  let bestScore = -Infinity;
31
32
  for (const build of builds) {
32
33
  let score = 0;
33
- // Flash size match gives highest priority
34
+ // USB interface match - if specified, must match
35
+ if (build.usbInterface !== undefined) {
36
+ if (detectedUsbInterface !== undefined &&
37
+ build.usbInterface === detectedUsbInterface) {
38
+ score += 1000; // Strong preference for explicit usbInterface match
39
+ }
40
+ else {
41
+ // Mismatched usbInterface - disqualify this build
42
+ continue;
43
+ }
44
+ }
45
+ // Builds without usbInterface stay neutral (compatible with any)
46
+ // Flash size match gives second priority
34
47
  if (build.flashSizeMB !== undefined && detectedFlashSizeMB !== undefined) {
35
48
  if (build.flashSizeMB === detectedFlashSizeMB) {
36
49
  score += 100; // Exact flash size match
@@ -118,6 +131,20 @@ logger, manifestPath, eraseFirst, firmwareBuffer, _baudRate) => {
118
131
  }
119
132
  flashSize = esploader.flashSize; // e.g., "4MB", "8MB"
120
133
  const flashSizeMB = flashSize ? parseFlashSizeToMB(flashSize) : undefined;
134
+ // Detect USB connection type to pick CDC vs UART firmware variants
135
+ // - true: native USB (USB-JTAG/USB-OTG) -> CDC
136
+ // - false: external USB-to-Serial bridge -> UART
137
+ let detectedUsbInterface;
138
+ if (typeof esploader.detectUsbConnectionType === "function") {
139
+ try {
140
+ const isUsbJtagOrOtg = await esploader.detectUsbConnectionType();
141
+ detectedUsbInterface = isUsbJtagOrOtg ? "CDC" : "UART";
142
+ logger.debug(`Detected USB interface: ${detectedUsbInterface}`);
143
+ }
144
+ catch (err) {
145
+ logger.debug("Failed to detect USB connection type:", err);
146
+ }
147
+ }
121
148
  fireStateEvent({
122
149
  state: "initializing" /* FlashStateType.INITIALIZING */,
123
150
  message: `Initialized. Found ${chipFamily}${chipVariant ? ` (${chipVariant})` : ""}${flashSize ? `, ${flashSize}` : ""}`,
@@ -154,9 +181,9 @@ logger, manifestPath, eraseFirst, firmwareBuffer, _baudRate) => {
154
181
  // Prefer builds with more matching qualifiers (flashSizeMB)
155
182
  const exactVariantBuilds = compatibleBuilds.filter((b) => b.chipVariant !== undefined && b.chipVariant === chipVariant);
156
183
  const variantAgnosticBuilds = compatibleBuilds.filter((b) => b.chipVariant === undefined);
157
- build = selectBestBuild(exactVariantBuilds, flashSizeMB);
184
+ build = selectBestBuild(exactVariantBuilds, flashSizeMB, detectedUsbInterface);
158
185
  if (!build) {
159
- build = selectBestBuild(variantAgnosticBuilds, flashSizeMB);
186
+ build = selectBestBuild(variantAgnosticBuilds, flashSizeMB, detectedUsbInterface);
160
187
  }
161
188
  if (!build) {
162
189
  fireStateEvent({