Просмотр исходного кода

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>
Filip Tsachev 22 часов назад
Родитель
Сommit
2165fa72a4
1 измененных файлов с 63 добавлено и 0 удалено
  1. 63 0
      custom_components/tuya_local/devices/earu_dpn_circuitbreaker.yaml

+ 63 - 0
custom_components/tuya_local/devices/earu_dpn_circuitbreaker.yaml

@@ -53,3 +53,66 @@ entities:
         force: true
         mapping:
           - scale: 10
+  - entity: sensor
+    category: diagnostic
+    class: temperature
+    dps:
+      - id: 47
+        name: sensor
+        type: integer
+        unit: C
+        class: measurement
+        optional: true
+        force: true
+  - entity: binary_sensor
+    category: diagnostic
+    class: problem
+    dps:
+      - id: 26
+        type: bitfield
+        name: sensor
+        optional: true
+        force: true
+        mapping:
+          - dps_val: 0
+            value: false
+          - dps_val: null
+            value: false
+          - value: true
+      - id: 26
+        type: bitfield
+        name: fault_code
+        optional: true
+      - id: 26
+        type: bitfield
+        name: description
+        optional: true
+        mapping:
+          - dps_val: 0
+            value: ok
+          - dps_val: 1
+            value: over_current
+          - dps_val: 2
+            value: over_voltage
+          - dps_val: 4
+            value: over_power
+          - dps_val: 8
+            value: under_current
+          - dps_val: 16
+            value: under_voltage
+          - dps_val: 32
+            value: under_power
+          - dps_val: 64
+            value: short_circuit
+          - dps_val: 128
+            value: overload
+          - dps_val: 256
+            value: leakage_current
+          - dps_val: 512
+            value: self_test
+          - dps_val: 1024
+            value: high_temperature
+          - dps_val: 2048
+            value: phase_unbalance
+          - dps_val: 4096
+            value: phase_loss