feat(M06-C): 完成设备协议适配与消息幂等

This commit is contained in:
Codex
2026-06-22 18:29:07 +08:00
parent c96045f6ef
commit e795cdb693
15 changed files with 867 additions and 17 deletions
@@ -0,0 +1,42 @@
import type { MqttTransport } from '../mqtt/mqtt-service.js';
import { generateCommandId, type IotMessageService } from './iot-message-service.js';
export class DeviceCommandService {
private sequence = 0;
constructor(
private readonly messages: Pick<IotMessageService,
'createCommand' | 'markPublished' | 'markPublishFailed'>,
private readonly transport: Pick<MqttTransport, 'publishDeviceCommand'>
) {}
async issue(input: {
tenantId: string; assetId: string; deviceId: string; storeId: string;
roomId?: string | null; orderId?: string | null; commandType: string;
payloadFactory: (commandId: string) => Record<string, unknown>;
traceId: string; expiresAt?: Date | null;
}) {
const commandId = generateCommandId(Date.now(), this.sequence++);
const payload = input.payloadFactory(commandId);
await this.messages.createCommand({
tenantId: input.tenantId,
assetId: input.assetId,
storeId: input.storeId,
roomId: input.roomId,
orderId: input.orderId,
commandId,
commandType: input.commandType,
payload,
traceId: input.traceId,
expiresAt: input.expiresAt
});
try {
await this.transport.publishDeviceCommand(input.deviceId, JSON.stringify(payload));
await this.messages.markPublished(input.tenantId, commandId);
return { commandId, status: 'PUBLISHED' as const };
} catch (error) {
await this.messages.markPublishFailed(input.tenantId, commandId, 'MQTT_PUBLISH_FAILED');
throw error;
}
}
}