matterbridge-roborock-vacuum-plugin 1.0.8-rc06 → 1.0.8-rc07
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/README.md +7 -4
- package/dist/behaviors/roborock.vacuum/default/initalData.js +13 -7
- package/dist/behaviors/roborock.vacuum/smart/initalData.js +2 -2
- package/dist/behaviors/roborock.vacuum/smart/smart.js +1 -1
- package/dist/initialData/getSupportedCleanModes.js +5 -5
- package/dist/model/DockingStationStatus.js +3 -0
- package/dist/platform.js +1 -1
- package/dist/platformRunner.js +35 -7
- package/dist/rvc.js +4 -3
- package/matterbridge-roborock-vacuum-plugin.config.json +3 -2
- package/matterbridge-roborock-vacuum-plugin.schema.json +6 -1
- package/package.json +1 -1
- package/src/behaviors/roborock.vacuum/default/initalData.ts +16 -8
- package/src/behaviors/roborock.vacuum/smart/initalData.ts +3 -2
- package/src/behaviors/roborock.vacuum/smart/smart.ts +1 -1
- package/src/initialData/getSupportedCleanModes.ts +6 -5
- package/src/model/DockingStationStatus.ts +5 -1
- package/src/model/ExperimentalFeatureSetting.ts +1 -0
- package/src/platform.ts +1 -1
- package/src/platformRunner.ts +40 -9
- package/src/rvc.ts +15 -3
package/README.md
CHANGED
|
@@ -74,11 +74,14 @@ To get the **DUID** for your devices, you have two options:
|
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
|
-
**➡️ [See Supported & Tested Roborock Devices](./README_SUPPORTED.md)**
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
### ➡️ [See Supported & Tested Roborock Devices](./README_SUPPORTED.md)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
📋 **Apple Home ↔️ Roborock Clean Mode Mapping:**
|
|
82
|
+
For a detailed table of how Apple Home clean modes map to Roborock settings, see 👉 [Apple Home ↔️ Roborock Clean Mode Mapping](./README_CLEANMODE.md)
|
|
83
|
+
|
|
84
|
+
---
|
|
82
85
|
|
|
83
86
|
### 📦 Prerequisites
|
|
84
87
|
|
|
@@ -19,8 +19,8 @@ export function getDefaultSupportedRunModes() {
|
|
|
19
19
|
},
|
|
20
20
|
];
|
|
21
21
|
}
|
|
22
|
-
export function getDefaultSupportedCleanModes() {
|
|
23
|
-
|
|
22
|
+
export function getDefaultSupportedCleanModes(enableExperimentalFeature) {
|
|
23
|
+
const result = [
|
|
24
24
|
{
|
|
25
25
|
label: RvcCleanModeDisplayMap[5],
|
|
26
26
|
mode: 5,
|
|
@@ -96,12 +96,18 @@ export function getDefaultSupportedCleanModes() {
|
|
|
96
96
|
mode: 69,
|
|
97
97
|
modeTags: [{ value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Quick }],
|
|
98
98
|
},
|
|
99
|
-
{
|
|
100
|
-
label: RvcCleanModeDisplayMap[99],
|
|
101
|
-
mode: 99,
|
|
102
|
-
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Vacation }],
|
|
103
|
-
},
|
|
104
99
|
];
|
|
100
|
+
if (enableExperimentalFeature?.advancedFeature?.useVacationModeToSendVacuumToDock ?? false) {
|
|
101
|
+
return [
|
|
102
|
+
...result,
|
|
103
|
+
{
|
|
104
|
+
label: RvcCleanModeDisplayMap[99],
|
|
105
|
+
mode: 99,
|
|
106
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Vacation }],
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
105
111
|
}
|
|
106
112
|
export function getDefaultOperationalStates() {
|
|
107
113
|
return [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RvcCleanMode } from 'matterbridge/matter/clusters';
|
|
2
2
|
import { RvcCleanMode as RvcCleanModeDisplayMap } from './smart.js';
|
|
3
3
|
import { getDefaultSupportedCleanModes } from '../default/initalData.js';
|
|
4
|
-
export function getSupportedCleanModesSmart() {
|
|
4
|
+
export function getSupportedCleanModesSmart(enableExperimentalFeature) {
|
|
5
5
|
return [
|
|
6
6
|
{
|
|
7
7
|
label: RvcCleanModeDisplayMap[4],
|
|
@@ -13,6 +13,6 @@ export function getSupportedCleanModesSmart() {
|
|
|
13
13
|
mode: 5,
|
|
14
14
|
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Day }],
|
|
15
15
|
},
|
|
16
|
-
...getDefaultSupportedCleanModes().filter((x) => x.mode !== 4 && x.mode !== 5),
|
|
16
|
+
...getDefaultSupportedCleanModes(enableExperimentalFeature).filter((x) => x.mode !== 4 && x.mode !== 5),
|
|
17
17
|
];
|
|
18
18
|
}
|
|
@@ -51,7 +51,7 @@ export function setCommandHandlerSmart(duid, handler, logger, roborockService, c
|
|
|
51
51
|
break;
|
|
52
52
|
}
|
|
53
53
|
case 'Go Vacation': {
|
|
54
|
-
logger.notice('
|
|
54
|
+
logger.notice('BehaviorSmart-GoHome');
|
|
55
55
|
await roborockService.stopAndGoHome(duid);
|
|
56
56
|
break;
|
|
57
57
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { getSupportedCleanModesSmart } from '../behaviors/roborock.vacuum/smart/initalData.js';
|
|
2
2
|
import { getDefaultSupportedCleanModes } from '../behaviors/roborock.vacuum/default/initalData.js';
|
|
3
3
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
4
|
-
export function getSupportedCleanModes(model,
|
|
5
|
-
if (forceRunAtDefault) {
|
|
6
|
-
return getDefaultSupportedCleanModes();
|
|
4
|
+
export function getSupportedCleanModes(model, enableExperimentalFeature) {
|
|
5
|
+
if (enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false) {
|
|
6
|
+
return getDefaultSupportedCleanModes(enableExperimentalFeature);
|
|
7
7
|
}
|
|
8
8
|
switch (model) {
|
|
9
9
|
case DeviceModel.QREVO_EDGE_5V1:
|
|
10
|
-
return getSupportedCleanModesSmart();
|
|
10
|
+
return getSupportedCleanModesSmart(enableExperimentalFeature);
|
|
11
11
|
case DeviceModel.S7_MAXV:
|
|
12
12
|
case DeviceModel.S8_PRO_ULTRA:
|
|
13
13
|
case DeviceModel.S6_PURE:
|
|
14
14
|
default:
|
|
15
|
-
return getDefaultSupportedCleanModes();
|
|
15
|
+
return getDefaultSupportedCleanModes(enableExperimentalFeature);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -15,6 +15,9 @@ export function parseDockingStationStatus(dss) {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
export function hasDockingStationError(status) {
|
|
18
|
+
if (!status) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
18
21
|
return (status.cleanFluidStatus === DockingStationStatusType.Error ||
|
|
19
22
|
status.waterBoxFilterStatus === DockingStationStatusType.Error ||
|
|
20
23
|
status.dustBagStatus === DockingStationStatusType.Error ||
|
package/dist/platform.js
CHANGED
|
@@ -113,7 +113,7 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
113
113
|
routineAsRoom = getSupportedScenes(vacuum.scenes, this.log);
|
|
114
114
|
this.roborockService.setSupportedScenes(vacuum.duid, routineAsRoom);
|
|
115
115
|
}
|
|
116
|
-
this.robot = new RoborockVacuumCleaner(username, vacuum, roomMap, routineAsRoom, this.enableExperimentalFeature
|
|
116
|
+
this.robot = new RoborockVacuumCleaner(username, vacuum, roomMap, routineAsRoom, this.enableExperimentalFeature, this.log);
|
|
117
117
|
this.robot.configurateHandler(behaviorHandler);
|
|
118
118
|
this.log.info('vacuum:', debugStringify(vacuum));
|
|
119
119
|
this.setSelectDevice(this.robot.serialNumber ?? '', this.robot.deviceName ?? '', undefined, 'hub');
|
package/dist/platformRunner.js
CHANGED
|
@@ -159,7 +159,10 @@ export class PlatformRunner {
|
|
|
159
159
|
}
|
|
160
160
|
const operationalStateId = state_to_matter_operational_status(status);
|
|
161
161
|
if (operationalStateId) {
|
|
162
|
-
|
|
162
|
+
const dssHasError = hasDockingStationError(platform.robot?.dockStationStatus);
|
|
163
|
+
if (!(dssHasError && self.triggerDssError())) {
|
|
164
|
+
platform.robot?.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
165
|
+
}
|
|
163
166
|
}
|
|
164
167
|
break;
|
|
165
168
|
}
|
|
@@ -211,18 +214,27 @@ export class PlatformRunner {
|
|
|
211
214
|
});
|
|
212
215
|
}
|
|
213
216
|
async processAdditionalProps(robot, message) {
|
|
217
|
+
const dssStatus = this.getDssStatus(message);
|
|
218
|
+
if (dssStatus) {
|
|
219
|
+
this.triggerDssError();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
getDssStatus(message) {
|
|
214
223
|
const platform = this.platform;
|
|
224
|
+
const robot = platform.robot;
|
|
215
225
|
if (platform.enableExperimentalFeature &&
|
|
216
226
|
platform.enableExperimentalFeature.enableExperimentalFeature &&
|
|
217
227
|
platform.enableExperimentalFeature.advancedFeature.includeDockStationStatus &&
|
|
218
228
|
message.dss !== undefined) {
|
|
219
229
|
const dss = parseDockingStationStatus(message.dss);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
230
|
+
if (dss && robot) {
|
|
231
|
+
robot.dockStationStatus = dss;
|
|
232
|
+
}
|
|
233
|
+
if (dss && hasDockingStationError(dss)) {
|
|
234
|
+
return RvcOperationalState.OperationalState.Error;
|
|
224
235
|
}
|
|
225
236
|
}
|
|
237
|
+
return undefined;
|
|
226
238
|
}
|
|
227
239
|
isStatusUpdate(result) {
|
|
228
240
|
return (Array.isArray(result) &&
|
|
@@ -262,11 +274,27 @@ export class PlatformRunner {
|
|
|
262
274
|
}
|
|
263
275
|
const operationalStateId = state_to_matter_operational_status(state);
|
|
264
276
|
if (operationalStateId) {
|
|
265
|
-
|
|
266
|
-
platform.
|
|
277
|
+
const dssHasError = hasDockingStationError(platform.robot?.dockStationStatus);
|
|
278
|
+
this.platform.log.debug(`dssHasError: ${dssHasError}, dockStationStatus: ${debugStringify(platform.robot?.dockStationStatus ?? {})}`);
|
|
279
|
+
if (!(dssHasError && this.triggerDssError())) {
|
|
280
|
+
this.platform.log.debug(`updateFromHomeData-OperationalState: ${RvcOperationalState.OperationalState[operationalStateId]}`);
|
|
281
|
+
platform.robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
282
|
+
}
|
|
267
283
|
}
|
|
268
284
|
if (batteryLevel) {
|
|
269
285
|
platform.robot.updateAttribute(PowerSource.Cluster.id, 'batChargeState', getBatteryState(state, batteryLevel), platform.log);
|
|
270
286
|
}
|
|
271
287
|
}
|
|
288
|
+
triggerDssError() {
|
|
289
|
+
const platform = this.platform;
|
|
290
|
+
const currentOperationState = platform?.robot?.getAttribute(RvcOperationalState.Cluster.id, 'operationalState');
|
|
291
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Error) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Docked) {
|
|
295
|
+
platform.robot?.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', RvcOperationalState.OperationalState.Error, platform.log);
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
272
300
|
}
|
package/dist/rvc.js
CHANGED
|
@@ -6,12 +6,13 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
|
|
|
6
6
|
device;
|
|
7
7
|
rrHomeId;
|
|
8
8
|
roomInfo;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
dockStationStatus;
|
|
10
|
+
constructor(username, device, roomMap, routineAsRoom, enableExperimentalFeature, log) {
|
|
11
|
+
const cleanModes = getSupportedCleanModes(device.data.model, enableExperimentalFeature);
|
|
11
12
|
const supportedRunModes = getSupportedRunModes();
|
|
12
13
|
const supportedAreas = [...getSupportedAreas(device.rooms, roomMap, log), ...routineAsRoom];
|
|
13
14
|
const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
|
|
14
|
-
log.debug(`Creating RoborockVacuumCleaner for device: ${deviceName}, model: ${device.data.model}, forceRunAtDefault: ${forceRunAtDefault}`);
|
|
15
|
+
log.debug(`Creating RoborockVacuumCleaner for device: ${deviceName}, model: ${device.data.model}, forceRunAtDefault: ${enableExperimentalFeature?.advancedFeature?.forceRunAtDefault}`);
|
|
15
16
|
log.debug(`Supported Clean Modes: ${JSON.stringify(cleanModes)}`);
|
|
16
17
|
log.debug(`Supported Run Modes: ${JSON.stringify(supportedRunModes)}`);
|
|
17
18
|
super(deviceName, device.duid, supportedRunModes[0].mode, supportedRunModes, cleanModes[0].mode, cleanModes, undefined, undefined, RvcOperationalState.OperationalState.Docked, getOperationalStates(), supportedAreas, undefined, supportedAreas[0].areaId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-roborock-vacuum-plugin",
|
|
3
3
|
"type": "DynamicPlatform",
|
|
4
|
-
"version": "1.0.8-
|
|
4
|
+
"version": "1.0.8-rc07",
|
|
5
5
|
"whiteList": [],
|
|
6
6
|
"blackList": [],
|
|
7
7
|
"useInterval": true,
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"advancedFeature": {
|
|
11
11
|
"showRoutinesAsRooms": false,
|
|
12
12
|
"includeDockStationStatus": false,
|
|
13
|
-
"forceRunAtDefault": false
|
|
13
|
+
"forceRunAtDefault": false,
|
|
14
|
+
"useVacationModeToSendVacuumToDock": false
|
|
14
15
|
},
|
|
15
16
|
"cleanModeSettings": {
|
|
16
17
|
"enableCleanModeMapping": false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "Matterbridge Roborock Vacuum Plugin",
|
|
3
|
-
"description": "matterbridge-roborock-vacuum-plugin v. 1.0.8-
|
|
3
|
+
"description": "matterbridge-roborock-vacuum-plugin v. 1.0.8-rc07 by https://github.com/RinDevJunior",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"required": ["username", "password"],
|
|
6
6
|
"properties": {
|
|
@@ -79,6 +79,11 @@
|
|
|
79
79
|
"title": "Force Run At Default Implementation",
|
|
80
80
|
"type": "boolean",
|
|
81
81
|
"default": false
|
|
82
|
+
},
|
|
83
|
+
"useVacationModeToSendVacuumToDock": {
|
|
84
|
+
"title": "Use Vacation Mode To Send Vacuum To Dock",
|
|
85
|
+
"type": "boolean",
|
|
86
|
+
"default": false
|
|
82
87
|
}
|
|
83
88
|
}
|
|
84
89
|
},
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RvcCleanMode, RvcOperationalState, RvcRunMode } from 'matterbridge/matter/clusters';
|
|
2
2
|
import { RvcCleanMode as RvcCleanModeDisplayMap } from './default.js';
|
|
3
|
+
import { ExperimentalFeatureSetting } from '../../../model/ExperimentalFeatureSetting.js';
|
|
3
4
|
|
|
4
5
|
export function getDefaultSupportedRunModes(): RvcRunMode.ModeOption[] {
|
|
5
6
|
return [
|
|
@@ -21,8 +22,8 @@ export function getDefaultSupportedRunModes(): RvcRunMode.ModeOption[] {
|
|
|
21
22
|
];
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export function getDefaultSupportedCleanModes(): RvcCleanMode.ModeOption[] {
|
|
25
|
-
|
|
25
|
+
export function getDefaultSupportedCleanModes(enableExperimentalFeature: ExperimentalFeatureSetting | undefined): RvcCleanMode.ModeOption[] {
|
|
26
|
+
const result = [
|
|
26
27
|
{
|
|
27
28
|
label: RvcCleanModeDisplayMap[5],
|
|
28
29
|
mode: 5,
|
|
@@ -101,13 +102,20 @@ export function getDefaultSupportedCleanModes(): RvcCleanMode.ModeOption[] {
|
|
|
101
102
|
mode: 69,
|
|
102
103
|
modeTags: [{ value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Quick }],
|
|
103
104
|
},
|
|
104
|
-
|
|
105
|
-
{
|
|
106
|
-
label: RvcCleanModeDisplayMap[99],
|
|
107
|
-
mode: 99,
|
|
108
|
-
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Vacation }],
|
|
109
|
-
},
|
|
110
105
|
];
|
|
106
|
+
|
|
107
|
+
if (enableExperimentalFeature?.advancedFeature?.useVacationModeToSendVacuumToDock ?? false) {
|
|
108
|
+
return [
|
|
109
|
+
...result,
|
|
110
|
+
{
|
|
111
|
+
label: RvcCleanModeDisplayMap[99],
|
|
112
|
+
mode: 99,
|
|
113
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Vacation }],
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
export function getDefaultOperationalStates(): RvcOperationalState.OperationalStateStruct[] {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { RvcCleanMode } from 'matterbridge/matter/clusters';
|
|
2
2
|
import { RvcCleanMode as RvcCleanModeDisplayMap } from './smart.js';
|
|
3
3
|
import { getDefaultSupportedCleanModes } from '../default/initalData.js';
|
|
4
|
+
import { ExperimentalFeatureSetting } from '../../../model/ExperimentalFeatureSetting.js';
|
|
4
5
|
|
|
5
|
-
export function getSupportedCleanModesSmart(): RvcCleanMode.ModeOption[] {
|
|
6
|
+
export function getSupportedCleanModesSmart(enableExperimentalFeature: ExperimentalFeatureSetting | undefined): RvcCleanMode.ModeOption[] {
|
|
6
7
|
return [
|
|
7
8
|
{
|
|
8
9
|
label: RvcCleanModeDisplayMap[4],
|
|
@@ -14,6 +15,6 @@ export function getSupportedCleanModesSmart(): RvcCleanMode.ModeOption[] {
|
|
|
14
15
|
mode: 5,
|
|
15
16
|
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Day }],
|
|
16
17
|
},
|
|
17
|
-
...getDefaultSupportedCleanModes().filter((x) => x.mode !== 4 && x.mode !== 5), // Exclude modes 4 and 5 which are already defined
|
|
18
|
+
...getDefaultSupportedCleanModes(enableExperimentalFeature).filter((x) => x.mode !== 4 && x.mode !== 5), // Exclude modes 4 and 5 which are already defined
|
|
18
19
|
];
|
|
19
20
|
}
|
|
@@ -2,20 +2,21 @@ import { RvcCleanMode } from 'matterbridge/matter/clusters';
|
|
|
2
2
|
import { getSupportedCleanModesSmart } from '../behaviors/roborock.vacuum/smart/initalData.js';
|
|
3
3
|
import { getDefaultSupportedCleanModes } from '../behaviors/roborock.vacuum/default/initalData.js';
|
|
4
4
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
5
|
+
import { ExperimentalFeatureSetting } from '../model/ExperimentalFeatureSetting.js';
|
|
5
6
|
|
|
6
|
-
export function getSupportedCleanModes(model: string,
|
|
7
|
-
if (forceRunAtDefault) {
|
|
8
|
-
return getDefaultSupportedCleanModes();
|
|
7
|
+
export function getSupportedCleanModes(model: string, enableExperimentalFeature: ExperimentalFeatureSetting | undefined): RvcCleanMode.ModeOption[] {
|
|
8
|
+
if (enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false) {
|
|
9
|
+
return getDefaultSupportedCleanModes(enableExperimentalFeature);
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
switch (model) {
|
|
12
13
|
case DeviceModel.QREVO_EDGE_5V1:
|
|
13
|
-
return getSupportedCleanModesSmart();
|
|
14
|
+
return getSupportedCleanModesSmart(enableExperimentalFeature);
|
|
14
15
|
|
|
15
16
|
case DeviceModel.S7_MAXV:
|
|
16
17
|
case DeviceModel.S8_PRO_ULTRA:
|
|
17
18
|
case DeviceModel.S6_PURE:
|
|
18
19
|
default:
|
|
19
|
-
return getDefaultSupportedCleanModes();
|
|
20
|
+
return getDefaultSupportedCleanModes(enableExperimentalFeature);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -25,7 +25,11 @@ export function parseDockingStationStatus(dss: number): DockingStationStatus {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function hasDockingStationError(status: DockingStationStatus): boolean {
|
|
28
|
+
export function hasDockingStationError(status: DockingStationStatus | undefined): boolean {
|
|
29
|
+
if (!status) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
return (
|
|
30
34
|
status.cleanFluidStatus === DockingStationStatusType.Error ||
|
|
31
35
|
status.waterBoxFilterStatus === DockingStationStatusType.Error ||
|
package/src/platform.ts
CHANGED
|
@@ -162,7 +162,7 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
162
162
|
this.roborockService.setSupportedScenes(vacuum.duid, routineAsRoom);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
this.robot = new RoborockVacuumCleaner(username, vacuum, roomMap, routineAsRoom, this.enableExperimentalFeature
|
|
165
|
+
this.robot = new RoborockVacuumCleaner(username, vacuum, roomMap, routineAsRoom, this.enableExperimentalFeature, this.log);
|
|
166
166
|
this.robot.configurateHandler(behaviorHandler);
|
|
167
167
|
|
|
168
168
|
this.log.info('vacuum:', debugStringify(vacuum));
|
package/src/platformRunner.ts
CHANGED
|
@@ -192,7 +192,10 @@ export class PlatformRunner {
|
|
|
192
192
|
|
|
193
193
|
const operationalStateId = state_to_matter_operational_status(status);
|
|
194
194
|
if (operationalStateId) {
|
|
195
|
-
|
|
195
|
+
const dssHasError = hasDockingStationError(platform.robot?.dockStationStatus);
|
|
196
|
+
if (!(dssHasError && self.triggerDssError())) {
|
|
197
|
+
platform.robot?.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
198
|
+
}
|
|
196
199
|
}
|
|
197
200
|
break;
|
|
198
201
|
}
|
|
@@ -254,7 +257,15 @@ export class PlatformRunner {
|
|
|
254
257
|
|
|
255
258
|
private async processAdditionalProps(robot: RoborockVacuumCleaner, message: CloudMessageResult): Promise<void> {
|
|
256
259
|
// dss -> DockingStationStatus
|
|
260
|
+
const dssStatus = this.getDssStatus(message);
|
|
261
|
+
if (dssStatus) {
|
|
262
|
+
this.triggerDssError();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private getDssStatus(message: CloudMessageResult): RvcOperationalState.OperationalState | undefined {
|
|
257
267
|
const platform = this.platform;
|
|
268
|
+
const robot = platform.robot;
|
|
258
269
|
if (
|
|
259
270
|
platform.enableExperimentalFeature &&
|
|
260
271
|
platform.enableExperimentalFeature.enableExperimentalFeature &&
|
|
@@ -262,15 +273,15 @@ export class PlatformRunner {
|
|
|
262
273
|
message.dss !== undefined
|
|
263
274
|
) {
|
|
264
275
|
const dss = parseDockingStationStatus(message.dss);
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
276
|
+
if (dss && robot) {
|
|
277
|
+
robot.dockStationStatus = dss;
|
|
278
|
+
}
|
|
268
279
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', RvcOperationalState.OperationalState.Error, platform.log);
|
|
280
|
+
if (dss && hasDockingStationError(dss)) {
|
|
281
|
+
return RvcOperationalState.OperationalState.Error;
|
|
272
282
|
}
|
|
273
283
|
}
|
|
284
|
+
return undefined;
|
|
274
285
|
}
|
|
275
286
|
|
|
276
287
|
private isStatusUpdate(result: unknown): boolean {
|
|
@@ -317,13 +328,33 @@ export class PlatformRunner {
|
|
|
317
328
|
}
|
|
318
329
|
|
|
319
330
|
const operationalStateId = state_to_matter_operational_status(state);
|
|
331
|
+
|
|
320
332
|
if (operationalStateId) {
|
|
321
|
-
|
|
322
|
-
platform.
|
|
333
|
+
const dssHasError = hasDockingStationError(platform.robot?.dockStationStatus);
|
|
334
|
+
this.platform.log.debug(`dssHasError: ${dssHasError}, dockStationStatus: ${debugStringify(platform.robot?.dockStationStatus ?? {})}`);
|
|
335
|
+
if (!(dssHasError && this.triggerDssError())) {
|
|
336
|
+
this.platform.log.debug(`updateFromHomeData-OperationalState: ${RvcOperationalState.OperationalState[operationalStateId]}`);
|
|
337
|
+
platform.robot.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', operationalStateId, platform.log);
|
|
338
|
+
}
|
|
323
339
|
}
|
|
324
340
|
|
|
325
341
|
if (batteryLevel) {
|
|
326
342
|
platform.robot.updateAttribute(PowerSource.Cluster.id, 'batChargeState', getBatteryState(state, batteryLevel), platform.log);
|
|
327
343
|
}
|
|
328
344
|
}
|
|
345
|
+
|
|
346
|
+
private triggerDssError(): boolean {
|
|
347
|
+
const platform = this.platform;
|
|
348
|
+
const currentOperationState = platform?.robot?.getAttribute(RvcOperationalState.Cluster.id, 'operationalState') as RvcOperationalState.OperationalState;
|
|
349
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Error) {
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (currentOperationState === RvcOperationalState.OperationalState.Docked) {
|
|
354
|
+
platform.robot?.updateAttribute(RvcOperationalState.Cluster.id, 'operationalState', RvcOperationalState.OperationalState.Error, platform.log);
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
329
360
|
}
|
package/src/rvc.ts
CHANGED
|
@@ -5,20 +5,32 @@ import { getOperationalStates, getSupportedAreas, getSupportedCleanModes, getSup
|
|
|
5
5
|
import { AnsiLogger } from 'matterbridge/logger';
|
|
6
6
|
import { BehaviorFactoryResult } from './behaviorFactory.js';
|
|
7
7
|
import { ModeBase, RvcOperationalState, ServiceArea } from 'matterbridge/matter/clusters';
|
|
8
|
+
import { ExperimentalFeatureSetting } from './model/ExperimentalFeatureSetting.js';
|
|
9
|
+
import { DockingStationStatus } from './model/DockingStationStatus.js';
|
|
8
10
|
|
|
9
11
|
export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
|
|
10
12
|
username: string | undefined;
|
|
11
13
|
device: Device;
|
|
12
14
|
rrHomeId: number;
|
|
13
15
|
roomInfo: RoomMap | undefined;
|
|
16
|
+
dockStationStatus: DockingStationStatus | undefined;
|
|
14
17
|
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
18
|
+
constructor(
|
|
19
|
+
username: string,
|
|
20
|
+
device: Device,
|
|
21
|
+
roomMap: RoomMap,
|
|
22
|
+
routineAsRoom: ServiceArea.Area[],
|
|
23
|
+
enableExperimentalFeature: ExperimentalFeatureSetting | undefined,
|
|
24
|
+
log: AnsiLogger,
|
|
25
|
+
) {
|
|
26
|
+
const cleanModes = getSupportedCleanModes(device.data.model, enableExperimentalFeature);
|
|
17
27
|
const supportedRunModes = getSupportedRunModes();
|
|
18
28
|
const supportedAreas = [...getSupportedAreas(device.rooms, roomMap, log), ...routineAsRoom];
|
|
19
29
|
const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
|
|
20
30
|
|
|
21
|
-
log.debug(
|
|
31
|
+
log.debug(
|
|
32
|
+
`Creating RoborockVacuumCleaner for device: ${deviceName}, model: ${device.data.model}, forceRunAtDefault: ${enableExperimentalFeature?.advancedFeature?.forceRunAtDefault}`,
|
|
33
|
+
);
|
|
22
34
|
log.debug(`Supported Clean Modes: ${JSON.stringify(cleanModes)}`);
|
|
23
35
|
log.debug(`Supported Run Modes: ${JSON.stringify(supportedRunModes)}`);
|
|
24
36
|
|