feat: integrate learned peripherals into mode creation
Expose safe NFC-bound infrared actions to semantic scene composition, require flashing-light actions for romantic and Mid-Autumn modes, and preserve mixed CAN/IR mode flows. Fix NFC device reassignment and retry extension/toy MQTT publication when an active card's binding catalog changes.
This commit is contained in:
@@ -106,6 +106,19 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(synced["count"], 1)
|
||||
self.assertRegex(synced["catalog_revision"], r"^[0-9a-f]{16}$")
|
||||
self.assertEqual(
|
||||
synced["catalog_revision"], service.peripheral_catalog_revision()
|
||||
)
|
||||
with self.assertRaisesRegex(GatewayError, "其他会话更新"):
|
||||
service.sync_peripheral_catalog(
|
||||
[],
|
||||
expected_revision="stale-revision",
|
||||
)
|
||||
self.assertEqual(
|
||||
[item["id"] for item in service.list_peripheral_capabilities()],
|
||||
["toy-001-light-on"],
|
||||
)
|
||||
with closing(sqlite3.connect(database_path)) as connection, connection:
|
||||
connection.execute(
|
||||
"UPDATE infrared_slots SET device_id = '', "
|
||||
@@ -696,6 +709,73 @@ class SelfExtensionTests(unittest.TestCase):
|
||||
self.assertEqual(changed["device_id"], "toy-light-v2")
|
||||
self.assertEqual(service.list_peripheral_capabilities(), [])
|
||||
|
||||
def test_nfc_card_can_be_reassigned_from_existing_to_new_device(self) -> None:
|
||||
with TemporaryDirectory() as directory:
|
||||
service = SelfExtensionService(
|
||||
SimulationGateway(),
|
||||
catalog_db_path=Path(directory, "infrared-slots.sqlite3"),
|
||||
)
|
||||
service.save_infrared_slot(
|
||||
1,
|
||||
{
|
||||
"device_id": "old-light",
|
||||
"object_names": ["旧闪烁灯"],
|
||||
"action_names": ["打开"],
|
||||
"source": "tcp",
|
||||
},
|
||||
)
|
||||
service.save_infrared_slot(
|
||||
21,
|
||||
{
|
||||
"device_id": "new-light",
|
||||
"object_names": ["新灯带"],
|
||||
"action_names": ["打开"],
|
||||
"source": "tcp",
|
||||
},
|
||||
)
|
||||
initial = service.sync_peripheral_catalog(
|
||||
[
|
||||
{
|
||||
"id": "ir-slot:old-light:1",
|
||||
"status": "learned",
|
||||
"enabled": True,
|
||||
"device_id": "old-light",
|
||||
"device_name": "旧闪烁灯",
|
||||
"object_names": ["旧闪烁灯"],
|
||||
"card_uid": "E113B203",
|
||||
"action": "打开",
|
||||
"action_names": ["打开"],
|
||||
"slot": 1,
|
||||
}
|
||||
]
|
||||
)
|
||||
rebound = service.sync_peripheral_catalog(
|
||||
[
|
||||
{
|
||||
"id": "ir-slot:new-light:21",
|
||||
"status": "learned",
|
||||
"enabled": True,
|
||||
"device_id": "new-light",
|
||||
"device_name": "新灯带",
|
||||
"object_names": ["新灯带"],
|
||||
"card_uid": "E113B203",
|
||||
"action": "打开",
|
||||
"action_names": ["打开"],
|
||||
"slot": 21,
|
||||
}
|
||||
],
|
||||
expected_revision=initial["catalog_revision"],
|
||||
)
|
||||
|
||||
self.assertEqual(rebound["count"], 1)
|
||||
self.assertEqual(
|
||||
[
|
||||
(item["device_id"], item["slot"], item["card_uid"])
|
||||
for item in service.list_peripheral_capabilities()
|
||||
],
|
||||
[("new-light", 21, "E113B203")],
|
||||
)
|
||||
|
||||
def test_new_structured_slot_is_parseable_before_nfc_authorization(self) -> None:
|
||||
with TemporaryDirectory() as directory:
|
||||
service = SelfExtensionService(
|
||||
|
||||
Reference in New Issue
Block a user