Repository: XKNX/xknx
Pull request #1685 (2025-05-11 19:05:24)

Fix flipped DPT 235.001 data validity bits
<!--
  You are awesome! Thanks for contributing to our project!
  Please, DO NOT DELETE ANY TEXT from this template!.
-->
## Description
<!--
Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context.
List any dependencies that are required for this change.
-->
Fix DPT 235.001 validation check.
When we look at the specifications : 
![DPT235.001 spec](https://user-images.githubusercontent.com/10090794/208304366-843c6c51-d2e9-4af5-a133-ad0a8e516d23.png)

We can see that validation bits are at 1 when data is **_not_** valid.
Current check does the opposite, checking if it has 1 value to consider them as valid


Fixes # (issue)

## Type of change
<!--
Please tick the applicable options.
NOTE: Ticking multiple options most likely indicates
that your change is to big and it is suggested to split it into several smaller PRs.
-->

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Code quality improvements to existing code or addition of tests

## Checklist

- [ ] The documentation has been adjusted accordingly
- [ ] Tests have been added that prove the fix is effective or that the feature works
- [ ] The changes are documented in the changelog (docs/changelog.md)

NHanser: @farmio thanks for the review, I definitely did it too quickly....should be fixed now
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/XKNX/xknx/pull/1685?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 97.32%. Comparing base [(`007140c`)](https://app.codecov.io/gh/XKNX/xknx/commit/007140c038c96d1aeaad106d913a4028d4f2d763?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) to head [(`c988007`)](https://app.codecov.io/gh/XKNX/xknx/commit/c988007763807b42270e345e2a7ba7d949885703?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX).

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/XKNX/xknx/pull/1685/graphs/tree.svg?width=650&height=150&src=pr&token=irWbIygS84&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)](https://app.codecov.io/gh/XKNX/xknx/pull/1685?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)

```diff
@@           Coverage Diff           @@
##             main    #1685   +/-   ##
=======================================
  Coverage   97.32%   97.32%           
=======================================
  Files         160      160           
  Lines       10749    10749           
=======================================
  Hits        10462    10462           
  Misses        287      287           
```

| [Files with missing lines](https://app.codecov.io/gh/XKNX/xknx/pull/1685?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) | Coverage Δ | |
|---|---|---|
| [xknx/dpt/dpt\_235.py](https://app.codecov.io/gh/XKNX/xknx/pull/1685?src=pr&el=tree&filepath=xknx%2Fdpt%2Fdpt_235.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9kcHQvZHB0XzIzNS5weQ==) | `100.00% <100.00%> (ø)` | |

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>

Patch:
diff --git a/xknx/dpt/dpt_235.py b/xknx/dpt/dpt_235.py
index ee51d762..244cc38c 100644
--- a/xknx/dpt/dpt_235.py
+++ b/xknx/dpt/dpt_235.py
@@ -65,8 +65,8 @@ class DPTTariffActiveEnergy(DPTComplex[TariffActiveEnergy]):
     def from_knx(cls, payload: DPTArray | DPTBinary) -> TariffActiveEnergy:
         """Parse/deserialize from KNX/IP raw data."""
         raw = cls.validate_payload(payload)
-        energy_valid = raw[5] >> 1 & 0b1
-        tariff_valid = raw[5] & 0b1
+        energy_valid = (raw[5] >> 1 & 0b1) == 0
+        tariff_valid = (raw[5] & 0b1) == 0
         return TariffActiveEnergy(
             energy=(
                 DPTActiveEnergy.from_knx(DPTArray(raw[:4])) if energy_valid else None
@@ -89,6 +89,6 @@ class DPTTariffActiveEnergy(DPTComplex[TariffActiveEnergy]):
             (
                 *energy,
                 *tariff,
-                (value.energy is not None) << 1 | (value.tariff is not None),
+                (value.energy is None) << 1 | (value.tariff is None),
             )
         )


Test patch:
diff --git a/test/dpt_tests/dpt_235_tariff_active_energy_test.py b/test/dpt_tests/dpt_235_tariff_active_energy_test.py
index fcca7a1c..3bbbc2f2 100644
--- a/test/dpt_tests/dpt_235_tariff_active_energy_test.py
+++ b/test/dpt_tests/dpt_235_tariff_active_energy_test.py
@@ -69,27 +69,27 @@ class TestDPTTariffActiveEnergy:
         [
             (
                 TariffActiveEnergy(0, 0),
-                (0x00, 0x00, 0x00, 0x00, 0x00, 0x03),
+                (0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
             ),  # zero values
             (
                 TariffActiveEnergy(-2_147_483_648, 0),
-                (0x80, 0x00, 0x00, 0x00, 0x00, 0x03),
+                (0x80, 0x00, 0x00, 0x00, 0x00, 0x00),
             ),  # min values
             (
                 TariffActiveEnergy(2_147_483_647, 254),
-                (0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x03),
+                (0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x00),
             ),  # max values
             (
                 TariffActiveEnergy(None, 0),
-                (0x00, 0x00, 0x00, 0x00, 0x00, 0x01),
+                (0x00, 0x00, 0x00, 0x00, 0x00, 0x02),
             ),  # energy None
             (
                 TariffActiveEnergy(0, None),
-                (0x00, 0x00, 0x00, 0x00, 0x00, 0x02),
+                (0x00, 0x00, 0x00, 0x00, 0x00, 0x01),
             ),  # tariff None
-            (TariffActiveEnergy(None, None), (0x00, 0x00, 0x00, 0x00, 0x00, 0x00)),
-            (TariffActiveEnergy(128, 128), (0x00, 0x00, 0x00, 0x80, 0x80, 0x03)),
-            (TariffActiveEnergy(204, 204), (0x00, 0x00, 0x00, 0xCC, 0xCC, 0x03)),
+            (TariffActiveEnergy(None, None), (0x00, 0x00, 0x00, 0x00, 0x00, 0x03)),
+            (TariffActiveEnergy(128, 128), (0x00, 0x00, 0x00, 0x80, 0x80, 0x00)),
+            (TariffActiveEnergy(204, 204), (0x00, 0x00, 0x00, 0xCC, 0xCC, 0x00)),
         ],
     )
     def test_dpt_tariff_active_energy_value(
@@ -103,8 +103,8 @@ class TestDPTTariffActiveEnergy:
     @pytest.mark.parametrize(
         ("value", "raw"),
         [
-            ({"tariff": 128, "energy": 128}, (0x00, 0x00, 0x00, 0x80, 0x80, 0x03)),
-            ({"tariff": 204, "energy": 204}, (0x00, 0x00, 0x00, 0xCC, 0xCC, 0x03)),
+            ({"tariff": 128, "energy": 128}, (0x00, 0x00, 0x00, 0x80, 0x80, 0x00)),
+            ({"tariff": 204, "energy": 204}, (0x00, 0x00, 0x00, 0xCC, 0xCC, 0x00)),
         ],
     )
     def test_dpt_tariff_active_energy_to_knx_from_dict(