feat: update CAN integration and T2G seat firmware

This commit is contained in:
vee
2026-08-01 15:55:21 +08:00
parent 8cda026ac2
commit 4aded5c21d
1443 changed files with 1007122 additions and 4978 deletions
+57 -23
View File
@@ -9,27 +9,27 @@ class LocalIntentParserTests(unittest.TestCase):
@staticmethod
def context(level: int = 0) -> dict:
return {
"last_target": "driver" if level else None,
"last_target": "passenger" if level else None,
"devices": {
"driver": {
"ventilation": {"state": "on" if level else "off", "level": level},
"ventilation": {"state": "off", "level": 0},
"heating": {"state": "off", "level": 0},
},
"passenger": {
"ventilation": {"state": "off", "level": 0},
"ventilation": {"state": "on" if level else "off", "level": level},
"heating": {"state": "off", "level": 0},
},
},
}
def test_parses_driver_ventilation_on(self) -> None:
result = parse_local_intent("打开主驾座椅通风")
def test_parses_passenger_ventilation_on(self) -> None:
result = parse_local_intent("打开副驾座椅通风")
self.assertEqual(
result["actions"],
[
{
"target": "driver",
"target": "passenger",
"function": "ventilation",
"state": "on",
"requested_level": None,
@@ -38,31 +38,65 @@ class LocalIntentParserTests(unittest.TestCase):
)
self.assertEqual(result["ambiguities"], [])
def test_expands_front_seats(self) -> None:
def test_rejects_scope_that_includes_driver(self) -> None:
result = parse_local_intent("主副驾座椅通风都打开")
self.assertEqual({item["target"] for item in result["actions"]}, {"driver", "passenger"})
self.assertTrue(all(item["state"] == "on" for item in result["actions"]))
def test_keeps_requested_level_for_safety_validation(self) -> None:
result = parse_local_intent("主驾座椅加热开到三档")
self.assertEqual(result["actions"][0]["requested_level"], 3)
def test_requires_target(self) -> None:
result = parse_local_intent("打开座椅通风")
self.assertEqual(result["actions"], [])
self.assertEqual(result["ambiguities"][0]["field"], "target")
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
def test_keeps_requested_level_for_safety_validation(self) -> None:
result = parse_local_intent("副驾座椅加热开到三档")
self.assertEqual(result["actions"][0]["requested_level"], 3)
def test_defaults_missing_target_to_passenger(self) -> None:
result = parse_local_intent("打开座椅通风")
self.assertEqual(result["actions"][0]["target"], "passenger")
self.assertEqual(result["ambiguities"], [])
def test_parses_four_axis_zero_for_passenger(self) -> None:
result = parse_local_intent("把水平、坐盆、靠背、腿托四轴归零")
self.assertEqual(result["ambiguities"], [])
self.assertEqual(
[(action["axis"], action["position_pct"]) for action in result["actions"]],
[
("longitudinal", 0),
("cushion_tilt", 0),
("backrest_recline", 0),
("legrest_height", 0),
],
)
self.assertTrue(
all(action["target"] == "passenger" for action in result["actions"])
)
def test_parses_explicit_motion_percentages(self) -> None:
result = parse_local_intent("副驾水平移到63%,靠背调到54%")
self.assertEqual(result["ambiguities"], [])
self.assertEqual(
[(action["axis"], action["position_pct"]) for action in result["actions"]],
[("longitudinal", 63), ("backrest_recline", 54)],
)
def test_rejects_driver_four_axis_zero(self) -> None:
result = parse_local_intent("把主驾座椅四轴归零")
self.assertEqual(result["actions"], [])
self.assertEqual(result["ambiguities"][0]["field"], "target")
self.assertIn("仅控制副驾", result["ambiguities"][0]["question"])
def test_maps_mild_hot_and_stuffy_feedback_to_level_one(self) -> None:
result = parse_local_intent("主驾有点热,有点闷", self.context())
result = parse_local_intent("副驾有点热,有点闷", self.context())
self.assertEqual(
result["actions"],
[
{
"target": "driver",
"target": "passenger",
"function": "ventilation",
"state": "on",
"requested_level": 1,
@@ -75,7 +109,7 @@ class LocalIntentParserTests(unittest.TestCase):
result = parse_local_intent("还有点闷", self.context(level=1))
self.assertEqual(result["actions"][0]["requested_level"], 2)
self.assertEqual(result["actions"][0]["target"], "driver")
self.assertEqual(result["actions"][0]["target"], "passenger")
self.assertIn("提升到2档", "".join(result["decision_summary"]))
def test_cold_feedback_reduces_active_ventilation_before_heating(self) -> None:
@@ -85,7 +119,7 @@ class LocalIntentParserTests(unittest.TestCase):
result["actions"],
[
{
"target": "driver",
"target": "passenger",
"function": "ventilation",
"state": "off",
"requested_level": None,
@@ -114,7 +148,7 @@ class LocalIntentParserTests(unittest.TestCase):
self.assertIn("致冷来源", "".join(result["decision_summary"]))
def test_cold_and_stuffy_are_independent_comfort_dimensions(self) -> None:
result = parse_local_intent("主驾有点冷、有点闷", self.context())
result = parse_local_intent("副驾有点冷、有点闷", self.context())
self.assertEqual(
{
@@ -24,7 +24,7 @@ class MatrixCompilerTests(unittest.TestCase):
self.compiler = SeatCompiler(DOMAIN_ROOT / "can" / "signal-mapping.yaml")
def test_encodes_combined_control_bits(self) -> None:
parsed = parse_local_intent("打开主驾座椅通风,同时关闭副驾座椅加热")
parsed = parse_local_intent("打开副驾座椅通风,同时关闭副驾座椅加热")
config = build_function_config(parsed, "req-test-001", "local_rules")
plan = self.compiler.compile(config)
command = plan["spec"]["commands"][0]
@@ -32,7 +32,7 @@ class MatrixCompilerTests(unittest.TestCase):
frame = self.matrix.encode(command["message"], command["signals"])
self.assertEqual(frame["frame_id"], "0x42A")
self.assertEqual(frame["data_hex"], "01 80")
self.assertEqual(frame["data_hex"], "00 90")
def test_compilation_is_deterministic(self) -> None:
parsed = parse_local_intent("关闭副驾座椅通风")
@@ -46,20 +46,20 @@ class MatrixCompilerTests(unittest.TestCase):
"actions": [
{
"action_type": "position",
"target": "driver",
"target": "passenger",
"axis": "longitudinal",
"position_pct": 35,
},
{
"action_type": "position",
"target": "driver",
"target": "passenger",
"axis": "backrest_recline",
"position_pct": 60,
},
],
"deferred_requests": [],
"ambiguities": [],
"decision_summary": ["Move two driver-seat axes."],
"decision_summary": ["Move two front-passenger-seat axes."],
"confidence": 1.0,
}
config = build_function_config(parsed, "req-motion-001", "test")
@@ -68,15 +68,15 @@ class MatrixCompilerTests(unittest.TestCase):
self.assertEqual(len(plan["spec"]["commands"]), 2)
first, second = plan["spec"]["commands"]
self.assertEqual(first["message"], "Driver_Seat_Motion_Command_550")
self.assertEqual(first["message"], "Passenger_Seat_Motion_Command_551")
self.assertEqual(first["signals"]["Longitudinal_Target_Pct"], 35)
self.assertEqual(first["signals"]["Motion_Enable_Mask"], 1)
self.assertEqual(first["completion"]["message"], "Driver_Seat_Motion_Status_558")
self.assertEqual(first["completion"]["message"], "Passenger_Seat_Motion_Status_559")
self.assertEqual(first["completion"]["signal"], "Longitudinal_Actual_Pct")
self.assertEqual(second["signals"]["Backrest_Recline_Target_Pct"], 60)
self.assertEqual(second["signals"]["Motion_Enable_Mask"], 4)
frame = self.combined_matrix.encode(first["message"], first["signals"])
self.assertEqual(frame["frame_id"], "0x550")
self.assertEqual(frame["frame_id"], "0x551")
self.assertEqual(frame["payload_size"], 8)
File diff suppressed because it is too large Load Diff