feat(M06-C): 完成设备协议适配与消息幂等
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user