UNPKG

matterbridge-roborock-vacuum-plugin

Version:
135 lines (122 loc) 6.53 kB
import { getRunningMode } from '../initialData/getSupportedRunModes.js'; import { CloudMessageModel } from '../model/CloudMessageModel.js'; import { hasDockingStationError } from '../model/DockingStationStatus.js'; import { RoborockMatterbridgePlatform } from '../platform.js'; import { AdditionalPropCode, DeviceStatusNotify, Protocol } from '../roborockCommunication/index.js'; import { state_to_matter_operational_status, state_to_matter_state } from '../share/function.js'; import { RvcCleanMode, RvcOperationalState, RvcRunMode, ServiceArea } from 'matterbridge/matter/clusters'; import { triggerDssError } from './handleLocalMessage.js'; import { DpsPayload } from '../roborockCommunication/broadcast/model/dps.js'; import { getRoomMapFromDevice, isStatusUpdate } from '../helper.js'; import { debugStringify } from 'matterbridge/logger'; import { CloudMessageResult } from '../roborockCommunication/Zmodel/messageResult.js'; import { NotifyMessageTypes } from '../notifyMessageTypes.js'; import { getCurrentCleanModeFunc } from '../share/runtimeHelper.js'; import { getSupportedAreas } from '../initialData/getSupportedAreas.js'; import { PlatformRunner } from '../platformRunner.js'; import { RoborockVacuumCleaner } from '../rvc.js'; export async function handleCloudMessage(data: CloudMessageModel, platform: RoborockMatterbridgePlatform, runner: PlatformRunner, duid: string): Promise<void> { const messageTypes = Object.keys(data.dps).map(Number); const robot = platform.robots.get(duid); if (robot === undefined) { platform.log.error(`Error3: Robot with DUID ${duid} not found`); return; } // Known: 122, 121, 102, // Unknown: 128, 139 messageTypes.forEach(async (messageType) => { switch (messageType) { case Protocol.status_update: { const status = Number(data.dps[messageType]); const matterState = state_to_matter_state(status); if (matterState) { robot.updateAttribute(RvcRunMode.Cluster.id, 'currentMode', getRunningMode(matterState), platform.log); } const operationalStateId = state_to_matter_operational_status(status); if (operationalStateId) { const dssHasError = hasDockingStationError(robot.dockStationStatus); if (!(dssHasError && triggerDssError(robot, platform))) { robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log); } } break; } case Protocol.rpc_response: { const response = data.dps[messageType] as DpsPayload; // ignore network info if (!isStatusUpdate(response.result)) { platform.log.debug('Ignore message:', debugStringify(data)); return; } let roboStatus: CloudMessageResult | undefined; if (Array.isArray(response.result) && response.result.length > 0) { roboStatus = response.result[0] as CloudMessageResult; } if (roboStatus) { const message = { ...roboStatus } as DeviceStatusNotify; platform.log.debug('rpc_response:', debugStringify(message)); await runner.updateFromMQTTMessage(NotifyMessageTypes.LocalMessage, message, duid, true); } break; } case Protocol.suction_power: case Protocol.water_box_mode: { await platform.roborockService?.getCleanModeData(duid).then((cleanModeData) => { if (cleanModeData) { const currentCleanMode = getCurrentCleanModeFunc( robot.device.data.model, platform.enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false, )({ suctionPower: cleanModeData.suctionPower, waterFlow: cleanModeData.waterFlow, distance_off: cleanModeData.distance_off, mopRoute: cleanModeData.mopRoute, }); platform.log.debug(`Clean mode data: ${debugStringify(cleanModeData)}`); platform.log.debug(`Current clean mode: ${currentCleanMode}`); if (currentCleanMode) { robot.updateAttribute(RvcCleanMode.Cluster.id, 'currentMode', currentCleanMode, platform.log); } } }); break; // Do nothing, handled in local message } case Protocol.additional_props: { platform.log.notice(`Received additional properties for robot ${duid}: ${debugStringify(data)}`); const propCode = data.dps[Protocol.additional_props] as number; platform.log.debug(`DPS for additional properties: ${propCode}, AdditionalPropCode: ${AdditionalPropCode[propCode]}`); if (propCode === AdditionalPropCode.map_change) { await handleMapChange(robot, platform, duid); } break; } case Protocol.back_type: { // TODO: check if this is needed break; } default: { platform.log.notice(`Unknown message type ${messageType}, protocol: ${Protocol[messageType]}, message: ${debugStringify(data)}`); break; } } }); } export async function handleMapChange(robot: RoborockVacuumCleaner, platform: RoborockMatterbridgePlatform, duid: string): Promise<void> { const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap) ?? false; if (!enableMultipleMap) return; await getRoomMapFromDevice(robot.device, platform).then((roomMap) => { const { supportedAreas, supportedMaps, roomIndexMap } = getSupportedAreas(robot.device.rooms, roomMap, enableMultipleMap, platform.log); platform.log.debug(`handleMapChange - supportedAreas: ${debugStringify(supportedAreas)}`); platform.log.debug(`handleMapChange - supportedMaps: ${debugStringify(supportedMaps)}`); platform.log.debug(`handleMapChange - roomIndexMap: `, roomIndexMap); platform.roborockService?.setSupportedAreas(duid, supportedAreas); platform.roborockService?.setSelectedAreas(duid, []); robot.updateAttribute(ServiceArea.Cluster.id, 'supportedAreas', supportedAreas, platform.log); robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log); robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log); if (enableMultipleMap) { platform.roborockService?.setSupportedAreaIndexMap(duid, roomIndexMap); robot.updateAttribute(ServiceArea.Cluster.id, 'supportedMaps', supportedMaps, platform.log); } }); }