Tests now verify packed values via comment strings and non-zero
checks rather than decoding individual bit positions. This removes
the coupling to internal bit layout constants.
Tests now go through _setup_entity_impl + setup_device_class/
setup_unit_of_measurement + finalize_entity_strings using real
CONF_* keys instead of internal _KEY_* constants.
- Remove hardcoded _ENTITY_CATEGORY_NAMES dict, derive from cv.ENTITY_CATEGORIES keys
- Remove redundant local import re (already at top level)
- Remove last setup_test_environment noqa line
Move set_internal(), set_disabled_by_default(), set_entity_category(),
and set_device() to protected on EntityBase. These were codegen-only
setters never intended for runtime use.
internal, disabled_by_default, and entity_category are now packed into
the existing configure_entity_() uint32 parameter alongside string
indices, eliminating up to 3 separate function calls per entity.
set_device() is renamed to set_device_() per protected naming convention
and remains a separate call (pointer can't be packed).
Entity category integer mapping is derived from cv.ENTITY_CATEGORIES
to stay in sync with the C++ enum automatically.
Move the pure logic (string building, escaping, byte length
calculation) out of the nested closure into a module-level function
that can be tested without codegen mocks. Tests cover both copilot
review concerns: empty friendly_name with MAC suffix, and UTF-8
byte length for non-ASCII characters.
Add generate_boards.py script that reads board definitions and variant
pin headers from the arduino-pico repository to auto-generate boards.py
with support for 143+ boards including RP2350 variants.
Fix the Pico W LED pin from 32 (non-existent GPIO, never worked) to 64
(CYW43 wireless GPIO 0, hardware verified).
Make gpio.py pin validation data-driven:
- CYW43 virtual pin detection uses board pin map data
- Pin range based on MCU type from generated board metadata
- No hardcoded board names or magic numbers
Serial ports in the chooser may belong to other devices (e.g. FT232R),
not the RP2040. Show the BOOTSEL tip whenever no BOOTSEL device is
detected via picotool, regardless of whether serial ports are present.
Replace UF2 file copy to mass storage volume with direct picotool upload.
This avoids macOS "disk not ejected properly" warnings caused by the RP2040
resetting immediately after receiving the firmware.
- Use picotool (already installed by PlatformIO) for BOOTSEL detection
and firmware upload via USB
- Upload ELF directly with `picotool load -v -x` for real-time progress
- Remove platform-specific mass storage volume detection (macOS/Linux/Windows)
- Show helpful udev rules message on Linux permission errors
Move signed bin creation from post_build script to upload_using_platformio.
The post_build AddPostAction only runs during build, not during nobuild
upload, so the file was missing when PlatformIO tried to upload.
Now create firmware.bin.signed before calling PlatformIO upload.
Add auto-detection of RP2040 BOOTSEL mass storage volumes (RPI-RP2) on
macOS, Linux, and Windows. Show detected volumes as upload targets with
a progress bar for UF2 file copy. Display helpful BOOTSEL instructions
when no RP2040 device is found.
- Add get_rp2040_mass_storage_volumes() to detect mounted RPI-RP2 volumes
- Add PortType.MASS_STORAGE and upload_using_uf2_copy() with progress bar
- Move ProgressBar to helpers.py for shared use
- Wait for USB-CDC serial port after upload for log output
- Auto-select single serial port for logs after mass storage upload
- Create firmware.bin.signed in post_build to fix nobuild upload target
- Show BOOTSEL tip when only OTA options are available
Every entity generated two codegen calls:
entity->set_name("Name", hash);
entity->set_entity_strings(packed);
Merge these into a single configure_entity(name, hash, packed) call
to reduce generated code size. For a config with 50+ entities this
eliminates 50+ function calls from the generated setup() function.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Defense-in-depth: validate device class strings don't exceed the
48-byte PROGMEM buffer limit (47 chars + null), matching the same
pattern used for icon strings.
The Python tests were testing a Python reimplementation, not the
actual C++ code. Replace with an integration test that exercises
the real micros_to_millis() on the host platform, covering boundary
values, carry paths, and mod-8 shift edge cases (25 checks).