import { BleProtocolService } from './BleProtocolService'; import { COMMAND_TYPES } from '../protocol/Constants'; export class FileTransferService { private static instance: FileTransferService; private protocol = BleProtocolService.getInstance(); private constructor() {} public static getInstance(): FileTransferService { if (!FileTransferService.instance) { FileTransferService.instance = new FileTransferService(); } return FileTransferService.instance; } public async transferFile(deviceId: string, filePath: string, type: COMMAND_TYPES, onProgress?: (progress: number) => void): Promise { try { const response = await fetch(filePath); if (!response.ok) { throw new Error(`Failed to load file: ${response.statusText}`); } const blob = await response.blob(); const reader = new FileReader(); const arrayBuffer = await new Promise((resolve, reject) => { reader.onload = () => resolve(reader.result as ArrayBuffer); reader.onerror = reject; reader.readAsArrayBuffer(blob); }); await this.protocol.send(deviceId, type, arrayBuffer, onProgress); } catch (e) { console.error("File transfer failed", e); throw e; } } public async transferOta(deviceId: string, filePath: string) { return this.transferFile(deviceId, filePath, COMMAND_TYPES.OTA_PACKAGE); } public async transferBootAnimation(deviceId: string, filePath: string) { return this.transferFile(deviceId, filePath, COMMAND_TYPES.TRANSFER_BOOT_ANIMATION); } public async transferWatchfaceStyle(deviceId: string, filePath: string) { return this.transferFile(deviceId, filePath, COMMAND_TYPES.TRANSFER_AVI_VIDEO); } }