matterbridge-roborock-vacuum-plugin-regions 1.1.1-jb.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build.yml +56 -0
- package/.github/workflows/coverage.yml +59 -0
- package/.github/workflows/publish.yml +37 -0
- package/.tarignore +5 -0
- package/CHANGELOG.md +62 -0
- package/LICENSE +202 -0
- package/README.md +135 -0
- package/README_CLEANMODE.md +29 -0
- package/README_DEV.md +75 -0
- package/README_REPORT_ISSUE.md +34 -0
- package/README_SUPPORTED.md +67 -0
- package/dist/behaviorFactory.js +26 -0
- package/dist/behaviors/BehaviorDeviceGeneric.js +22 -0
- package/dist/behaviors/roborock.vacuum/default/default.js +183 -0
- package/dist/behaviors/roborock.vacuum/default/initalData.js +143 -0
- package/dist/behaviors/roborock.vacuum/default/runtimes.js +21 -0
- package/dist/behaviors/roborock.vacuum/smart/initalData.js +18 -0
- package/dist/behaviors/roborock.vacuum/smart/runtimes.js +11 -0
- package/dist/behaviors/roborock.vacuum/smart/smart.js +119 -0
- package/dist/clientManager.js +17 -0
- package/dist/helper.js +76 -0
- package/dist/index.js +4 -0
- package/dist/initialData/getBatteryStatus.js +24 -0
- package/dist/initialData/getOperationalStates.js +82 -0
- package/dist/initialData/getSupportedAreas.js +120 -0
- package/dist/initialData/getSupportedCleanModes.js +17 -0
- package/dist/initialData/getSupportedRunModes.js +11 -0
- package/dist/initialData/getSupportedScenes.js +26 -0
- package/dist/initialData/index.js +6 -0
- package/dist/model/CloudMessageModel.js +1 -0
- package/dist/model/DockingStationStatus.js +26 -0
- package/dist/model/ExperimentalFeatureSetting.js +30 -0
- package/dist/model/RoomMap.js +19 -0
- package/dist/model/roomIndexMap.js +21 -0
- package/dist/notifyMessageTypes.js +9 -0
- package/dist/platform.js +312 -0
- package/dist/platformRunner.js +90 -0
- package/dist/roborockCommunication/RESTAPI/roborockAuthenticateApi.js +213 -0
- package/dist/roborockCommunication/RESTAPI/roborockIoTApi.js +95 -0
- package/dist/roborockCommunication/Zenum/additionalPropCode.js +4 -0
- package/dist/roborockCommunication/Zenum/authenticateResponseCode.js +7 -0
- package/dist/roborockCommunication/Zenum/dockType.js +4 -0
- package/dist/roborockCommunication/Zenum/operationStatusCode.js +44 -0
- package/dist/roborockCommunication/Zenum/vacuumAndDockErrorCode.js +68 -0
- package/dist/roborockCommunication/Zmodel/apiResponse.js +1 -0
- package/dist/roborockCommunication/Zmodel/authenticateFlowState.js +1 -0
- package/dist/roborockCommunication/Zmodel/authenticateResponse.js +1 -0
- package/dist/roborockCommunication/Zmodel/baseURL.js +1 -0
- package/dist/roborockCommunication/Zmodel/batteryMessage.js +1 -0
- package/dist/roborockCommunication/Zmodel/device.js +1 -0
- package/dist/roborockCommunication/Zmodel/deviceModel.js +28 -0
- package/dist/roborockCommunication/Zmodel/deviceSchema.js +1 -0
- package/dist/roborockCommunication/Zmodel/deviceStatus.js +22 -0
- package/dist/roborockCommunication/Zmodel/dockInfo.js +6 -0
- package/dist/roborockCommunication/Zmodel/home.js +1 -0
- package/dist/roborockCommunication/Zmodel/homeInfo.js +1 -0
- package/dist/roborockCommunication/Zmodel/map.js +1 -0
- package/dist/roborockCommunication/Zmodel/mapInfo.js +29 -0
- package/dist/roborockCommunication/Zmodel/messageResult.js +7 -0
- package/dist/roborockCommunication/Zmodel/multipleMap.js +1 -0
- package/dist/roborockCommunication/Zmodel/networkInfo.js +1 -0
- package/dist/roborockCommunication/Zmodel/product.js +1 -0
- package/dist/roborockCommunication/Zmodel/room.js +1 -0
- package/dist/roborockCommunication/Zmodel/roomInfo.js +22 -0
- package/dist/roborockCommunication/Zmodel/scene.js +16 -0
- package/dist/roborockCommunication/Zmodel/userData.js +1 -0
- package/dist/roborockCommunication/Zmodel/vacuumError.js +27 -0
- package/dist/roborockCommunication/broadcast/abstractClient.js +55 -0
- package/dist/roborockCommunication/broadcast/client/LocalNetworkClient.js +174 -0
- package/dist/roborockCommunication/broadcast/client/LocalNetworkUDPClient.js +129 -0
- package/dist/roborockCommunication/broadcast/client/MQTTClient.js +139 -0
- package/dist/roborockCommunication/broadcast/client.js +1 -0
- package/dist/roborockCommunication/broadcast/clientRouter.js +82 -0
- package/dist/roborockCommunication/broadcast/listener/abstractConnectionListener.js +1 -0
- package/dist/roborockCommunication/broadcast/listener/abstractMessageHandler.js +1 -0
- package/dist/roborockCommunication/broadcast/listener/abstractMessageListener.js +1 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/chainedConnectionListener.js +26 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/chainedMessageListener.js +11 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/connectionStateListener.js +43 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/generalSyncMessageListener.js +28 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/simpleMessageListener.js +27 -0
- package/dist/roborockCommunication/broadcast/listener/implementation/syncMessageListener.js +33 -0
- package/dist/roborockCommunication/broadcast/listener/index.js +1 -0
- package/dist/roborockCommunication/broadcast/messageProcessor.js +148 -0
- package/dist/roborockCommunication/broadcast/model/contentMessage.js +1 -0
- package/dist/roborockCommunication/broadcast/model/dps.js +1 -0
- package/dist/roborockCommunication/broadcast/model/headerMessage.js +1 -0
- package/dist/roborockCommunication/broadcast/model/messageContext.js +37 -0
- package/dist/roborockCommunication/broadcast/model/protocol.js +28 -0
- package/dist/roborockCommunication/broadcast/model/requestMessage.js +38 -0
- package/dist/roborockCommunication/broadcast/model/responseMessage.js +14 -0
- package/dist/roborockCommunication/helper/chunkBuffer.js +17 -0
- package/dist/roborockCommunication/helper/cryptoHelper.js +23 -0
- package/dist/roborockCommunication/helper/messageDeserializer.js +98 -0
- package/dist/roborockCommunication/helper/messageSerializer.js +84 -0
- package/dist/roborockCommunication/helper/nameDecoder.js +66 -0
- package/dist/roborockCommunication/helper/sequence.js +16 -0
- package/dist/roborockCommunication/index.js +13 -0
- package/dist/roborockService.js +494 -0
- package/dist/runtimes/handleCloudMessage.js +110 -0
- package/dist/runtimes/handleHomeDataMessage.js +57 -0
- package/dist/runtimes/handleLocalMessage.js +169 -0
- package/dist/rvc.js +51 -0
- package/dist/settings.js +1 -0
- package/dist/share/function.js +93 -0
- package/dist/share/runtimeHelper.js +17 -0
- package/dist/tests/testData/mockData.js +359 -0
- package/eslint.config.js +80 -0
- package/jest.config.js +22 -0
- package/jest.setup.js +2 -0
- package/logo.png +0 -0
- package/matterbridge-roborock-vacuum-plugin.config.json +46 -0
- package/matterbridge-roborock-vacuum-plugin.schema.json +293 -0
- package/misc/status.md +119 -0
- package/package.json +111 -0
- package/prettier.config.js +49 -0
- package/screenshot/IMG_1.PNG +0 -0
- package/screenshot/IMG_2.PNG +0 -0
- package/screenshot/IMG_3.PNG +0 -0
- package/screenshot/IMG_4.PNG +0 -0
- package/screenshot/IMG_5.PNG +0 -0
- package/screenshot/IMG_6.PNG +0 -0
- package/screenshot/IMG_7.PNG +0 -0
- package/src/behaviorFactory.ts +41 -0
- package/src/behaviors/BehaviorDeviceGeneric.ts +31 -0
- package/src/behaviors/roborock.vacuum/default/default.ts +238 -0
- package/src/behaviors/roborock.vacuum/default/initalData.ts +152 -0
- package/src/behaviors/roborock.vacuum/default/runtimes.ts +23 -0
- package/src/behaviors/roborock.vacuum/smart/initalData.ts +20 -0
- package/src/behaviors/roborock.vacuum/smart/runtimes.ts +15 -0
- package/src/behaviors/roborock.vacuum/smart/smart.ts +159 -0
- package/src/clientManager.ts +23 -0
- package/src/helper.ts +97 -0
- package/src/index.ts +16 -0
- package/src/initialData/getBatteryStatus.ts +26 -0
- package/src/initialData/getOperationalStates.ts +94 -0
- package/src/initialData/getSupportedAreas.ts +162 -0
- package/src/initialData/getSupportedCleanModes.ts +22 -0
- package/src/initialData/getSupportedRunModes.ts +14 -0
- package/src/initialData/getSupportedScenes.ts +32 -0
- package/src/initialData/index.ts +6 -0
- package/src/model/CloudMessageModel.ts +11 -0
- package/src/model/DockingStationStatus.ts +41 -0
- package/src/model/ExperimentalFeatureSetting.ts +77 -0
- package/src/model/RoomMap.ts +38 -0
- package/src/model/roomIndexMap.ts +26 -0
- package/src/notifyMessageTypes.ts +8 -0
- package/src/platform.ts +424 -0
- package/src/platformRunner.ts +103 -0
- package/src/roborockCommunication/RESTAPI/roborockAuthenticateApi.ts +302 -0
- package/src/roborockCommunication/RESTAPI/roborockIoTApi.ts +107 -0
- package/src/roborockCommunication/Zenum/additionalPropCode.ts +3 -0
- package/src/roborockCommunication/Zenum/authenticateResponseCode.ts +6 -0
- package/src/roborockCommunication/Zenum/dockType.ts +3 -0
- package/src/roborockCommunication/Zenum/operationStatusCode.ts +43 -0
- package/src/roborockCommunication/Zenum/vacuumAndDockErrorCode.ts +68 -0
- package/src/roborockCommunication/Zmodel/apiResponse.ts +3 -0
- package/src/roborockCommunication/Zmodel/authenticateFlowState.ts +6 -0
- package/src/roborockCommunication/Zmodel/authenticateResponse.ts +5 -0
- package/src/roborockCommunication/Zmodel/baseURL.ts +5 -0
- package/src/roborockCommunication/Zmodel/batteryMessage.ts +16 -0
- package/src/roborockCommunication/Zmodel/device.ts +50 -0
- package/src/roborockCommunication/Zmodel/deviceModel.ts +27 -0
- package/src/roborockCommunication/Zmodel/deviceSchema.ts +8 -0
- package/src/roborockCommunication/Zmodel/deviceStatus.ts +30 -0
- package/src/roborockCommunication/Zmodel/dockInfo.ts +9 -0
- package/src/roborockCommunication/Zmodel/home.ts +13 -0
- package/src/roborockCommunication/Zmodel/homeInfo.ts +5 -0
- package/src/roborockCommunication/Zmodel/map.ts +20 -0
- package/src/roborockCommunication/Zmodel/mapInfo.ts +54 -0
- package/src/roborockCommunication/Zmodel/messageResult.ts +75 -0
- package/src/roborockCommunication/Zmodel/multipleMap.ts +8 -0
- package/src/roborockCommunication/Zmodel/networkInfo.ts +7 -0
- package/src/roborockCommunication/Zmodel/product.ts +9 -0
- package/src/roborockCommunication/Zmodel/room.ts +4 -0
- package/src/roborockCommunication/Zmodel/roomInfo.ts +30 -0
- package/src/roborockCommunication/Zmodel/scene.ts +44 -0
- package/src/roborockCommunication/Zmodel/userData.ts +26 -0
- package/src/roborockCommunication/Zmodel/vacuumError.ts +35 -0
- package/src/roborockCommunication/broadcast/abstractClient.ts +80 -0
- package/src/roborockCommunication/broadcast/client/LocalNetworkClient.ts +218 -0
- package/src/roborockCommunication/broadcast/client/LocalNetworkUDPClient.ts +157 -0
- package/src/roborockCommunication/broadcast/client/MQTTClient.ts +174 -0
- package/src/roborockCommunication/broadcast/client.ts +19 -0
- package/src/roborockCommunication/broadcast/clientRouter.ts +104 -0
- package/src/roborockCommunication/broadcast/listener/abstractConnectionListener.ts +6 -0
- package/src/roborockCommunication/broadcast/listener/abstractMessageHandler.ts +11 -0
- package/src/roborockCommunication/broadcast/listener/abstractMessageListener.ts +5 -0
- package/src/roborockCommunication/broadcast/listener/implementation/chainedConnectionListener.ts +33 -0
- package/src/roborockCommunication/broadcast/listener/implementation/chainedMessageListener.ts +16 -0
- package/src/roborockCommunication/broadcast/listener/implementation/connectionStateListener.ts +57 -0
- package/src/roborockCommunication/broadcast/listener/implementation/generalSyncMessageListener.ts +38 -0
- package/src/roborockCommunication/broadcast/listener/implementation/simpleMessageListener.ts +37 -0
- package/src/roborockCommunication/broadcast/listener/implementation/syncMessageListener.ts +50 -0
- package/src/roborockCommunication/broadcast/listener/index.ts +3 -0
- package/src/roborockCommunication/broadcast/messageProcessor.ts +184 -0
- package/src/roborockCommunication/broadcast/model/contentMessage.ts +5 -0
- package/src/roborockCommunication/broadcast/model/dps.ts +19 -0
- package/src/roborockCommunication/broadcast/model/headerMessage.ts +7 -0
- package/src/roborockCommunication/broadcast/model/messageContext.ts +53 -0
- package/src/roborockCommunication/broadcast/model/protocol.ts +28 -0
- package/src/roborockCommunication/broadcast/model/requestMessage.ts +51 -0
- package/src/roborockCommunication/broadcast/model/responseMessage.ts +19 -0
- package/src/roborockCommunication/helper/chunkBuffer.ts +18 -0
- package/src/roborockCommunication/helper/cryptoHelper.ts +30 -0
- package/src/roborockCommunication/helper/messageDeserializer.ts +119 -0
- package/src/roborockCommunication/helper/messageSerializer.ts +101 -0
- package/src/roborockCommunication/helper/nameDecoder.ts +78 -0
- package/src/roborockCommunication/helper/sequence.ts +18 -0
- package/src/roborockCommunication/index.ts +25 -0
- package/src/roborockService.ts +657 -0
- package/src/runtimes/handleCloudMessage.ts +134 -0
- package/src/runtimes/handleHomeDataMessage.ts +67 -0
- package/src/runtimes/handleLocalMessage.ts +209 -0
- package/src/rvc.ts +97 -0
- package/src/settings.ts +1 -0
- package/src/share/function.ts +103 -0
- package/src/share/runtimeHelper.ts +23 -0
- package/src/tests/behaviors/roborock.vacuum/default/default.test.ts +134 -0
- package/src/tests/behaviors/roborock.vacuum/smart/runtimes.test.ts +64 -0
- package/src/tests/behaviors/roborock.vacuum/smart/smart.test.ts +215 -0
- package/src/tests/helper.test.ts +162 -0
- package/src/tests/initialData/getSupportedAreas.test.ts +181 -0
- package/src/tests/model/DockingStationStatus.test.ts +39 -0
- package/src/tests/platformRunner.test.ts +188 -0
- package/src/tests/platformRunner2.test.ts +228 -0
- package/src/tests/platformRunner3.test.ts +46 -0
- package/src/tests/roborockCommunication/RESTAPI/roborockAuthenticateApi.test.ts +144 -0
- package/src/tests/roborockCommunication/RESTAPI/roborockIoTApi.test.ts +106 -0
- package/src/tests/roborockCommunication/broadcast/client/LocalNetworkClient.test.ts +189 -0
- package/src/tests/roborockCommunication/broadcast/client/MQTTClient.test.ts +208 -0
- package/src/tests/roborockCommunication/broadcast/clientRouter.test.ts +168 -0
- package/src/tests/roborockCommunication/broadcast/listener/implementation/chainedConnectionListener.test.ts +59 -0
- package/src/tests/roborockCommunication/broadcast/listener/implementation/chainedMessageListener.test.ts +46 -0
- package/src/tests/roborockCommunication/broadcast/listener/implementation/simpleMessageListener.test.ts +71 -0
- package/src/tests/roborockCommunication/broadcast/listener/implementation/syncMessageListener.test.ts +86 -0
- package/src/tests/roborockCommunication/broadcast/messageProcessor.test.ts +126 -0
- package/src/tests/roborockService.setSelectedAreas.test.ts +61 -0
- package/src/tests/roborockService.test.ts +517 -0
- package/src/tests/roborockService2.test.ts +69 -0
- package/src/tests/roborockService3.test.ts +133 -0
- package/src/tests/roborockService4.test.ts +76 -0
- package/src/tests/roborockService5.test.ts +79 -0
- package/src/tests/runtimes/handleCloudMessage.test.ts +200 -0
- package/src/tests/runtimes/handleHomeDataMessage.test.ts +54 -0
- package/src/tests/runtimes/handleLocalMessage.test.ts +227 -0
- package/src/tests/testData/mockData.ts +370 -0
- package/src/tests/testData/mockHomeData-a187.json +286 -0
- package/tsconfig.jest.json +21 -0
- package/tsconfig.json +37 -0
- package/tsconfig.production.json +19 -0
- package/tslint.json +9 -0
- package/web-for-testing/README.md +47 -0
- package/web-for-testing/nodemon.json +7 -0
- package/web-for-testing/package-lock.json +6600 -0
- package/web-for-testing/package.json +36 -0
- package/web-for-testing/src/app.ts +194 -0
- package/web-for-testing/tsconfig-ext.json +19 -0
- package/web-for-testing/tsconfig.json +23 -0
- package/web-for-testing/views/index.ejs +172 -0
- package/web-for-testing/watch.mjs +93 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { getRunningMode } from '../initialData/getSupportedRunModes.js';
|
|
2
|
+
import { CloudMessageModel } from '../model/CloudMessageModel.js';
|
|
3
|
+
import { hasDockingStationError } from '../model/DockingStationStatus.js';
|
|
4
|
+
import { RoborockMatterbridgePlatform } from '../platform.js';
|
|
5
|
+
import { AdditionalPropCode, DeviceStatusNotify, Protocol } from '../roborockCommunication/index.js';
|
|
6
|
+
import { state_to_matter_operational_status, state_to_matter_state } from '../share/function.js';
|
|
7
|
+
import { RvcCleanMode, RvcOperationalState, RvcRunMode, ServiceArea } from 'matterbridge/matter/clusters';
|
|
8
|
+
import { triggerDssError } from './handleLocalMessage.js';
|
|
9
|
+
import { DpsPayload } from '../roborockCommunication/broadcast/model/dps.js';
|
|
10
|
+
import { getRoomMapFromDevice, isStatusUpdate } from '../helper.js';
|
|
11
|
+
import { debugStringify } from 'matterbridge/logger';
|
|
12
|
+
import { CloudMessageResult } from '../roborockCommunication/Zmodel/messageResult.js';
|
|
13
|
+
import { NotifyMessageTypes } from '../notifyMessageTypes.js';
|
|
14
|
+
import { getCurrentCleanModeFunc } from '../share/runtimeHelper.js';
|
|
15
|
+
import { getSupportedAreas } from '../initialData/getSupportedAreas.js';
|
|
16
|
+
import { PlatformRunner } from '../platformRunner.js';
|
|
17
|
+
import { RoborockVacuumCleaner } from '../rvc.js';
|
|
18
|
+
|
|
19
|
+
export async function handleCloudMessage(data: CloudMessageModel, platform: RoborockMatterbridgePlatform, runner: PlatformRunner, duid: string): Promise<void> {
|
|
20
|
+
const messageTypes = Object.keys(data.dps).map(Number);
|
|
21
|
+
const robot = platform.robots.get(duid);
|
|
22
|
+
if (robot === undefined) {
|
|
23
|
+
platform.log.error(`Error3: Robot with DUID ${duid} not found`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Known: 122, 121, 102,
|
|
28
|
+
// Unknown: 128, 139
|
|
29
|
+
messageTypes.forEach(async (messageType) => {
|
|
30
|
+
switch (messageType) {
|
|
31
|
+
case Protocol.status_update: {
|
|
32
|
+
const status = Number(data.dps[messageType]);
|
|
33
|
+
const matterState = state_to_matter_state(status);
|
|
34
|
+
|
|
35
|
+
if (matterState) {
|
|
36
|
+
robot.updateAttribute(RvcRunMode.Cluster.id, 'currentMode', getRunningMode(matterState), platform.log);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const operationalStateId = state_to_matter_operational_status(status);
|
|
40
|
+
if (operationalStateId) {
|
|
41
|
+
const dssHasError = hasDockingStationError(robot.dockStationStatus);
|
|
42
|
+
if (!(dssHasError && triggerDssError(robot, platform))) {
|
|
43
|
+
robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case Protocol.rpc_response: {
|
|
49
|
+
const response = data.dps[messageType] as DpsPayload;
|
|
50
|
+
// ignore network info
|
|
51
|
+
if (!isStatusUpdate(response.result)) {
|
|
52
|
+
platform.log.debug('Ignore message:', debugStringify(data));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let roboStatus: CloudMessageResult | undefined;
|
|
57
|
+
if (Array.isArray(response.result) && response.result.length > 0) {
|
|
58
|
+
roboStatus = response.result[0] as CloudMessageResult;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (roboStatus) {
|
|
62
|
+
const message = { ...roboStatus } as DeviceStatusNotify;
|
|
63
|
+
platform.log.debug('rpc_response:', debugStringify(message));
|
|
64
|
+
await runner.updateFromMQTTMessage(NotifyMessageTypes.LocalMessage, message, duid, true);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case Protocol.suction_power:
|
|
69
|
+
case Protocol.water_box_mode: {
|
|
70
|
+
await platform.roborockService?.getCleanModeData(duid).then((cleanModeData) => {
|
|
71
|
+
if (cleanModeData) {
|
|
72
|
+
const currentCleanMode = getCurrentCleanModeFunc(
|
|
73
|
+
robot.device.data.model,
|
|
74
|
+
platform.enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false,
|
|
75
|
+
)({
|
|
76
|
+
suctionPower: cleanModeData.suctionPower,
|
|
77
|
+
waterFlow: cleanModeData.waterFlow,
|
|
78
|
+
distance_off: cleanModeData.distance_off,
|
|
79
|
+
mopRoute: cleanModeData.mopRoute,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
platform.log.debug(`Clean mode data: ${debugStringify(cleanModeData)}`);
|
|
83
|
+
platform.log.debug(`Current clean mode: ${currentCleanMode}`);
|
|
84
|
+
if (currentCleanMode) {
|
|
85
|
+
robot.updateAttribute(RvcCleanMode.Cluster.id, 'currentMode', currentCleanMode, platform.log);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
break; // Do nothing, handled in local message
|
|
90
|
+
}
|
|
91
|
+
case Protocol.additional_props: {
|
|
92
|
+
platform.log.notice(`Received additional properties for robot ${duid}: ${debugStringify(data)}`);
|
|
93
|
+
const propCode = data.dps[Protocol.additional_props] as number;
|
|
94
|
+
platform.log.debug(`DPS for additional properties: ${propCode}, AdditionalPropCode: ${AdditionalPropCode[propCode]}`);
|
|
95
|
+
if (propCode === AdditionalPropCode.map_change) {
|
|
96
|
+
await handleMapChange(robot, platform, duid);
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case Protocol.back_type: {
|
|
101
|
+
// TODO: check if this is needed
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
default: {
|
|
105
|
+
platform.log.notice(`Unknown message type ${messageType}, protocol: ${Protocol[messageType]}, message: ${debugStringify(data)}`);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function handleMapChange(robot: RoborockVacuumCleaner, platform: RoborockMatterbridgePlatform, duid: string): Promise<void> {
|
|
113
|
+
const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap) ?? false;
|
|
114
|
+
if (!enableMultipleMap) return;
|
|
115
|
+
|
|
116
|
+
await getRoomMapFromDevice(robot.device, platform).then((roomMap) => {
|
|
117
|
+
const { supportedAreas, supportedMaps, roomIndexMap } = getSupportedAreas(robot.device.rooms, roomMap, enableMultipleMap, platform.log);
|
|
118
|
+
|
|
119
|
+
platform.log.debug(`handleMapChange - supportedAreas: ${debugStringify(supportedAreas)}`);
|
|
120
|
+
platform.log.debug(`handleMapChange - supportedMaps: ${debugStringify(supportedMaps)}`);
|
|
121
|
+
platform.log.debug(`handleMapChange - roomIndexMap: `, roomIndexMap);
|
|
122
|
+
|
|
123
|
+
platform.roborockService?.setSupportedAreas(duid, supportedAreas);
|
|
124
|
+
platform.roborockService?.setSelectedAreas(duid, []);
|
|
125
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedAreas', supportedAreas, platform.log);
|
|
126
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
|
|
127
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
|
|
128
|
+
|
|
129
|
+
if (enableMultipleMap) {
|
|
130
|
+
platform.roborockService?.setSupportedAreaIndexMap(duid, roomIndexMap);
|
|
131
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedMaps', supportedMaps, platform.log);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { PowerSource, RvcOperationalState, RvcRunMode } from 'matterbridge/matter/clusters';
|
|
2
|
+
import { getVacuumProperty } from '../helper.js';
|
|
3
|
+
import { RoborockMatterbridgePlatform } from '../platform.js';
|
|
4
|
+
import { Device, Home } from '../roborockCommunication/index.js';
|
|
5
|
+
import { debugStringify } from 'matterbridge/logger';
|
|
6
|
+
import { getBatteryState, getBatteryStatus } from '../initialData/index.js';
|
|
7
|
+
import { state_to_matter_operational_status, state_to_matter_state } from '../share/function.js';
|
|
8
|
+
import { OperationStatusCode } from '../roborockCommunication/Zenum/operationStatusCode.js';
|
|
9
|
+
import { getRunningMode } from '../initialData/getSupportedRunModes.js';
|
|
10
|
+
import { hasDockingStationError } from '../model/DockingStationStatus.js';
|
|
11
|
+
import { triggerDssError } from './handleLocalMessage.js';
|
|
12
|
+
|
|
13
|
+
export async function updateFromHomeData(homeData: Home, platform: RoborockMatterbridgePlatform): Promise<void> {
|
|
14
|
+
if (platform.robots.size === 0) return;
|
|
15
|
+
const devices = homeData.devices.filter((d: Device) => platform.robots.has(d.duid));
|
|
16
|
+
|
|
17
|
+
for (const device of devices) {
|
|
18
|
+
const robot = platform.robots.get(device.duid);
|
|
19
|
+
if (robot === undefined) {
|
|
20
|
+
platform.log.error(`Error5: Robot with DUID ${device.duid} not found`);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const deviceData = robot.device.data;
|
|
25
|
+
if (!device || deviceData === undefined) {
|
|
26
|
+
platform.log.error('Device not found in home data');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
device.schema = homeData.products.find((prd) => prd.id === device.productId || prd.model === device.data.model)?.schema ?? [];
|
|
31
|
+
platform.log.debug('updateFromHomeData-homeData:', debugStringify(homeData));
|
|
32
|
+
platform.log.debug('updateFromHomeData-device:', debugStringify(device));
|
|
33
|
+
platform.log.debug('updateFromHomeData-schema:' + debugStringify(device.schema));
|
|
34
|
+
platform.log.debug('updateFromHomeData-battery:' + debugStringify(device.deviceStatus));
|
|
35
|
+
|
|
36
|
+
const batteryLevel = getVacuumProperty(device, 'battery');
|
|
37
|
+
if (batteryLevel) {
|
|
38
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batPercentRemaining', batteryLevel ? batteryLevel * 2 : 200, platform.log);
|
|
39
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batChargeLevel', getBatteryStatus(batteryLevel), platform.log);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const state = getVacuumProperty(device, 'state');
|
|
43
|
+
const matterState = state_to_matter_state(state);
|
|
44
|
+
if (!state || !matterState) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
platform.log.debug(`updateFromHomeData-RvcRunMode code: ${state} name: ${OperationStatusCode[state]}, matterState: ${RvcRunMode.ModeTag[matterState]}`);
|
|
48
|
+
|
|
49
|
+
if (matterState) {
|
|
50
|
+
robot.updateAttribute(RvcRunMode.Cluster.id, 'currentMode', getRunningMode(matterState), platform.log);
|
|
51
|
+
}
|
|
52
|
+
if (batteryLevel) {
|
|
53
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batChargeState', getBatteryState(state, batteryLevel), platform.log);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const operationalStateId = state_to_matter_operational_status(state);
|
|
57
|
+
|
|
58
|
+
if (operationalStateId) {
|
|
59
|
+
const dssHasError = hasDockingStationError(robot.dockStationStatus);
|
|
60
|
+
platform.log.debug(`dssHasError: ${dssHasError}, dockStationStatus: ${debugStringify(robot.dockStationStatus ?? {})}`);
|
|
61
|
+
if (!(dssHasError && triggerDssError(robot, platform))) {
|
|
62
|
+
platform.log.debug(`updateFromHomeData-OperationalState: ${RvcOperationalState.OperationalState[operationalStateId]}`);
|
|
63
|
+
robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { PowerSource, RvcCleanMode, RvcOperationalState, RvcRunMode, ServiceArea } from 'matterbridge/matter/clusters';
|
|
2
|
+
import { getRunningMode } from '../initialData/getSupportedRunModes.js';
|
|
3
|
+
import { CloudMessageResult } from '../roborockCommunication/Zmodel/messageResult.js';
|
|
4
|
+
import { state_to_matter_state } from '../share/function.js';
|
|
5
|
+
import { RoborockMatterbridgePlatform } from '../platform.js';
|
|
6
|
+
import { OperationStatusCode } from '../roborockCommunication/Zenum/operationStatusCode.js';
|
|
7
|
+
import { getRoomMap } from '../helper.js';
|
|
8
|
+
import { debugStringify } from 'matterbridge/logger';
|
|
9
|
+
import { getBatteryState, getBatteryStatus } from '../initialData/index.js';
|
|
10
|
+
import { getCurrentCleanModeFunc } from '../share/runtimeHelper.js';
|
|
11
|
+
import { RoborockVacuumCleaner } from '../rvc.js';
|
|
12
|
+
import { hasDockingStationError, parseDockingStationStatus } from '../model/DockingStationStatus.js';
|
|
13
|
+
|
|
14
|
+
export async function handleLocalMessage(data: CloudMessageResult, platform: RoborockMatterbridgePlatform, duid = ''): Promise<void> {
|
|
15
|
+
const robot = platform.robots.get(duid);
|
|
16
|
+
|
|
17
|
+
if (!robot) {
|
|
18
|
+
platform.log.error(`Robot with DUID ${duid} not found.`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const currentMappedAreas = platform.roborockService?.getSupportedAreas(duid);
|
|
23
|
+
const roomIndexMap = platform.roborockService?.getSupportedAreasIndexMap(duid);
|
|
24
|
+
const roomMap = await getRoomMap(duid, platform);
|
|
25
|
+
platform.log.debug(`RoomMap: ${roomMap ? debugStringify(roomMap) : 'undefined'}`);
|
|
26
|
+
platform.log.debug(`Current mapped areas: ${currentMappedAreas ? debugStringify(currentMappedAreas) : 'undefined'}`);
|
|
27
|
+
platform.log.debug(
|
|
28
|
+
`RoomIndexMap:
|
|
29
|
+
`,
|
|
30
|
+
roomIndexMap,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const deviceData = robot.device.data;
|
|
34
|
+
const state = state_to_matter_state(data.state);
|
|
35
|
+
if (state) {
|
|
36
|
+
robot.updateAttribute(RvcRunMode.Cluster.id, 'currentMode', getRunningMode(state), platform.log);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (data.state === OperationStatusCode.Idle) {
|
|
40
|
+
const selectedAreas = platform.roborockService?.getSelectedAreas(duid) ?? [];
|
|
41
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', selectedAreas, platform.log);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (state === RvcRunMode.ModeTag.Cleaning && !data.cleaning_info) {
|
|
45
|
+
platform.log.debug('No cleaning_info, setting currentArea to null');
|
|
46
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
|
|
47
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
|
|
48
|
+
} else {
|
|
49
|
+
const isMultipleMapEnable = platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap;
|
|
50
|
+
if (isMultipleMapEnable) {
|
|
51
|
+
await mapRoomsToAreasFeatureOn(platform, duid, data);
|
|
52
|
+
} else {
|
|
53
|
+
await mapRoomsToAreasFeatureOff(platform, duid, data);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (data.battery) {
|
|
58
|
+
const batteryLevel = data.battery as number;
|
|
59
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batPercentRemaining', batteryLevel * 2, platform.log);
|
|
60
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batChargeState', getBatteryState(data.state, data.battery), platform.log);
|
|
61
|
+
robot.updateAttribute(PowerSource.Cluster.id, 'batChargeLevel', getBatteryStatus(batteryLevel), platform.log);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const currentCleanModeSetting = {
|
|
65
|
+
suctionPower: data.cleaning_info?.fan_power ?? data.fan_power,
|
|
66
|
+
waterFlow: data.cleaning_info?.water_box_status ?? data.water_box_mode,
|
|
67
|
+
distance_off: data.distance_off,
|
|
68
|
+
mopRoute: data.cleaning_info?.mop_mode ?? data.mop_mode,
|
|
69
|
+
segment_id: data.cleaning_info?.segment_id,
|
|
70
|
+
target_segment_id: data.cleaning_info?.target_segment_id,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
platform.log.debug(`data: ${debugStringify(data)}`);
|
|
74
|
+
platform.log.notice(`currentCleanModeSetting: ${debugStringify(currentCleanModeSetting)}`);
|
|
75
|
+
|
|
76
|
+
if (currentCleanModeSetting.mopRoute && currentCleanModeSetting.suctionPower && currentCleanModeSetting.waterFlow) {
|
|
77
|
+
const currentCleanMode = getCurrentCleanModeFunc(deviceData.model, platform.enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false)(currentCleanModeSetting);
|
|
78
|
+
platform.log.debug(`Current clean mode: ${currentCleanMode}`);
|
|
79
|
+
|
|
80
|
+
if (currentCleanMode) {
|
|
81
|
+
robot.updateAttribute(RvcCleanMode.Cluster.id, 'currentMode', currentCleanMode, platform.log);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
processAdditionalProps(robot, data, duid, platform);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function triggerDssError(robot: RoborockVacuumCleaner, platform: RoborockMatterbridgePlatform): boolean {
|
|
89
|
+
const currentOperationState = robot.getAttribute(RvcOperationalState.Cluster.id, 'operationalState') as RvcOperationalState.OperationalState;
|
|
90
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Error) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Docked) {
|
|
95
|
+
robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', RvcOperationalState.OperationalState.Error, platform.log);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function processAdditionalProps(robot: RoborockVacuumCleaner, message: CloudMessageResult, duid: string, platform: RoborockMatterbridgePlatform): Promise<void> {
|
|
103
|
+
// dss -> DockingStationStatus
|
|
104
|
+
const dssStatus = getDssStatus(message, duid, platform);
|
|
105
|
+
if (dssStatus) {
|
|
106
|
+
triggerDssError(robot, platform);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getDssStatus(message: CloudMessageResult, duid: string, platform: RoborockMatterbridgePlatform): RvcOperationalState.OperationalState | undefined {
|
|
111
|
+
const robot = platform.robots.get(duid);
|
|
112
|
+
if (robot === undefined) {
|
|
113
|
+
platform.log.error(`Error4: Robot with DUID ${duid} not found`);
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (
|
|
118
|
+
platform.enableExperimentalFeature &&
|
|
119
|
+
platform.enableExperimentalFeature.enableExperimentalFeature &&
|
|
120
|
+
platform.enableExperimentalFeature.advancedFeature.includeDockStationStatus &&
|
|
121
|
+
message.dss !== undefined
|
|
122
|
+
) {
|
|
123
|
+
const dss = parseDockingStationStatus(message.dss);
|
|
124
|
+
if (dss && robot) {
|
|
125
|
+
robot.dockStationStatus = dss;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (dss && hasDockingStationError(dss)) {
|
|
129
|
+
return RvcOperationalState.OperationalState.Error;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function mapRoomsToAreasFeatureOff(platform: RoborockMatterbridgePlatform, duid: string, data: CloudMessageResult): Promise<void> {
|
|
136
|
+
const currentMappedAreas = platform.roborockService?.getSupportedAreas(duid);
|
|
137
|
+
const robot = platform.robots.get(duid);
|
|
138
|
+
if (!robot) {
|
|
139
|
+
platform.log.error(`Robot with DUID ${duid} not found.`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!data.cleaning_info) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const source_segment_id = data.cleaning_info.segment_id ?? -1; // 4
|
|
148
|
+
const source_target_segment_id = data.cleaning_info.target_segment_id ?? -1; // -1
|
|
149
|
+
const segment_id = source_segment_id !== -1 ? source_segment_id : source_target_segment_id; // 4
|
|
150
|
+
const mappedArea = currentMappedAreas?.find((x) => x.areaId == segment_id);
|
|
151
|
+
platform.log.debug(
|
|
152
|
+
`mappedArea:
|
|
153
|
+
source_segment_id: ${source_segment_id},
|
|
154
|
+
source_target_segment_id: ${source_target_segment_id},
|
|
155
|
+
segment_id: ${segment_id},
|
|
156
|
+
result: ${mappedArea ? debugStringify(mappedArea) : 'undefined'}
|
|
157
|
+
`,
|
|
158
|
+
);
|
|
159
|
+
if (segment_id !== -1 && mappedArea) {
|
|
160
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', segment_id, platform.log);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (segment_id == -1) {
|
|
164
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function mapRoomsToAreasFeatureOn(platform: RoborockMatterbridgePlatform, duid: string, data: CloudMessageResult): Promise<void> {
|
|
169
|
+
const robot = platform.robots.get(duid);
|
|
170
|
+
if (!robot) {
|
|
171
|
+
platform.log.error(`Robot with DUID ${duid} not found.`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!data.cleaning_info) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const currentMappedAreas = platform.roborockService?.getSupportedAreas(duid);
|
|
180
|
+
const roomIndexMap = platform.roborockService?.getSupportedAreasIndexMap(duid);
|
|
181
|
+
const source_segment_id = data.cleaning_info.segment_id ?? -1; // 4
|
|
182
|
+
const source_target_segment_id = data.cleaning_info.target_segment_id ?? -1; // -1
|
|
183
|
+
const segment_id = source_segment_id !== -1 ? source_segment_id : source_target_segment_id; // 4
|
|
184
|
+
const areaId = roomIndexMap?.getAreaId(segment_id, 0);
|
|
185
|
+
|
|
186
|
+
if (!areaId) {
|
|
187
|
+
platform.log.debug(`
|
|
188
|
+
source_segment_id: ${source_segment_id},
|
|
189
|
+
source_target_segment_id: ${source_target_segment_id},
|
|
190
|
+
segment_id: ${segment_id},
|
|
191
|
+
areaId: ${areaId}`);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const mappedArea = currentMappedAreas?.find((x) => x.areaId == areaId);
|
|
196
|
+
platform.log.debug(
|
|
197
|
+
`mappedArea:
|
|
198
|
+
source_segment_id: ${source_segment_id},
|
|
199
|
+
source_target_segment_id: ${source_target_segment_id},
|
|
200
|
+
segment_id: ${segment_id},
|
|
201
|
+
areaId: ${areaId},
|
|
202
|
+
result: ${mappedArea ? debugStringify(mappedArea) : 'undefined'}
|
|
203
|
+
`,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
if (areaId !== -1 && mappedArea) {
|
|
207
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log); // need to be 107
|
|
208
|
+
}
|
|
209
|
+
}
|
package/src/rvc.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { RoboticVacuumCleaner } from 'matterbridge/devices';
|
|
2
|
+
import { RoomMap } from './model/RoomMap.js';
|
|
3
|
+
import { Device } from './roborockCommunication/index.js';
|
|
4
|
+
import { getOperationalStates, getSupportedAreas, getSupportedCleanModes, getSupportedRunModes } from './initialData/index.js';
|
|
5
|
+
import { AnsiLogger, debugStringify } from 'matterbridge/logger';
|
|
6
|
+
import { BehaviorFactoryResult } from './behaviorFactory.js';
|
|
7
|
+
import { ModeBase, RvcOperationalState, ServiceArea } from 'matterbridge/matter/clusters';
|
|
8
|
+
import { ExperimentalFeatureSetting } from './model/ExperimentalFeatureSetting.js';
|
|
9
|
+
import { DockingStationStatus } from './model/DockingStationStatus.js';
|
|
10
|
+
|
|
11
|
+
interface IdentifyCommandRequest {
|
|
12
|
+
identifyTime?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
|
|
16
|
+
username: string | undefined;
|
|
17
|
+
device: Device;
|
|
18
|
+
roomInfo: RoomMap | undefined;
|
|
19
|
+
dockStationStatus: DockingStationStatus | undefined;
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
username: string,
|
|
23
|
+
device: Device,
|
|
24
|
+
roomMap: RoomMap,
|
|
25
|
+
routineAsRoom: ServiceArea.Area[],
|
|
26
|
+
enableExperimentalFeature: ExperimentalFeatureSetting | undefined,
|
|
27
|
+
log: AnsiLogger,
|
|
28
|
+
) {
|
|
29
|
+
const cleanModes = getSupportedCleanModes(device.data.model, enableExperimentalFeature);
|
|
30
|
+
const supportedRunModes = getSupportedRunModes();
|
|
31
|
+
const enableMultipleMap = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableMultipleMap;
|
|
32
|
+
|
|
33
|
+
const { supportedAreas, supportedMaps } = getSupportedAreas(device.rooms, roomMap, enableMultipleMap, log);
|
|
34
|
+
const supportedAreaAndRoutines = [...supportedAreas, ...routineAsRoom];
|
|
35
|
+
const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
|
|
36
|
+
|
|
37
|
+
log.debug(
|
|
38
|
+
`Creating RoborockVacuumCleaner for device: ${deviceName}, model: ${device.data.model}, forceRunAtDefault: ${enableExperimentalFeature?.advancedFeature?.forceRunAtDefault}`,
|
|
39
|
+
);
|
|
40
|
+
log.debug(`Supported Clean Modes: ${JSON.stringify(cleanModes)}`);
|
|
41
|
+
log.debug(`Supported Run Modes: ${JSON.stringify(supportedRunModes)}`);
|
|
42
|
+
log.debug(`Supported Areas: ${JSON.stringify(supportedAreas)}`);
|
|
43
|
+
log.debug(`Supported Maps: ${JSON.stringify(supportedMaps)}`);
|
|
44
|
+
|
|
45
|
+
const bridgeMode = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableServerMode ? 'server' : undefined;
|
|
46
|
+
super(
|
|
47
|
+
deviceName, // name
|
|
48
|
+
device.duid, // serial
|
|
49
|
+
bridgeMode, // mode
|
|
50
|
+
supportedRunModes[0].mode, // currentRunMode
|
|
51
|
+
supportedRunModes, // supportedRunModes
|
|
52
|
+
cleanModes[0].mode, // currentCleanMode
|
|
53
|
+
cleanModes, // supportedCleanModes
|
|
54
|
+
undefined, // currentPhase
|
|
55
|
+
undefined, // phaseList
|
|
56
|
+
RvcOperationalState.OperationalState.Docked, // operationalState
|
|
57
|
+
getOperationalStates(), // operationalStateList
|
|
58
|
+
supportedAreaAndRoutines, // supportedAreas
|
|
59
|
+
undefined, // selectedAreas
|
|
60
|
+
supportedAreas[0].areaId, // currentArea
|
|
61
|
+
supportedMaps, // supportedMaps
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
this.username = username;
|
|
65
|
+
this.device = device;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public configurateHandler(behaviorHandler: BehaviorFactoryResult): void {
|
|
69
|
+
this.addCommandHandler('identify', async ({ request, cluster, attributes, endpoint }) => {
|
|
70
|
+
this.log.info(`Identify command received for endpoint ${endpoint}, cluster ${cluster}, attributes ${debugStringify(attributes)}, request: ${JSON.stringify(request)}`);
|
|
71
|
+
behaviorHandler.executeCommand('playSoundToLocate', (request as IdentifyCommandRequest).identifyTime ?? 0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
this.addCommandHandler('selectAreas', async ({ request }) => {
|
|
75
|
+
const { newAreas } = request as ServiceArea.SelectAreasRequest;
|
|
76
|
+
this.log.info(`Selecting areas: ${newAreas?.join(', ')}`);
|
|
77
|
+
behaviorHandler.executeCommand('selectAreas', newAreas);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
this.addCommandHandler('changeToMode', async ({ request }) => {
|
|
81
|
+
const { newMode } = request as ModeBase.ChangeToModeRequest;
|
|
82
|
+
behaviorHandler.executeCommand('changeToMode', newMode);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
this.addCommandHandler('pause', async () => {
|
|
86
|
+
behaviorHandler.executeCommand('pause');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this.addCommandHandler('resume', async () => {
|
|
90
|
+
behaviorHandler.executeCommand('resume');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
this.addCommandHandler('goHome', async () => {
|
|
94
|
+
behaviorHandler.executeCommand('goHome');
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
package/src/settings.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PLUGIN_NAME = 'matterbridge-roborock-vacuum-plugin-jb';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { OperationStatusCode } from '../roborockCommunication/Zenum/operationStatusCode.js';
|
|
2
|
+
import { RvcRunMode, RvcOperationalState } from 'matterbridge/matter/clusters';
|
|
3
|
+
|
|
4
|
+
export function state_to_matter_state(state: number | undefined): RvcRunMode.ModeTag | undefined {
|
|
5
|
+
if (state === null) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
switch (state) {
|
|
10
|
+
case OperationStatusCode.RemoteControl:
|
|
11
|
+
case OperationStatusCode.Cleaning:
|
|
12
|
+
case OperationStatusCode.ReturningDock:
|
|
13
|
+
case OperationStatusCode.ManualMode:
|
|
14
|
+
case OperationStatusCode.SpotCleaning:
|
|
15
|
+
case OperationStatusCode.ReturnToDock:
|
|
16
|
+
case OperationStatusCode.GoTo:
|
|
17
|
+
case OperationStatusCode.ZoneClean:
|
|
18
|
+
case OperationStatusCode.RoomClean:
|
|
19
|
+
case OperationStatusCode.WashingTheMop:
|
|
20
|
+
case OperationStatusCode.GoingToWashTheMop:
|
|
21
|
+
case OperationStatusCode.EmptyingDustContainer:
|
|
22
|
+
case OperationStatusCode.Initiating:
|
|
23
|
+
case OperationStatusCode.Paused:
|
|
24
|
+
case OperationStatusCode.AirDryingStopping:
|
|
25
|
+
case OperationStatusCode.CleanMopCleaning:
|
|
26
|
+
case OperationStatusCode.CleanMopMopping:
|
|
27
|
+
case OperationStatusCode.RoomMopping:
|
|
28
|
+
case OperationStatusCode.RoomCleanMopCleaning:
|
|
29
|
+
case OperationStatusCode.RoomCleanMopMopping:
|
|
30
|
+
case OperationStatusCode.ZoneMopping:
|
|
31
|
+
case OperationStatusCode.ZoneCleanMopCleaning:
|
|
32
|
+
case OperationStatusCode.ZoneCleanMopMopping:
|
|
33
|
+
case OperationStatusCode.BackToDockWashingDuster:
|
|
34
|
+
return RvcRunMode.ModeTag.Cleaning;
|
|
35
|
+
|
|
36
|
+
case OperationStatusCode.Mapping:
|
|
37
|
+
return RvcRunMode.ModeTag.Mapping;
|
|
38
|
+
|
|
39
|
+
case OperationStatusCode.Idle:
|
|
40
|
+
case OperationStatusCode.Sleeping:
|
|
41
|
+
case OperationStatusCode.Charging:
|
|
42
|
+
case OperationStatusCode.FullyCharged:
|
|
43
|
+
default:
|
|
44
|
+
return RvcRunMode.ModeTag.Idle;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function state_to_matter_operational_status(state: number | undefined): RvcOperationalState.OperationalState | null {
|
|
49
|
+
switch (state) {
|
|
50
|
+
case OperationStatusCode.Initiating:
|
|
51
|
+
case OperationStatusCode.RemoteControl:
|
|
52
|
+
case OperationStatusCode.Cleaning:
|
|
53
|
+
case OperationStatusCode.ManualMode:
|
|
54
|
+
case OperationStatusCode.SpotCleaning:
|
|
55
|
+
case OperationStatusCode.GoTo:
|
|
56
|
+
case OperationStatusCode.ZoneClean:
|
|
57
|
+
case OperationStatusCode.RoomClean:
|
|
58
|
+
case OperationStatusCode.InCall:
|
|
59
|
+
case OperationStatusCode.Mapping:
|
|
60
|
+
case OperationStatusCode.Patrol:
|
|
61
|
+
case OperationStatusCode.CleanMopCleaning:
|
|
62
|
+
case OperationStatusCode.CleanMopMopping:
|
|
63
|
+
case OperationStatusCode.RoomMopping:
|
|
64
|
+
case OperationStatusCode.RoomCleanMopCleaning:
|
|
65
|
+
case OperationStatusCode.RoomCleanMopMopping:
|
|
66
|
+
case OperationStatusCode.ZoneMopping:
|
|
67
|
+
case OperationStatusCode.ZoneCleanMopCleaning:
|
|
68
|
+
case OperationStatusCode.ZoneCleanMopMopping:
|
|
69
|
+
case OperationStatusCode.RobotStatusMopping:
|
|
70
|
+
return RvcOperationalState.OperationalState.Running;
|
|
71
|
+
|
|
72
|
+
case OperationStatusCode.InError:
|
|
73
|
+
case OperationStatusCode.ChargingError:
|
|
74
|
+
case OperationStatusCode.Unknown:
|
|
75
|
+
case OperationStatusCode.DeviceOffline:
|
|
76
|
+
case OperationStatusCode.Locked:
|
|
77
|
+
case OperationStatusCode.AirDryingStopping:
|
|
78
|
+
return RvcOperationalState.OperationalState.Error;
|
|
79
|
+
|
|
80
|
+
case OperationStatusCode.Paused:
|
|
81
|
+
return RvcOperationalState.OperationalState.Paused;
|
|
82
|
+
|
|
83
|
+
case OperationStatusCode.ShuttingDown:
|
|
84
|
+
return RvcOperationalState.OperationalState.Stopped;
|
|
85
|
+
|
|
86
|
+
case OperationStatusCode.ReturnToDock:
|
|
87
|
+
case OperationStatusCode.ReturningDock:
|
|
88
|
+
case OperationStatusCode.WashingTheMop:
|
|
89
|
+
case OperationStatusCode.WashingTheMop2:
|
|
90
|
+
case OperationStatusCode.GoingToWashTheMop:
|
|
91
|
+
case OperationStatusCode.BackToDockWashingDuster:
|
|
92
|
+
case OperationStatusCode.EmptyingDustContainer:
|
|
93
|
+
return RvcOperationalState.OperationalState.SeekingCharger;
|
|
94
|
+
|
|
95
|
+
case OperationStatusCode.Idle:
|
|
96
|
+
case OperationStatusCode.Sleeping:
|
|
97
|
+
case OperationStatusCode.Updating:
|
|
98
|
+
case OperationStatusCode.FullyCharged:
|
|
99
|
+
case OperationStatusCode.Charging:
|
|
100
|
+
default:
|
|
101
|
+
return RvcOperationalState.OperationalState.Docked;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CleanModeSetting } from '../behaviors/roborock.vacuum/default/default.js';
|
|
2
|
+
import { getCurrentCleanModeDefault } from '../behaviors/roborock.vacuum/default/runtimes.js';
|
|
3
|
+
import { getCurrentCleanModeSmart } from '../behaviors/roborock.vacuum/smart/runtimes.js';
|
|
4
|
+
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
5
|
+
|
|
6
|
+
export type CleanModeFunc = (setting: CleanModeSetting) => number | undefined;
|
|
7
|
+
|
|
8
|
+
export function getCurrentCleanModeFunc(model: string, forceRunAtDefault: boolean): CleanModeFunc {
|
|
9
|
+
if (forceRunAtDefault) {
|
|
10
|
+
return getCurrentCleanModeDefault;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
switch (model) {
|
|
14
|
+
case DeviceModel.QREVO_EDGE_5V1:
|
|
15
|
+
return getCurrentCleanModeSmart;
|
|
16
|
+
|
|
17
|
+
case DeviceModel.S7_MAXV:
|
|
18
|
+
case DeviceModel.S8_PRO_ULTRA:
|
|
19
|
+
case DeviceModel.S6_PURE:
|
|
20
|
+
default:
|
|
21
|
+
return getCurrentCleanModeDefault;
|
|
22
|
+
}
|
|
23
|
+
}
|