Skip to content

Commit c7d2bb2

Browse files
committed
refactor: Declare legacy component actions on the gateway payload
DeviceStatus.from_raw_response reached into the legacy mapper's private attrs key to merge Gen1 actions into available_actions, so the domain entity knew the mapper's internals. The mapper now declares each component's actions as a first-class available_actions list on its payload, and the entity merges any declared list generically with the actions derived from the RPC method list. attrs keeps only the gateway-private routing keys.
1 parent 53a27f6 commit c7d2bb2

4 files changed

Lines changed: 50 additions & 6 deletions

File tree

packages/core/src/core/domain/entities/device_status.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,12 @@ def from_raw_response(
7272
for component_data in components_data:
7373
component = ComponentFactory.create_component(component_data)
7474
component.available_actions = component.get_available_actions(methods)
75-
legacy_actions = component.attrs.get("legacy_actions")
76-
if isinstance(legacy_actions, list):
77-
component.available_actions.extend(legacy_actions)
75+
# A gateway may declare per-component actions directly in its
76+
# payload; the legacy mapper does, since Gen1 has no method list
77+
# to derive them from.
78+
declared_actions = component_data.get("available_actions")
79+
if isinstance(declared_actions, list):
80+
component.available_actions.extend(declared_actions)
7881
components.append(component)
7982

8083
for key, status in status_dict.items():

packages/core/src/core/gateways/device/legacy_component_mapper.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,10 @@ def _build_input_components(
191191
"enable": config.get("enable", True),
192192
"invert": config.get("invert", False),
193193
},
194+
"available_actions": LEGACY_INPUT_ACTIONS.copy(),
194195
"attrs": {
195196
"legacy_component": "input",
196197
"legacy_id": idx,
197-
"legacy_actions": LEGACY_INPUT_ACTIONS.copy(),
198198
},
199199
}
200200
)
@@ -250,10 +250,10 @@ def _build_switch_components(
250250
"current_limit", config.get("max_current", 0.0)
251251
),
252252
},
253+
"available_actions": LEGACY_SWITCH_ACTIONS.copy(),
253254
"attrs": {
254255
"legacy_component": "relay",
255256
"legacy_id": idx,
256-
"legacy_actions": LEGACY_SWITCH_ACTIONS.copy(),
257257
},
258258
}
259259
)
@@ -306,10 +306,10 @@ def _build_cover_components(
306306
"maxtime_close": config.get("maxtime_close", 0),
307307
"power_limit": config.get("power_limit", 0),
308308
},
309+
"available_actions": LEGACY_COVER_ACTIONS.copy(),
309310
"attrs": {
310311
"legacy_component": "roller",
311312
"legacy_id": idx,
312-
"legacy_actions": LEGACY_COVER_ACTIONS.copy(),
313313
},
314314
}
315315
)

packages/core/tests/unit/domain/entities/test_device_status.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@ def test_it_creates_device_status_without_zigbee_data(self):
7777
zigbee_comp = device_status.get_component_by_key("zigbee")
7878
assert zigbee_comp is None
7979

80+
def test_it_extends_derived_actions_with_the_ones_a_gateway_declares(self):
81+
response_data = {
82+
"components": [
83+
{
84+
"key": "switch:0",
85+
"status": {"output": True},
86+
"config": {"name": "Test Switch"},
87+
"available_actions": ["Legacy.Toggle", "Legacy.TurnOn"],
88+
"attrs": {},
89+
}
90+
],
91+
}
92+
93+
device_status = DeviceStatus.from_raw_response(
94+
"192.168.1.100", response_data, available_methods=["Switch.Toggle"]
95+
)
96+
97+
switch_comp = device_status.get_component_by_key("switch:0")
98+
assert switch_comp is not None
99+
assert switch_comp.available_actions == [
100+
"Switch.Toggle",
101+
"Legacy.Toggle",
102+
"Legacy.TurnOn",
103+
]
104+
80105
def test_it_gets_zigbee_info_method(self):
81106
zigbee_comp = ZigbeeComponent(
82107
key="zigbee", component_type="zigbee", network_state="joined", enabled=True

packages/core/tests/unit/gateways/device/test_legacy_component_mapper.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@ def _switch_config(mapper, relay_settings):
2020
return switch["config"]
2121

2222

23+
class TestLegacyActionDeclaration:
24+
def test_it_declares_the_relay_actions_on_the_component_payload(self, mapper):
25+
components = mapper.map(
26+
{"mac": "AABBCCDDEEFF", "type": "SHSW-1"},
27+
{"relays": [{"ison": False}]},
28+
{"relays": [{}]},
29+
)
30+
31+
switch = next(c for c in components if c["key"] == "switch:0")
32+
assert switch["available_actions"] == [
33+
"Legacy.Toggle",
34+
"Legacy.TurnOn",
35+
"Legacy.TurnOff",
36+
]
37+
38+
2339
class TestLegacyAutoTimerMapping:
2440
@pytest.mark.parametrize(
2541
"value, expected_flag, expected_delay",

0 commit comments

Comments
 (0)