Skip to content

feat(light): support 2-digit Area 0 point-to-point addressing (01-09) (#684) - #713

Merged
GreenGrassBlueOcean merged 1 commit into
v2-phase1-architecturefrom
feat/issue-684-area0-point-lighting
Oct 14, 2026
Merged

GreenGrassBlueOcean merged 1 commit into
v2-phase1-architecturefrom
feat/issue-684-area0-point-lighting

Conversation

@GreenGrassBlueOcean

Copy link
Copy Markdown
Contributor

Resolves #684. Grounded in OpenWebNet-HA/own-firmware-oracle#35, OpenWebNet-HA/own-firmware-oracle#39, and firmware findings in MH200N/area0-lighting.md.
Builds upon and completes the trace fixture merged in #700 (tests/fixtures/traces/issue_684/physical_press_a0pl2_mh200.json).


What is the problem?

  1. Area 0 Light Points Assigned by Legrand Home + Project:
    Modern Legrand Eliot / Home + Project installations (e.g. paired with F460, F411/4, or MyHomeServer1) assign light point actuators starting at Area 0: A=0, PL=1, A=0, PL=2, etc.

  2. Rejection of 4-Digit Forms (0001–0009) by Gateway Firmware:
    Historically, is_apl_address() assumed Area 0 was represented exclusively as 4-digit APL (0001–0015). However, empirical testing across all 10 catalogued Linux gateways under QEMU emulation in own-firmware-oracle revealed that 4-digit zero-padded forms (*1*1*0001##, *1*1*0002##) are strictly NACKed / silent by MH200N, F460, F461, F454, F459, F453AV, and MyHomeServer1. Only 2-digit syntax (*1*1*02##) is translated to an SCS Point-to-Point telegram ($0302001200\r).

  3. Collision with Area Broadcasts via Zero Stripping:
    Because is_apl_address("02") returned False, normalize_where("02") treated "02" as a non-APL numeric string and stripped the leading zero:

    normalize_where("02") == "2"  # collides with Area 2 broadcast!

    This created a critical sharp edge (pinned in test(fixtures): A=0 PL=2 physical press trace from an MH200 (#684) #700):

    • A light configured at where: "02" had its normalized address aliased to "2".
    • Any Area 2 broadcast frame on the bus (*1*1*2## or *1*0*2##) falsely updated or toggled the state of the Area 0 light.
    • area_of_where("02") returned None, preventing proper area status synchronization with Area 0 ("00").

How is it solved?

  1. Recognize 2-Digit Area 0 APL Addresses (01–09):
    In custom_components/myhome/const.py:is_apl_address():

    • For 2-digit addresses (len(base) == 2), accept a == 0 and 1 <= pl <= 9.
    • Addresses "01" through "09" are now recognized as valid Point-to-Point (APL) addresses.
    • Broadcast "00" (a == 0, pl == 0) continues to be correctly rejected as point-to-point.
  2. Map Area 0 Point-to-Point to Area Status WHERE "00":
    In custom_components/myhome/const.py:area_of_where():

    • For 2-digit addresses where base[0] == "0" ("01"–"09"), returns "00".
    • Area 0 point-to-point lights synchronize with Area 0 status broadcasts ("00"), completely decoupled from Area 2 ("2").
  3. Preserve Leading Zeros on 2-Digit Area 0 Addresses:
    In custom_components/myhome/const.py:normalize_where():

    • Because is_apl_address("02") is True, norm_base preserves "02".
    • normalize_where("02") == "02" and normalize_where("02#4#01") == "02#4#01".
    • Eliminates the alias collision between Area 0 PL 2 and Area 2 Broadcast ("2").

How is it tested?

  1. Resolution of Sharp Edge in Issue Support Area-0 point-to-point lighting addresses (A=0, PL=1–15) assigned by Home + Project #684 Trace Tests (tests/test_issue_684_area0_press_trace.py):

    • test_two_digit_form_is_canonical_apl_accepted_by_gateways: verifies is_apl_address("02") is True.
    • test_two_digit_where_does_not_collide_with_area_after_normalisation: asserts normalize_where("02") == "02", area_of_where("02") == "00", and normalize_where("02") != normalize_where("2").
    • test_light_configured_at_02_sends_the_two_digit_frame: asserts turning on an Area 0 light dispatches *1*1*02##.
  2. Exhaustive Address Matrix (tests/test_infeasible_commands.py):

    • Added test_all_feasible_2_digit_area_0_combinations: asserts feasibility, normalization, and area mapping ("00") for all 9 Area 0 combinations (01–09).
    • Added "00" to infeasible_zero_pl asserting broadcast "00" is not feasible APL.
  3. Full Regression & Quality Suite:

    • WSL test execution: All 3,709 tests passed (pytest tests -q).
    • Ruff: 0 errors / clean.
    • Architectural standards: All 54/54 Platinum rules verified (verify_ha_standards.py).
    • Anti-drift documentation sentinel: clean (sync_documentation.py --check).

…#684)

In Home + Project installations, light actuators are assigned starting at A=0, PL=1..15.

Firmware reverse-engineering and empirical testing across the gateway fleet (own-firmware-oracle#35, own-firmware-oracle#39, findings/MH200N/area0-lighting.md) proved that:
- Area 0 actuators with PL in 1..9 are addressed using 2-digit format '01'..'09' (*1*1*02## -> SCS Point-to-Point \), accepted across MH200N, F460, F461, F454, F459, F453AV, and MyHomeServer1.
- 4-digit zero-padded forms (*1*1*0002##) are strictly NACKed by gateway firmware.
- Single-digit '2' (*1*1*2##) is universally parsed as Area 2 Broadcast (\).

Previously, is_apl_address('02') returned False, causing normalize_where('02') to strip the leading zero to '2'. This caused Area 0 lights to falsely alias and react to Area 2 broadcasts.

Changes:
- const.py:
  - is_apl_address(): accept 2-digit Area 0 point-to-point addresses (01-09) where a == 0 and 1 <= pl <= 9.
  - area_of_where(): map 2-digit Area 0 point-to-point addresses (01-09) to Area 0 status WHERE ('00').
  - normalize_where(): preserve leading zero on 2-digit Area 0 addresses (01-09), preventing alias collision with Area broadcasts ('2').
- tests/test_issue_684_area0_press_trace.py:
  - update assertions to verify that '02' is recognized as canonical APL, normalizes to '02', does not alias '2', and maps to area '00' (resolves the sharp edge pinned in #700).
- tests/test_infeasible_commands.py:
  - add test_all_feasible_2_digit_area_0_combinations asserting feasibility, normalization, and area mapping for 01-09.
  - add '00' to infeasible_zero_pl.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@GreenGrassBlueOcean
GreenGrassBlueOcean merged commit 3d033eb into v2-phase1-architecture Oct 14, 2026
30 checks passed
@GreenGrassBlueOcean
GreenGrassBlueOcean deleted the feat/issue-684-area0-point-lighting branch October 14, 2026 21:16
@peterbeepping

Copy link
Copy Markdown

I solved the problem in my home by using an old touchscreen (my home touchscreen 3,5" axolute h4890) as the openweb gateway. This old touchscreen handles the zero adresses correctly.
I asked and got the old firmware of the mh200 from Legrand support. I'm going to try to update the mh200 with it. Maybe then it will work again. But you were also interested in it, so I included the file in this post. I don't have the orginal cd rom.
MH200_020102.zip

@GreenGrassBlueOcean

Copy link
Copy Markdown
Contributor Author

@peterbeepping Thank you so much for attaching the original MH200_020102.zip! We have already verified the archive hashes, unlocked the vendor packaging layers (MH200 and bticino), and unpacked all 279 filesystem entries into our manifest. Because the binaries are 32-bit ARM matching our existing QEMU harness, we can now ingest the MH200 firmware directly into own-firmware-oracle and replay the bus commands against the real MH200 bt_luci binary.

How Area 0 & Zero Handling Was Solved

Thanks to your authentic physical press traces and testing across 10 emulated gateways, we merged a series of PRs that completely resolve Area 0 point-to-point addressing without colliding with Area broadcasts:

  1. Authentic Trace Capture (#700):
    We added your real-world MH200 A0PL2 capture (tests/fixtures/traces/issue_684/physical_press_a0pl2_mh200.json) to the test suite. This pinned down the exact sharp edge: on the SCS bus, the actuator reports *1*1*2##, which previously caused MyHOME to strip the leading zero and treat the light as an Area 2 broadcast.

  2. 2-Digit Area 0 Point-to-Point Addressing (#713):

    • Address Recognition (is_apl_address): We updated the address validator so that 2-digit addresses with A=0 ("01" through "09") are recognized as valid Point-to-Point addresses, while "00" remains correctly rejected as an area broadcast.
    • Preserving Leading Zeros (normalize_where): Addresses like "02" (or routed forms like "02#4#01") no longer get stripped to "2". This eliminates the alias collision where controlling Area 0 PL 2 switched all lights in Area 2.
    • Area Status Synchronization (area_of_where): 2-digit Area 0 addresses ("01"–"09") now map strictly to Area 0 status broadcasts ("00"), decoupling them completely from Area 2.
  3. Gateway Protocol Verification (own-firmware-oracle#39):
    Replaying Area 0 frames across 10 gateways confirmed that modern gateways translate the 2-digit form (*1*1*02##) directly to SCS Point-to-Point telegrams ($0302001200\r), whereas 4-digit zero-padded forms (*1*1*0002##) are dropped or NACKed.

Note on the Axolute 3.5" Touchscreen (H4890)

Your observation that the Axolute 3.5" touchscreen gateway handles Area 0 addresses cleanly is very valuable. We recently added colour touchscreen profile support and WHO 1013 diagnostics for the H4684 family in OWNd (OWNd#112), so having confirmation that the Axolute H4890 gateway translates Area 0 point-to-point correctly gives another verified hardware baseline for users with Home + Project plants.

GreenGrassBlueOcean pushed a commit that referenced this pull request Oct 25, 2026
…`04`) (#147) (#798)

Canonicalise 4-digit area-0 point addresses (`0001`..`0009`) to their 2-digit form (`01`..`09`) across YAML validation, stored `migrated_yaml_platforms`, WHO 1 / WHO 2 `expose` bindings and subentries, WHO 1 `binary_sensor` / `sensor` schemas, and persisted cover calibrations, while leaving `0000`, `0010`..`0015`, non-zero areas (including `#135`'s `0809`), and WHO 5 alarm addresses as typed.

Migrate existing `{mac}-{1|2}-0004[#4#II][-suffix]` entities and devices to the canonical spelling at setup, carrying unset `area_id`, `icon`, `name`, `name_by_user`, and `labels`, removing ghost lights + companion buttons on WHO 1 switches/covers, and merging bus-discovered WHO 1 `motion` / `illuminance` twins (`{mac}-04-<suffix>`).

Refs #147, #713.

Co-Authored-By: gdluck <innowebdevs@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants