feat(washer): add model-number-based device-type detection fallback
This commit is contained in:
1 parent
779c2f9881
commit
2852a21c4a
2 files changed
+97
-1
No files matched your search
@@ -4,7 +4,7 @@ from typing import Optional
|
||||
from ._base import DeviceRegistry
|
||||
from . import dishwasher, dryer, oven, refrigerator, washer
|
||||
|
||||
__all__ = ['DeviceRegistry', '_type_key', 'for_device']
|
||||
__all__ = ['DeviceRegistry', '_type_key', 'for_device', 'for_device_by_model']
|
||||
|
||||
|
||||
_REGISTRY_BY_KEY: dict[str, DeviceRegistry] = {
|
||||
@@ -56,3 +56,36 @@ def for_device(one_ui_version: str) -> Optional[DeviceRegistry]:
|
||||
if key.endswith(f'_{rkey}'):
|
||||
return reg
|
||||
return None
|
||||
|
||||
|
||||
# Consumer-model prefix (first two letters of the '_'-delimited token in
|
||||
# `description` right before any '/board-info' suffix) -> registry key.
|
||||
# NOT derived from `modelNum` -- washer and dryer share the same 'DA_WM_'
|
||||
# internal board-family prefix there, and dishwasher's modelNum contains
|
||||
# the substring 'WW', so a modelNum-only rule misroutes both.
|
||||
_CONSUMER_PREFIX_TO_KEY: dict[str, str] = {
|
||||
'WW': 'washer',
|
||||
'WD': 'washer',
|
||||
'DV': 'dryer',
|
||||
'DW': 'dishwasher',
|
||||
}
|
||||
|
||||
|
||||
def for_device_by_model(model_num: str, description: str) -> Optional[DeviceRegistry]:
|
||||
"""Fallback device-type detection for hardware that never reports
|
||||
oneUiVersion (confirmed for washers -- their /otninformation/vs/0 has
|
||||
no swVersionInfo key at all).
|
||||
|
||||
Args:
|
||||
model_num: x.com.samsung.da.modelNum from /information/vs/0.
|
||||
description: x.com.samsung.da.description from /information/vs/0.
|
||||
|
||||
Returns:
|
||||
DeviceRegistry if the consumer-model code or modelNum resolves to a
|
||||
known type, None otherwise.
|
||||
"""
|
||||
token = (description or '').split('/', 1)[0].rsplit('_', 1)[-1]
|
||||
key = _CONSUMER_PREFIX_TO_KEY.get(token[:2].upper())
|
||||
if key is None and '_REF_' in (model_num or ''):
|
||||
key = 'refrigerator'
|
||||
return _REGISTRY_BY_KEY.get(key) if key else None
|
||||
@@ -99,3 +99,66 @@ class TestWasherRegistry:
|
||||
'/diagnosis/vs/0', '/otninformation/vs/0',
|
||||
):
|
||||
assert href in registry.capabilities, f"{href} missing from washer registry"
|
||||
|
||||
|
||||
class TestForDeviceByModel:
|
||||
"""Fallback device-type detection for hardware without oneUiVersion."""
|
||||
|
||||
def test_washer_ww_prefix(self):
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model(
|
||||
'DA_WM_TP1_21_COMMON|20375141|20010002001811424AA30217008A0000',
|
||||
'DA_WM_TP1_21_COMMON_WW5000C/DC92-03495A_B048',
|
||||
)
|
||||
assert reg is not None
|
||||
assert reg.name == 'washer'
|
||||
|
||||
def test_washer_wd_prefix(self):
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model(
|
||||
'DA_WM_TP1_21_COMMON|20375141|20010002001811424AA30217008A0000',
|
||||
'DA_WM_TP1_21_COMMON_WD7000B/DC92-03724A_004D',
|
||||
)
|
||||
assert reg is not None
|
||||
assert reg.name == 'washer'
|
||||
|
||||
def test_dryer_not_misdetected_as_washer(self):
|
||||
"""Dryer shares the DA_WM_ board prefix with washer -- must not
|
||||
be misrouted despite the shared prefix."""
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model(
|
||||
'DA_WM_TP2_20_COMMON_DV5000T', 'DA_WM_TP2_20_COMMON_DV5000T',
|
||||
)
|
||||
assert reg is not None
|
||||
assert reg.name == 'dryer'
|
||||
|
||||
def test_dishwasher_not_misdetected_as_washer(self):
|
||||
"""Dishwasher's modelNum contains the substring 'WW' -- must not
|
||||
be misrouted by a naive substring match."""
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model(
|
||||
'ADW-WW-RTL-24-AILITE|90000541|400002010019130059C1000500E10000',
|
||||
'ADW-WW-RTL-24-AILITE_DW9000F/DD91-00002A_0002',
|
||||
)
|
||||
assert reg is not None
|
||||
assert reg.name == 'dishwasher'
|
||||
|
||||
def test_refrigerator_via_modelnum_ref_token(self):
|
||||
"""Refrigerator's description has no consumer-model suffix; falls
|
||||
back to the '_REF_' token in modelNum."""
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model(
|
||||
'TP1X_REF_21K|00176141|00000850031813294103010041030000',
|
||||
'TP1X_REF_21K',
|
||||
)
|
||||
assert reg is not None
|
||||
assert reg.name == 'refrigerator'
|
||||
|
||||
def test_unknown_model_returns_none(self):
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
reg = for_device_by_model('SOME-UNKNOWN-BOARD', 'SOME-UNKNOWN-BOARD')
|
||||
assert reg is None
|
||||
|
||||
def test_empty_inputs_return_none(self):
|
||||
from custom_components.localthings.registry.by_type import for_device_by_model
|
||||
assert for_device_by_model('', '') is None
|
||||
Reference in new issue
Block a user