* Keep the first panic in the ESP32 crash recorder
When the panic handler stalls, the interrupt watchdog re-enters through
panicHandler() and custom_crash_recorder() replaced the record of the
original exception with a frame that only shows the panic handler itself
(EPC inside xt_unhandled_exception, exccause 6 reported as
"IntegerDivideByZero" although it is PANIC_RSN_INTWDT_CPU1).
Record only the first panic of a boot, remember whether it came in via
panicHandler() and decode its exccause with the PANIC_RSN_* names in
that case.
* Move pseudo exccause names to PROGMEM
- Preserve fractional values in Berry MI32.set_temp() and MI32.set_hum().
- Limit saved MI32 configurations safely to 32 sensors.
- Respect the configured temperature unit (SetOption8) in dashboard temperature and dew-point values.
- Update browser-side age counters using real elapsed time.
- Allow a Berry widget response to contain multiple independent cards.
- Send dashboard metrics in a dedicated response every ten seconds.
- Pause dashboard polling while the browser tab is hidden.
- Display chained knob button presses as their numeric count.
- Various small improvements.
Z_Data::toAttributes() added attributes with no explicit suffix, so
Z_attribute_list::addAttribute defaulted to key_suffix =
countAttribute(attr.key) - an insertion-order counter, not the
device's real endpoint. Since toAttributes() is called once per
device.data element, the suffix each endpoint's attribute landed on
depended on device.data's internal list order, which isn't guaranteed
to be endpoint-ascending. On a 4-gang relay whose endpoints were
discovered as [2,1,3,4], this mapped endpoint 2 to bare "Power" and
endpoint 1 to "Power2" - swapped - while 3 and 4 happened to land
correctly.
SetOption101 does not fix this: it's only applied in
Z_postProcessAttributes(), which runs on the live per-message
ZbReceived path and correctly uses the frame's true src_ep. That
corrected data does get merged into device.attr_list, but
zigbee.find(name).info()/ZbStatus2 read from the separate device.data
store via toAttributes(), a parallel path Z_postProcessAttributes()
never touches.
Fix: suffix by the record's true endpoint (Z_Data::getEndpoint()),
matching the same key_suffix = src_ep convention
Z_postProcessAttributes() already uses. getEndpoint() == 0 ("any
endpoint") falls back to the original count-based behavior, unchanged.
Verified on hardware: a Tuya TS0004 4-gang relay with a non-ascending
Config list now reports all 4 endpoints under their correct suffix,
with no regression on a naturally-ordered multi-endpoint device.
* Add Shelly emulation for ESP32 (EMUL_SHELLY)
Presents Tasmota as a generation 2 Shelly Pro 2PM to controllers
speaking the Shelly Gen2 RPC protocol, such as the Sigenergy
mySigen application.
The emulation follows Belkin WeMo and Hue Bridge: compiled in
with USE_EMULATION_SHELLY (ESP32 only, as it needs the IDF mDNS
component) and selected at runtime with `Emulation 3` or on the
Configure Other web page, where it appears as "Shelly single
device".
When selected, the driver advertises _shelly._tcp over mDNS with
the IPv4 and IPv6 addresses of all active interfaces and serves
/shelly and /rpc. Up to two switch, two input and two metering
channels are mapped onto Tasmota relays, switches and the energy
driver. Channels beyond the relays configured keep their state
in NVS so a controller still sees two working outputs.
Shelly controllers discard mDNS replies that do not carry the
RFC 6762 TTL of 255, which Espressif's mDNS component only sets
on multicast, so the driver raises the TTL on the mDNS sockets
after registration.
* Make Shelly emulation opt-in and renumber driver
* [EQ3-TRV] More code refactoring
Here is the next major refactoring of the EQ3/TRV ESP32 BLE driver.
Below are the key highlights, alongside many other changes:
* **Optimize data presentation:** Hide sensor data in the Web UI if it is too old.
* **Minimize RAM footprint:** Sort `eq3_device_t` structure members to eliminate compiler memory padding.
* **Robust subcommand queue:** Rework command queue handling utilizing C++ container types to completely prevent memory leaks and minimize heap fragmentation.
* **Streamline device discovery:** Rework `Add device` logic to improve search performance and adapt to an index-free approach.
* **Decouple timeout handling:** Move slot cleanup into the cyclic `EQ3EverySecond` task for deterministic background execution.
* **Smart poll scheduling:** Rewrite polling routines to distribute requests evenly over `EQ3Period` while preventing Bluetooth stack congestion.
* **Unify command syntax:** Change CLI/MQTT commands from `TRV <CMD>` to `TRV<CMD>`.
* **Improve type safety:** Introduce strongly-typed `enum` definitions for driver operation results.
* **Modern C++ practices:** Replace legacy index-based arrays with range-based for loops (*for-each*) when possible.
* Uppercase TRV
* Simplify prefix matching
Building with UDSP_DEBUG enabled fails:
lib/lib_display/UDisplay/src/uDisplay.cpp:908:24: error: #if with no expression
908 | #if USE_UNIVERSAL_TOUCH
| ^
USE_UNIVERSAL_TOUCH is defined without a value (my_user_config.h and the
user_config_override.h convention both use a bare `#define`), so `#if` expands
to an empty expression and the preprocessor errors out.
Every other test of this macro already uses #ifdef:
uDisplay.cpp:47 #ifdef USE_UNIVERSAL_TOUCH
uDisplay.cpp:792 #ifdef USE_UNIVERSAL_TOUCH
uDisplay_touch.cpp:4 #ifdef USE_UNIVERSAL_TOUCH
so this looks like a typo rather than a deliberate value test.
Introduced in a1639507d ("Udisp SPI fix for mono color display", #24899). It
goes unnoticed in normal builds because the block sits inside #ifdef
UDSP_DEBUG, which ships commented out at uDisplay.cpp:27 — it only surfaces
for anyone who turns that debug logging on. Found on an ESP32-P4 build with
UDSP_DEBUG enabled for DSI init diagnostics.
Co-authored-by: Ari Friedman <afriedman@millsupplyco.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Large refactor of the EQ3/TRV ESP32 BLE driver. The primary goal was to replace `strcmp`-based logic in TRV subcommand handling with an index-driven approach.
Additional improvements included:
* Optimizing ESP32 memory management using `constexpr` and removing obsolete `PSTR` and `PROGMEM` statements
* Adjusting variable types for better efficiency
* Improving overall code readability
* Enabling safer, compile-time constants
These changes reduce binary size, flash usage, RAM footprint, and CPU overhead.
Functional behavior remains entirely unchanged.