fix(M06-C-R1): 校正控制箱与门锁协议
This commit is contained in:
@@ -20,9 +20,14 @@ assert.deepEqual(control.controlPower({
|
||||
assert.equal(control.controlDoor({
|
||||
id: '1234567890123', order: 'open'
|
||||
}).action, 'Crldoor');
|
||||
assert.equal(control.playTts({
|
||||
id: '1234567890123', content: '欢迎光临'
|
||||
}).action, 'PlayTTS');
|
||||
assert.deepEqual(control.playTts({
|
||||
id: '1234567890123', content: '欢迎光临', volume: 7, firstPlay: 1,
|
||||
loop: 2, speaker: 3, style: 2, speed: 6, intonation: 4
|
||||
}), {
|
||||
action: 'PlayTTS', content: '欢迎光临', vol: 7, firstPlay: 1,
|
||||
loop: 2, speaker: 3, style: 2, speed: 6, intona: 4,
|
||||
id: '1234567890123'
|
||||
});
|
||||
assert.deepEqual(control.stopTts('1234567890123'), {
|
||||
action: 'stopTTS', id: '1234567890123'
|
||||
});
|
||||
@@ -45,14 +50,26 @@ assert.throws(
|
||||
|
||||
const lock = new JilianSub1GLockAdapter();
|
||||
assert.deepEqual(lock.pair({ id: '123', timeout: 60 }), {
|
||||
action: 'AddDevice', id: '123', timeout: 60
|
||||
action: 'AddDevice', time: 60, id: '123'
|
||||
});
|
||||
assert.deepEqual(lock.control({
|
||||
id: '123', subtype: '14', subID: 'SUB001', order: 'setcard',
|
||||
value: 'a1b2c3d4'
|
||||
}), {
|
||||
action: 'CtrlDevice', subtype: '14', subID: 'SUB001', order: 'setcard',
|
||||
value: 'A1B2C3D4', id: '123'
|
||||
});
|
||||
assert.equal(lock.control({
|
||||
id: '123', subID: 'SUB001', order: 'open', delayTime: 4
|
||||
}).action, 'CtrlDevice');
|
||||
assert.throws(
|
||||
() => lock.control({ id: '123', subID: 'SUB001', order: 'setkey' }),
|
||||
/content is required/
|
||||
() => lock.control({
|
||||
id: '123', subtype: '14', subID: 'SUB001', order: 'setkey', value: '12345'
|
||||
}),
|
||||
/6-digit passwords/
|
||||
);
|
||||
assert.throws(
|
||||
() => lock.control({
|
||||
id: '123', subtype: '15', subID: 'SUB001', order: 'setcard', value: 'not-card'
|
||||
}),
|
||||
/8-digit hex card IDs/
|
||||
);
|
||||
|
||||
const socket = new JilianSmartSocketAdapter();
|
||||
@@ -74,6 +91,17 @@ const ack = control.parseUplink({
|
||||
assert.equal(ack.kind, 'ACK');
|
||||
assert.equal(ack.result, 'unconfirm');
|
||||
assert.equal(ack.eventType, 'task');
|
||||
assert.equal(control.parseUplink({
|
||||
DeviceID: 'BOX_001', id: '124', result: 'paraerror', action: 'PlayTTS'
|
||||
}).result, 'paraerror');
|
||||
assert.equal(control.parseUplink({
|
||||
DeviceID: 'BOX_001', id: '125', result: 'vendor-new-code', action: 'task'
|
||||
}).result, 'UNKNOWN_VENDOR_RESULT');
|
||||
const configVariant = control.parseUplink({
|
||||
DeviceID: 'BOX_001', setting: 'mqttconfig', welvoice: 'hello'
|
||||
});
|
||||
assert.equal(configVariant.eventType, 'mqttConfig');
|
||||
assert.equal(configVariant.payload.welcomevoice, 'hello');
|
||||
const event = lock.parseUplink({
|
||||
deviceID: 'BOX_001', event: 'record', type: 'card', state: 'open',
|
||||
timestamp: 1782120000
|
||||
@@ -81,6 +109,13 @@ const event = lock.parseUplink({
|
||||
assert.equal(event.kind, 'EVENT');
|
||||
assert.equal(event.eventType, 'record');
|
||||
assert.equal(event.eventAt?.getUTCFullYear(), 2026);
|
||||
for (const eventType of ['magstate', 'taskfinish', 'Poweron', 'connected']) {
|
||||
const fixture = control.parseUplink({
|
||||
DeviceID: 'BOX_001', event: eventType, state: 'open', timestamp: 1782120000
|
||||
});
|
||||
assert.equal(fixture.kind, 'EVENT');
|
||||
assert.equal(fixture.eventType, eventType);
|
||||
}
|
||||
|
||||
assert.equal(generateCommandId(1782120000000, 7), '1782120000007');
|
||||
assert.match(generateCommandId(), /^\d{13}$/);
|
||||
@@ -156,6 +191,55 @@ assert.equal(calls.some((item) =>
|
||||
item.sql.includes('INSERT INTO qipai_device_alerts')
|
||||
&& item.params.includes('DEVICE_UNCONFIRM')
|
||||
), true);
|
||||
for (const [id, result, failureCode] of [
|
||||
['125', 'busy', 'DEVICE_BUSY'],
|
||||
['126', 'fail', 'DEVICE_FAIL']
|
||||
]) {
|
||||
await service.handle('/devicesend/BOX_001', Buffer.from(JSON.stringify({
|
||||
DeviceID: 'BOX_001', id, action: 'task', result
|
||||
})));
|
||||
assert.equal(calls.some((item) =>
|
||||
item.sql.includes('UPDATE qipai_iot_commands')
|
||||
&& item.params[0] === 'FAILED'
|
||||
&& item.params[2] === failureCode
|
||||
), true);
|
||||
}
|
||||
const commandUpdatesBeforeEvents = calls.filter((item) =>
|
||||
item.sql.includes('UPDATE qipai_iot_commands')
|
||||
).length;
|
||||
for (const eventType of ['magstate', 'taskfinish']) {
|
||||
await service.handle('/devicesend/BOX_001', Buffer.from(JSON.stringify({
|
||||
DeviceID: 'BOX_001', event: eventType, state: 'close'
|
||||
})));
|
||||
}
|
||||
assert.equal(calls.filter((item) =>
|
||||
item.sql.includes('UPDATE qipai_iot_commands')
|
||||
).length, commandUpdatesBeforeEvents);
|
||||
|
||||
const deadLettersBeforeWill = calls.filter((item) =>
|
||||
item.sql.includes('qipai_iot_dead_letters')
|
||||
).length;
|
||||
await service.handle('/devicewill/BOX_001', Buffer.from('close'));
|
||||
assert.equal(calls.some((item) =>
|
||||
item.sql.includes('UPDATE qipai_devices') && item.params[0] === 'OFFLINE'
|
||||
), true);
|
||||
assert.equal(calls.filter((item) =>
|
||||
item.sql.includes('qipai_iot_dead_letters')
|
||||
).length, deadLettersBeforeWill);
|
||||
|
||||
await service.handle('/devicesend/BOX_001', Buffer.from(JSON.stringify({
|
||||
DeviceID: 'BOX_001', id: '127', action: 'task', result: 'vendor-new-code'
|
||||
})));
|
||||
assert.equal(calls.some((item) =>
|
||||
item.sql.includes('qipai_iot_dead_letters')
|
||||
&& item.params.includes('UNKNOWN_VENDOR_RESULT')
|
||||
), true);
|
||||
assert.equal(calls.some((item) =>
|
||||
item.sql.includes('UPDATE qipai_iot_commands')
|
||||
&& item.params[0] === 'FAILED'
|
||||
&& item.params[2] === 'UNKNOWN_VENDOR_RESULT'
|
||||
), true);
|
||||
|
||||
await service.handle('/devicesend/SOCKET_001', Buffer.from(JSON.stringify({
|
||||
DeviceID: 'SOCKET_001', event: 'workInfo', switch: 'on',
|
||||
powerW: 3601, temperature: 82, overLoad: true
|
||||
@@ -182,6 +266,20 @@ await assert.rejects(
|
||||
/IOT_COMMAND_ID_INVALID/
|
||||
);
|
||||
|
||||
await service.createCommand({
|
||||
tenantId: '7', assetId: '51', storeId: '11', commandId: '128',
|
||||
commandType: 'CtrlDevice', traceId: 'secret-test',
|
||||
payload: {
|
||||
action: 'CtrlDevice', subtype: '14', subID: 'SUB001',
|
||||
order: 'setkey', value: '123456'
|
||||
}
|
||||
});
|
||||
const secretCommandInsert = calls.findLast((item) =>
|
||||
item.sql.includes('INSERT INTO qipai_iot_commands')
|
||||
);
|
||||
assert.equal(secretCommandInsert.params[7].includes('123456'), false);
|
||||
assert.equal(secretCommandInsert.params[7].includes('valueHash'), true);
|
||||
|
||||
const commandCalls = [];
|
||||
const commandService = new DeviceCommandService({
|
||||
async createCommand(input) { commandCalls.push(['create', input]); },
|
||||
|
||||
Reference in New Issue
Block a user