优化了副驾座椅控制

This commit is contained in:
minghanchen
2026-08-25 11:39:41 +08:00
parent 33c92d1352
commit 9ac8fdface
34 changed files with 31714 additions and 289 deletions
+232
View File
@@ -0,0 +1,232 @@
from __future__ import annotations
import os
from pathlib import Path
import tempfile
from unittest.mock import patch
import pytest
from cognitive_agent.application.direct_can_control import build_direct_can_intent
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
def test_driver_device_batch_keeps_each_exact_control_independent() -> None:
commands = [
"seat driver vent low",
"seat driver heat off",
"seat driver massage mode stretch",
"seat driver massage strength strong",
]
normalized, parsed = build_direct_can_intent(commands)
assert normalized == commands
assert [item["capability"] for item in parsed["native_can_actions"]] == [
"seat.set_driver_ventilation_native",
"seat.set_driver_heating_native",
"seat.set_driver_massage_native",
"seat.set_driver_massage_native",
]
assert [item["parameters"] for item in parsed["native_can_actions"]] == [
{"state": "on", "level": 2},
{"state": "off"},
{"action": "mode", "mode": "stretch"},
{"action": "strength", "strength": 3},
]
assert {
item["parse_source"] for item in parsed["native_can_actions"]
} == {"direct_control"}
def test_passenger_device_batch_builds_can0_position_action() -> None:
normalized, parsed = build_direct_can_intent(
["seat passenger backrest position 36"]
)
assert normalized == ["seat passenger backrest position 36"]
assert parsed["native_can_actions"] == []
assert parsed["actions"] == [
{
"target": "passenger",
"action_type": "position",
"axis": "backrest_recline",
"position_pct": 36,
"parse_source": "direct_control",
"source_span": "seat passenger backrest position 36",
}
]
def test_passenger_can0_canonical_absolute_relative_thermal_and_dynamic() -> None:
context = {
"devices": {
"passenger": {
"position": {
"longitudinal": {"position_pct": 40},
"cushion_tilt": {"position_pct": 50},
"backrest_recline": {"position_pct": 60},
"legrest_height": {"position_pct": 70},
}
}
}
}
commands = [
"seat passenger horizontal position 35",
"seat passenger basin relative up 10",
"seat passenger vent medium",
"seat passenger dynamic rocking-horse",
"seat passenger dynamic stop",
]
normalized, parsed = build_direct_can_intent(commands, context)
assert normalized == commands
assert parsed["detected_domains"] == ["seat"]
assert parsed["actions"][0]["axis"] == "longitudinal"
assert parsed["actions"][0]["position_pct"] == 35
assert parsed["actions"][1]["axis"] == "cushion_tilt"
assert parsed["actions"][1]["position_pct"] == 40
assert parsed["actions"][1]["motion_intent"] == {
"mode": "relative",
"direction": "decrease",
"start_position_pct": 50,
"delta_position_pct": 10,
}
assert parsed["actions"][2]["function"] == "ventilation"
assert parsed["actions"][2]["requested_level"] == 2
assert parsed["actions"][3]["action_type"] == "dynamic_mode"
assert parsed["actions"][3]["mode_id"] == 1
assert parsed["actions"][4]["action_type"] == "dynamic_mode_stop"
def test_passenger_can0_relative_command_requires_current_position() -> None:
with pytest.raises(ValueError, match="requires a valid current"):
build_direct_can_intent(
["seat passenger horizontal relative forward 10"],
{"devices": {"passenger": {"position": {}}}},
)
@pytest.mark.parametrize(
"commands",
(
[],
["seat driver vent medium"],
["seat passenger height position 101"],
["headlight low-beam on"],
),
)
def test_direct_batch_rejects_non_whitelisted_commands(commands: list[str]) -> None:
with pytest.raises(ValueError):
build_direct_can_intent(commands)
def test_service_direct_batch_bypasses_natural_language_interpreter() -> None:
with tempfile.TemporaryDirectory() as directory, patch.dict(
os.environ,
{
"COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false",
"COGNITIVE_AGENT_VEHICLE_CAN_ENABLED": "false",
},
clear=False,
):
service = SeatDemoService(REPOSITORY_ROOT)
service.artifact_root = Path(directory) / "artifacts"
with patch.object(
service,
"_interpret",
side_effect=AssertionError("natural-language parsing must not run"),
):
result = service.process_can_commands(
[
"ac on",
"ac temp driver 24",
"ac fan 2",
"ac cycle internal",
],
execution_mode="dry_run",
control_transport="wireless_mqtt",
)
assert result["status"] == "succeeded"
assert result["provider_used"] == "direct_can_control"
assert result["control_transport"] == "wireless_mqtt"
assert result["can_commands"] == [
"ac on",
"ac temp driver 24",
"ac fan 2",
"ac cycle internal",
]
operations = [
operation
for configuration in result["function_configs"].values()
for operation in configuration["spec"]["operations"]
]
assert [item["capability"] for item in operations] == [
"climate.set_power",
"climate.set_temperature",
"climate.set_fan_level",
"climate.set_cycle_mode",
]
assert {item["parse_source"] for item in operations} == {"direct_control"}
def test_service_direct_batch_combines_can0_and_can1_semantics() -> None:
with tempfile.TemporaryDirectory() as directory, patch.dict(
os.environ,
{
"COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false",
"COGNITIVE_AGENT_VEHICLE_CAN_ENABLED": "false",
},
clear=False,
):
service = SeatDemoService(REPOSITORY_ROOT)
service.artifact_root = Path(directory) / "artifacts"
result = service.process_can_commands(
[
"seat passenger basin relative up 10",
"seat passenger vent medium",
"seat passenger dynamic rocking-horse",
"ac fan 2",
"light ambient on",
],
conversation_id="conv-direct-can0-can1",
execution_mode="dry_run",
)
assert result["status"] == "succeeded"
assert result["can_commands"] == [
"seat passenger basin relative up 10",
"seat passenger vent medium",
"seat passenger dynamic rocking-horse",
"ac fan 2",
"light ambient on",
]
operations = [
operation
for configuration in result["function_configs"].values()
for operation in configuration["spec"]["operations"]
]
by_capability = {item["capability"]: item for item in operations}
assert by_capability["seat.set_cushion_tilt"]["parameters"] == {
"position_pct": 40
}
assert by_capability["seat.set_cushion_tilt"]["motion"] == {
"mode": "relative",
"direction": "decrease",
"start_position_pct": 50,
"delta_position_pct": 10,
}
assert by_capability["seat.start_dynamic_mode"]["parameters"] == {
"mode_id": 1
}
assert by_capability["seat.set_ventilation"]["parameters"] == {
"state": "on",
"level": 2,
}
assert by_capability["climate.set_fan_level"]["parameters"] == {"level": 2}
assert by_capability["ambient_light.set_power"]["parameters"] == {
"state": "on"
}
assert {item["parse_source"] for item in operations} == {"direct_control"}