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
@@ -27,7 +27,7 @@ class SeatContractTests(unittest.TestCase):
self.assertEqual(self.validator.validate(config), [])
def test_inferred_level_function_config_matches_both_schemas(self) -> None:
parsed = parse_local_intent("主驾有点热,有点闷")
parsed = parse_local_intent("副驾有点热,有点闷")
config = build_function_config(parsed, "req-contract-002", "local_rules")
self.assertEqual(config["spec"]["operations"][0]["parameters"]["level"], 1)
@@ -6,6 +6,7 @@ from pathlib import Path
from unittest.mock import patch
from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService
from cognitive_agent.infrastructure.llm.openai_responses import OpenAIIntentError
class SeatServiceIntegrationTests(unittest.TestCase):
@@ -17,13 +18,13 @@ class SeatServiceIntegrationTests(unittest.TestCase):
def test_supported_request_completes_full_dry_run(self) -> None:
result = self.service.process(
"打开主驾座椅通风,同时关闭副驾座椅加热", provider="local"
"打开副驾座椅通风,同时关闭副驾座椅加热", provider="local"
)
self.assertEqual(result["status"], "succeeded")
self.assertEqual(len(result["function_config"]["spec"]["operations"]), 2)
telemetry = result["execution_report"]["spec"]["results"][0]["telemetry"]
self.assertEqual(telemetry["command_frame"]["data_hex"], "01 80")
self.assertEqual(telemetry["command_frame"]["data_hex"], "00 90")
self.assertTrue(Path(result["artifact_path"]).is_absolute())
self.assertTrue(
(self.service.artifact_root / result["request_id"] / "result.json").is_file()
@@ -32,7 +33,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
self.assertEqual(self.service.contracts.validate(event), [])
def test_gear_request_is_preserved_and_simulated(self) -> None:
result = self.service.process("主驾座椅加热开到三档", provider="local")
result = self.service.process("副驾座椅加热开到三档", provider="local")
self.assertEqual(result["status"], "succeeded")
operation = result["function_config"]["spec"]["operations"][0]
@@ -48,21 +49,21 @@ class SeatServiceIntegrationTests(unittest.TestCase):
conversation_id = "conv-test-context"
first = self.service.process(
"主驾有点热,有点闷",
"副驾有点热,有点闷",
provider="local",
conversation_id=conversation_id,
)
second = self.service.process(
"主驾还有点闷",
"副驾还有点闷",
provider="local",
conversation_id=conversation_id,
)
self.assertEqual(first["status"], "succeeded")
self.assertEqual(first["actuator_state"]["driver"]["ventilation"]["level"], 1)
self.assertEqual(first["actuator_state"]["passenger"]["ventilation"]["level"], 1)
self.assertEqual(second["status"], "succeeded")
self.assertEqual(second["conversation_turn"], 2)
self.assertEqual(second["actuator_state"]["driver"]["ventilation"]["level"], 2)
self.assertEqual(second["actuator_state"]["passenger"]["ventilation"]["level"], 2)
operation = second["function_config"]["spec"]["operations"][0]
self.assertEqual(operation["parameters"], {"state": "on", "level": 2})
self.assertIn("提升到2档", "".join(second["decision_summary"]))
@@ -94,12 +95,15 @@ class SeatServiceIntegrationTests(unittest.TestCase):
self.assertEqual(fourth_operation["target"]["instance"], "passenger")
self.assertEqual(fourth_operation["capability"], "seat.set_ventilation")
self.assertEqual(fourth_operation["parameters"], {"state": "off"})
self.assertEqual(fourth["actuator_state"]["driver"]["heating"], {"state": "on", "level": 1})
self.assertEqual(
fourth["actuator_state"]["passenger"]["heating"],
{"state": "on", "level": 1},
)
self.assertEqual(fourth["conversation_turn"], 4)
def test_compound_cold_and_stuffy_feedback_generates_balanced_dry_run(self) -> None:
result = self.service.process(
"主驾有点冷、有点闷",
"副驾有点冷、有点闷",
provider="local",
conversation_id="conv-compound-comfort",
)
@@ -113,7 +117,10 @@ class SeatServiceIntegrationTests(unittest.TestCase):
command = result["command_plan"]["spec"]["commands"][0]
self.assertEqual(
command["signals"],
{"Driver_Seat_Heating_S": 1, "Driver_Seat_Ventilation_S": 1},
{
"Front_Passenger_Seat_Heating_S": 1,
"Front_Passenger_Seat_Ventilation_S": 1,
},
)
self.assertIn(
"COMBINED_THERMAL_SIMULATED",
@@ -179,6 +186,30 @@ class SeatServiceIntegrationTests(unittest.TestCase):
"车上太闷了", context, self.service.capability_context
)
def test_explicit_gpt_failure_falls_back_to_local_rules(self) -> None:
self.service.openai.api_key = "test-key"
with patch.object(
self.service.openai,
"interpret",
side_effect=OpenAIIntentError("invalid_api_key"),
):
result = self.service.process(
"打开副驾座椅通风",
"openai",
"conv-explicit-gpt-fallback",
)
self.assertEqual(result["status"], "succeeded")
self.assertEqual(result["provider_used"], "local_rules_fallback")
self.assertEqual(
result["function_config"]["spec"]["operations"][0]["target"]["instance"],
"passenger",
)
self.assertTrue(
any("已降级到本地规则解析" in item for item in result["decision_summary"])
)
def test_model_climate_request_completes_domain_loop(self) -> None:
model_output = {
"detected_domains": ["climate"],
@@ -220,13 +251,13 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_heating",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "activate",
"parameters": [
{"name": "state", "value": "on"},
{"name": "level", "value": 1},
],
"reason": "Warm the driver seat.",
"reason": "Warm the passenger seat.",
},
{
"domain": "climate",
@@ -245,14 +276,17 @@ class SeatServiceIntegrationTests(unittest.TestCase):
with patch.object(self.service.openai, "interpret", return_value=model_output):
result = self.service.process(
"主驾有点冷、有点闷",
"副驾有点冷、有点闷",
"openai",
"conv-model-partial",
)
self.assertEqual(result["status"], "succeeded")
self.assertIsNotNone(result["execution_report"])
self.assertEqual(result["actuator_state"]["driver"]["heating"], {"state": "on", "level": 1})
self.assertEqual(
result["actuator_state"]["passenger"]["heating"],
{"state": "on", "level": 1},
)
self.assertEqual(result["domain_state"]["climate"]["fan_level"], 2)
self.assertEqual(set(result["function_configs"]), {"seat", "climate"})
self.assertEqual(result["scene_config"]["kind"], "SceneConfig")
@@ -264,18 +298,18 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_longitudinal_position",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "set",
"parameters": [{"name": "position_pct", "value": 35}],
"reason": "Move the driver seat backward from its current midpoint.",
"reason": "Move the passenger seat backward from its current midpoint.",
},
{
"domain": "seat",
"capability": "seat.set_backrest_recline",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "set",
"parameters": [{"name": "position_pct", "value": 60}],
"reason": "Recline the driver backrest.",
"reason": "Recline the passenger backrest.",
},
{
"domain": "seat",
@@ -302,7 +336,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
with patch.object(self.service.openai, "interpret", return_value=model_output):
result = self.service.process(
"主驾往后一点并把靠背躺下,副驾腿托升起并伸长",
"副驾往后一点并把靠背躺下,腿托升起并伸长",
"openai",
"conv-model-motion",
)
@@ -311,20 +345,18 @@ class SeatServiceIntegrationTests(unittest.TestCase):
self.assertEqual(len(result["function_config"]["spec"]["operations"]), 4)
self.assertEqual(len(result["command_plan"]["spec"]["commands"]), 4)
self.assertEqual(len(result["execution_report"]["spec"]["results"]), 4)
driver = result["actuator_state"]["driver"]["position"]
passenger = result["actuator_state"]["passenger"]["position"]
self.assertEqual(driver["longitudinal"]["position_pct"], 35)
self.assertEqual(driver["backrest_recline"]["position_pct"], 60)
self.assertEqual(passenger["longitudinal"]["position_pct"], 35)
self.assertEqual(passenger["backrest_recline"]["position_pct"], 60)
self.assertEqual(passenger["legrest_height"]["position_pct"], 65)
self.assertEqual(passenger["legrest_extension"]["position_pct"], 70)
telemetry = result["execution_report"]["spec"]["results"][0]["telemetry"]
self.assertEqual(telemetry["start_position_pct"], 50)
self.assertEqual(telemetry["effective_position_pct"], 35)
self.assertEqual(telemetry["feedback_frame"]["frame_id"], "0x558")
self.assertEqual(telemetry["feedback_frame"]["frame_id"], "0x559")
self.assertEqual(telemetry["fault_mask"], 0)
codes = {issue["code"] for issue in result["validation"]}
self.assertIn("SYNTHETIC_MOTION_CAN", codes)
self.assertIn("DRIVER_MOTION_INTERLOCK_NOT_IMPLEMENTED", codes)
def test_motion_follow_up_state_is_supplied_to_model(self) -> None:
def output(position: int) -> dict[str, object]:
@@ -334,7 +366,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_longitudinal_position",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "increase",
"parameters": [{"name": "position_pct", "value": position}],
"reason": "Model resolved the relative request.",
@@ -352,27 +384,29 @@ class SeatServiceIntegrationTests(unittest.TestCase):
side_effect=[output(60), output(70)],
) as interpret:
first = self.service.process(
"主驾往后一点", "openai", "conv-motion-follow-up"
"副驾往后一点", "openai", "conv-motion-follow-up"
)
second = self.service.process(
"还是靠前,再往后一点", "openai", "conv-motion-follow-up"
)
self.assertEqual(
first["actuator_state"]["driver"]["position"]["longitudinal"][
first["actuator_state"]["passenger"]["position"]["longitudinal"][
"position_pct"
],
60,
)
self.assertEqual(
second["actuator_state"]["driver"]["position"]["longitudinal"][
second["actuator_state"]["passenger"]["position"]["longitudinal"][
"position_pct"
],
70,
)
second_context = interpret.call_args_list[1].args[1]
self.assertEqual(
second_context["devices"]["driver"]["position"]["longitudinal"]["position_pct"],
second_context["devices"]["passenger"]["position"]["longitudinal"][
"position_pct"
],
60,
)
@@ -383,7 +417,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_longitudinal_position",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "decrease",
"parameters": [{"name": "distance_mm", "value": 50}],
"reason": "Move forward by a physical distance.",
@@ -391,7 +425,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_backrest_recline",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "increase",
"parameters": [{"name": "angle_delta_deg", "value": 10}],
"reason": "Recline by a relative physical angle.",
@@ -405,7 +439,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
with patch.object(self.service.openai, "interpret", return_value=model_output) as interpret:
result = self.service.process(
"主驾水平向前移动50毫米,靠背往后10度",
"副驾水平向前移动50毫米,靠背往后10度",
"openai",
"conv-vehicle-profile-relative",
vehicle_id="denza_n7",
@@ -417,22 +451,22 @@ class SeatServiceIntegrationTests(unittest.TestCase):
self.assertEqual(operations[0]["parameters"], {"position_pct": 27})
self.assertEqual(
operations[1]["parameters"],
{"position_pct": 38, "angle_deg": 116},
{"position_pct": 35, "angle_deg": 118.6},
)
backrest_motion = operations[1]["motion"]
self.assertEqual(backrest_motion["mode"], "relative")
self.assertEqual(backrest_motion["direction"], "increase")
self.assertEqual(backrest_motion["start_position_pct"], 20)
self.assertEqual(backrest_motion["delta_position_pct"], 18)
self.assertEqual(backrest_motion["start_angle_deg"], 106.0)
self.assertEqual(backrest_motion["delta_position_pct"], 15)
self.assertEqual(backrest_motion["start_angle_deg"], 108.6)
self.assertEqual(backrest_motion["delta_angle_deg"], 10)
context_sent_to_model = interpret.call_args.args[1]
self.assertEqual(context_sent_to_model["vehicle"]["id"], "denza_n7")
self.assertEqual(
context_sent_to_model["devices"]["driver"]["position"][
context_sent_to_model["devices"]["passenger"]["position"][
"backrest_recline"
]["angle_deg"],
106.0,
108.6,
)
def test_vehicle_profile_angle_limits_are_accepted(self) -> None:
@@ -452,7 +486,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
"capability": "seat.set_legrest_height",
"target_scope": "passenger",
"operation": "set",
"parameters": [{"name": "angle_deg", "value": 173}],
"parameters": [{"name": "angle_deg", "value": 167}],
"reason": "Use the vehicle-specific maximum legrest angle.",
},
],
@@ -464,7 +498,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
with patch.object(self.service.openai, "interpret", return_value=model_output):
result = self.service.process(
"副驾靠背到163度,腿托到173度",
"副驾靠背到163度,腿托到167度",
"openai",
"conv-vehicle-angle-limits",
vehicle_id="denza_n7",
@@ -473,7 +507,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
self.assertEqual(result["status"], "succeeded")
operations = result["function_config"]["spec"]["operations"]
self.assertEqual(operations[0]["parameters"], {"position_pct": 100, "angle_deg": 163})
self.assertEqual(operations[1]["parameters"], {"position_pct": 100, "angle_deg": 173})
self.assertEqual(operations[1]["parameters"], {"position_pct": 100, "angle_deg": 167})
def test_motion_adapter_does_not_resolve_missing_absolute_target(self) -> None:
model_output = {
@@ -482,7 +516,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
{
"domain": "seat",
"capability": "seat.set_longitudinal_position",
"target_scope": "driver",
"target_scope": "passenger",
"operation": "decrease",
"parameters": [],
"reason": "No absolute target was produced.",
@@ -496,7 +530,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
with patch.object(self.service.openai, "interpret", return_value=model_output):
result = self.service.process(
"主驾往后一点", "openai", "conv-motion-missing-target"
"副驾往后一点", "openai", "conv-motion-missing-target"
)
self.assertEqual(result["status"], "needs_confirmation")
@@ -630,7 +664,7 @@ class SeatServiceIntegrationTests(unittest.TestCase):
)
self.assertEqual(
first_operations[1]["parameters"],
{"position_pct": 49, "angle_deg": 133},
{"position_pct": 53, "angle_deg": 133},
)
self.assertEqual(
first["actuator_state"]["passenger"]["position"]["backrest_recline"][
@@ -698,11 +732,53 @@ class SeatServiceIntegrationTests(unittest.TestCase):
apply_context = interpret.call_args_list[4].args[1]
self.assertEqual(apply_context["presets"][0]["name"], "零重力模式")
def test_missing_target_requests_confirmation(self) -> None:
def test_missing_target_defaults_to_passenger(self) -> None:
result = self.service.process("打开座椅通风", provider="local")
self.assertEqual(result["status"], "succeeded")
operation = result["function_config"]["spec"]["operations"][0]
self.assertEqual(operation["target"]["instance"], "passenger")
def test_explicit_driver_target_is_rejected(self) -> None:
result = self.service.process("打开主驾座椅通风", provider="local")
self.assertEqual(result["status"], "needs_confirmation")
self.assertIsNone(result["function_config"])
questions = [
item["question"] for item in result["intent_ir"]["spec"]["ambiguities"]
]
self.assertTrue(any("仅控制副驾" in question for question in questions))
def test_model_driver_target_is_rejected(self) -> None:
model_output = {
"detected_domains": ["seat"],
"requests": [
{
"domain": "seat",
"capability": "seat.set_ventilation",
"target_scope": "driver",
"operation": "activate",
"parameters": [{"name": "state", "value": "on"}],
"reason": "Ventilate the explicitly requested driver seat.",
}
],
"ambiguities": [],
"decision_summary": ["Explicit driver-seat request."],
"confidence": 0.95,
}
self.service.openai.api_key = "test-key"
with patch.object(self.service.openai, "interpret", return_value=model_output):
result = self.service.process(
"打开主驾座椅通风", "openai", "conv-driver-rejected"
)
self.assertEqual(result["status"], "needs_confirmation")
self.assertIsNone(result["function_config"])
questions = [
item["question"] for item in result["intent_ir"]["spec"]["ambiguities"]
]
self.assertTrue(any("仅控制副驾" in question for question in questions))
if __name__ == "__main__":
+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