arch(protocol): move remaining OpenWebNet string/dimension edge-case decoding to OWNd and remove production shims/MagicMock checks #736
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Architectural Assessment & Severity
- Critique Point: Heating - WHO4 - Error list index out of range #7 — Protocol edge-case accumulation instead of stricter modeling
- Severity: P1 (High — Rank Installing this integration in an HA instance running on Docker #5)
- Related Issues:
OWNd#60,OWNd#97,OWNd#102, Spurious ERROR logged on startup discovery when subsystems are not present (*#4*0##, *#16*0##) #406
Problem Statement
While custom_components/myhome/where_grammar.py (enforced by tests/test_where_usage_guard.py) successfully centralized WHO=4 WHERE grammar (1..99 zone, #0 central unit, Z#N actuator, 0#N pump, PZZ probe), several other OpenWebNet protocol edge cases and string-parsing workarounds have accumulated inside MyHOME instead of being strictly modeled in OWNd:
- WHO=1 APL / Area-0 Addressing & Timer Frame String Construction in
const.py:is_apl_address(),area_of_where(), andnormalize_where()(custom_components/myhome/const.py:244-321) implement OpenWebNet 2-digit vs. 4-digit APL and Area00/100string parsing directly in Home Assistant.build_timed_turn_on_command()(const.py:519-555) formats raw*1*{what}*{where}##and*#1*{where}*#2*{h}*{m}*{s}##frame strings as fallbacks.
- WHO=1 Group Dimension Private-Attribute Parsing in
light_group.py:MyHOMELightGroup.handle_event()(custom_components/myhome/light_group.py:180-196) reaches intogetattr(msg, "_dimension_value", [])and manually decodes Dimension 1 (raw - 100for100 <= raw <= 200), Dimension 14 (int(1000000 / int(vals[0]))), and Dimension 12 (h <= 360sentinel check for*12*511*127*255), duplicatingOWNLightingEventparsing.
- WHO=4 Sign-Magnitude Temperature Decoding in
const.py:who4_raw_to_celsius()(custom_components/myhome/const.py:214-222) decodes 4-digitSXXXtemperature strings (1xxxnegative,0xxxpositive tenths of °C) inMyHOMEwhenOWNdleaves raw dimension values undecoded.
- WHO=16 Stepped Volume (
WHAT=1001..1015/1101..1115) String Splitting inmedia_player_power.py:apply_volume_delta_from_what()(custom_components/myhome/media_player_power.py:57-92) splitswhat.split("#", 1)[0]and checks1001 <= what_code <= 1015/1101 <= what_code <= 1115to computestep / 31.0becauseOWNSoundDiffusionEvent(OWNd/message/sound.py) only maps discreteWHATcodes in_SOUND_WHAT_TABLE.
- Obsolete
OWNdShims &MagicMockChecks in Production Code:try ... except ImportErrorshims inclimate.py:49-55(MESSAGE_TYPE_SEASON, merged inOWNd#97) andsensor.py:39-48(MESSAGE_TYPE_AUTO_UPDATE_INTERVAL, merged inOWNd#102), plusMESSAGE_TYPE_ZONE_STATE = "zone_state"inclimate.py:90(OWNd#60)._StatusRequestLogFilteringateway.py:128-146mutatingOWNdlog records in-place forOWNd < 2.0.0b8.- 5 production checks for
MagicMock(gateway_events.py:285, 327,gateway_resync.py:124,sensor.py:849,services.py:77).
Proposed Solution (PR Scope)
- Extend Typed Protocol Models in
OWNd:- Export
MESSAGE_TYPE_ZONE_STATE(WHO=4Dimension 7) and ensure all WHO=4 temperature dimensions decode sign-magnitudeSXXXvalues inOWNHeatingEvent. - Decode WHO=16 stepped volume
WHAT=1001..1015(+1..+15) andWHAT=1101..1115(-1..-15) as a typedvolume_step_delta: int | Noneproperty onOWNSoundDiffusionEvent. - Expose typed
brightness,color_temp_kelvin, andhs_colorproperties on WHO=1 group dimension commands/events (*#1*#G*#D*...##) inOWNd/message/lighting.py. - Move
is_apl_address,area_of_where, andnormalize_whereintoOWNd's addressing module (and re-export inMyHOMEalongsidewhere_grammar.py).
- Export
- Purge Protocol Hacks, Shims &
MagicMockChecks inMyHOME:- Replace raw
_dimension_valueparsing inlight_group.py,what.split("#")volume math inmedia_player_power.py, andwho4_raw_to_celsiusinconst.pywith typedOWNdproperties. - Delete the obsolete
ImportErrorshims inclimate.pyandsensor.pyand_StatusRequestLogFilteringateway.py. - Remove all 5
MagicMockchecks fromcustom_components/myhome/and fix test mocks to supply typed attributes. - Add an AST/regex guard test in
tests/test_where_usage_guard.pyforbiddingMagicMockreferences and private_dimension_valueaccesses insidecustom_components/myhome/.
- Replace raw
Verification Plan
- Run
pytest tests/test_where_usage_guard.py(extended with protocol boundary and no-MagicMockguards). - Run full test suite against the updated
OWNdpackage (pytest tests -q --cov=custom_components/myhome) andruff check.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
fix(protocol): add PyPI OWNd < 2.0.0b11 compatibility bridge in where…
Merge pull request #737 from OpenWebNet-HA/arch/issue-736-protocol-bo…
GreenGrassBlueOcean commentedon Oct 21, 2026
Resolved in PR #737 (
5d9218d1):OWNd.ImportErrorshims and all productionMagicMockchecks acrosscustom_components/myhome/.MagicMockguards intests/test_where_usage_guard.py.