Commit Graph
21654 Commits
Author SHA1 Message Date
Theo Arends 35bf395e54 Update security policy 2026-09-27 16:47:47 +02:00
Theo Arends 40ed9e48ee Update change logs 2026-09-27 15:39:13 +02:00
c683ec3bce Matter: add Electrical Power Measurement cluster to On/Off Plug-in Unit (#24922)
* Matter: add Electrical Power Measurement cluster to On/Off Plug-in Unit

Adds a new "relay_power" plugin type (Matter_Plugin_OnOff_Power) that extends
the existing relay/OnOff Plug-in Unit (0x010A) with the Electrical Power
Measurement cluster (0x0090), reporting Voltage, Current, ActivePower,
ApparentPower, ReactivePower, Frequency and PowerFactor from Tasmota's ENERGY
sensor JSON, so Matter controllers can display live power usage for smart
plugs with energy monitoring.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Matter: add v_relay_power virtual variant for Electrical Power Measurement

Adds Matter_Plugin_Virt_OnOff_Power ("v_relay_power") so the new
ElectricalPowerMeasurement-enabled plug can be exercised without physical
hardware, driven entirely via `MtrUpdate` (e.g. Voltage/Current/ActivePower/
ApparentPower/ReactivePower/Factor/Frequency).

Also guards Matter_Plugin_OnOff_Power.parse_sensors() against VIRTUAL
instances (it must not read the local ENERGY sensor) and declares
UPDATE_COMMANDS so MtrUpdate accepts the new measurement keys. The wattage
key is named `ActivePower` rather than `Power` since `Power` is already the
inherited On/Off boolean command.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Matter: register new plugin headers in be_matter_module.c

be_matter_module.c maintains an explicit, hand-written list of solidified
Berry header includes (no auto-discovery). The new OnOff_Power and
Virt_OnOff_Power plugin files were missing from that list, so their classes
were never defined, causing the "undeclared" build failures reported by CI
(be_class_Matter_Plugin_OnOff_Power / be_class_Matter_Plugin_Virt_OnOff_Power)
even though matter.plugins_classes referenced them by name.

* Matter: add http_relay_power bridge variant for Electrical Power Measurement

Adds Matter_Plugin_Bridge_OnOff_Power ("http_relay_power") so the
ElectricalPowerMeasurement-enabled plug can also be bridged from a remote
Tasmota device over HTTP (polling `Status 10`), completing the local/virtual/
bridge trio already used by other plugins (relay, relay_power now included).

Refactors the ENERGY-object parsing in Matter_Plugin_OnOff_Power into a
shared `_parse_energy()` helper used by both `parse_sensors()` (local device)
and the new `parse_status()` override (bridge, index 10 / Status 10), and
guards `parse_sensors()` against BRIDGE instances so a bridge endpoint never
reads the local gateway's own ENERGY sensor by mistake.

Registers the new solidified header in be_matter_module.c (missed this for
the previous two plugin files, which broke CI) and adds http_relay_power to
the bridge type dropdown in Matter_UI.be.

Verified with a full PlatformIO build for tasmota32s3 (SUCCESS).

* Matter: auto-detect relay_power on remote bridge devices with an ENERGY sensor

The "Add Remote sensor or device" auto-detection always suggested plain
light0/relay for every detected relay channel, even when the remote device
reports an ENERGY sensor (e.g. a NOUS A5T 4-outlet power strip with a single
shared CSE7766 meter) - so relay+power devices showed up as plain "Light 0
OnOff" with no way to pick relay_power from that screen (the type column is
static text for already-detected rows, only editable for a brand new blank
row).

generate_config_from_status() now tags the first detected relay as
relay_power when ENERGY is present, leaving the rest as plain relays: most
Tasmota energy-monitoring boards have a single meter for the whole device,
not one per relay, so duplicating the cluster across every channel would
misleadingly show the same aggregate reading on each endpoint.

* Matter: compose Electrical Sensor device type onto the power-monitoring plug

Adds device type 0x0510 (Electrical Sensor) alongside 0x010A (On/Off
Plug-in Unit) on the same endpoint for relay_power/v_relay_power/
http_relay_power, plus the mandatory Power Topology cluster (0x009C) with
the NODE feature (this single ENERGY sensor meters the whole device, not a
subset of endpoints - matches Tasmota's non-indexed ENERGY object).

Matches the Matter 1.4.1 Device Library requirement that Electrical Power
Measurement lives on an Electrical Sensor device type, while keeping the
cluster on the plug's own endpoint (composed DeviceTypeList) rather than a
separate endpoint, since controllers only recognize the measurement
capability when the Electrical Sensor device type is actually declared.

Verified on real ESP32-S3 hardware via chip-tool: endpoint 2 now reports
DeviceTypeList = [266 (On/Off Plug-in Unit), 1296/0x0510 (Electrical
Sensor), 19 (Bridged Node)], and Power Topology FeatureMap = 1 (NODE).

---------

Co-authored-by: Ludovic BOUÉ <938089+lboue@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-27 15:35:46 +02:00
John Murfett b0c8e4f53f DALI-2 push button bindings to control gear targets (DaliBind) (#25073)
* DALI: bind DALI-2 push button events to control gear targets

Add command DaliBind<1..8> <device>,<instance>,<target>,<mode> to link
push button events (IEC 62386-301) from an input device instance to a
control gear target. Modes are Toggle, On, Off, Up and Down; Up and Down
start a fade on button press and stop it on release. The first matching
binding is executed. DaliBind<x> 0 removes a binding and DaliBind alone
lists them all.

Bindings are stored in the DALI settings file, packed as one uint32 per
slot, so they survive a restart.

* Describe how start-up brightness stored differently per short addres vs dali groups
2026-09-27 15:33:18 +02:00
Theo Arends cadd9a5612 Update change logs 2026-09-27 15:24:00 +02:00
Jason2866 a622f395d4 fix: be_matter_module.c:280:19: error: #if with no expression (#25075) 2026-09-27 14:37:51 +02:00
Jason2866 300b3bfb9a Platform 2026.09.50 Tasmota Arduino Core 3.3.12 based on IDF 5.5.5 (#25072) 2026-09-26 18:39:45 +02:00
Theo Arends e0ee732bac Bump version v15.6.0.2 2026-09-26 17:24:39 +02:00
Erin of Yukis a3394ba0aa Shutter: Split EnableEndStopTime into OpenEndStopTime and CloseEndStopTime (#25020)
Allows adding the extra 1s recalibration time only when opening or only when
closing, does not make the 1s number configurable.
2026-09-26 16:59:18 +02:00
Bogdan ShatikandClaude Sonnet 5 4bdce61d93 RC522: throttle idle polling and add self-healing watchdog (#25052)
Two independent reliability fixes for the MFRC522 driver, found while
debugging a real device:

- LoadAvg climbing toward its ceiling: idle polling every 250ms was
  hitting the reader's own ~25ms internal REQA timeout every time
  (PCD_CommunicateWithPICC busy-waits synchronously with no yield()
  until TReloadReg's on-chip timer fires), i.e. a permanent ~10% duty
  cycle from polling alone. Throttles idle polling to roughly once a
  second and shortens the on-chip poll timeout via TReloadReg
  (RC522ShortenPollTimeout, ~2.5ms instead of 25ms - still well above
  a real tag's few-hundred-microsecond ISO14443A response time), an
  order of magnitude cheaper without hurting detection reliability.
  Also added exponential backoff as a safety net if a poll is ever
  genuinely slow (e.g. RF noise triggering the anticollision path).

- Reader silently stopping card detection after a few reads, only
  recoverable with a manual reset: traced to MIFARE_Authenticate
  (used by USE_RC522_DATA_FUNCTION) occasionally leaving the crypto1
  cipher engine stuck engaged, which garbles all further card
  communication even though simple register reads keep succeeding.
  Added a 1s watchdog that checks two registers that reveal this
  broken-but-alive state - Status2Reg's MFCrypto1On bit and
  TxControlReg's antenna-field bits - and does a full PCD_Reset()+
  PCD_Init() the moment either looks wrong, rather than waiting for a
  user to notice and run RC522Reset. Toggle with RC522Watchdog 0/1
  (on by default); new RC522Status field, "Healthy", reports the same
  check on demand.

Also stopped calling PCD_PerformSelfTest() at init - it resets the
chip and writes test patterns into several registers, needing a full
re-init to undo (the library's own docs note "self-test blows init").
A plain VersionReg read is already a reliable presence check without
that risk.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 16:58:41 +02:00
s-hadinger a8d91f4acb MQTT tolerate delayed PINGRESP (#25067)
* MQTT tolerate delayed PINGRESP

* Add default MQTT_MAX_PING_OUTSTANDING
2026-09-26 16:37:52 +02:00
s-hadinger 830cb206cc Doc detailed (#25071)
* Draft 1

* Add ESP32C5

* MCUs bold

* Matter protocol
2026-09-26 15:21:28 +02:00
s-hadinger f151ad8145 Fix Matter commissioning mDNS announcements (#25069) 2026-09-26 15:18:39 +02:00
SteWers f79b26cb5d Improve tooltip on touch devices and provide BSSID to Berry (#25057)
* Improve tooltip on touch devices and provide SSID to Berry

* Improve rendering of battery symbol
2026-09-25 20:06:53 +02:00
s-hadinger ad1addfd4e Touch GT911 fix template (#25068) 2026-09-25 15:14:48 +02:00
s-hadinger 5bb6c38cfb Fix Berry parsing from upstream (#25064) 2026-09-24 19:21:33 +02:00
Theo Arends e5d9a568cb Undocumented command DaliRetry 0..64 to test target probe (#25035) 2026-09-22 17:17:25 +02:00
Theo Arends cba5a24da6 Change command SetOption46 201..255 init wait 1 to 55 seconds instead of 2010 to 2550 msec (#25035) 2026-09-22 16:09:13 +02:00
Theo Arends fbe502840e Update change logs 2026-09-22 15:04:10 +02:00
s-hadinger b945c1469c Fix WT32_ETH01 initialization (#25051) 2026-09-22 10:33:44 +02:00
Yvan JanssensandClaude Fable 5.1 d8f0d14005 MI32: add Xiaomi Mi Body Composition Scale (MIBCS/MIBFS) support (#25049)
Decode the 13-byte body composition record the scale broadcasts as
service data for UUID 0x181B (also sent as 0x2A9C notifications), and
register the scale as MI32 device type MIBCS with fake product ID 0x181b.

Per weighing session the driver publishes the weight once when the
scale's stable flag is set and the impedance once when the impedance
stable flag is set (repeating the weight so the message is self
contained). If the user steps off before a usable impedance arrives,
ImpedanceFailed:1 is published instead. A session ends on the finished
flag or after 10 s of silence, so repeated broadcasts of the final
record do not produce duplicate messages. Overload readings (0xFFF0)
and the impedance sentinels 0xFFFE/0xFFFD are ignored. The unit (kg,
lb, jin) is derived from the flag bits and published alongside.

Web UI: weight and impedance rows on the main page; with USE_MI_EXT_GUI
a dashboard tile with a 24 h weight history graph (kept in kg).

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 10:29:18 +02:00
Grzegorz cc02a727cd MiELHVAC: trim the web panel's state table, add an Error row (#25039)
* MiELHVAC: trim the state table to what the controls do not show, add Error

Set Temp, Mode, Fan, Vane V / H, Air Direction and Prohibit are dropped
from the read-only state table below the panel controls, they duplicated
the selector directly above each of them. Room Temp stays first, and an
Error row is added last, showing the same packed-BCD code SENSOR's
ErrorCode carries, with the spec's 8000 no-error code shown as "no"
instead of the number.

Also swapped the remaining semicolons in the driver's head doc block and
the state-table function comment for commas, per house style.

* MiELHVAC: add Timer On/Off to the state table, split Compressor and Frequency

Timer On and Timer Off (0x62 0x05, read-only) show as the last two rows of
the state table, the clock time each side fires at, the unit only reports
minutes remaining, so this adds Tasmota's local clock.

Compressor now shows on/off and Frequency (Hz) is its own row right after
it, instead of one row showing only the frequency.
2026-09-22 10:27:52 +02:00
John MurfettandClaude Fable 5.1 ae2c7f75ae Dali2 input device events (#25029)
* DALI: decode and publish DALI-2 input device event messages

Input devices such as push buttons (IEC 62386-301), occupancy sensors
(303) and light sensors (304) communicate with 24-bit event messages.
Tasmota logged these frames at log level 4 and discarded them, so it
could not react to any DALI-2 switch or sensor on the bus.

Decode the 24-bit frame according to the five IEC 62386-103 addressing
schemes and publish the result for rules and MQTT, for example

  {"DALI":{"Event":"0x82840B","Scheme":"Instance","Type":1,"Instance":1,
           "Info":11,"Name":"LongPressRepeat"}}

Push button events carry the part 301 event name, occupancy events the
Movement/Occupied/Repeat/Sensor flags and light sensor events the
Illuminance value. 24-bit frames with bit 16 set are commands from
another application controller and are ignored.

Tested with a zencontrol zc-switch rotary on an ESP32-S3-Pico with the
Waveshare Pico-DALI2, driving one channel of a DA4-T DT6 driver via
rules.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* DALI: commission DALI-2 control devices and query their instances

Control devices (IEC 62386-103) such as push buttons and sensors are
addressed with 24-bit frames and have their own short address space,
separate from control gear. Until now they could only be commissioned
by hand with raw DaliSend255 frames.

Add DaliDeviceScan 1|2[,<max_count>] which assigns short addresses using
the 24-bit INITIALISE / RANDOMISE / COMPARE / PROGRAM SHORT ADDRESS
sequence. The existing binary search used by DaliScan is shared through
a device flag so control gear commissioning is unchanged. Mode 2 probes
the bus first so addresses already in use are never reassigned.

Add DaliDevice which lists addressed control devices, reports one
device's version, status and instances (type, enabled, event scheme),
and sets the event scheme of all its instances, for example

  {"DaliDevice":{"Device":1,"Version":"2.0","Status":0,"Instances":[
    {"Instance":0,"Type":1,"Name":"PushButton","Enabled":1,"Scheme":"Instance"}]}}

Input devices default to the Instance event scheme which carries no
short address, so DaliDevice <device>,2 switches them to DeviceInstance
events that identify the sending device.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 10:27:23 +02:00
s-hadinger f55fe444d7 MQTT 5.0 with focus on request/response (optional) (#25050) 2026-09-22 10:24:51 +02:00
UBWH 61c57300a0 Update LHT52.be (#25042) 2026-09-21 18:13:08 +02:00
UBWH ae8459a3d5 Add hashCheck variable to LwDecoLDS02 class (#25041) 2026-09-21 18:12:56 +02:00
UBWH 400b5210b4 Add hashCheck variable to LwDecoDDS75LB class (#25040) 2026-09-21 18:12:40 +02:00
92b377f66d MiELHVAC: add Home Assistant MQTT discovery (#25027)
* MIELHVAC New features and bug fixes

## Changelog

### Bug Fixes

**Memory leak in `miel_hvac_pre_init()`** — `goto del` jumped past the `free(sc)` label, leaking the allocated struct on serial init failure. Replaced with explicit `delete`/`free`/`return`.

**`remotetemp_clear` semantics inverted** — variable was `true` on boot causing a CLR frame to be sent before any sensor registered. Renamed to `remotetemp_active`, initialised `false`.

**`HVACSetPurify` used wrong map** — `airdirection_map` was passed instead of `purifier_map`.

**`0x08` Set Run State flags wrong byte order** — flags are little-endian on the wire (ref: muart-group/muart-group.github.io#17). Removed `htons()` from all `0x08` flag assignments.

**`widevane_isee` false positives** — values like `0x84`/`0x85`/`0x8c` (ISEE bit + position nibble) incorrectly reported `AirDirection:"even"`. Reverted to exact-match for `0x80`, `0x28`, `0xaa`.

---

### New Features

**`0x42` HVAC Options polling** — added `miel_hvac_data_hvac_options` struct and `MIEL_HVAC_REQUEST_HVAC_OPTIONS` request. The unit is polled for Purifier, NightMode and EconoCool state. Requires short request form (len=1). Results stored in `sc_hvac_options` and published in SENSOR and HVACSETTINGS when `cap_run_state=true`.

**Run State commands (`0x41 0x08`)** — new commands `HVACSetPurify`, `HVACSetNightMode`, `HVACSetEconoCool` and `HVACSetAirDirection` sent via `0x08` on units that report `cap_run_state=true`. Optimistic update to `sc_hvac_options` applied before confirmation.

**EconoCool** — `0x08` byte 14, flag `0x10`, COOL mode only. Command `HVACSetEconoCool on|off`.

**Base Capabilities (`0x5B 0xC9`)** — queried once after connecting. Parsed into `miel_hvac_capabilities`. Results published flat inside `MiElHVAC` as `*Supported` fields. Temperature ranges published as °C. Raw packet in `CapabilitiesHex`.

**Capabilities-aware command validation** — commands blocked when unit reports feature unavailable: modes (heat/dry/fan), temperature range from capabilities, fan speeds, run state commands return `NotSupported` or `ControlNotSupported`.

**`0x42` polling skip** — skipped on units with `cap_run_state=false`, eliminating recurring timeouts.

**`miel_hvac_append_settings_json()`** — shared helper replacing ~80 lines of duplicated JSON code between SENSOR and HVACSETTINGS topics.

---

### JSON Changes

- `Power` (W) and `Energy` (kWh) published inside `MiElHVAC` and also in a separate `ENERGY{}` object outside `MiElHVAC` for Home Assistant auto-discovery
- `Purifier`, `NightMode`, `EconoCool` shown in SENSOR and HVACSETTINGS when `cap_run_state=true`; otherwise omitted
- `AirDirection` always shows current state from `0x62 0x02` regardless of control support
- `*Supported` capability fields published flat inside `MiElHVAC`: `HeatSupported`, `DrySupported`, `FanSupported`, `VaneVSupported`, `SwingSupported`, `AutoFanSupported`, `OutdoorTempSupported`, `AirDirectionSupported`, `PurifierSupported`, `NightModeSupported`, `EconoCoolSupported`

---

### Tested on
MSZ-LN25VG2W — `cap_run_state=false`, temp ranges 16–31 °C cool/auto, 10–31 °C heat, 5 fan speeds.

* Extend AirDirection capability, added web ui energy sensor, cleanup

### AirDirection — respect i-See sensor presence

`AirDirection` now requires three conditions instead of just the vertical vane capability:
- `cap_vane_v` — unit has a vertical vane
- `sc_has_isee` — i-See sensor observed at runtime (widevane ever seen with bit `0x80`, or value `0x28`/`0xaa`)
- `cap_run_state` — unit supports `0x08` for control

Resulting behaviour:

| `cap_vane_v` | `sc_has_isee` | `cap_run_state` | `AirDirection` visible | `AirDirectionSupported` |
|:-:|:-:|:-:|:-:|:-:|
| ❌ | — | — | hidden | `not_supported` |
| ✅ | ❌ | — | hidden | `not_supported` |
| ✅ | ✅ | ❌ | shown | `control_not_supported` |
| ✅ | ✅ | ✅ | shown | `on` |

Units with vertical + horizontal vanes but no i-See sensor now correctly report `AirDirectionSupported:"not_supported"` and omit `AirDirection` from both `MiElHVAC` and `HVACSettings` JSON.

### Capability field renames

For naming consistency across the `*Supported` fields:
- `cap_heat` → `cap_mode_heat`, `HeatSupported` → `ModeHeatSupported`
- `cap_dry` → `cap_mode_dry`, `DrySupported` → `ModeDrySupported`
- `cap_fan_mode` → `cap_mode_fan`, `FanSupported` → `ModeFanSupported`
- `cap_auto_fan` → `cap_fan_auto`, `AutoFanSupported` → `FanAutoSupported`
- `OutdoorTempSupported` → `OutdoorTemperatureSupported`
- `TempCool` / `TempHeat` / `TempAuto` → `SetTemperatureCoolMinMax` / `SetTemperatureHeatMinMax` / `SetTemperatureAutoMinMax`

### Energy values

- `Power` (W) and `Energy` (kWh) published both inside `MiElHVAC` and in a standard Tasmota `ENERGY{}` sub-object (`Power`/`Total`) for Home Assistant auto-discovery.
- Added Web UI rows via `FUNC_WEB_SENSOR` showing instantaneous power (W) and cumulative total (kWh) on the Tasmota main page.

### Runtime i-See detection

New `sc_has_isee` flag in `miel_hvac_softc`, set in `miel_hvac_input_settings` on the first widevane value indicating i-See state. Once set, stays set for the session.

**Practical note:** after boot, the flag starts `false`. Units with i-See that has never been activated since Tasmota started will show `AirDirection` as hidden until i-See is first used (via IR remote or `HVACSetAirDirection`). Safe default — prevents showing misleading values on units without i-See.

* MiElHVAC Full support of AirDirection control

* MiELHVAC fix globals, VLA, duplicate JSON fields and float formatting

## Summary

- **Remove file-scope globals** (`temp_type`, `remotetemp_active`,
  `remotetemp_auto_clear_time`, `remotetemp_last_call_time`,
  `remotetemp_half`): moved into `miel_hvac_softc` as `sc_temp_type`
  and `sc_remotetemp_*`. All references updated. Eliminates potential
  conflict with other drivers sharing the same translation unit.

- **Fix VLA in `miel_hvac_send`**: `char hex_d[(len + 1) * 2]` replaced
  with fixed-size `(MIEL_HVAC_DATABUFLEN + 1) * 2`. Variable-length
  arrays on the stack are disallowed by `-Wvla` and unreliable on
  embedded targets.

- **Make `temp_type` explicit**: helper functions `miel_hvac_deg2temp`,
  `miel_hvac_temp2deg`, `miel_hvac_roomtemp2deg` now take `bool
  temp_type` as a parameter. Detection of the extended encoding moved
  from render functions to `miel_hvac_input_data()`, removing a hidden
  side effect inside JSON serialisation code.

- **Remove duplicate JSON fields**: `Purifier`, `NightMode`, `EconoCool`
  were emitted twice (from both the settings block and the options
  block). Options block now only emits `OptionsHex`.

- **Fix `RemoteTemperatureSensorAutoClearTime` JSON type**: was
  serialised as a string (`"10000"`), now a proper JSON number (`10000`).

- **Bool consistency**: assignments `= 1` / `= 0` on `bool` fields
  replaced with `= true` / `= false`.

* MiElHVAC auto-enable i-See widevane when setting AirDirection

### Problem
`HVACSetAirDirection` (`indirect` / `direct` / `even`) sets the i-See airflow
direction via a `0x41 0x08` runstate packet (flag `0x2000`). The unit only
honors that value once i-See airflow control is enabled, which requires
`widevane=0x80` sent in a `0x01` settings packet.

Until now the user had to manually run `HVACSetWideVane isee` **before**
`HVACSetAirDirection`, otherwise the direction change was silently ignored.

### Change
`HVACSetAirDirection` now sets the widevane to
`MIEL_HVAC_SETTINGS_WIDEVANE_ISEE` (`0x80`) in the same call.

The dispatcher always sends the settings (`0x01`) packet before the runstate
(`0x41`) packet, so the unit receives the i-See enable first and the direction
value on the following tick — no manual ordering required.

### Notes
- `off` is unchanged (still expressed as `widevane=0x8c` via `0x01`).
- The existing capability guard (`cap_vane_v` + `sc_has_isee`) is unchanged.

* Fix GPIO name table offset from duplicate MODBUSRELAY entry

kSensorNames had the four D_MODBUSRELAY_* tokens twice while the
UserSelectablePins enum lists GPIO_MODBUSRELAY_* once, shifting every
following name by four - the GPIO dropdown showed MiEl HVAC MB Tx/Rx/DE
and CC1101 CS as 'MbsRelay ...'. Drop the duplicate row.

* MiEL HVAC accept fan_only as alias for fan mode

Home Assistant's climate integration uses 'fan_only'; map it to the same
value as 'fan' so HVACSetMode/HVACSetHAMode accept it. Reporting is
unchanged (miel_hvac_map_byval still returns 'fan').

* MiEL HVAC Modbus: mirror sensor values on FC03 holding registers

Add holding registers 0x0010..0x0017 as read-only mirrors of room
temperature, compressor, instantaneous power, stage operation/fan/mode
and the requests/CRC-error diagnostic counters, so a master that only
speaks FC03 can read them. Writes to these addresses still return
exception 0x02.

* MiEL HVAC Modbus: start FC03 mirror block at 0x000f, no gap after control block

* MiEL HVAC Modbus: queue writes when HVAC link is not up yet

Return to the master with a normal response and queue the update
(same as the HVACSet* console commands) instead of Modbus exception
0x04, so a PLC can pre-load settings and bench testing works without
the AC connected.

* MiEL HVAC Modbus: frame incoming requests by length, not the T3.5 gap

A FUNC_LOOP poll cannot measure the 3.5-char inter-frame gap reliably
above 9600 baud, so a frame split across two polls was processed as two
truncated frames (CRC error count exceeded the request count on a busy
19200 8E1 bus). Compute the expected request length from the function
code and dispatch as soon as it is buffered; keep the idle gap only to
flush a stuck partial frame or retry an unknown function code. Also skip
requests addressed to other slaves without a CRC check.

* MiEL HVAC Modbus: byte-level resync, larger RX buffer, no flush on auto-direction

CrcErrors was still ~1:1 with Requests on a busy 19200 8E1 multi-drop bus.
- resync one byte at a time on a framing/CRC mismatch instead of dropping
  the whole assumed frame and waiting for bus idle
- only count a CRC error when the frame claims our own address
- 1 kB RX buffer so a late FUNC_LOOP poll does not lose bytes to a UART
  FIFO overflow (TasmotaSerial cannot report the overflow on ESP32)
- bulk serial read instead of byte-at-a-time
- skip flush() when no DE pin is configured - on ESP32 flush() also
  discards the RX buffer, dropping the next request on a shared bus

* MiEL HVAC Modbus: add link status to the FC03 sensor mirror

Holding register 0x0017 (PLC 40024) mirrors input 0x0001 - connected to
the HVAC unit (0/1).

* MiEL HVAC Modbus: wait the RTU turnaround silence before answering

Intermittent corrupted responses (master saw e.g. 80 C8 ...) on an
auto-direction transceiver at 19200: the slave started transmitting
before the master's line had turned around. Hold quiet for up to 3.5
char times after the last received byte before sending the response.
Track the last-byte time per read so the wait is accurate.

* MiEL HVAC Modbus: do not send a late reply once the master has re-polled

When a FUNC_LOOP stall makes the response miss the master's timeout
(Siemens S7 MB_MASTER STATUS 0x80C8), a newer request is already
buffered behind the stale one. Apply the stale request but skip its
response so it cannot land on the master's next transaction and make
that one time out too.

* MiEL HVAC Modbus: strip the i-See bit from the swingH register

Input 0x0015 / holding 0x0005 (40006) returned the raw wide-vane byte,
so a unit with an i-See sensor reported e.g. 131 (0x83 = 0x80 | center).
Report the position only (1..8, 12), or 0x80 when the byte encodes
i-See direction mode - matching the SwingH field in the SENSOR JSON.

* MiEL HVAC: document the driver and Modbus slave in the file header

Move the Modbus RTU slave detail out of the changelog into a doc block
at the head of xdrv_44_miel_hvac.ino, per the PR #24993 review.

* MiELHVAC: add Home Assistant MQTT discovery

Publishes a single retained "climate" entity covering mode, current/target
temperature, fan speed, action, vertical swing, horizontal swing/widevane
and air direction (as a preset), the same layout as a manually written
climate: YAML config, so the device appears in Home Assistant without any
manual configuration. Republishes on every MQTT (re)connect and honors
SetOption19 like the rest of Tasmota's HA discovery.

Fan speed, both swing controls and air direction use Jinja dict templates
to show capitalized display labels (e.g. "Up Middle") while still sending
the driver's own lower_snake_case values over MQTT. The web control panel's
own labels are updated to match, it previously used "Up-Middle" style
hyphens for these, inconsistent with the discovery config.

Widevane's "I-See" position is a read-back of air direction control being
active, not a directly settable vane position, so it's only listed once
the unit is known to support it, and selecting it now re-engages air
direction at the last active direction instead of sending a widevane byte
the unit won't act on. The same option and behavior are now available in
the web control panel, which previously hid "I-See" unconditionally.

Also adds a computed "HAAction" SENSOR field (heating/cooling/drying/fan/
idle/defrosting/preheating/off), using the Stage packet's OperationStage
(standby/defrost/preheat) as well as HAMode, so the discovery config
doesn't need to derive it with a template and HA gets the more specific
action whenever the unit reports one.

The combined discovery payload does not fit under Tasmota's default
MQTT_MAX_PACKET_SIZE (1200 bytes), so my_user_config.h raises it to 4096.

* MiELHVAC: expose HA discovery capabilities dynamically

Build fan_modes from cap_fan_auto and the C9-reported fan count instead
of a fixed list, drop Quiet from MQTT since some CN105 units report an
IR-selected Quiet back as fan speed 1, and gate the AirDirection preset
on isee_capable so it is only advertised on units that actually support
it. Republish discovery once C9 capabilities and i-See are known, not
just on MQTT connect, since TasRediscover only re-runs Tasmota's native
discovery and never this driver's custom HA payload.

Based on a suggestion from mamrai1 in grzegorz914/Tasmota#2.

* MiELHVAC: also hide Quiet in the web panel fan speed selector

The web control panel's Fan speed dropdown still offered Quiet whenever
the unit reported 5 fan speeds. Since some CN105 units report an
IR-selected Quiet back as fan speed 1, hide it unconditionally there
too, matching the HA discovery fan_modes list.

* MiELHVAC: make web panel and MQTT discovery use the same capability gates

The web panel's AirDirection control, its widevane I-See option, the
readout row and the SENSOR JSON AirDirection field all defaulted to
shown until capabilities proved otherwise, while HA discovery's
preset_modes/isee_capable gate defaulted to hidden until proven
supported. Standardize all of them on the stricter confirmed-capable
gate so MQTT and the web panel never disagree about whether AirDirection
is available.

Also cap the web panel's Fan speed 2 and 3 options to the C9-reported
fan count, matching the numbered-speed cap already applied to the HA
discovery fan_modes list (only speed 4 was capped there before).

* MiELHVAC: order horizontal vane positions left-to-right

swing_horizontal_modes (HA discovery) and the web panel's Vane
horizontal select listed positions in raw protocol byte order
(left, left_middle, center, right_middle, right, left_center,
right_center), which reads oddly in a dropdown. Reorder both, and
the backing miel_hvac_widevane_map, to the physical left-to-right
order: left, left_middle, left_center, center, right_center,
right_middle, right, then split/swing/isee.

* MiELHVAC: restore capability-gated Quiet instead of removing it outright

Unconditionally dropping Quiet from fan_modes assumed CN105 units
universally can't distinguish a Quiet selection from fan speed 1 on
readback. Testing on a real unit that reports 5 fan speeds (Auto,
Quiet, 1-4) showed Quiet works correctly and reports back reliably,
so removing it lost a real, working mode.

Gate Quiet on fan_count == 5 instead, the same threshold SetFanSpeed
already enforces when rejecting the command -- both HA discovery's
fan_modes/fan_mode_state_template/fan_mode_command_template and the
web panel's Fan speed selector now only expose Quiet once the C9
capabilities response confirms the unit actually has it.

* MiELHVAC: add Home Assistant MQTT discovery for Prohibit

Publish the Prohibit / remote-control lock as a separate select entity
(homeassistant/select/<id>_prohibit/config), mirroring the web panel's
Prohibit dropdown -- climate entities have no native lockout concept.
Clear its retained config alongside the climate entity's when SetOption19
disables discovery.

Based on a suggestion from mamrai1 in grzegorz914/Tasmota#2.

* MiELHVAC: document why Prohibit's entity_category hides it from Area cards

Note in the code that entity_category "config" is a deliberate choice,
not an oversight -- HA excludes config/diagnostic entities from the
Area dashboard's auto-generated card even once an Area is assigned,
by design. The entity stays reachable from the device page and
Settings > Areas.

* MiELHVAC: document confirmed dual-vane widevane behavior, no renames

Tested against a real MSZ-LN unit: left/center/right/split/swing move
both horizontal vanes together, while the *_middle/*_center values
move only one vane independently. Considered relabeling raw 4/5 and
6/7 based on mUART's protocol docs (which describe a single continuous
left-right axis plus generic "Split" combinations), but that scheme
does not match this unit's actual behavior, and there is no capability
bit indicating vane count or per-side behavior to detect which scheme
applies on a given unit. Document the confirmed behavior as
model-specific instead of renaming, to avoid baking in an assumption
that breaks a different model.

* MiELHVAC: swap right/right_middle labels to match actual vane extremes

Confirmed by testing: WIDEVANE_RR (0x05) drives the right vane to its
furthest-right extreme (single vane only), while WIDEVANE_R (0x04)
moves both vanes together to a lesser right-ward position. The
previous naming had this backwards -- "right" pointed at the lesser,
synchronized position and "right_middle" at the extreme one.

Swap the two labels in miel_hvac_widevane_map so "right" means the
same thing intuitively on both sides: the furthest position, matching
how "left" already refers to the full-left extreme. HA discovery and
the web panel need no changes -- they key off these string names, not
the raw byte values, so they pick up the corrected mapping
automatically.

* MiELHVAC: fix web panel never showing I-See as the current Vane horizontal

The web panel's "Vane horizontal" selector passed set->widevane masked
with MIEL_HVAC_SETTINGS_WIDEVANE_MASK (0x0f) as the current value, but
i-See is signaled by the high bit (0x80) or one of two odd raw values
(0x28/0xaa) seen in the wild -- none of which survive that mask. The
dropdown could therefore never show I-See as selected, even right
after engaging AirDirection (which sets widevane to exactly 0x80).

Compute the same wv_isee check already used correctly elsewhere in
this function (readout rows, Air Direction control) before masking,
and share it between the Vane horizontal selector and the Air
Direction block below it.

* MiELHVAC: fix live-sync never updating Vane horizontal when I-See engages

Same class of bug as the earlier "Vane horizontal never shows I-See as
selected" fix, in a different spot: the JS live-sync path in
miel_hvac_web_readout() (which pushes S('hvh', ...) updates into the
already-rendered web panel without a full reload, skipping controls
the user has focused) computed wn as NULL whenever i-See was active,
so the S('hvh', ...) call was skipped entirely and the selector was
left showing its last non-i-See value instead of updating live.

* MiELHVAC: gate MQTT_MAX_PACKET_SIZE bump on USE_MIEL_HVAC

Raising MQTT_MAX_PACKET_SIZE to 4096 in my_user_config.h applied to
every build regardless of whether MiELHVAC was even enabled, costing
every other user extra RAM for a buffer only this driver's Home
Assistant discovery payload needs. Wrap it in #ifdef USE_MIEL_HVAC,
placed after the user_config_override.h include so the driver's own
enable flag is already visible, keeping the 1200 byte default for
everyone else.

Addresses maintainer review feedback from arendst on PR #25027.

* Update xdrv_44_miel_hvac.ino

* MiELHVAC: document confirmed vaneH split/sync behavior precisely

Update the widevane_map comment with the fully confirmed picture from
testing: left/left_middle/center/right_middle/right/split/swing move
both vanes together to that position, while left_center and
right_center are asymmetric splits (left_center puts the left vane at
the left_middle angle and the right vane at center, right_center
mirrors that). Earlier revisions of this comment described
left_middle/left_center as left-vane-only, which testing has now
superseded.

Also notes a second real unit (from a PR reviewer) showed yet another
variant, reinforcing that this is model-specific.

* MiELHVAC: no semicolons in prose comments

Replace two semicolons in the widevane_map doc comment, one with a
comma (continuing a single flowing clause), one with a period (a true
independent-clause boundary).

* MiELHVAC: fix cap_run_state gating, confirm Purifier/NightMode/EconoCool per option

cap_run_state (0xC9 byte 9 bit 0x10) turned out to be undocumented and
unreliable per mUART's own docs ("???", observed both true and false),
and this file's own struct comment even pointed at the wrong byte (6
instead of 9) for it. It was wrongly used to block the HVACSetPurify/
HVACSetNightMode/HVACSetEconoCool commands, the matching web panel
controls, and 0x42 polling itself outright, hiding these features even
on units that do support them.

Removed all cap_run_state-based gating. Purifier/NightMode/EconoCool
are now only reported once independently proven via a round trip: a Set
Run State request that actually asks for a different value than last
confirmed is armed, and the option is marked confirmed only if the next
genuine 0x42 response reads back exactly that requested value (not all
units that answer 0x42 support all three, so a single shared confirmed
flag was too coarse). No optimistic apply — these fields reflect the
unit's own confirmed state only, never what was just requested, since
on units where 0x42 never responds an optimistic guess would never get
corrected. The web panel only shows a button once its option is
confirmed; *Supported (capabilities) is the single source of truth for
support status, so the Settings block doesn't repeat "not_supported".

Also adds a debug-only HVACProbeRunState command (MIEL_HVAC_DEBUG-gated)
for sending an arbitrary flags/byte/value combination on the 0x08 Set
Run State surface, to correlate a raw packet with a physically observed
effect on real hardware rather than a 0x42 read-back that may never
arrive.

Verified against a real MSZ-LN unit whose 0xC9 fingerprint (byte 6/9 =
0x07/0x25) independently matches the "non-supporting" signature reported
in https://github.com/echavet/MitsubishiCN105ESPHome/discussions/366 —
0x42 never responds, Set Run State commands are ACKed but produce no
observable effect (including a buzzer test that works on other units),
and toggling these options via the physical remote does not leak into
any other polled response type either.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Update xdrv_44_miel_hvac.ino

Added a sensor for horizontal wide-vane support.

Horizontal wide-vane support is assumed to be available by default. If a requested horizontal vane position change is rejected by the unit, support is marked as unavailable and the horizontal wide-vane controls are hidden.

* MiELHVAC: add Home Assistant MQTT discovery for Purifier/NightMode/EconoCool

Publishes each as a separate switch entity, climate has no slot for
arbitrary on/off toggles. Each is only published once its own
round-trip-confirmed flag is set (sc_purifier_confirmed et al), matching
the SENSOR JSON and the web panel, both of which already gate on these
per-feature flags instead of the unreliable cap_run_state bit. Cleared
along with the climate entity and Prohibit select when SetOption19
disables discovery.

* MiELHVAC: document that SwingV only reports the right vertical vane

On dual-vertical-vane units (confirmed on MSZ-LN, remote has separate
Left/Right vertical vane buttons) the vane byte tracks only the right
vane. Confirmed by testing: setting left=up/right=down then
left=down/right=up gave the same final vane byte both times (matches
the right vane, not a combined state), changing only the right vane
moved the byte, changing only the left vane three times in a row left
every byte of the Settings packet unchanged. No other field in the
packet exposes the left vane either, this is the same class of gap as
Purifier/NightMode/EconoCool being settable from the remote but
unreported over CN105.

Documentation only, no behavior change.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: mamrai1 <57288344+mamrai1@users.noreply.github.com>
2026-09-21 18:11:39 +02:00
Gustavo Cateim c34a8ce467 fix(esp32): release UART0 console when the template uses its pins (#25047)
On ESP32-S3, C3 and C6 the command console falls back to UART0 when no
USB host is detected at boot. Those SoCs expose UART0 on ordinary GPIOs
(S3 43/44, C3/C6 20/21), so a template can assign them to another
function. UART0 then keeps driving those pads and silently corrupts
whatever the template put there.

Found on a KinCony AG8, where GPIO43 and GPIO44 are the MOSI and MISO of
the W5500. The ethernet chip is detected, since esp_eth_driver_install
reads its version register over SPI and succeeds, but the link never
comes up. Plugging a USB cable moves the console to CDC and the link
closes in 2.1 seconds, which isolates the console as the only variable.

GpioInit now releases the console with Serial.end() in the window after
SetPin has built the pin map and before SPI is configured, instead of
letting UART0 keep pads the template already owns. SerialLog 0 is not a
workaround: it only silences logging without freeing the pins, and
Serial.begin runs before the settings are loaded.
2026-09-21 18:11:07 +02:00
LesNewellandClaude Sonnet 5 8a7e815f6d Cap Berry GC threshold growth on PSRAM to avoid multi-second stalls (#25044)
Without this, threshold = usage * 2 (default steprate) lets PSRAM
heaps grow unbounded until a GC sweeps tens of thousands of objects
out of a nearly-full pool in one go, costing multiple seconds
(observed: 4.4s freeing 25k objects from a 2.6MB heap). Cap growth to
fixed increments instead, same as the non-PSRAM case, just scaled up
for the bigger heap.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 10:47:58 +02:00
Jason2866 0f8da17766 Change pioarduino dependency version to 6.1.19
Updated the PlatformIO Arduino dependency version to 6.1.19 in multiple steps.
2026-09-20 19:43:53 +02:00
Jason2866 ed1433d66b Change pioarduino installation to version 6.1.19
Updated pioarduino dependency version to 6.1.19 in multiple steps.
2026-09-20 19:41:52 +02:00
Jason2866 a8c3b20c6d Pin pioarduino version to 6.1.19 in workflows 2026-09-20 19:40:01 +02:00
UBWH 1180a5b994 Change default behaviour to hashCeck = disabled (#25037)
* Add support for LoRaWAN sensor discovery for Home Assistant

See https://github.com/arendst/Tasmota/discussions/24398#discussioncomment-15649631

* Introduce hashCheck to LwDecoDrgD20

Add hashCheck variable to LwDecoDrgD20 class.
2026-09-18 11:26:45 +02:00
UBWH e03a1b39b6 Add static variable hashCheck to LwDecoLHT65 class (#25034)
Added a static variable 'hashCheck' to the LwDecoLHT65 class.
2026-09-18 11:26:29 +02:00
UBWH aa73fd62a8 Add static hashCheck variable to LwDecoPSLI5 class (#25033)
Added a static variable 'hashCheck' to the LwDecoPSLI5 class.
2026-09-18 11:26:06 +02:00
UBWH 2ff79d3fd4 Add hashCheck variable to LwDecoSE01L class (#25032)
Added hashCheck variable to LwDecoSE01L class.
2026-09-18 11:25:52 +02:00
UBWH 9576343464 Add static hashCheck variable to LwDecoDrgSN50v3L class (#25031)
Added a static variable 'hashCheck' to the LwDecoDrgSN50v3L class.
2026-09-18 11:25:38 +02:00
Theo Arends 22079e531d Add uDisplay I2C contast control (DisplayDimmer) 2026-09-13 15:53:23 +02:00
SteWers 85d3e55c74 Fix regression from PR #25024 and enhance WiFi status line (#25026)
- Fix regression from PR #25024, which accidentally broke the layout and rendering of the WiFi configuration page,
- The WiFi status line now includes richer tooltip text with SSID, RSSI, and AP details.
2026-09-12 21:18:31 +02:00
Theo Arends cde8e62071 Restore default hostname %s functionality using topic name only, regression from v15.4.0.2 (#24731) 2026-09-12 15:15:11 +02:00
SteWers 946ba27108 Fix MI32 battery polling and period handling (#25024)
* Fix MI32 battery polling and period handling

- Add a dedicated hourly battery polling cycle for BLE devices, independent of the normal `MI32Period` / `TelePeriod` interval. This extends the battery life of the BLE devices, especially the LYWSD02MMC.
- Avoid redundant active reads for LYWSD02/03 sensors.
- `lastTime` is updated whenever temperature, humidity, or battery data is received.
- `MI32Period 1` correctly resets internal counters and trigger an immediate active polling cycle.
- `MI32Period 0` now correctly disables the active polling.
- Add device type to the title.

* Fix pollSeconds

* Multiline tooltip formatting

Split tooltip in two lines.
Adjust tooltip CSS to allow manual line breaks on mobile devices.

* Optimize tooltip position

* Update HTTP_HEAD_STYLE_TOOLTIP.h
2026-09-12 12:22:59 +02:00
Theo Arends 5e329df152 Add SSD1306 SPI display description 2026-09-11 11:18:44 +02:00
Theo Arends 50d9e8a13c Add support for M5Stack Unit6CL display 2026-09-11 09:50:05 +02:00
SteWers 5ef80a538e [MI32BLE] Add LYWSD02MMC unit/battery support (#25022) 2026-09-11 08:47:55 +02:00
SteWers 130d5342b1 [MI32BLE] Improve logging and command responses (#25021) 2026-09-10 13:33:46 +02:00
SteWers 9068fd7313 Store BLE security bonds in UfsJsonSettings (#25015)
* Store BLE security bonds in UfsJsonSettings

Store BLE security bonds in `UfsJsonSettings`, as promised in PR #25008

* Optimize LTK storage
2026-09-10 13:24:41 +02:00
Theo Arends d96c10dbad Fix Config Backup for Shutters on ESP32 (#25016) 2026-09-09 12:11:13 +02:00
Theo Arends bf5d60e3dc Use Tasmota seperator function 2026-09-09 11:25:36 +02:00
SteWers 211691d5fb [MI32BLE] Change RSSI to general format (#25014)
* [MI32BLE] Change RSSI to general format

Change RSSI to general format `xx% (-yy dBm)`

* Separate type
2026-09-08 09:12:36 +02:00