* Add support for multi-byte characters like emojis (💡) in WebButton labels for light device toggle buttons
- Remove the 3-character buffer truncation of light device toggle button labels allowing multi-byte characters like emojis
- Rely on CSS to handle truncation and add `max-width:0` to the td so it respects the provided percentage width instead of expanding to fit content
- Wrap button content in a span with overflow handling to prevent layout breakage
* Use localized `D_BUTTON_TOGGLE` for light device button default text
* Improve UTF-8 support in light device WebButton text
- Add `Utf8Truncate` function in `support.ino` to truncate UTF-8 strings to a max chars limit or max visual width limit
- Truncate light device button text to max 4 chars or max width of 4 before passing to button HTML template
- cache calls to GetWebButton so only called once and update bool var from `set_button` to `has_web_button`.
* Small tweaks to improve clarity in Utf8Truncate on codepoint limits and visual width handling
* Correctness fixes
---------
Co-authored-by: s-hadinger <49731213+s-hadinger@users.noreply.github.com>
- Replace broken "http" and "://" in file condition with file.startswith(("http://", "https://")) — the original always evaluated "http" as truthy and only tested for "://".
- Strip whitespace and skip blank lines from custom_files_upload entries, matching the pattern in solidify-from-url.py.
- Resolve relative local paths against $PROJECT_DIR rather than the build-time CWD.
- Replace 8-bit per-channel math with 10-bit intermediates to preserve color ratios at low brightness.
- When SetOption105 (white blend mode) is enabled on a 4-byte RGBW strip, extract the minimum RGB component as a white channel (scaled by rgbwwTable[3]) rather than zeroing it, mirroring the logic in xdrv_04_light.ino.
- Gamma correction is applied via ledGamma10_10 throughout, including the extracted white channel.
- solidify_all_python.be imports tasmota_defines during solidification, but the actual file is generated post-compilation by gen-berry-defines.py. If it doesn't exist yet, solidification fails. Create an empty stub before calling prepareBerryFiles so the import succeeds regardless of build order.
* Add local file support to solidify-from-url.py and fix URL rename alias bug
- Add support for local .be file paths (absolute or PROJECT_DIR-relative) in prepareBerryFiles used by custom_berry_solidify project option in solidify-from-url.py
- Fix URL path to use "/" as separator instead of os.path.sep, and pass the rename alias to addHeaderFile so the solidified header name matches the actual target filename
* solidify-from-url: replace compiled berry binary with berry_port Python interpreter
- Remove ensureBerry() and the shell invocation of the compiled `berry` binary.
- Instead run solidify_all_python.be via `python3 -m berry_port`, matching how gen-berry-structures.py drives solidification for all other berry modules.
- Use Popen to filter routine per-file output and call env.Exit on failure.
- Route single-specifier hostnames through Format() so patterns like %NX (last N MAC hex chars) work correctly, while preserving the existing two-specifier %s-%04d behavior via snprintf
- Update comment in my_user_config.h to accurately describe chip ID rather than MAC
- Position tracking (abs_position, rel_position) was previously skipped when SEESAW_ENCODER_LIKE_ROTARY light control mode was active due to an early return. Moved position updates before the light control block so Show() and Telemetry always reflect current position.
- Also adds Pos (global relative position) alongside Pos1/Pos2 in JSON telemetry responses, rule triggers, and the web UI display.
* Add an independent MQTT client for use by Berry applications and extensions
- Introduce `mqttclient` Berry class (ESP32) for connecting to MQTT brokers with own credentials, TLS, LWT, and auto-reconnect separate from global MQTT client
- Berry `mqttclient` aims to match functionality of global MQTT client including backoff logic using Settings->mqtt_retry, mqtt_keepalive, and mqtt_socket_timeout
- Rename `retry_counter_delay` to `retry_counter_multiplier` in xdrv_02_9_mqtt for clarity and avoid redundant multiplication.
* Added `USE_BERRY_MQTTCLIENT` flag for conditional compilation of the standalone Berry MQTT client
- Bug fix to remove type check for 'int' in `breathe.be` color so ValueProviders are supported alongside integer colors (same as #24284 which was removed in later commits)
- Fix existing tests in `breath_animation_test.be` and add tests for color as a ValueProvider
- Style clean up in `breathe.be` `on_param_changed` to use `set_param()` instead of individual assignments
- Fix to remove duplicate `super().on_param_changed()` call in `rich_palette.be`
- Move `super()` call to top of `on_param_changed` in `breathe_color_provider.be` to be consistent
- Add comment about brightness scaling applied by `Leds` to `animation.be` init_strip
- Consolidate multiple states into a single uint8_t flags field and removes unused last_change_time
- Move position tracking to after early returns in Handler()
- Merge GetEncoderByIndex() two loops into a single loop
- Add SEESAW_ENCODER_HIDE_WEB_DISPLAY compile flag
- Refactored `xsns_81_seesaw_soil.ino` to utilize a base class `xsns_81_seesaw.ino` for Adafruit Seesaw devices
- Add `xsns_81_seesaw_encoder.ino` for handling Adafruit I2C QT Rotary Encoder with NeoPixel and button functionalities.
- Implemented option to have Adafruit I2C rotary encoder behave like a GPIO rotary encoders
- Update Adafruit Seesaw library files to v1.7.9
- In TasmotaLED: fixes for `_w_before` to use correct bitmask and for Show() to build 4 byte buffer correctly
- In xlgt_01_ws2812_esp32: fixes to set white value in Ws2812SetColor(), use correct bitmasks, and determine `light_type` based on PixelType if set