feat(M06-D): 接入控制箱与Sub-1G门锁业务控制

This commit is contained in:
Codex
2026-06-22 18:38:28 +08:00
parent f71ac09a0b
commit d15fd3f0ff
10 changed files with 685 additions and 9 deletions
@@ -1727,6 +1727,62 @@ async function assertIotMessages(pool, context) {
FROM qipai_iot_dead_letters WHERE topic = '/invalid/topic'`
);
assert.deepEqual(deadRows, [{ errorCode: 'MQTT_TOPIC_INVALID', receiveCount: 1 }]);
await service.handle(`/devicesend/${device.deviceId}`, Buffer.from(JSON.stringify({
DeviceID: device.deviceId,
event: 'record',
type: 'card',
state: 'open',
content: 'PRIVATE-CARD-001',
battery: 9,
timestamp: 1782120001
})));
const [recordRows] = await pool.query(
`SELECT JSON_UNQUOTE(JSON_EXTRACT(raw_payload, '$.content')) AS content,
JSON_UNQUOTE(JSON_EXTRACT(raw_payload, '$.contentHash')) AS contentHash
FROM qipai_iot_device_events
WHERE tenant_id = ? AND event_type = 'record'`,
[context.tenantId]
);
assert.equal(recordRows[0].content, null);
assert.match(recordRows[0].contentHash, /^[a-f0-9]{64}$/);
const [alertRows] = await pool.query(
`SELECT alert_type AS alertType, severity
FROM qipai_device_alerts
WHERE tenant_id = ? AND device_id = ? AND status = 'OPEN'`,
[context.tenantId, device.id]
);
assert.deepEqual(alertRows, [{ alertType: 'LOW_BATTERY', severity: 'HIGH' }]);
await service.createCommand({
tenantId: context.tenantId,
assetId: String(device.id),
storeId: String(device.storeId),
roomId: String(device.roomId),
commandId: '1782120000002',
commandType: 'AddDevice',
payload: { action: 'AddDevice', id: '1782120000002', timeout: 60 },
traceId: 'm06d-pair-test'
});
await service.markPublished(context.tenantId, '1782120000002');
await service.handle(`/devicesend/${device.deviceId}`, Buffer.from(JSON.stringify({
DeviceID: device.deviceId,
id: '1782120000002',
action: 'AddDevice',
result: 'ok',
subID: 'SUB-AUTO-001',
subtype: '14',
timestamp: 1782120002
})));
const [linkRows] = await pool.query(
`SELECT l.sub_id AS subId, l.subtype, d.model
FROM qipai_device_links l
INNER JOIN qipai_devices d
ON d.tenant_id = l.tenant_id AND d.id = l.child_device_id
WHERE l.tenant_id = ? AND l.parent_device_id = ? AND l.sub_id = 'SUB-AUTO-001'`,
[context.tenantId, device.id]
);
assert.deepEqual(linkRows, [{ subId: 'SUB-AUTO-001', subtype: '14', model: '701C' }]);
}
const config = loadConfig();
@@ -1797,7 +1853,7 @@ try {
await executeMigrationPlan(pool, plans.down);
assert.deepEqual(await readCoreTables(pool), []);
await assertLegacyCompatibility(pool);
console.log('PASS: down removed all M01-B through M06-C tables.');
console.log('PASS: down removed all M01-B through M06-C migration tables.');
await executeMigrationPlan(pool, plans.up);
await executeMigrationPlan(pool, plans.verify);
@@ -1925,6 +1981,10 @@ try {
'QoS 1 duplicate event receive count',
'ACK correlation without duplicate side effects',
'invalid Topic dead-letter persistence'
,
'door record credential hashing and masking',
'low-battery alert upsert',
'AddDevice ACK creates 701C parent-child topology'
]
}, null, 2));
} finally {