feat: improve mode and peripheral orchestration
This commit is contained in:
@@ -1406,6 +1406,15 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
def test_main_peripheral_sequence_executes_validated_actions_and_delays(self) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
catalog = [
|
||||
{
|
||||
"id": "on",
|
||||
"status": "learned",
|
||||
"device_id": "third-party-light",
|
||||
"device_name": "第三方氛围灯",
|
||||
"card_uid": "1A53DD95",
|
||||
"action": "打开灯光",
|
||||
"slot": 1,
|
||||
},
|
||||
{
|
||||
"id": "red",
|
||||
"status": "learned",
|
||||
@@ -1457,16 +1466,24 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
result["orchestration_route"], "nfc_peripheral_sequence"
|
||||
)
|
||||
self.assertEqual(result["sequence"]["step_count"], 3)
|
||||
self.assertEqual(result["sequence"]["action_count"], 2)
|
||||
self.assertEqual(result["sequence"]["emit_count"], 2)
|
||||
self.assertEqual(result["sequence"]["step_count"], 4)
|
||||
self.assertEqual(result["sequence"]["action_count"], 3)
|
||||
self.assertEqual(result["sequence"]["emit_count"], 3)
|
||||
self.assertEqual(result["sequence"]["total_delay_ms"], 5000)
|
||||
self.assertEqual(result["sequence"]["steady_blink_fallbacks"], 1)
|
||||
self.assertEqual(
|
||||
[item["status"] for item in result["operation_results"]],
|
||||
["succeeded", "succeeded", "succeeded"],
|
||||
["succeeded", "succeeded", "succeeded", "succeeded"],
|
||||
)
|
||||
self.assertEqual(
|
||||
[
|
||||
item["parameters"]["slot"]
|
||||
for item in result["function_config"]["spec"]["operations"]
|
||||
],
|
||||
[1, 3, 4],
|
||||
)
|
||||
sleep.assert_any_call(5.0)
|
||||
sleep.assert_any_call(0.8)
|
||||
self.assertNotIn(0.5, [call.args[0] for call in sleep.call_args_list])
|
||||
|
||||
def test_failed_first_emit_retains_complete_compiled_infrared_plan(self) -> None:
|
||||
@@ -1630,6 +1647,107 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
)
|
||||
)
|
||||
|
||||
def test_color_only_request_automatically_executes_power_on_first(self) -> None:
|
||||
with TemporaryDirectory() as directory:
|
||||
service = SelfExtensionService(
|
||||
SimulationGateway(),
|
||||
catalog_db_path=Path(directory, "infrared.sqlite3"),
|
||||
)
|
||||
service.sync_peripheral_catalog(
|
||||
[
|
||||
{
|
||||
"id": "flash-on",
|
||||
"status": "learned",
|
||||
"enabled": True,
|
||||
"device_id": "flash-light",
|
||||
"device_name": "闪烁灯",
|
||||
"object_names": ["闪烁灯"],
|
||||
"card_uid": "2CC8B103",
|
||||
"action": "打开",
|
||||
"action_names": ["打开", "开启", "启动"],
|
||||
"slot": 1,
|
||||
},
|
||||
{
|
||||
"id": "flash-blue",
|
||||
"status": "learned",
|
||||
"enabled": True,
|
||||
"device_id": "flash-light",
|
||||
"device_name": "闪烁灯",
|
||||
"object_names": ["闪烁灯"],
|
||||
"card_uid": "2CC8B103",
|
||||
"action": "切换为蓝色",
|
||||
"action_names": ["蓝色", "设置为蓝色"],
|
||||
"slot": 3,
|
||||
},
|
||||
]
|
||||
)
|
||||
color = next(
|
||||
item
|
||||
for item in service.list_peripheral_capabilities()
|
||||
if item["id"] == "flash-blue"
|
||||
)
|
||||
|
||||
result = service.execute_peripheral_request(
|
||||
"把闪烁灯设置为蓝色",
|
||||
color,
|
||||
conversation_id="conv-color-power-dependency",
|
||||
execution_mode="dry_run",
|
||||
)
|
||||
|
||||
self.assertEqual(result["status"], "succeeded")
|
||||
self.assertEqual(result["sequence"]["action_count"], 2)
|
||||
self.assertEqual(
|
||||
[
|
||||
item["parameters"]["slot"]
|
||||
for item in result["function_config"]["spec"]["operations"]
|
||||
],
|
||||
[1, 3],
|
||||
)
|
||||
self.assertEqual(
|
||||
[
|
||||
item["signals"]["slot"]
|
||||
for item in result["command_plan"]["spec"]["commands"]
|
||||
],
|
||||
[1, 3],
|
||||
)
|
||||
service.close()
|
||||
|
||||
def test_color_request_is_rejected_when_power_on_is_not_authorized(self) -> None:
|
||||
with TemporaryDirectory() as directory:
|
||||
service = SelfExtensionService(
|
||||
SimulationGateway(),
|
||||
catalog_db_path=Path(directory, "infrared.sqlite3"),
|
||||
)
|
||||
service.sync_peripheral_catalog(
|
||||
[
|
||||
{
|
||||
"id": "strip-red",
|
||||
"status": "learned",
|
||||
"enabled": True,
|
||||
"device_id": "light-strip",
|
||||
"device_name": "灯带",
|
||||
"object_names": ["灯带"],
|
||||
"card_uid": "1A3AB103",
|
||||
"action": "切换为红色",
|
||||
"action_names": ["红色", "设置为红色"],
|
||||
"slot": 24,
|
||||
}
|
||||
]
|
||||
)
|
||||
color = service.list_peripheral_capabilities()[0]
|
||||
|
||||
with self.assertRaisesRegex(
|
||||
ExtensionIntegrationError,
|
||||
"设置颜色前需要先打开",
|
||||
):
|
||||
service.execute_peripheral_request(
|
||||
"把灯带设置为红色",
|
||||
color,
|
||||
conversation_id="conv-color-missing-power",
|
||||
execution_mode="dry_run",
|
||||
)
|
||||
service.close()
|
||||
|
||||
def test_color_sequence_never_cycles_the_power_off_capability(self) -> None:
|
||||
service = SelfExtensionService(SimulationGateway())
|
||||
catalog = [
|
||||
|
||||
Reference in New Issue
Block a user