UNPKG

matterbridge-roborock-vacuum-plugin

Version:
128 lines 6.21 kB
import { WATCHDOG_CHECK_INTERVAL_MS, WATCHDOG_THRESHOLD_MS } from './constants/index.js'; import { BurstPollingManager } from './platform/burstPollingManager.js'; import { updateFromHomeData } from './runtimes/handleHomeDataMessage.js'; import { handleBatteryUpdate } from './runtimes/handlers/batteryStateHandler.js'; import { handleCleanModeUpdate } from './runtimes/handlers/cleanModeHandler.js'; import { handleDeviceStatusSimpleUpdate, handleDeviceStatusUpdate } from './runtimes/handlers/deviceStateHandler.js'; import { handleErrorOccurred } from './runtimes/handlers/errorStateHandler.js'; import { handleActiveMapChanged, handleServiceAreaUpdate } from './runtimes/handlers/serviceAreaHandler.js'; import { NotifyMessageTypes } from './types/notifyMessageTypes.js'; export class PlatformRunner { platform; activateHandlers = false; watchdogTimer; burstPolling; constructor(platform) { this.platform = platform; this.burstPolling = new BurstPollingManager(platform); } startWatchdog() { this.watchdogTimer = setInterval(() => { const threshold = Date.now() - WATCHDOG_THRESHOLD_MS; for (const robot of this.platform.registry.robotsMap.values()) { if (robot.lastUpdateAt !== null && robot.lastUpdateAt < threshold) { this.platform.log.error(`[${robot.device.duid}] [${robot.device.name}] No status update received in the last ${WATCHDOG_THRESHOLD_MS / 60_000} minutes`); } } }, WATCHDOG_CHECK_INTERVAL_MS); } stopWatchdog() { if (this.watchdogTimer) { clearInterval(this.watchdogTimer); this.watchdogTimer = undefined; } } activateHandlerFunctions() { this.activateHandlers = true; } /** * Request and process home data update from Roborock service. * Fetches latest home data including device states and triggers robot state updates. * Returns early if no robots configured, no home ID set, or service unavailable. */ async requestHomeData() { const platform = this.platform; if (platform.registry.robotsMap.size === 0 || !platform.rrHomeId) return; if (platform.roborockService === undefined) return; const robots = [...platform.registry.robotsMap.values()]; const threshold = Date.now() - WATCHDOG_THRESHOLD_MS; const allDevicesFresh = robots.every((x) => x.device.specs.hasRealTimeConnection && x.lastUpdateAt !== null && x.lastUpdateAt > threshold); if (allDevicesFresh) return; const homeData = await platform.roborockService.getHomeDataForUpdating(platform.rrHomeId); if (homeData === undefined) return; await this.updateRobotWithPayload({ type: NotifyMessageTypes.HomeData, data: homeData }); } /** * Update robot state based on message payload. * Routes to appropriate handler using type-safe discriminated unions. */ async updateRobotWithPayload(payload) { if (!this.activateHandlers) return; const { type } = payload; switch (type) { case NotifyMessageTypes.ErrorOccurred: await this.executeWithRobot(payload.data.duid, payload.data, (robot, data) => handleErrorOccurred(robot, data, this.platform)); break; case NotifyMessageTypes.BatteryUpdate: await this.executeWithRobot(payload.data.duid, payload.data, (robot, data) => handleBatteryUpdate(robot, data, this.platform)); break; case NotifyMessageTypes.DeviceStatus: await this.executeWithRobot(payload.data.duid, payload.data, async (robot, data) => { const shouldBurst = await handleDeviceStatusUpdate(robot, data, this.platform); if (shouldBurst && !this.burstPolling.has(robot.device.duid)) { this.burstPolling.startBurstPolling(robot.device.duid); } }); break; case NotifyMessageTypes.DeviceStatusSimple: await this.executeWithRobot(payload.data.duid, payload.data, (robot, data) => handleDeviceStatusSimpleUpdate(robot, data, this.platform)); break; case NotifyMessageTypes.CleanModeUpdate: await this.executeWithRobot(payload.data.duid, payload.data, (robot, data) => handleCleanModeUpdate(robot, data, this.platform)); break; case NotifyMessageTypes.ServiceAreaUpdate: await this.executeWithRobot(payload.data.duid, payload.data, (robot, data) => handleServiceAreaUpdate(robot, data, this.platform)); break; case NotifyMessageTypes.HomeData: await updateFromHomeData(payload.data, this.platform); break; case NotifyMessageTypes.ActiveMapChanged: await this.executeWithRobot(payload.data.duid, payload.data, async (robot, data) => { if (robot.homeInFo.activeMapId === data.mapId) return; robot.homeInFo.activeMapId = data.mapId; await handleActiveMapChanged(robot, data.mapId, this.platform); }); break; default: this.platform.log.warn(`No handler registered for message type: ${type}`); } } /** * Template method: Execute handler with robot instance. * Handles robot lookup, error logging, and passes data to handler. */ async executeWithRobot(duid, data, handler) { const robot = this.getRobotOrLogError(duid); if (!robot) return; await handler(robot, data); robot.lastUpdateAt = Date.now(); } /** * Get robot by DUID or log error if not found. */ getRobotOrLogError(duid) { const robot = this.platform.registry.getRobot(duid); if (!robot) { this.platform.log.error(`Robot with DUID ${duid} not found`); } return robot; } } //# sourceMappingURL=platformRunner.js.map