Repository navigation
fix(gateway,climate): ingest H/L4684 FW 6.0.11 trace and fix H/L4684 & WHO 4 bugs (#466) - #818
Merged
GreenGrassBlueOcean merged 1 commit intoOct 26, 2026
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
GreenGrassBlueOcean
force-pushed
the
fix/issue-466-hl4684-trace-and-bugs
branch
from
October 25, 2026 22:15
096b1f3 to
99e3f80
Compare
This was referenced Oct 26, 2026
gdluck
pushed a commit
to gdluck/HomeAssistant-MyHOME
that referenced
this pull request
Oct 26, 2026
…ile_for_model (OpenWebNet-HA#804 follow-up) _async_apply_gateway_identity called get_gateway_profile(model, gateway.model_number): OWNd's signature is (model_name, firmware_version), and model_number is always None on the manual path, so the second argument was inert and read as if a model number were a firmware. The runtime resolves the same correction through _profile_for_model (OpenWebNet-HA#818), which also maps the SSDP spellings; the flow now uses it, without a firmware, which is not known before the first connection. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the problem
A physical BTicino H/L4684 Colour Touch Screen (
FW 6.0.11, kernel2.6.2, distro6.0.0,WHO 13device type23) diagnostics capture contributed by@andrea-magin#466(comment6398442412) uncovered six integration & trace-matrix bugs acrossWHO 3,WHO 4,WHO 13,WHO 16/22,WHO 1013, SSDP discovery, and diagnostics redaction:modelName = "H/L4684"missedmanifest.json& fell back toGenericGatewayProfile:H/L4684(urn:schemas-bticino-it:device:touchscreen:1) announces"H/L4684"(with a slash), whereasmanifest.jsononly matched"HL4684".OWNd==2.0.0b11,"H/L4684"fell back toGenericGatewayProfile(command_session_limit()returnedNoneinstead of1, andWHO 5/WHO 25remained enabled), whilesupports_zone_statuschecked"HL4684" in "H/L4684"(False) and"H4684" in "H/L4684"(False), leavingsupports_zone_status == Trueon"H/L4684".FW >= 6.0.0(6.0.11),H/L4684runs bothbt_difson(WHO 16) andbt_multi(WHO 22), which was not advertised byprofile_supports_who(22)orgateway_supported_whos("H/L4684", "6.0.11"), andWHO 13Dimension 16 auto-detection did not refreshself.gateway.profile.WHO 13device type23&"/"normalization):H/L4684(FW 6.0.11) reports*#13**15*23##on the wire (WHO 13device type23), which was listed only in the unverified third-party Nmap table rather than field-confirmed BTicino hardware, and"/"was not stripped ingateway_model_family()/_normalized().ClimateEntityFeature.FAN_MODE:@andrea-mag's capture (11, 22, 33, 44, 55, 66, 77, 88, whereZone 33hasfan: trueand the other 7 havefan: false) emit*#4*Z#N*20*5##on Dimension 20.climate.py, receiving20*5tentatively enablesClimateEntityFeature.FAN_MODE(auto/low/medium/high) and queries Dimension 19 via_ask_fan_coil_sides()(*#4*Z*19##), which on pure-valve zones answers*#4*Z*19*0*0##(VALVE_STATUS: neither heating nor cooling uses a fan coil, as captured inmyhomeserver1_live_2026-10-25zones35..70andissue_674F455). Previously,climate.pynever retracted tentativeFAN_MODEonce Dimension 19 proved neither side of an unconfigured zone is a fan coil.options["config_file_path"]:diagnostics.pyredacted legacy"file_path"(CONF_LEGACY_FILE_PATH) but omitted"config_file_path"(CONF_FILE_PATH).myhome.sweep_busomitted*#1013*0*1##(OBJECT_MODEL):sweep_busqueriedWHO 13(0, 15, 16, 23, 24) but never queried*#1013*0*1##, leavingwho1013_code: nullin user-submitted sweep/diagnostics captures unlessWHO 13returned shared code200.WHO 3(Load) andH/L4684canonicalization:scripts/update_trace_matrix.pyomittedWHO 3and keyed"H/L4684"separately from"H4684".Relates to #466
Companion
OWNdPR: OpenWebNet-HA/OWNd#147Note
Merge Order (
MyHOME#818first): Merge this PR beforeOpenWebNet-HA/OWNd#147.MyHOME#818passes against both pinnedOWNd==2.0.0b11andOWNd#147, and updates the 4MyHOMEtests thatOWNd'smyhome-conformance.ymlCI workflow runs againstv2-phase1-architecture.What is the solution
H4684Profilebinding, andFW >= 6.0.0WHO 22gating (manifest.json,gateway.py,identity.py,topology.py,scripts/update_gateway_profiles.py):"H/L4684"SSDP matcher tocustom_components/myhome/manifest.json(alongside pre-existing"HL4684")._profile_for_model()and_firmware_at_least()(withTODO(OWNd>2.0.0b11)markers for the temporary shims) so"H/L4684","HL4684", and"HC4684"resolve toH4684Profileunder bothOWNd==2.0.0b11andOWNd#147, refreshself.gateway.profilewhen*#13**16*V*R*B##updatesgateway.firmware, advertiseWHO 22whenFW >= (6, 0, 0), and evaluatesupports_zone_status == Falseacross allH/L4684spellings and MyHOME_Suite catalogue codes.WHO 13code23&"/"normalization (const.py,identity.py):"23": ("H4684", "H/L4684", "L4684")toWHO13_OBSERVED_DEVICE_TYPES(while keepingWHO1013_OBJECT_MODELS["19"] = ("H4684", "L4684")faithful toMHCatalogue.db, with_same_product_names()linking"H/L4684"/"HL4684"across bothWHO 13andWHO 1013), added"H4684"toSUPPORTED_GATEWAY_MODELS, and stripped"/"ingateway_model_family()andidentity._normalized().FAN_MODEon pure-valve zones proven non-fan-coil by Dimension 19 (climate.py):self._fan_configured = bool(fan and not self._central),_has_no_fan_coil_sides(), and_disable_fan_mode().*#4*Z*19*CV*HV##) reportsfan_coil_heating is False and fan_coil_cooling is Falseon a zone not explicitly configured withfan=True, tentativeClimateEntityFeature.FAN_MODE,fan_modes, andfan_modeare retracted and prevented from re-activating on subsequent20*5frames or stale state restore, while preserving explicitfan=Truezones (Zone 33) and genuine fan-coil zones (19*5*0).CONF_FILE_PATHin diagnostics & include*#1013*0*1##inmyhome.sweep_bus(diagnostics.py,services.py):CONF_FILE_PATH("config_file_path") toTO_REDACT."*#1013*0*1##"togateway_queriesinhandle_sweep_bus.H/L4684(FW 6.0.11) trace & update Hardware Trace Availability Matrix:tests/fixtures/traces/issue_466/config_entry-myhome_HL4684_fw6_0_11.json+README.md, addedWHO 3 (Load)andH/L4684canonicalization toscripts/update_trace_matrix.py, and synchronizedREADME.md+docs/viascripts/sync_documentation.py --update.State Diagram
stateDiagram-v2 [*] --> PureOrUnknownZone: MyHOMEClimate(fan=False) [*] --> ExplicitFanZone: MyHOMEClimate(fan=True) PureOrUnknownZone --> TentativeFanZone: Rx *#4*Z#N*20*{5..8}##\n(_ask_fan_coil_sides -> *#4*Z*19##) PureOrUnknownZone --> ConfirmedPureValve: Rx *#4*Z*19*0*0##\n(CV not in 5..8 & HV not in 5..8) PureOrUnknownZone --> ConfirmedFanCoil: Rx *#4*Z*19*{5..8}*0## or *0*{5..8}## TentativeFanZone --> ConfirmedPureValve: Rx *#4*Z*19*0*0##\n_disable_fan_mode() retracts FAN_MODE TentativeFanZone --> ConfirmedFanCoil: Rx *#4*Z*19*{5..8}*...##\nFAN_MODE retained ConfirmedPureValve --> ConfirmedPureValve: Rx *#4*Z#N*20*5## or *20*1##\nTracks actuator state & hvac_action\n(FAN_MODE stays disabled) ExplicitFanZone --> ExplicitFanZone: Rx *#4*Z*19*0*0##\n_fan_configured=True preserves FAN_MODEHardware Verification
FW 6.0.11, kernel2.6.2, distro6.0.0,WHO 13device type23) capture from@andrea-mag's multi-subsystem SCS plant (68lights,8switches,8heating zones11..88+#0central unit,8WHO 3load-priority channels#1..#8,12dual-dialectWHO 16+WHO 22amplifier zones +2active stereo sources).#466(comment6402416947).How is it tested
tests/test_issue_466_hl4684_trace.py:test_hl4684_trace_fixture_integrity_and_parser_coverage: parses all257frames (212 rx,45 tx) acrossWHO 1, 2, 3, 4, 13, 16, 22, verifies29OWNLoadEventframes across#1..#8, and assertsconfig_file_pathredaction.test_scs_gateway_aliases_disable_point_to_point_zone_status: verifiessupports_zone_status is Falseacross"H/L4684","HL4684","HC4684","H4684","L4684","BTicino H/L4684", and MyHOME_Suite catalogue codes (003598,003594,003565,003535,573992).test_hl4684_ssdp_profile_identity_and_fw6_who22: replays*#13**15*23##,*#13**16*6*0*11##,*#13**23*2*6*2##,*#13**24*6*0*0##and*#1013**1*19*15*5*0##, verifying dynamicWHO 22activation onFW 6.0.11and conflict-free identity corroboration.test_hl4684_diagnostics_redacts_config_file_path: verifiesasync_get_config_entry_diagnosticsredactsoptions["config_file_path"].test_hl4684_trace_f430_4_pure_valve_vs_fancoil_zones: replays all64WHO 4frames across zones11..88, asserts_ask_fan_coil_sides()(*#4*Z*19##) is queued on20*5, verifies19*0*0retracts tentativeFAN_MODEonfan=Falsezones (11, 22, 44, 55, 66, 77, 88) while preserving explicitfan=True(33) and genuine fan-coil (19*5*0) zones, and checks state restoration.test_hl4684_trace_dual_dialect_sound_inventory_deduplication: replays all28WHO 16+WHO 22rx frames (24zone +4source frames) and verifies clean deduplication into12amplifier-zonemedia_playerentities.test_startup_requests_per_firmware.py,test_climate_humidity_poll_gate.py,test_gateway_identification.py,test_gateway_profiles.py,test_diagnostics.py,test_services.py, andtest_multi_gateway.py.pytest tests -q --cov=custom_components/myhome(againstOWNd#147on rebasedv2-phase1-architecture): 4,980 passed, 100.0% line coverage (16,810 / 16,810,0missed lines)pytestagainst pinnedOWNd==2.0.0b11wheel: All checks passedscripts/typing_ratchet.py(mypy --strictagainstOWNd==2.0.0b11): 0 errors across all modulesruff check custom_components tests scripts: All checks passedscripts/verify_ha_standards.py: All 54/54 Platinum Home Assistant standards passedscripts/sync_documentation.py --check: All documentation & trace matrices calibrated and in syncWhere are the traces
tests/fixtures/traces/issue_466/config_entry-myhome_HL4684_fw6_0_11.json(257frames:84WHO 1,2WHO 2,29WHO 3,64WHO 4,5WHO 13,14WHO 16,14WHO 22rx +45tx) andtests/fixtures/traces/issue_466/README.md.WHO 1, 2, 3, 4, 13, 16, 18, 22, 1013inREADME.mdanddocs/trace-availability.md.What does the Firmware Oracle / Encyclopedia say
WHO = 4,WHO = 13,OWN-DEV-0135):WHO = 4DIMENSION = 19(VALVE_STATUS,*#4*where*19*CV*HV##):0 = OFF,1 = ON,2 = OPENED,3 = CLOSED,4 = STOP,5 = OFF_FAN_COIL,6 = ON_SPEED_1,7 = ON_SPEED_2,8 = ON_SPEED_3. When neitherCVnorHVis in{5, 6, 7, 8}(19*0*0), neither side is a fan coil even if actuator channels (DIMENSION = 20) emit5while idle.WHO = 13DIMENSION = 15: official 2006 spec assigns13toH4684, while field firmware6.0.11emits23(*#13**15*23##).OWN-DEV-0135(Colour Touch ScreeninMHCatalogue.db) maps commercial SKUsH4684(Axolute) andL4684(LivingLight).*#4*0##,*#4*1*19##,*#1013*0*1##):*#4*0##is"silent"onH4684020054(trace-corpus.tsv) — corroborated on liveH/L46846.0.11(*#4*0##yielded0WHO 4event frames before the next sweep query1.33 slater).*#4*1*19##isOUT (Bus)across all 12 emulated gateway images (thermo-valve.tsv, dispatching$0499013013\ronH4684020054).*#1013*0*1##(OBJECT_MODEL) is answered locally by the gateway (ACK *#*1##, returning*#1013**1*19##onH4684020054) with0SCS bus frames across all 12 emulated gateway images (trace-corpus.tsv), making it zero-bus-load to include inmyhome.sweep_bus.Checklist
What is the problem,What is the solution,State Diagram,How is it tested,Where are the traces,What does the Firmware Oracle / Encyclopedia say).handle_event()and do not manually subscribe viaasync_dispatcher_connect.pytest,ruff, andscripts/verify_ha_standards.pypass.