- Make href Optional[str] = None for pattern capabilities - Remove observe field (v2 architecture observes all hrefs) - Add rt_filter, match_fn, key_fn fields to Capability - Add entities default value tuple[()] to Capability - Add key_override field to BoundEntity - Update _key() to use key_override when present - Update _make_observe_paths() to observe all unique hrefs (OBSERVE as accelerator) - Guard _build() to skip pattern capabilities (href is None) - Add test_bound_entity_key_override_takes_precedence test - Update test_capability_defaults to remove observe assertion All 61 tests passing (60 existing + 1 new).
88 lines
3.6 KiB
Python
88 lines
3.6 KiB
Python
import json
|
|
|
|
from samsung_appliance.registry.adapter import build_runtime_descriptor
|
|
from samsung_appliance.registry.capabilities import common
|
|
from samsung_appliance.registry.discovery import discover
|
|
|
|
|
|
def _bound(resources):
|
|
reg = {c.href: c for c in (common.KIDS_LOCK, common.ENERGY_METER)}
|
|
return discover(resources, reg)
|
|
|
|
|
|
def _bound_with_power(resources):
|
|
reg = {c.href: c for c in (common.KIDS_LOCK, common.ENERGY_METER, common.POWER)}
|
|
return discover(resources, reg)
|
|
|
|
|
|
def test_flatten_applies_value_fn(dishwasher_resources):
|
|
rd = build_runtime_descriptor(
|
|
_bound(dishwasher_resources), topic_prefix='t', ha_prefix='homeassistant',
|
|
device_name='Dishwasher', model='M', name='dishwasher', default_port=49154)
|
|
flat = rd.flatten(dishwasher_resources)
|
|
assert flat['power_watts'] is not None
|
|
assert isinstance(flat['child_lock'], bool)
|
|
|
|
|
|
def test_observe_paths_are_segment_lists(dishwasher_resources):
|
|
rd = build_runtime_descriptor(
|
|
_bound(dishwasher_resources), topic_prefix='t', ha_prefix='homeassistant',
|
|
device_name='Dishwasher', model='M', name='dishwasher', default_port=49154)
|
|
assert ['kidslock', 'vs', '0'] in rd.observe_paths
|
|
|
|
|
|
def test_discovery_payloads_have_unique_ids(dishwasher_resources):
|
|
rd = build_runtime_descriptor(
|
|
_bound(dishwasher_resources), topic_prefix='samsung_dishwasher',
|
|
ha_prefix='homeassistant', device_name='Dishwasher', model='M',
|
|
name='dishwasher', default_port=49154)
|
|
topics = [t for t, _ in rd.discovery_payloads]
|
|
# one config topic per produced sensor/binary_sensor entity
|
|
assert any('/binary_sensor/samsung_dishwasher/child_lock/config' in t for t in topics)
|
|
assert any('/sensor/samsung_dishwasher/power_watts/config' in t for t in topics)
|
|
# payloads are JSON bytes carrying unique_id
|
|
cfg = json.loads(next(p for t, p in rd.discovery_payloads if 'child_lock' in t))
|
|
assert cfg['unique_id'] == 'samsung_dishwasher_child_lock'
|
|
|
|
|
|
def test_switch_discovery_config_has_correct_payloads(dishwasher_resources):
|
|
rd = build_runtime_descriptor(
|
|
_bound_with_power(dishwasher_resources), topic_prefix='samsung_dishwasher',
|
|
ha_prefix='homeassistant', device_name='Dishwasher', model='M',
|
|
name='dishwasher', default_port=49154)
|
|
cfg = json.loads(next(p for t, p in rd.discovery_payloads if 'power_switch' in t))
|
|
assert cfg['payload_on'] == 'On'
|
|
assert cfg['payload_off'] == 'Off'
|
|
assert cfg['state_on'] == 'On'
|
|
assert cfg['state_off'] == 'Off'
|
|
assert 'On' in cfg['value_template']
|
|
assert 'Off' in cfg['value_template']
|
|
|
|
|
|
def test_bound_entity_key_override_takes_precedence():
|
|
from samsung_appliance.registry.adapter import _key
|
|
from samsung_appliance.registry.discovery import BoundEntity
|
|
from samsung_appliance.registry.entities import SensorDesc
|
|
|
|
cap = common.ENERGY_METER
|
|
desc = SensorDesc(
|
|
key='power_watts',
|
|
field='x.com.samsung.da.power',
|
|
unit='W',
|
|
device_class='power',
|
|
state_class='measurement',
|
|
value_fn=lambda x: x,
|
|
)
|
|
|
|
# Without key_override, should use desc.key
|
|
b1 = BoundEntity(href='/power/vs/0', capability=cap, desc=desc, instance='')
|
|
assert _key(b1) == 'power_watts'
|
|
|
|
# With key_override, should use key_override
|
|
b2 = BoundEntity(href='/power/vs/0', capability=cap, desc=desc, instance='', key_override='foo')
|
|
assert _key(b2) == 'foo'
|
|
|
|
# key_override with instance suffix should preserve instance suffix
|
|
b3 = BoundEntity(href='/power/vs/0', capability=cap, desc=desc, instance='_1', key_override='bar')
|
|
assert _key(b3) == 'bar_1'
|