fbuild 1.1.0__py3-none-any.whl

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.

Potentially problematic release.


This version of fbuild might be problematic. Click here for more details.

Files changed (93) hide show
  1. fbuild/__init__.py +0 -0
  2. fbuild/assets/example.txt +1 -0
  3. fbuild/build/__init__.py +117 -0
  4. fbuild/build/archive_creator.py +186 -0
  5. fbuild/build/binary_generator.py +444 -0
  6. fbuild/build/build_component_factory.py +131 -0
  7. fbuild/build/build_state.py +325 -0
  8. fbuild/build/build_utils.py +98 -0
  9. fbuild/build/compilation_executor.py +422 -0
  10. fbuild/build/compiler.py +165 -0
  11. fbuild/build/compiler_avr.py +574 -0
  12. fbuild/build/configurable_compiler.py +612 -0
  13. fbuild/build/configurable_linker.py +637 -0
  14. fbuild/build/flag_builder.py +186 -0
  15. fbuild/build/library_dependency_processor.py +185 -0
  16. fbuild/build/linker.py +708 -0
  17. fbuild/build/orchestrator.py +67 -0
  18. fbuild/build/orchestrator_avr.py +656 -0
  19. fbuild/build/orchestrator_esp32.py +797 -0
  20. fbuild/build/orchestrator_teensy.py +543 -0
  21. fbuild/build/source_compilation_orchestrator.py +220 -0
  22. fbuild/build/source_scanner.py +516 -0
  23. fbuild/cli.py +566 -0
  24. fbuild/cli_utils.py +312 -0
  25. fbuild/config/__init__.py +16 -0
  26. fbuild/config/board_config.py +457 -0
  27. fbuild/config/board_loader.py +92 -0
  28. fbuild/config/ini_parser.py +209 -0
  29. fbuild/config/mcu_specs.py +88 -0
  30. fbuild/daemon/__init__.py +34 -0
  31. fbuild/daemon/client.py +929 -0
  32. fbuild/daemon/compilation_queue.py +293 -0
  33. fbuild/daemon/daemon.py +474 -0
  34. fbuild/daemon/daemon_context.py +196 -0
  35. fbuild/daemon/error_collector.py +263 -0
  36. fbuild/daemon/file_cache.py +332 -0
  37. fbuild/daemon/lock_manager.py +270 -0
  38. fbuild/daemon/logging_utils.py +149 -0
  39. fbuild/daemon/messages.py +301 -0
  40. fbuild/daemon/operation_registry.py +288 -0
  41. fbuild/daemon/process_tracker.py +366 -0
  42. fbuild/daemon/processors/__init__.py +12 -0
  43. fbuild/daemon/processors/build_processor.py +157 -0
  44. fbuild/daemon/processors/deploy_processor.py +327 -0
  45. fbuild/daemon/processors/monitor_processor.py +146 -0
  46. fbuild/daemon/request_processor.py +401 -0
  47. fbuild/daemon/status_manager.py +216 -0
  48. fbuild/daemon/subprocess_manager.py +316 -0
  49. fbuild/deploy/__init__.py +17 -0
  50. fbuild/deploy/deployer.py +67 -0
  51. fbuild/deploy/deployer_esp32.py +314 -0
  52. fbuild/deploy/monitor.py +495 -0
  53. fbuild/interrupt_utils.py +34 -0
  54. fbuild/packages/__init__.py +53 -0
  55. fbuild/packages/archive_utils.py +1098 -0
  56. fbuild/packages/arduino_core.py +412 -0
  57. fbuild/packages/cache.py +249 -0
  58. fbuild/packages/downloader.py +366 -0
  59. fbuild/packages/framework_esp32.py +538 -0
  60. fbuild/packages/framework_teensy.py +346 -0
  61. fbuild/packages/github_utils.py +96 -0
  62. fbuild/packages/header_trampoline_cache.py +394 -0
  63. fbuild/packages/library_compiler.py +203 -0
  64. fbuild/packages/library_manager.py +549 -0
  65. fbuild/packages/library_manager_esp32.py +413 -0
  66. fbuild/packages/package.py +163 -0
  67. fbuild/packages/platform_esp32.py +383 -0
  68. fbuild/packages/platform_teensy.py +312 -0
  69. fbuild/packages/platform_utils.py +131 -0
  70. fbuild/packages/platformio_registry.py +325 -0
  71. fbuild/packages/sdk_utils.py +231 -0
  72. fbuild/packages/toolchain.py +436 -0
  73. fbuild/packages/toolchain_binaries.py +196 -0
  74. fbuild/packages/toolchain_esp32.py +484 -0
  75. fbuild/packages/toolchain_metadata.py +185 -0
  76. fbuild/packages/toolchain_teensy.py +404 -0
  77. fbuild/platform_configs/esp32.json +150 -0
  78. fbuild/platform_configs/esp32c2.json +144 -0
  79. fbuild/platform_configs/esp32c3.json +143 -0
  80. fbuild/platform_configs/esp32c5.json +151 -0
  81. fbuild/platform_configs/esp32c6.json +151 -0
  82. fbuild/platform_configs/esp32p4.json +149 -0
  83. fbuild/platform_configs/esp32s3.json +151 -0
  84. fbuild/platform_configs/imxrt1062.json +56 -0
  85. fbuild-1.1.0.dist-info/METADATA +447 -0
  86. fbuild-1.1.0.dist-info/RECORD +93 -0
  87. fbuild-1.1.0.dist-info/WHEEL +5 -0
  88. fbuild-1.1.0.dist-info/entry_points.txt +5 -0
  89. fbuild-1.1.0.dist-info/licenses/LICENSE +21 -0
  90. fbuild-1.1.0.dist-info/top_level.txt +2 -0
  91. fbuild_lint/__init__.py +0 -0
  92. fbuild_lint/ruff_plugins/__init__.py +0 -0
  93. fbuild_lint/ruff_plugins/keyboard_interrupt_checker.py +158 -0
@@ -0,0 +1,457 @@
1
+ """
2
+ Board configuration loader for Arduino boards.
3
+
4
+ This module provides functionality to load and parse board-specific configurations
5
+ from boards.txt files, extracting MCU type, frequency, and other build parameters.
6
+ """
7
+
8
+ from pathlib import Path
9
+ from typing import Dict, Optional
10
+
11
+
12
+ class BoardConfigError(Exception):
13
+ """Exception raised for board configuration errors."""
14
+
15
+ pass
16
+
17
+
18
+ class BoardConfig:
19
+ """
20
+ Loader and parser for Arduino boards.txt configuration.
21
+
22
+ boards.txt files contain board-specific definitions like MCU type,
23
+ frequency, fuse settings, and other build parameters.
24
+
25
+ Example boards.txt entry:
26
+ uno.name=Arduino Uno
27
+ uno.build.mcu=atmega328p
28
+ uno.build.f_cpu=16000000L
29
+ uno.build.board=AVR_UNO
30
+ uno.build.core=arduino
31
+ uno.build.variant=standard
32
+
33
+ Usage:
34
+ # Load from boards.txt file
35
+ config = BoardConfig.from_boards_txt(Path("boards.txt"), "uno")
36
+
37
+ # Or create directly with known values
38
+ config = BoardConfig(
39
+ name="uno",
40
+ mcu="atmega328p",
41
+ f_cpu="16000000L",
42
+ board="AVR_UNO",
43
+ core="arduino",
44
+ variant="standard"
45
+ )
46
+ """
47
+
48
+ # Default Arduino Uno configuration (used as fallback)
49
+ UNO_DEFAULTS = {
50
+ "name": "Arduino Uno",
51
+ "mcu": "atmega328p",
52
+ "f_cpu": "16000000L",
53
+ "board": "AVR_UNO",
54
+ "core": "arduino",
55
+ "variant": "standard",
56
+ "vid": "0x2341",
57
+ "pid": "0x0043",
58
+ }
59
+
60
+ # Other common boards with defaults
61
+ BOARD_DEFAULTS = {
62
+ "uno": UNO_DEFAULTS,
63
+ "mega": {
64
+ "name": "Arduino Mega",
65
+ "mcu": "atmega2560",
66
+ "f_cpu": "16000000L",
67
+ "board": "AVR_MEGA2560",
68
+ "core": "arduino",
69
+ "variant": "mega",
70
+ },
71
+ "nano": {
72
+ "name": "Arduino Nano",
73
+ "mcu": "atmega328p",
74
+ "f_cpu": "16000000L",
75
+ "board": "AVR_NANO",
76
+ "core": "arduino",
77
+ "variant": "eightanaloginputs",
78
+ },
79
+ "leonardo": {
80
+ "name": "Arduino Leonardo",
81
+ "mcu": "atmega32u4",
82
+ "f_cpu": "16000000L",
83
+ "board": "AVR_LEONARDO",
84
+ "core": "arduino",
85
+ "variant": "leonardo",
86
+ },
87
+ "esp32-c3-devkitm-1": {
88
+ "name": "ESP32-C3 DevKit M-1",
89
+ "mcu": "esp32c3",
90
+ "f_cpu": "160000000L",
91
+ "board": "ESP32_DEV",
92
+ "core": "esp32",
93
+ "variant": "esp32c3",
94
+ },
95
+ "esp32-c6-devkitc-1": {
96
+ "name": "ESP32-C6 DevKit C-1",
97
+ "mcu": "esp32c6",
98
+ "f_cpu": "160000000L",
99
+ "board": "ESP32_DEV",
100
+ "core": "esp32",
101
+ "variant": "esp32c6",
102
+ },
103
+ "esp32-c6-devkitm-1": {
104
+ "name": "ESP32-C6 DevKit M-1",
105
+ "mcu": "esp32c6",
106
+ "f_cpu": "160000000L",
107
+ "board": "ESP32_DEV",
108
+ "core": "esp32",
109
+ "variant": "esp32c6",
110
+ },
111
+ "esp32-c5-devkitc-1": {
112
+ "name": "ESP32-C5 DevKit C-1",
113
+ "mcu": "esp32c5",
114
+ "f_cpu": "160000000L",
115
+ "board": "ESP32_DEV",
116
+ "core": "esp32",
117
+ "variant": "esp32c5",
118
+ },
119
+ "teensy40": {
120
+ "name": "Teensy 4.0",
121
+ "mcu": "imxrt1062",
122
+ "f_cpu": "600000000L",
123
+ "board": "TEENSY40",
124
+ "core": "teensy4",
125
+ "variant": "teensy40",
126
+ },
127
+ "teensy41": {
128
+ "name": "Teensy 4.1",
129
+ "mcu": "imxrt1062",
130
+ "f_cpu": "600000000L",
131
+ "board": "TEENSY41",
132
+ "core": "teensy4",
133
+ "variant": "teensy41",
134
+ },
135
+ }
136
+
137
+ def __init__(
138
+ self,
139
+ name: str,
140
+ mcu: str,
141
+ f_cpu: str,
142
+ board: str,
143
+ core: str = "arduino",
144
+ variant: str = "standard",
145
+ vid: Optional[str] = None,
146
+ pid: Optional[str] = None,
147
+ extra_flags: Optional[Dict[str, str]] = None,
148
+ ):
149
+ """
150
+ Initialize board configuration.
151
+
152
+ Args:
153
+ name: Human-readable board name (e.g., "Arduino Uno")
154
+ mcu: Microcontroller type (e.g., "atmega328p")
155
+ f_cpu: CPU frequency (e.g., "16000000L")
156
+ board: Board identifier for defines (e.g., "AVR_UNO")
157
+ core: Core library name (default: "arduino")
158
+ variant: Variant directory name (default: "standard")
159
+ vid: USB Vendor ID (optional)
160
+ pid: USB Product ID (optional)
161
+ extra_flags: Additional board-specific flags (optional)
162
+ """
163
+ self.name = name
164
+ self.mcu = mcu
165
+ self.f_cpu = f_cpu
166
+ self.board = board
167
+ self.core = core
168
+ self.variant = variant
169
+ self.vid = vid
170
+ self.pid = pid
171
+ self.extra_flags = extra_flags or {}
172
+
173
+ @property
174
+ def platform(self) -> str:
175
+ """
176
+ Detect platform type from MCU.
177
+
178
+ Returns:
179
+ Platform identifier: "avr", "esp32", or "teensy"
180
+ """
181
+ if self.mcu.startswith("atmega"):
182
+ return "avr"
183
+ elif self.mcu.startswith("esp32"):
184
+ return "esp32"
185
+ elif self.mcu.startswith("imxrt"):
186
+ return "teensy"
187
+ else:
188
+ # Default to AVR for unknown
189
+ return "avr"
190
+
191
+ @classmethod
192
+ def from_boards_txt(
193
+ cls,
194
+ boards_txt_path: Path,
195
+ board_id: str,
196
+ overrides: Optional[Dict[str, str]] = None,
197
+ ) -> "BoardConfig":
198
+ """
199
+ Load board configuration from a boards.txt file.
200
+
201
+ Args:
202
+ boards_txt_path: Path to boards.txt file
203
+ board_id: Board identifier (e.g., "uno", "mega")
204
+ overrides: Optional overrides from platformio.ini
205
+ (e.g., board_build.mcu, board_build.f_cpu)
206
+
207
+ Returns:
208
+ BoardConfig instance
209
+
210
+ Raises:
211
+ BoardConfigError: If file not found or board not defined
212
+
213
+ Example:
214
+ config = BoardConfig.from_boards_txt(
215
+ Path("hardware/arduino/avr/boards.txt"),
216
+ "uno"
217
+ )
218
+ """
219
+ if not boards_txt_path.exists():
220
+ raise BoardConfigError(f"boards.txt not found: {boards_txt_path}")
221
+
222
+ # Parse boards.txt
223
+ board_data = cls._parse_boards_txt(boards_txt_path, board_id)
224
+
225
+ if not board_data:
226
+ raise BoardConfigError(f"Board '{board_id}' not found in {boards_txt_path}")
227
+
228
+ # Apply overrides from platformio.ini (board_build.*)
229
+ if overrides:
230
+ board_data.update(overrides)
231
+
232
+ # Extract required fields with validation
233
+ try:
234
+ return cls(
235
+ name=board_data.get("name", board_id),
236
+ mcu=board_data["mcu"],
237
+ f_cpu=board_data["f_cpu"],
238
+ board=board_data["board"],
239
+ core=board_data.get("core", "arduino"),
240
+ variant=board_data.get("variant", "standard"),
241
+ vid=board_data.get("vid"),
242
+ pid=board_data.get("pid"),
243
+ extra_flags={
244
+ k: v
245
+ for k, v in board_data.items()
246
+ if k
247
+ not in {
248
+ "name",
249
+ "mcu",
250
+ "f_cpu",
251
+ "board",
252
+ "core",
253
+ "variant",
254
+ "vid",
255
+ "pid",
256
+ }
257
+ },
258
+ )
259
+ except KeyError as e:
260
+ raise BoardConfigError(f"Board '{board_id}' is missing required field: {e}") from e
261
+
262
+ @classmethod
263
+ def from_board_id(cls, board_id: str, overrides: Optional[Dict[str, str]] = None) -> "BoardConfig":
264
+ """
265
+ Load board configuration using built-in defaults.
266
+
267
+ This is a fallback when boards.txt is not available. It uses
268
+ hardcoded configurations for common Arduino boards.
269
+
270
+ Args:
271
+ board_id: Board identifier (e.g., "uno", "mega")
272
+ overrides: Optional overrides (e.g., from platformio.ini)
273
+
274
+ Returns:
275
+ BoardConfig instance
276
+
277
+ Raises:
278
+ BoardConfigError: If board_id not recognized
279
+
280
+ Example:
281
+ config = BoardConfig.from_board_id("uno")
282
+ """
283
+ # Normalize board_id (handle common variations)
284
+ board_id = board_id.lower()
285
+ if board_id == "megaatmega2560":
286
+ board_id = "mega"
287
+
288
+ if board_id not in cls.BOARD_DEFAULTS:
289
+ raise BoardConfigError(f"Unknown board: {board_id}. " + f"Supported boards: {', '.join(cls.BOARD_DEFAULTS.keys())}")
290
+
291
+ board_data = cls.BOARD_DEFAULTS[board_id].copy()
292
+
293
+ # Apply overrides
294
+ if overrides:
295
+ board_data.update(overrides)
296
+
297
+ return cls(
298
+ name=board_data["name"],
299
+ mcu=board_data["mcu"],
300
+ f_cpu=board_data["f_cpu"],
301
+ board=board_data["board"],
302
+ core=board_data.get("core", "arduino"),
303
+ variant=board_data.get("variant", "standard"),
304
+ vid=board_data.get("vid"),
305
+ pid=board_data.get("pid"),
306
+ )
307
+
308
+ @staticmethod
309
+ def _parse_boards_txt(boards_txt_path: Path, board_id: str) -> Dict[str, str]:
310
+ """
311
+ Parse boards.txt file and extract configuration for a specific board.
312
+
313
+ Args:
314
+ boards_txt_path: Path to boards.txt
315
+ board_id: Board identifier to extract
316
+
317
+ Returns:
318
+ Dictionary of board configuration keys and values
319
+
320
+ Example boards.txt format:
321
+ uno.name=Arduino Uno
322
+ uno.build.mcu=atmega328p
323
+ uno.build.f_cpu=16000000L
324
+ """
325
+ board_data = {}
326
+ prefix = f"{board_id}."
327
+
328
+ try:
329
+ with open(boards_txt_path, "r", encoding="utf-8") as f:
330
+ for line in f:
331
+ line = line.strip()
332
+
333
+ # Skip comments and empty lines
334
+ if not line or line.startswith("#"):
335
+ continue
336
+
337
+ # Parse key=value pairs
338
+ if "=" not in line:
339
+ continue
340
+
341
+ key, value = line.split("=", 1)
342
+ key = key.strip()
343
+ value = value.strip()
344
+
345
+ # Only process lines for our board
346
+ if not key.startswith(prefix):
347
+ continue
348
+
349
+ # Remove board prefix and extract the field name
350
+ # uno.build.mcu -> mcu (from build.*)
351
+ # uno.name -> name
352
+ field = key[len(prefix) :]
353
+
354
+ # Handle build.* fields
355
+ if field.startswith("build."):
356
+ field = field[6:] # Remove 'build.' prefix
357
+
358
+ # Handle upload.* fields (vid, pid)
359
+ elif field.startswith("upload."):
360
+ field = field[7:] # Remove 'upload.' prefix
361
+
362
+ board_data[field] = value
363
+
364
+ except KeyboardInterrupt as ke:
365
+ from fbuild.interrupt_utils import handle_keyboard_interrupt_properly
366
+
367
+ handle_keyboard_interrupt_properly(ke)
368
+ except Exception as e:
369
+ raise BoardConfigError(f"Failed to parse {boards_txt_path}: {e}") from e
370
+
371
+ return board_data
372
+
373
+ def get_defines(self) -> Dict[str, str]:
374
+ """
375
+ Get preprocessor defines for this board configuration.
376
+
377
+ Returns:
378
+ Dictionary of define names to values
379
+
380
+ Example:
381
+ {
382
+ 'PLATFORMIO': '60118',
383
+ 'F_CPU': '16000000L',
384
+ 'ARDUINO': '10819',
385
+ 'ARDUINO_AVR_UNO': '',
386
+ 'ARDUINO_ARCH_AVR': '',
387
+ '__AVR_ATmega328P__': ''
388
+ }
389
+ """
390
+ defines = {
391
+ "PLATFORMIO": "60118", # PlatformIO version identifier
392
+ "F_CPU": self.f_cpu,
393
+ "ARDUINO": "10819", # Arduino version (1.8.19)
394
+ f"ARDUINO_{self.board}": "",
395
+ "ARDUINO_ARCH_AVR": "",
396
+ }
397
+
398
+ # Add MCU-specific define (e.g., __AVR_ATmega328P__)
399
+ mcu_define = f"__AVR_{self.mcu.upper()}__"
400
+ defines[mcu_define] = ""
401
+
402
+ # Add any extra defines from board configuration
403
+ for key, value in self.extra_flags.items():
404
+ if key.startswith("define_"):
405
+ define_name = key[7:].upper()
406
+ defines[define_name] = value
407
+
408
+ return defines
409
+
410
+ def get_include_paths(self, core_path: Path) -> list[Path]:
411
+ """
412
+ Get include paths for compilation.
413
+
414
+ Args:
415
+ core_path: Path to Arduino core installation
416
+
417
+ Returns:
418
+ List of include directory paths
419
+
420
+ Example:
421
+ [
422
+ Path('/path/to/cores/arduino'),
423
+ Path('/path/to/variants/standard')
424
+ ]
425
+ """
426
+ return [
427
+ core_path / "cores" / self.core,
428
+ core_path / "variants" / self.variant,
429
+ ]
430
+
431
+ def get_core_sources_dir(self, core_path: Path) -> Path:
432
+ """
433
+ Get path to core source files directory.
434
+
435
+ Args:
436
+ core_path: Path to Arduino core installation
437
+
438
+ Returns:
439
+ Path to core sources (e.g., cores/arduino)
440
+ """
441
+ return core_path / "cores" / self.core
442
+
443
+ def get_variant_dir(self, core_path: Path) -> Path:
444
+ """
445
+ Get path to board variant directory.
446
+
447
+ Args:
448
+ core_path: Path to Arduino core installation
449
+
450
+ Returns:
451
+ Path to variant directory (e.g., variants/standard)
452
+ """
453
+ return core_path / "variants" / self.variant
454
+
455
+ def __repr__(self) -> str:
456
+ """String representation of board configuration."""
457
+ return f"BoardConfig(name='{self.name}', mcu='{self.mcu}', f_cpu='{self.f_cpu}', board='{self.board}')"
@@ -0,0 +1,92 @@
1
+ """Board configuration loading utilities.
2
+
3
+ This module provides utilities for loading board configurations with support
4
+ for both built-in boards and platform-specific boards (ESP32, etc.).
5
+ """
6
+
7
+ from typing import Dict
8
+
9
+ from .board_config import BoardConfig, BoardConfigError
10
+
11
+
12
+ class BoardConfigLoader:
13
+ """Utility class for loading board configurations with platform detection."""
14
+
15
+ @staticmethod
16
+ def load_board_config(board_id: str, env_config: Dict) -> BoardConfig:
17
+ """
18
+ Load board configuration with platform-specific handling.
19
+
20
+ This method first attempts to load the board from built-in defaults.
21
+ If that fails and the platform is ESP32, it creates a minimal BoardConfig
22
+ with MCU detection based on the board ID.
23
+
24
+ Args:
25
+ board_id: Board identifier (e.g., 'uno', 'esp32dev')
26
+ env_config: Environment configuration from platformio.ini
27
+
28
+ Returns:
29
+ BoardConfig instance
30
+
31
+ Raises:
32
+ BoardConfigError: If board configuration cannot be loaded
33
+ """
34
+ # Extract overrides from env_config (board_build.*)
35
+ overrides = {}
36
+ for key, value in env_config.items():
37
+ if key.startswith("board_build."):
38
+ override_key = key[12:] # Remove 'board_build.' prefix
39
+ overrides[override_key] = value
40
+
41
+ try:
42
+ # Try to load from built-in defaults first
43
+ return BoardConfig.from_board_id(board_id, overrides)
44
+ except BoardConfigError:
45
+ # Check if this is an ESP32 board by looking at platform URL
46
+ platform_url = env_config.get("platform", "")
47
+ if "espressif32" in platform_url or "esp32" in platform_url.lower():
48
+ # For ESP32 boards, create a minimal BoardConfig
49
+ # The actual board JSON will be loaded by ESP32Platform
50
+ mcu = BoardConfigLoader._detect_esp32_mcu(board_id)
51
+
52
+ return BoardConfig(
53
+ name=board_id,
54
+ mcu=mcu,
55
+ f_cpu="240000000L", # Default ESP32 frequency
56
+ board="ESP32_DEV",
57
+ core="esp32",
58
+ variant="esp32",
59
+ )
60
+
61
+ # If not ESP32, re-raise original error
62
+ raise BoardConfigError(f"Unknown board: {board_id}\n" + "Supported AVR boards: uno, mega, nano, leonardo\n" + "For ESP32 boards, ensure platform URL contains 'espressif32'")
63
+
64
+ @staticmethod
65
+ def _detect_esp32_mcu(board_id: str) -> str:
66
+ """
67
+ Detect ESP32 MCU variant from board ID.
68
+
69
+ Args:
70
+ board_id: Board identifier
71
+
72
+ Returns:
73
+ MCU identifier (esp32, esp32s3, esp32c3, etc.)
74
+ """
75
+ board_id_lower = board_id.lower()
76
+
77
+ # Check for specific ESP32 variants
78
+ if "esp32s3" in board_id_lower or "esp32-s3" in board_id_lower:
79
+ return "esp32s3"
80
+ elif "esp32s2" in board_id_lower or "esp32-s2" in board_id_lower:
81
+ return "esp32s2"
82
+ elif "esp32c3" in board_id_lower or "esp32-c3" in board_id_lower:
83
+ return "esp32c3"
84
+ elif "esp32c6" in board_id_lower or "esp32-c6" in board_id_lower:
85
+ return "esp32c6"
86
+ elif "esp32c2" in board_id_lower or "esp32-c2" in board_id_lower:
87
+ return "esp32c2"
88
+ elif "esp32h2" in board_id_lower or "esp32-h2" in board_id_lower:
89
+ return "esp32h2"
90
+ else:
91
+ # Default to esp32
92
+ return "esp32"