43 lines
1.5 KiB
TypeScript
43 lines
1.5 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
}
|