import { Buffer } from 'buffer' import { COMMAND_TYPES, EVENT_TYPES } from '../protocol/Constants' import { type BindingResponse, type DeleteFileResponse, type DeviceInfo, type PrepareTransferResponse, type UnBindResponse, type VersionInfo, } from '../protocol/types' import { BleProtocolService } from './BleProtocolService' export class DeviceInfoService { private protocol = BleProtocolService.getInstance() private static instance: DeviceInfoService private listeners: Map> = new Map() private constructor() { this.protocol.addListener(EVENT_TYPES.DEVICE_INFO.code, this.onDeviceInfo) this.protocol.addListener(EVENT_TYPES.VERSION_INFO.code, this.onVersionInfo) this.protocol.addListener(EVENT_TYPES.BIND_DEVICE.code, this.onBindDevice) this.protocol.addListener(EVENT_TYPES.UNBIND_DEVICE.code, this.onUnBindDevice) this.protocol.addListener(EVENT_TYPES.DELETE_FILE.code, this.onDeleteFile) this.protocol.addListener(EVENT_TYPES.PREPARE_TRANSFER.code, this.onPrepareTransfer) } private onDeviceInfo = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.DEVICE_INFO.name, json) } catch (e) { console.error('Failed to parse device info', e) } } private onVersionInfo = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.VERSION_INFO.name, json) } catch (e) { console.error('Failed to parse activation status', e) } } private onBindDevice = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.BIND_DEVICE.name, json) } catch (e) { console.error('Failed to parse activation status', e) } } private onUnBindDevice = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.UNBIND_DEVICE.name, json) } catch (e) { console.error('Failed to parse activation status', e) } } private onDeleteFile = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.DELETE_FILE.name, json) } catch (e) { console.error('Failed to parse delete file response', e) } } private onPrepareTransfer = (data: ArrayBuffer, deviceId: string) => { try { const json = this.prase(data) this.emit(EVENT_TYPES.PREPARE_TRANSFER.name, json) } catch (e) { console.error('Failed to parse prepare transfer response', e) } } public static getInstance(): DeviceInfoService { if (!DeviceInfoService.instance) { DeviceInfoService.instance = new DeviceInfoService() } return DeviceInfoService.instance } private prase(data: ArrayBuffer): T { const str = Buffer.from(data).toString('utf-8') const cleanStr = str.replace(/\0/g, '') return JSON.parse(cleanStr) as T } public addListener(event: string, cb: Function) { if (!this.listeners.has(event)) this.listeners.set(event, new Set()) this.listeners.get(event)!.add(cb) } public removeListener(event: string, cb: Function) { if (this.listeners.has(event)) { this.listeners.get(event)!.delete(cb) } } public removeAllListeners() { this.listeners.clear() console.debug('All DeviceInfoService listeners cleared') } private emit(event: string, data: any) { this.listeners.get(event)?.forEach((cb) => cb(data)) } public async getDeviceInfo(deviceId: string) { await this.protocol.send(deviceId, COMMAND_TYPES.GET_DEVICE_INFO, { type: COMMAND_TYPES.GET_DEVICE_INFO }) } public async getDeviceVersion(deviceId: string) { await this.protocol.send(deviceId, COMMAND_TYPES.GET_DEVICE_VERSION, { type: COMMAND_TYPES.GET_DEVICE_VERSION }) } public async bindDevice(deviceId: string, userId: string) { await this.protocol.send(deviceId, COMMAND_TYPES.BIND_DEVICE, { type: COMMAND_TYPES.BIND_DEVICE, userId: userId }) } public async unbindDevice(deviceId: string, userId: string) { await this.protocol.send(deviceId, COMMAND_TYPES.UNBIND_DEVICE, { type: COMMAND_TYPES.UNBIND_DEVICE, userId: userId, }) } public async deleteFile(deviceId: string, key: string) { await this.protocol.send(deviceId, COMMAND_TYPES.DELETE_FILE, { type: COMMAND_TYPES.DELETE_FILE, key: key, }) } public async prepareTransfer(deviceId: string, key: string, size: number) { await this.protocol.send(deviceId, COMMAND_TYPES.PREPARE_TRANSFER, { type: COMMAND_TYPES.PREPARE_TRANSFER, key: key, size: size, }) } }