feat: synchronize CH1 vehicle control and feedback
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from cognitive_agent.application.conversation_state import ConversationStateStore
|
||||
|
||||
|
||||
class NativeStateSyncTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.store = ConversationStateStore()
|
||||
|
||||
def apply(self, action: dict) -> dict:
|
||||
return self.store.apply_successful_actions(
|
||||
"conv-native-sync",
|
||||
"test",
|
||||
[{**action, "feedback_source": "physical_can_ch1"}],
|
||||
[],
|
||||
)
|
||||
|
||||
def test_driver_seat_native_feedback_never_updates_passenger(self) -> None:
|
||||
state = self.apply(
|
||||
{
|
||||
"domain": "seat",
|
||||
"capability": "seat.set_driver_heating_native",
|
||||
"target": "driver",
|
||||
"parameters": {"state": "low"},
|
||||
}
|
||||
)
|
||||
self.assertEqual(state["devices"]["driver"]["heating"]["state"], "on")
|
||||
self.assertEqual(state["devices"]["driver"]["heating"]["level"], 1)
|
||||
self.assertEqual(
|
||||
state["devices"]["driver"]["heating"]["feedback_source"],
|
||||
"physical_can_ch1",
|
||||
)
|
||||
self.assertEqual(state["devices"]["passenger"]["heating"]["state"], "off")
|
||||
|
||||
def test_window_feedback_updates_frontend_domain_state(self) -> None:
|
||||
state = self.apply(
|
||||
{
|
||||
"domain": "window",
|
||||
"capability": "window.set_position",
|
||||
"target": "front_left",
|
||||
"parameters": {"position_pct": 25},
|
||||
}
|
||||
)
|
||||
window = state["domain_devices"]["window"]["positions"]["front_left"]
|
||||
self.assertEqual(window["position_pct"], 25)
|
||||
self.assertFalse(window["closed"])
|
||||
self.assertEqual(window["feedback_source"], "physical_can_ch1")
|
||||
|
||||
def test_rear_lock_updates_only_rear_locks(self) -> None:
|
||||
state = self.apply(
|
||||
{
|
||||
"domain": "door",
|
||||
"capability": "door.set_rear_lock",
|
||||
"target": "rear",
|
||||
"parameters": {"state": "lock"},
|
||||
}
|
||||
)
|
||||
locks = state["domain_devices"]["door"]["locks"]
|
||||
self.assertEqual(locks["rear_left"]["state"], "lock")
|
||||
self.assertEqual(locks["rear_right"]["state"], "lock")
|
||||
self.assertEqual(locks["front_left"]["state"], "unknown")
|
||||
|
||||
def test_vehicle_lock_projection_updates_logical_and_all_door_states(self) -> None:
|
||||
state = self.apply(
|
||||
{
|
||||
"domain": "door",
|
||||
"capability": "door.set_vehicle_lock",
|
||||
"target": "vehicle",
|
||||
"parameters": {"state": "lock"},
|
||||
}
|
||||
)
|
||||
door = state["domain_devices"]["door"]
|
||||
self.assertEqual(door["vehicle_lock"]["state"], "lock")
|
||||
self.assertTrue(
|
||||
all(item["state"] == "lock" for item in door["locks"].values())
|
||||
)
|
||||
|
||||
def test_authoritative_ch1_feedback_overrides_requested_ui_projection(self) -> None:
|
||||
state = self.store.synchronize_physical_ch1_feedback(
|
||||
"conv-native-sync",
|
||||
[
|
||||
{
|
||||
"source": "physical_can_ch1",
|
||||
"channel": 1,
|
||||
"frame_id": "0x404",
|
||||
"feedback_frame_id": "0x404",
|
||||
"valid": True,
|
||||
"verification": {
|
||||
"authoritative": True,
|
||||
"channel": 1,
|
||||
"simulated": False,
|
||||
"feedback_required": True,
|
||||
"feedback_observed": True,
|
||||
"feedback_match": True,
|
||||
"frame_id": "0x404",
|
||||
"payload_size": 8,
|
||||
},
|
||||
"actuator_state": {
|
||||
"driver": {
|
||||
"ventilation": {"state": "on", "level": 3},
|
||||
"massage": {"mode": "relax", "strength": "weak"},
|
||||
}
|
||||
},
|
||||
"domain_state": {
|
||||
"climate": {
|
||||
"power": "on",
|
||||
"ac": "on",
|
||||
"control_mode": "manual",
|
||||
"cycle_mode": "internal",
|
||||
"fan_level": 3,
|
||||
"zones": {
|
||||
"driver": {
|
||||
"temperature_c": 24,
|
||||
"outlet_mode": "defrost",
|
||||
}
|
||||
},
|
||||
},
|
||||
"roof": {
|
||||
"shade_position_pct": 2,
|
||||
"motion_state": "stopped",
|
||||
},
|
||||
"ambient_light": {
|
||||
"power": "on",
|
||||
"front_brightness_level": 3,
|
||||
"rear_brightness_level": 3,
|
||||
"front_color_index": 32,
|
||||
"rear_color_index": 32,
|
||||
},
|
||||
"door": {
|
||||
"locks": {
|
||||
"rear_left": {"state": "lock"},
|
||||
"rear_right": {"state": "lock"},
|
||||
}
|
||||
},
|
||||
"window": {
|
||||
"positions": {
|
||||
"front_left": {
|
||||
"position_pct": 9,
|
||||
"closed": False,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(state["devices"]["driver"]["ventilation"]["level"], 3)
|
||||
self.assertEqual(
|
||||
state["devices"]["driver"]["ventilation"]["feedback_source"],
|
||||
"physical_can_ch1",
|
||||
)
|
||||
climate = state["domain_devices"]["climate"]
|
||||
self.assertEqual(climate["zones"]["driver"]["outlet_mode"], "defrost")
|
||||
self.assertEqual(climate["cycle_mode"], "internal")
|
||||
self.assertEqual(climate["feedback_source"], "physical_can_ch1")
|
||||
self.assertEqual(state["domain_devices"]["roof"]["shade_position_pct"], 2)
|
||||
self.assertEqual(state["domain_devices"]["ambient_light"]["brightness_pct"], 100)
|
||||
self.assertEqual(
|
||||
state["domain_devices"]["door"]["locks"]["rear_left"]["feedback_source"],
|
||||
"physical_can_ch1",
|
||||
)
|
||||
self.assertEqual(
|
||||
state["domain_devices"]["window"]["positions"]["front_left"]["position_pct"],
|
||||
9,
|
||||
)
|
||||
self.assertNotIn(
|
||||
"feedback_source",
|
||||
state["domain_devices"]["window"]["positions"]["rear_left"],
|
||||
)
|
||||
self.assertNotIn(
|
||||
"feedback_source",
|
||||
state["domain_devices"]["door"]["locks"]["front_left"],
|
||||
)
|
||||
|
||||
def test_non_authoritative_feedback_is_ignored(self) -> None:
|
||||
before = self.store.snapshot("conv-native-sync")
|
||||
after = self.store.synchronize_physical_ch1_feedback(
|
||||
"conv-native-sync",
|
||||
[
|
||||
{
|
||||
"source": "physical_can_ch0",
|
||||
"channel": 0,
|
||||
"valid": True,
|
||||
"domain_state": {"climate": {"power": "on"}},
|
||||
}
|
||||
],
|
||||
)
|
||||
self.assertEqual(after, before)
|
||||
|
||||
def test_unverified_or_empty_feedback_never_updates_state(self) -> None:
|
||||
before = self.store.snapshot("conv-native-sync")
|
||||
for feedback in (
|
||||
{
|
||||
"source": "physical_can_ch1",
|
||||
"channel": 1,
|
||||
"frame_id": "0x404",
|
||||
"feedback_frame_id": "0x404",
|
||||
"valid": True,
|
||||
"domain_state": {"climate": {"power": "on"}},
|
||||
},
|
||||
{
|
||||
"source": "physical_can_ch1",
|
||||
"channel": 1,
|
||||
"frame_id": "0x404",
|
||||
"feedback_frame_id": "0x404",
|
||||
"valid": True,
|
||||
"verification": {
|
||||
"authoritative": True,
|
||||
"channel": 1,
|
||||
"simulated": False,
|
||||
"feedback_required": True,
|
||||
"feedback_observed": True,
|
||||
"feedback_match": True,
|
||||
"frame_id": "0x404",
|
||||
"payload_size": 8,
|
||||
},
|
||||
},
|
||||
):
|
||||
with self.subTest(feedback=feedback):
|
||||
after = self.store.synchronize_physical_ch1_feedback(
|
||||
"conv-native-sync", [feedback]
|
||||
)
|
||||
self.assertEqual(after, before)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user