earu_dpn_circuitbreaker: expose internal temperature (DP 47) and fault bitfield (DP 26) (#6275)
## What
The `earu_dpn_circuitbreaker` profile (EARU SW MCB, product id
`azpywu5zfg5wyzpn`) already matched and configured the device, but two
dps that the hardware reports were not exposed:
| DP | Tuya code | Now exposed as |
|----|-----------|----------------|
| 47 | `temp_value` | `sensor.temperature` (°C) |
| 26 | fault bitmap | `binary_sensor.problem`, with `fault_code` and
per-bit `description` attributes |
## Why `optional: true` on both
Per the repo's device-config rules, dps added to an existing config must
be marked `optional: true` so older variants of the same product that
don't report them still match this file. Without it, adding these two
would have made DP 47 and DP 26 *required* for matching, and any EARU SW
MCB lacking them would stop matching this config entirely.
## Why `force: true` on both
`tuya_local` only requests the dps listed in `force_dps` when
reconnecting (`device.py` → `updatedps(self._force_dps)`), so a
non-forced dp populates on the *first* connect (which fetches full
status) and then sits `unavailable` after every restart. The existing
voltage/current/power entries in this file already carry `force: true`
for exactly this reason; these two need it too.
This is not theoretical — it's what a first pass without `force` did:
the entities reported correctly until the next restart, then went
permanently `unavailable`.
## Fault bitfield
Follows the pattern used by e.g. `zmp71sh_pool_pump.yaml` /
`earu_eaemp3c100_energymeter.yaml`: `class: problem`, `0 → false` with
the default mapping to `true`, plus `fault_code` (raw bitmap) and a
`description` mapping.
DP 26 carries 13 bits, from the Tuya "Query Things Data Model" for this
product:
`ov_cr`, `ov_vol`, `ov_pwr`, `ls_cr`, `ls_vol`, `ls_pow`,
`short_circuit_alarm`, `overload_alarm`, `leakagecurr_alarm`,
`self_test_alarm`, `high_temp`, `unbalance_alarm`, `miss_phase_alarm`
mapped to `over_current`, `over_voltage`, `over_power`, `under_current`,
`under_voltage`, `under_power`, `short_circuit`, `overload`,
`leakage_current`, `self_test`, `high_temperature`, `phase_unbalance`,
`phase_loss`.
Note that only the first matching bit is reported in `description`
(standard behaviour for these bitfield mappings), so `fault_code` should
be used when the exact combination matters.
## Verification
- `uv run pytest tests/test_device_config.py` — 33 passed
- `uv run yamllint
custom_components/tuya_local/devices/earu_dpn_circuitbreaker.yaml` —
clean
- `uv run ruff check .`, `uv run ruff check --select=I .`, `uv run ruff
format --check .` — clean
- `prettier --check` on the changed file — clean
- `uv run duplicates earu_dpn_circuitbreaker.yaml` — best matches
`simple_multi_switch` / `pj1103_clamp_meter` at 57%, no 100% duplicate
Live on real hardware: two EARU SW MCB units reporting 32 °C idle with
all fault bits clear; DP 47/26 values confirmed against the device
directly over the LAN and cross-checked with the cloud data model.
---------
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Jason Rumney <make-all@users.noreply.github.com>