fix(modes): only activate peripherals and show individual seat actions
This commit is contained in:
@@ -10,7 +10,9 @@ from cognitive_agent.application.romantic_lighting import romantic_light_actions
|
||||
from cognitive_agent.application.scene_composer import scene_required_peripheral_refs
|
||||
from cognitive_agent.application.mode_profile import ModeProfileRegistry
|
||||
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
|
||||
from cognitive_agent.application.self_extension import GatewayError, SelfExtensionService, SimulationGateway
|
||||
from cognitive_agent.application.self_extension import (
|
||||
ExtensionIntegrationError, GatewayError, SelfExtensionService, SimulationGateway,
|
||||
)
|
||||
from cognitive_agent.server import SeatDemoHandler
|
||||
|
||||
|
||||
@@ -33,22 +35,22 @@ def catalog():
|
||||
]
|
||||
|
||||
|
||||
def test_romantic_lights_all_use_on_then_red_and_preserve_on_only_candles():
|
||||
def test_romantic_lights_only_use_power_on():
|
||||
entries = catalog()
|
||||
entries += [
|
||||
light("light5", "落地灯", "红色", 61), # No known power-on command.
|
||||
light("light6", "投影灯", "打开", 71),
|
||||
light("light6", "投影灯", "蓝色", 72), # Never substitute blue for red.
|
||||
light("light6", "投影灯", "蓝色", 72), # Color capability never becomes a mode action.
|
||||
light("light7", "灯笼", "打开", 81, enabled=False),
|
||||
light("light7", "灯笼", "红色", 82, enabled=False),
|
||||
]
|
||||
before = deepcopy(entries)
|
||||
assert [item["slot"] for item in romantic_light_actions(entries)] == [2, 3, 22, 23, 41, 51, 52]
|
||||
assert [item["slot"] for item in romantic_light_actions(entries)] == [2, 22, 41, 51, 71]
|
||||
assert entries == before
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["浪漫模式", "浪漫影院模式", "约会模式", "Romantic cinema"])
|
||||
def test_creation_replaces_old_colors_and_orders_all_required_lights(name):
|
||||
def test_creation_removes_colors_and_only_opens_required_lights(name):
|
||||
actions = [{
|
||||
"ref": f"ir:{item['slot']}", "device_key": item["device_id"],
|
||||
"device_label": item["device_name"], "action_label": item["action"],
|
||||
@@ -56,7 +58,7 @@ def test_creation_replaces_old_colors_and_orders_all_required_lights(name):
|
||||
} for item in catalog()]
|
||||
context = {"peripheral_actions": actions}
|
||||
required = scene_required_peripheral_refs(name, context)
|
||||
assert required == ["ir:2", "ir:3", "ir:22", "ir:23", "ir:41", "ir:51", "ir:52"]
|
||||
assert required == ["ir:2", "ir:22", "ir:41", "ir:51"]
|
||||
context["scene_semantics"] = {"mode_name": name, "peripheral_policy": {"required_refs": required}}
|
||||
plan = {"requests": [{
|
||||
"domain": "self_extension", "capability": "infrared.emit",
|
||||
@@ -73,10 +75,39 @@ def test_same_named_lights_remain_separate_devices():
|
||||
"device_label": "灯笼", "action_label": label,
|
||||
} for device in ["one", "two"] for action, label in [("on", "打开"), ("red", "红色")]]
|
||||
assert [item["ref"] for item in romantic_light_actions(actions)] == [
|
||||
"ir:one-on", "ir:one-red", "ir:two-on", "ir:two-red",
|
||||
"ir:one-on", "ir:two-on",
|
||||
]
|
||||
|
||||
|
||||
def test_mode_creation_deduplicates_colors_into_authorized_activation():
|
||||
capabilities = catalog()
|
||||
handler = object.__new__(SeatDemoHandler)
|
||||
handler.extension = SimpleNamespace(list_peripheral_capabilities=lambda: capabilities)
|
||||
entries = [{"capability": capabilities[index]} for index in [3, 2, 1, 5, 4, 6]]
|
||||
selected = handler._mode_creation_activation_entries(entries)
|
||||
assert [entry["capability"]["slot"] for entry in selected] == [2, 22, 41]
|
||||
|
||||
|
||||
def test_mode_creation_rejects_color_only_device_or_rebound_power_on():
|
||||
red = light("light1", "灯笼", "红色", 3)
|
||||
handler = object.__new__(SeatDemoHandler)
|
||||
for available in [
|
||||
[red],
|
||||
[red, light("light1", "灯笼", "打开", 2, enabled=False)],
|
||||
[red, light("light1", "灯笼", "打开", 2, card_uid="00000002")],
|
||||
]:
|
||||
handler.extension = SimpleNamespace(list_peripheral_capabilities=lambda: available)
|
||||
with pytest.raises(ExtensionIntegrationError, match="开启指令"):
|
||||
handler._mode_creation_activation_entries([{"capability": red}])
|
||||
|
||||
|
||||
def test_scene_defaults_never_fall_back_to_color_only_refs():
|
||||
context = {"peripheral_actions": [{
|
||||
"ref": "ir:strip-red", "device_label": "灯带", "action_label": "红色",
|
||||
}]}
|
||||
assert scene_required_peripheral_refs("中秋模式", context) == []
|
||||
|
||||
|
||||
def test_romantic_import_adds_ordered_lights_without_requiring_cinema_base(tmp_path: Path):
|
||||
service = SeatDemoService(REPOSITORY_ROOT)
|
||||
service.mode_profiles = ModeProfileRegistry(tmp_path / "presets", user_root=tmp_path / "modes")
|
||||
@@ -92,9 +123,9 @@ def test_romantic_import_adds_ordered_lights_without_requiring_cinema_base(tmp_p
|
||||
profile = service.get_mode_profile_card("romantic-date", "denza_n7")
|
||||
actions = profile.command_flow["source_scene"]["actions"]
|
||||
assert actions[0] == climate
|
||||
assert [item["parameters"]["slot"] for item in actions[1:]] == [2, 3, 22, 23, 41, 51, 52]
|
||||
assert [item["parameters"]["slot"] for item in actions[1:]] == [2, 22, 41, 51]
|
||||
scene = profile.command_flow["source_scene"]
|
||||
assert len(profile.operations) == 8
|
||||
assert len(profile.operations) == 5
|
||||
finally:
|
||||
service.close()
|
||||
|
||||
@@ -113,7 +144,7 @@ def test_saved_romantic_mode_orders_real_dispatch_and_stops_on_power_failure(tmp
|
||||
}})
|
||||
entries = handler._saved_mode_infrared_entries(profile)
|
||||
capabilities = [entry["capability"] for entry in entries]
|
||||
assert [item["slot"] for item in capabilities] == [2, 3, 22, 23, 41, 51, 52]
|
||||
assert [item["slot"] for item in capabilities] == [2, 22, 41, 51]
|
||||
sent = []
|
||||
|
||||
def send(_command, parameters):
|
||||
@@ -130,5 +161,5 @@ def test_saved_romantic_mode_orders_real_dispatch_and_stops_on_power_failure(tmp
|
||||
{"kind": "peripheral", "capability_id": item["id"]} for item in capabilities
|
||||
]}, capabilities, conversation_id="romantic-order-test", execution_mode="hardware",
|
||||
)
|
||||
assert sent == ([2] if fail_power else [2, 3, 22, 23, 41, 51, 52])
|
||||
assert sent == ([2] if fail_power else [2, 22, 41, 51])
|
||||
assert result["status"] == ("failed" if fail_power else "succeeded")
|
||||
|
||||
Reference in New Issue
Block a user