UNPKG

matterbridge-roborock-vacuum-plugin

Version:
160 lines 6.89 kB
import { DeviceError, DeviceNotFoundError } from '../errors/index.js'; import { Protocol, } from '../roborockCommunication/models/index.js'; /** Handles device discovery, initialization, and lifecycle. */ export class DeviceManagementService { logger; loginApi; userdata; iotApi; constructor(logger, loginApi, userdata) { this.logger = logger; this.loginApi = loginApi; this.userdata = userdata; } setIotApi(iotApi) { this.iotApi = iotApi; } /** Set IoT API instance after authentication. */ setAuthentication(userdata) { this.userdata = userdata; } /** List all devices for a user (enriched with rooms, scenes, metadata). */ async listDevices() { if (!this.iotApi || !this.userdata) { throw new DeviceError('Not authenticated. Please login first.'); } try { this.logger.debug('Fetching home details for user:', this.userdata.username); const homeInfo = await this.loginApi.getBasicHomeInfo(); if (!homeInfo?.rrHomeId) { throw new DeviceNotFoundError('No home found for user'); } const homeData = await this.iotApi.getHomeWithProducts(homeInfo.rrHomeId); if (!homeData) { throw new DeviceError('Failed to retrieve home data', undefined, { homeId: homeInfo.rrHomeId }); } this.logger.debug(`Processing home data for home ID: ${homeInfo.rrHomeId}`); const products = new Map(); homeData.products.forEach((p) => products.set(p.id, { model: p.model, category: p.category })); const devices = [...homeData.devices, ...homeData.receivedDevices]; // Fetch scenes for routine support const scenes = (await this.iotApi.getScenes(homeInfo.rrHomeId)) ?? []; const result = devices.map((device) => { return { ...device, rrHomeId: homeInfo.rrHomeId, localKey: device.localKey, pv: device.pv, serialNumber: device.sn, scenes: scenes.filter((sc) => sc.param && JSON.parse(sc.param).action.items.some((x) => x.entityId == device.duid)), specs: { id: device.duid, firmwareVersion: device.fv, serialNumber: device.sn, model: products.get(device.productId)?.model, protocol: device.pv, category: products.get(device.productId)?.category, batteryLevel: Number(device.deviceStatus?.[Protocol.battery] ?? 100), hasRealTimeConnection: false, }, store: { userData: this.userdata, localKey: device.localKey, pv: device.pv, model: products.get(device.productId)?.model, homeData: homeData, }, }; }); this.logger.notice(`Found ${result.length} devices`); return result; } catch (error) { this.logger.error('Failed to list devices:', error); if (error instanceof DeviceError) { throw error; } throw new DeviceError('Failed to retrieve device list', undefined, { originalError: error instanceof Error ? error.message : String(error), }); } } /** Get home data for periodic updates (falls back to v3/v1 APIs if needed). */ async getHomeDataForUpdating(homeid) { if (!this.iotApi || !this.userdata) { this.logger.error('Not authenticated'); return undefined; } try { let homeData = await this.iotApi.getHomev2(homeid); if (!homeData) { homeData = await this.iotApi.getHomev3(homeid); } if (!homeData) { homeData = await this.iotApi.getHome(homeid); } if (!homeData) { this.logger.error(`Home data not found for home ID: ${homeid}`); return undefined; } const products = new Map(); homeData.products.forEach((p) => products.set(p.id, { model: p.model, category: p.category })); const devices = homeData.devices.length > 0 ? homeData.devices : homeData.receivedDevices; // Fallback to older API versions if rooms are missing if (homeData.rooms.length === 0) { const homeDataV3 = await this.iotApi.getHomev3(homeid); if (homeDataV3?.rooms && homeDataV3.rooms.length > 0) { homeData.rooms = homeDataV3.rooms; } else { const homeDataV1 = await this.iotApi.getHome(homeid); if (homeDataV1?.rooms && homeDataV1.rooms.length > 0) { homeData.rooms = homeDataV1.rooms; } } } const dvs = devices.map((device) => { return { ...device, rrHomeId: homeid, serialNumber: device.sn, specs: { id: device.duid, firmwareVersion: device.fv, serialNumber: device.sn, model: products.get(device.productId)?.model, protocol: device.pv, category: products.get(device.productId)?.category, batteryLevel: Number(device.deviceStatus?.[Protocol.battery] ?? 100), hasRealTimeConnection: false, }, store: { userData: this.userdata, localKey: device.localKey, pv: device.pv, model: products.get(device.productId)?.model, homeData: homeData, }, }; }); return { ...homeData, devices: dvs, }; } catch (error) { this.logger.error('Failed to get home data for updating:', error); return undefined; } } /** * Stop the service and clean up all resources. * Disconnects all clients, clears intervals, and resets internal state. */ stopService() { this.logger.notice('Device management service stopped'); this.iotApi = undefined; this.userdata = undefined; } } //# sourceMappingURL=deviceManagementService.js.map