Skip to content

feat(lighting): migrate timed turn-on commands to OWNd b11 builders - #659

Merged
GreenGrassBlueOcean merged 5 commits into
OpenWebNet-HA:v2-phase1-architecturefrom
GreenGrassBlueOcean:feat/who1-lighting-timer-factories
Oct 9, 2026
Merged

GreenGrassBlueOcean merged 5 commits into
OpenWebNet-HA:v2-phase1-architecturefrom
GreenGrassBlueOcean:feat/who1-lighting-timer-factories

Conversation

@GreenGrassBlueOcean

@GreenGrassBlueOcean GreenGrassBlueOcean commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Note

Companion PR to OpenWebNet-HA/OWNd#93
Migrates MyHOME WHO 1 lighting timed turn-on commands to the typed OWNLightingCommand builders introduced in OWNd 2.0.0b11, with dual-compatibility for released OWNd 2.0.0b10.


1. Summary & Architectural Context

Historically, custom_components/myhome/const.py:build_timed_turn_on_command had to assemble OpenWebNet frames via string interpolation (*1*{what}*{where}## for standard preset timers and *#1*{where}*#2*{h}*{m}*{s}## for arbitrary variable timers) and re-parse them using OWNCommand.parse(...) because OWNLightingCommand lacked typed factory constructors for timed operations.

With OpenWebNet-HA/OWNd#93 completing the lighting command surface, OWNLightingCommand provides first-class, typed factory constructors with built-in parameter boundary validation and human-readable logging.

This PR:

  1. Migrates build_timed_turn_on_command to consume OWNLightingCommand.switch_on_timed and OWNLightingCommand.set_variable_timer.
  2. Implements dual-compatibility via hasattr checks with safe fallbacks and test skips (@pytest.mark.skipif), allowing CI to pass immediately against released OWNd==2.0.0b10 on PyPI while unlocking the typed constructors when OWNd>=2.0.0b11 is active or locally installed in development.
  3. Adds comprehensive unit test coverage in tests/test_lighting.py for all new OWNLightingCommand factory methods.

2. Protocol & Specification Grounding

The frames dispatched by these builders conform strictly to canonical Legrand/BTicino specifications and binary implementations:

Feature OpenWebNet Syntax Specification Grounding Client / Firmware Provenance
Preset Timers *1*<WHAT>*<WHERE>##
WHAT ∈ {11..18}
Legrand WHO_1.pdf (v1.1.0) §2.1.1 libqtdevices:lighting_device.cpp:24-32
Variable Timer *#1*<WHERE>*#2*<H>*<M>*<S>##
H ∈ 0..255, M,S ∈ 0..59
Legrand WHO_1.pdf (v1.1.0) §2.3.2 OpenWebNet Encyclopedia KB (WHO 1, DIMENSION 2)
Query Timer *#1*<WHERE>*2## Legrand WHO_1.pdf (v1.1.0) §2.3.2 bt_luci request frame
Brightness Presets *1*<WHAT>*<WHERE>##
WHAT ∈ {2..10} (10%..100%)
Legrand WHO_1.pdf (v1.1.0) §2.1.1 libqtdevices:lighting_device.cpp:45
Step Up / Down *1*30[*#<delta>[#<speed>]]*<WHERE>##
*1*31[*#<delta>[#<speed>]]*<WHERE>##
Legrand WHO_1.pdf (v1.1.0) §2.1.1 Dimmer 100 SCS telegrams

3. Empirical On-Wire Trace & Firmware Oracle Evidence

The frames generated by these builders are fully corroborated by authentic customer bus traces and firmware reverse engineering:

Authentic Customer On-Wire Traces in MyHOME

  • tests/fixtures/traces/issue_619/myhome_trace_F453AV_all_2026-10-04T08-28-13.json:
    Physical BTicino F414 dimmer on WHERE 13 cycling discrete preset levels:
    • Level 2 (20%): *1*2*13##
    • Level 3 (30%): *1*3*13##
    • Level 4 (40%): *1*4*13##
    • Level 5 (50%): *1*5*13##
    • Level 6 (60%): *1*6*13##
    • Level 7 (70%): *1*7*13##
  • tests/fixtures/traces/issue_466/myhome_trace_MH202_all_2026-09-26T16-59-17.json:
    Customer MH202 trace stepping physical dimmer through presets *1*2*14## through *1*9*14## and back down.
  • tests/fixtures/traces/issue_466/myhome_trace_MH200_f418u2_dimmer_2026-09-27T12-15-00.json:
    Authentic capture of BTicino F418U2 dimmer cycling presets *1*3*62##, *1*5*62##, and *1*7*62##.
  • tests/fixtures/traces/issue_466/myhome_sweep_H4890_all_2026-09-26T11-48-10.json:
    Live capture of an H4890 console emitting presets *1*6*01##, *1*7*01##, *1*8*01##, *1*9*01##.

Gateway Translator Daemon (bt_luci) Telegram Dispatch

Binary disassembly of bt_luci across MyHomeServer1, F454, and F459 confirms the exact SCS bus telegrams emitted for these OpenWebNet frames:

  • switch_on_timed(11, 11) (*1*11*11##) $\rightarrow$ SCS 11 00 12 16 (1 min fixed timer)
  • set_variable_timer(11, 0, 1, 0) (*#1*11*#2*0*1*0##) $\rightarrow$ SCS D1 11 01 42 06 00 01 00 (custom 1 min timer)
  • get_variable_timer(11) (*#1*11*2##) $\rightarrow$ SCS D1 11 01 43 06 00 00 00 (dimension 2 query)
  • set_brightness_preset(11, 2) (*1*2*11##) $\rightarrow$ SCS 11 00 12 1D (level 2)
  • step_up(11) (*1*30*11##) $\rightarrow$ SCS 11 00 12 03
  • step_down(11) (*1*31*11##) $\rightarrow$ SCS 11 00 12 04
  • step_up(11, 20, 1) (*1*30#20#1*11##) $\rightarrow$ SCS D1 11 01 42 0D 03 14 01 (Dimmer 100: $\Delta=20%$, speed 1)

4. Key Changes in This PR

  1. custom_components/myhome/const.py:

    • Refactored build_timed_turn_on_command to conditionally invoke OWNLightingCommand.switch_on_timed(where, what) and OWNLightingCommand.set_variable_timer(where, h, m, s) when available.
    • Retained string-building fallback with # pragma: no cover for released OWNd==2.0.0b10.
    • Preserves private bus interface routing (#4#INTERFACE) across all paths.
  2. custom_components/myhome/manifest.json & pyproject.toml:

    • Reverted requirement pins to OWNd==2.0.0b10 and OWNd>=2.0.0b10 to satisfy PyPI installation in CI pipelines until OWNd 2.0.0b11 wheel is released.
  3. tests/test_lighting.py:

    • Added unit test suite for all new OWNLightingCommand factory methods (test_switch_on_timed, test_set_variable_timer, test_get_variable_timer, test_set_brightness_preset, test_step_up, test_step_down).
    • Decorated the new builder tests with @pytest.mark.skipif(not hasattr(OWNLightingCommand, "switch_on_timed"), ...) to ensure the test suite executes cleanly on both released OWNd 2.0.0b10 and dev OWNd 2.0.0b11.
  4. tests/test_timed_lighting.py:

    • Expanded assertions ensuring returned commands are isinstance(cmd, OWNLightingCommand) across preset durations, custom durations, clamping bounds, and private bus routings.

5. Verification & Quality Gates

All checks executed inside the Python 3.14 WSL Ubuntu test harness:

  • Pytest against dev OWNd: 66 passed in 2.76s.
  • Pytest against isolated PyPI OWNd==2.0.0b10: 60 passed, 6 skipped in 2.45s (0 failures, 0 regressions).
  • Ruff Static Analysis: Clean with 0 violations (ruff check custom_components tests scripts).
  • Home Assistant Architectural Standards Validator: python scripts/verify_ha_standards.py passed with all Platinum criteria satisfied.
  • Documentation Anti-Drift Sentinel: python scripts/sync_documentation.py --check passed with 0 drift.

Adopt the newly introduced typed factory methods in OWNd 2.0.0b11 (OWNLightingCommand.switch_on_timed, set_variable_timer, get_variable_timer, step_up, step_down, set_brightness_preset). Bumps OWNd pin in manifest.json and pyproject.toml to 2.0.0b11.
@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 64800d3 into OpenWebNet-HA:v2-phase1-architecture Oct 9, 2026
16 checks passed
@GreenGrassBlueOcean
GreenGrassBlueOcean deleted the feat/who1-lighting-timer-factories branch October 21, 2026 19:35
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.

2 participants