matterbridge-roborock-vacuum-plugin 1.0.7-rc02 → 1.0.7
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 +11 -1
- package/dist/behaviorFactory.js +8 -2
- package/dist/behaviors/roborock.vacuum/QREVO_EDGE_5V1/a187.js +56 -11
- package/dist/behaviors/roborock.vacuum/S7_MAXV/a27.js +97 -0
- package/dist/behaviors/roborock.vacuum/S7_MAXV/initalData.js +76 -0
- package/dist/behaviors/roborock.vacuum/S7_MAXV/runtimes.js +33 -0
- package/dist/initialData/getOperationalStates.js +3 -0
- package/dist/initialData/getSupportedCleanModes.js +3 -0
- package/dist/initialData/getSupportedRunModes.js +3 -0
- package/dist/model/CleanModeSettings.js +5 -0
- package/dist/platform.js +15 -8
- package/dist/roborockCommunication/broadcast/messageProcessor.js +12 -7
- package/dist/roborockService.js +5 -2
- package/dist/rvc.js +2 -1
- package/dist/share/runtimeHelper.js +10 -0
- package/matterbridge-roborock-vacuum-plugin.config.json +1 -1
- package/matterbridge-roborock-vacuum-plugin.schema.json +118 -5
- package/package.json +1 -1
- package/src/behaviorFactory.ts +16 -2
- package/src/behaviors/roborock.vacuum/QREVO_EDGE_5V1/a187.test.ts +201 -0
- package/src/behaviors/roborock.vacuum/QREVO_EDGE_5V1/a187.ts +68 -12
- package/src/behaviors/roborock.vacuum/S7_MAXV/a27.ts +121 -0
- package/src/behaviors/roborock.vacuum/S7_MAXV/initalData.ts +80 -0
- package/src/behaviors/roborock.vacuum/S7_MAXV/runtimes.ts +26 -0
- package/src/initialData/getOperationalStates.ts +3 -0
- package/src/initialData/getSupportedCleanModes.ts +3 -0
- package/src/initialData/getSupportedRunModes.ts +3 -0
- package/src/model/CleanModeSettings.ts +17 -0
- package/src/platform.ts +18 -10
- package/src/roborockCommunication/broadcast/messageProcessor.ts +16 -7
- package/src/roborockService.ts +9 -2
- package/src/rvc.ts +2 -1
- package/src/share/runtimeHelper.ts +10 -0
package/README.md
CHANGED
|
@@ -42,13 +42,23 @@
|
|
|
42
42
|
---
|
|
43
43
|
### 🆔 How to Get Your DUID
|
|
44
44
|
|
|
45
|
-
To get the **DUID** for your devices
|
|
45
|
+
To get the **DUID** for your devices, you have two options:
|
|
46
46
|
|
|
47
|
+
**Option 1: From Matterbridge Logs**
|
|
47
48
|
1. **Start Matterbridge** with the plugin enabled.
|
|
48
49
|
2. **Watch the Docker console logs directly** (not the Matterbridge UI logs, as they may be truncated).
|
|
49
50
|
3. Look for the log message that says:
|
|
50
51
|
```text
|
|
51
52
|
Initializing - devices: [...]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Option 2: From the Roborock App**
|
|
56
|
+
1. Open the **Roborock app** on your phone.
|
|
57
|
+
2. Go to your **Device**.
|
|
58
|
+
3. Tap **Settings** > **Product Info**.
|
|
59
|
+
4. Find the **DID** field. The value will look like `rr_xxxxxxx`.
|
|
60
|
+
5. **Remove the `rr_` prefix** from the DID value. The remaining string is your DUID.
|
|
61
|
+
|
|
52
62
|
---
|
|
53
63
|
### 🚧 Project Status
|
|
54
64
|
|
package/dist/behaviorFactory.js
CHANGED
|
@@ -2,11 +2,17 @@ import { BehaviorDeviceGeneric } from './behaviors/BehaviorDeviceGeneric.js';
|
|
|
2
2
|
import { setCommandHandlerA187 } from './behaviors/roborock.vacuum/QREVO_EDGE_5V1/a187.js';
|
|
3
3
|
import { setDefaultCommandHandler } from './behaviors/roborock.vacuum/default/default.js';
|
|
4
4
|
import { DeviceModel } from './roborockCommunication/Zmodel/deviceModel.js';
|
|
5
|
-
|
|
5
|
+
import { setCommandHandlerA27 } from './behaviors/roborock.vacuum/S7_MAXV/a27.js';
|
|
6
|
+
export function configurateBehavior(model, duid, roborockService, cleanModeSettings, logger) {
|
|
6
7
|
switch (model) {
|
|
7
8
|
case DeviceModel.QREVO_EDGE_5V1: {
|
|
8
9
|
const deviceHandler = new BehaviorDeviceGeneric(logger);
|
|
9
|
-
setCommandHandlerA187(duid, deviceHandler, logger, roborockService);
|
|
10
|
+
setCommandHandlerA187(duid, deviceHandler, logger, roborockService, cleanModeSettings);
|
|
11
|
+
return deviceHandler;
|
|
12
|
+
}
|
|
13
|
+
case DeviceModel.S7_MAXV: {
|
|
14
|
+
const deviceHandler = new BehaviorDeviceGeneric(logger);
|
|
15
|
+
setCommandHandlerA27(duid, deviceHandler, logger, roborockService);
|
|
10
16
|
return deviceHandler;
|
|
11
17
|
}
|
|
12
18
|
default: {
|
|
@@ -27,15 +27,16 @@ export var MopWaterFlowA187;
|
|
|
27
27
|
MopWaterFlowA187[MopWaterFlowA187["Medium"] = 202] = "Medium";
|
|
28
28
|
MopWaterFlowA187[MopWaterFlowA187["High"] = 203] = "High";
|
|
29
29
|
MopWaterFlowA187[MopWaterFlowA187["Custom"] = 204] = "Custom";
|
|
30
|
+
MopWaterFlowA187[MopWaterFlowA187["CustomizeWithDistanceOff"] = 207] = "CustomizeWithDistanceOff";
|
|
30
31
|
MopWaterFlowA187[MopWaterFlowA187["Smart"] = 209] = "Smart";
|
|
31
32
|
})(MopWaterFlowA187 || (MopWaterFlowA187 = {}));
|
|
32
33
|
export var MopRouteA187;
|
|
33
34
|
(function (MopRouteA187) {
|
|
34
|
-
MopRouteA187[MopRouteA187["Fast"] = 304] = "Fast";
|
|
35
35
|
MopRouteA187[MopRouteA187["Standard"] = 300] = "Standard";
|
|
36
36
|
MopRouteA187[MopRouteA187["Deep"] = 301] = "Deep";
|
|
37
37
|
MopRouteA187[MopRouteA187["Custom"] = 302] = "Custom";
|
|
38
38
|
MopRouteA187[MopRouteA187["DeepPlus"] = 303] = "DeepPlus";
|
|
39
|
+
MopRouteA187[MopRouteA187["Fast"] = 304] = "Fast";
|
|
39
40
|
MopRouteA187[MopRouteA187["Smart"] = 306] = "Smart";
|
|
40
41
|
})(MopRouteA187 || (MopRouteA187 = {}));
|
|
41
42
|
const RvcRunMode = {
|
|
@@ -51,13 +52,13 @@ const RvcCleanMode = {
|
|
|
51
52
|
[8]: 'Custom',
|
|
52
53
|
};
|
|
53
54
|
const CleanSetting = {
|
|
54
|
-
[4]: { suctionPower: 0, waterFlow: 0, mopRoute: MopRouteA187.Smart },
|
|
55
|
-
[5]: { suctionPower: VacuumSuctionPowerA187.Off, waterFlow: MopWaterFlowA187.Medium, mopRoute: MopRouteA187.Custom },
|
|
56
|
-
[6]: { suctionPower: VacuumSuctionPowerA187.Balanced, waterFlow: MopWaterFlowA187.Off, mopRoute: MopRouteA187.Custom },
|
|
57
|
-
[7]: { suctionPower: VacuumSuctionPowerA187.Balanced, waterFlow: MopWaterFlowA187.Medium, mopRoute: MopRouteA187.Custom },
|
|
58
|
-
[8]: { suctionPower: VacuumSuctionPowerA187.Custom, waterFlow: MopWaterFlowA187.Custom, mopRoute: MopRouteA187.Custom },
|
|
55
|
+
[4]: { suctionPower: 0, waterFlow: 0, distance_off: 0, mopRoute: MopRouteA187.Smart },
|
|
56
|
+
[5]: { suctionPower: VacuumSuctionPowerA187.Off, waterFlow: MopWaterFlowA187.Medium, distance_off: 0, mopRoute: MopRouteA187.Custom },
|
|
57
|
+
[6]: { suctionPower: VacuumSuctionPowerA187.Balanced, waterFlow: MopWaterFlowA187.Off, distance_off: 0, mopRoute: MopRouteA187.Custom },
|
|
58
|
+
[7]: { suctionPower: VacuumSuctionPowerA187.Balanced, waterFlow: MopWaterFlowA187.Medium, distance_off: 0, mopRoute: MopRouteA187.Custom },
|
|
59
|
+
[8]: { suctionPower: VacuumSuctionPowerA187.Custom, waterFlow: MopWaterFlowA187.Custom, distance_off: 0, mopRoute: MopRouteA187.Custom },
|
|
59
60
|
};
|
|
60
|
-
export function setCommandHandlerA187(duid, handler, logger, roborockService) {
|
|
61
|
+
export function setCommandHandlerA187(duid, handler, logger, roborockService, cleanModeSettings) {
|
|
61
62
|
handler.setCommandHandler('changeToMode', async (newMode) => {
|
|
62
63
|
const activity = RvcRunMode[newMode] || RvcCleanMode[newMode];
|
|
63
64
|
switch (activity) {
|
|
@@ -67,20 +68,64 @@ export function setCommandHandlerA187(duid, handler, logger, roborockService) {
|
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
69
70
|
case 'Smart Plan':
|
|
70
|
-
case 'Mop':
|
|
71
|
-
case 'Vacuum':
|
|
72
|
-
case 'Vac & Mop':
|
|
73
71
|
case 'Custom': {
|
|
74
72
|
const setting = CleanSetting[newMode];
|
|
75
|
-
logger.notice(`BehaviorA187-ChangeCleanMode to: ${activity},
|
|
73
|
+
logger.notice(`BehaviorA187-ChangeCleanMode to: ${activity}, setting: ${debugStringify(setting)}`);
|
|
76
74
|
await roborockService.changeCleanMode(duid, setting);
|
|
77
75
|
return;
|
|
78
76
|
}
|
|
77
|
+
case 'Mop':
|
|
78
|
+
case 'Vacuum':
|
|
79
|
+
case 'Vac & Mop': {
|
|
80
|
+
const setting = cleanModeSettings ? getSettingFromCleanMode(activity, cleanModeSettings) : CleanSetting[newMode];
|
|
81
|
+
logger.notice(`BehaviorA187-ChangeCleanMode to: ${activity}, setting: ${debugStringify(setting ?? {})}`);
|
|
82
|
+
if (setting) {
|
|
83
|
+
await roborockService.changeCleanMode(duid, setting);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
79
87
|
default:
|
|
80
88
|
logger.notice('BehaviorA187-changeToMode-Unknown: ', newMode);
|
|
81
89
|
return;
|
|
82
90
|
}
|
|
83
91
|
});
|
|
92
|
+
const getSettingFromCleanMode = (activity, cleanModeSettings) => {
|
|
93
|
+
switch (activity) {
|
|
94
|
+
case 'Mop': {
|
|
95
|
+
const mopSetting = cleanModeSettings?.mopping;
|
|
96
|
+
const waterFlow = MopWaterFlowA187[mopSetting?.waterFlowMode] ?? MopWaterFlowA187.Medium;
|
|
97
|
+
const distance_off = waterFlow == MopWaterFlowA187.CustomizeWithDistanceOff ? 210 - 5 * (mopSetting?.distanceOff ?? 25) : 0;
|
|
98
|
+
return {
|
|
99
|
+
suctionPower: VacuumSuctionPowerA187.Off,
|
|
100
|
+
waterFlow,
|
|
101
|
+
distance_off,
|
|
102
|
+
mopRoute: MopRouteA187[mopSetting?.mopRouteMode] ?? MopRouteA187.Standard,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
case 'Vacuum': {
|
|
106
|
+
const vacuumSetting = cleanModeSettings?.vacuuming;
|
|
107
|
+
return {
|
|
108
|
+
suctionPower: VacuumSuctionPowerA187[vacuumSetting?.fanMode] ?? VacuumSuctionPowerA187.Balanced,
|
|
109
|
+
waterFlow: MopWaterFlowA187.Off,
|
|
110
|
+
distance_off: 0,
|
|
111
|
+
mopRoute: MopRouteA187[vacuumSetting?.mopRouteMode] ?? MopRouteA187.Standard,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
case 'Vac & Mop': {
|
|
115
|
+
const vacmopSetting = cleanModeSettings?.vacmop;
|
|
116
|
+
const waterFlow = MopWaterFlowA187[vacmopSetting?.waterFlowMode] ?? MopWaterFlowA187.Medium;
|
|
117
|
+
const distance_off = waterFlow == MopWaterFlowA187.CustomizeWithDistanceOff ? 210 - 5 * (vacmopSetting?.distanceOff ?? 25) : 0;
|
|
118
|
+
return {
|
|
119
|
+
suctionPower: VacuumSuctionPowerA187[vacmopSetting?.fanMode] ?? VacuumSuctionPowerA187.Balanced,
|
|
120
|
+
waterFlow,
|
|
121
|
+
distance_off,
|
|
122
|
+
mopRoute: MopRouteA187[vacmopSetting?.mopRouteMode] ?? MopRouteA187.Standard,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
default:
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
84
129
|
handler.setCommandHandler('selectAreas', async (newAreas) => {
|
|
85
130
|
logger.notice(`BehaviorA187-selectAreas: ${newAreas}`);
|
|
86
131
|
roborockService.setSelectedAreas(duid, newAreas ?? []);
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { debugStringify } from 'matterbridge/logger';
|
|
2
|
+
import { BehaviorRoborock } from '../../BehaviorDeviceGeneric.js';
|
|
3
|
+
export class BehaviorA27 extends BehaviorRoborock {
|
|
4
|
+
}
|
|
5
|
+
export var BehaviorRoborockA27;
|
|
6
|
+
(function (BehaviorRoborockA27) {
|
|
7
|
+
class State {
|
|
8
|
+
device;
|
|
9
|
+
}
|
|
10
|
+
BehaviorRoborockA27.State = State;
|
|
11
|
+
})(BehaviorRoborockA27 || (BehaviorRoborockA27 = {}));
|
|
12
|
+
export var VacuumSuctionPowerA27;
|
|
13
|
+
(function (VacuumSuctionPowerA27) {
|
|
14
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Quiet"] = 101] = "Quiet";
|
|
15
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Balanced"] = 102] = "Balanced";
|
|
16
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Turbo"] = 103] = "Turbo";
|
|
17
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Max"] = 104] = "Max";
|
|
18
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Off"] = 105] = "Off";
|
|
19
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["Custom"] = 106] = "Custom";
|
|
20
|
+
VacuumSuctionPowerA27[VacuumSuctionPowerA27["MaxPlus"] = 108] = "MaxPlus";
|
|
21
|
+
})(VacuumSuctionPowerA27 || (VacuumSuctionPowerA27 = {}));
|
|
22
|
+
export var MopWaterFlowA27;
|
|
23
|
+
(function (MopWaterFlowA27) {
|
|
24
|
+
MopWaterFlowA27[MopWaterFlowA27["Off"] = 200] = "Off";
|
|
25
|
+
MopWaterFlowA27[MopWaterFlowA27["Low"] = 201] = "Low";
|
|
26
|
+
MopWaterFlowA27[MopWaterFlowA27["Medium"] = 202] = "Medium";
|
|
27
|
+
MopWaterFlowA27[MopWaterFlowA27["High"] = 203] = "High";
|
|
28
|
+
MopWaterFlowA27[MopWaterFlowA27["Custom"] = 204] = "Custom";
|
|
29
|
+
})(MopWaterFlowA27 || (MopWaterFlowA27 = {}));
|
|
30
|
+
export var MopRouteA27;
|
|
31
|
+
(function (MopRouteA27) {
|
|
32
|
+
MopRouteA27[MopRouteA27["Standard"] = 300] = "Standard";
|
|
33
|
+
MopRouteA27[MopRouteA27["Deep"] = 301] = "Deep";
|
|
34
|
+
MopRouteA27[MopRouteA27["Custom"] = 302] = "Custom";
|
|
35
|
+
MopRouteA27[MopRouteA27["DeepPlus"] = 303] = "DeepPlus";
|
|
36
|
+
MopRouteA27[MopRouteA27["Fast"] = 304] = "Fast";
|
|
37
|
+
})(MopRouteA27 || (MopRouteA27 = {}));
|
|
38
|
+
const RvcRunMode = {
|
|
39
|
+
[1]: 'Idle',
|
|
40
|
+
[2]: 'Cleaning',
|
|
41
|
+
[3]: 'Mapping',
|
|
42
|
+
};
|
|
43
|
+
const RvcCleanMode = {
|
|
44
|
+
[5]: 'Mop',
|
|
45
|
+
[6]: 'Vacuum',
|
|
46
|
+
[7]: 'Vac & Mop',
|
|
47
|
+
[8]: 'Custom',
|
|
48
|
+
};
|
|
49
|
+
const CleanSetting = {
|
|
50
|
+
[5]: { suctionPower: VacuumSuctionPowerA27.Off, waterFlow: MopWaterFlowA27.Medium, mopRoute: MopRouteA27.Custom },
|
|
51
|
+
[6]: { suctionPower: VacuumSuctionPowerA27.Balanced, waterFlow: MopWaterFlowA27.Off, mopRoute: MopRouteA27.Custom },
|
|
52
|
+
[7]: { suctionPower: VacuumSuctionPowerA27.Balanced, waterFlow: MopWaterFlowA27.Medium, mopRoute: MopRouteA27.Custom },
|
|
53
|
+
[8]: { suctionPower: VacuumSuctionPowerA27.Custom, waterFlow: MopWaterFlowA27.Custom, mopRoute: MopRouteA27.Custom },
|
|
54
|
+
};
|
|
55
|
+
export function setCommandHandlerA27(duid, handler, logger, roborockService) {
|
|
56
|
+
handler.setCommandHandler('changeToMode', async (newMode) => {
|
|
57
|
+
const activity = RvcRunMode[newMode] || RvcCleanMode[newMode];
|
|
58
|
+
switch (activity) {
|
|
59
|
+
case 'Cleaning': {
|
|
60
|
+
logger.notice('BehaviorA27-ChangeRunMode to: ', activity);
|
|
61
|
+
await roborockService.startClean(duid);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
case 'Mop':
|
|
65
|
+
case 'Vacuum':
|
|
66
|
+
case 'Vac & Mop':
|
|
67
|
+
case 'Custom': {
|
|
68
|
+
const setting = CleanSetting[newMode];
|
|
69
|
+
logger.notice(`BehaviorA27-ChangeCleanMode to: ${activity}, code: ${debugStringify(setting)}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
default:
|
|
73
|
+
logger.notice('BehaviorA27-changeToMode-Unknown: ', newMode);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
handler.setCommandHandler('selectAreas', async (newAreas) => {
|
|
78
|
+
logger.notice(`BehaviorA27-selectAreas: ${newAreas}`);
|
|
79
|
+
roborockService.setSelectedAreas(duid, newAreas ?? []);
|
|
80
|
+
});
|
|
81
|
+
handler.setCommandHandler('pause', async () => {
|
|
82
|
+
logger.notice('BehaviorA27-Pause');
|
|
83
|
+
await roborockService.pauseClean(duid);
|
|
84
|
+
});
|
|
85
|
+
handler.setCommandHandler('resume', async () => {
|
|
86
|
+
logger.notice('BehaviorA27-Resume');
|
|
87
|
+
await roborockService.resumeClean(duid);
|
|
88
|
+
});
|
|
89
|
+
handler.setCommandHandler('goHome', async () => {
|
|
90
|
+
logger.notice('BehaviorA27-GoHome');
|
|
91
|
+
await roborockService.stopAndGoHome(duid);
|
|
92
|
+
});
|
|
93
|
+
handler.setCommandHandler('PlaySoundToLocate', async (identifyTime) => {
|
|
94
|
+
logger.notice('BehaviorA27-PlaySoundToLocate');
|
|
95
|
+
await roborockService.playSoundToLocate(duid);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { RvcCleanMode, RvcOperationalState, RvcRunMode } from 'matterbridge/matter/clusters';
|
|
2
|
+
export function getSupportedRunModesA27() {
|
|
3
|
+
return [
|
|
4
|
+
{
|
|
5
|
+
label: 'Idle',
|
|
6
|
+
mode: 1,
|
|
7
|
+
modeTags: [{ value: RvcRunMode.ModeTag.Idle }],
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
label: 'Cleaning',
|
|
11
|
+
mode: 2,
|
|
12
|
+
modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
label: 'Mapping',
|
|
16
|
+
mode: 3,
|
|
17
|
+
modeTags: [{ value: RvcRunMode.ModeTag.Mapping }],
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
export function getSupportedCleanModesA27() {
|
|
22
|
+
return [
|
|
23
|
+
{
|
|
24
|
+
label: 'Mop',
|
|
25
|
+
mode: 5,
|
|
26
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Auto }],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: 'Vacuum',
|
|
30
|
+
mode: 6,
|
|
31
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Auto }],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Mop & Vacuum',
|
|
35
|
+
mode: 7,
|
|
36
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.DeepClean }],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
label: 'Custom',
|
|
40
|
+
mode: 8,
|
|
41
|
+
modeTags: [{ value: RvcCleanMode.ModeTag.Mop }, { value: RvcCleanMode.ModeTag.Vacuum }, { value: RvcCleanMode.ModeTag.Quick }],
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
export function getOperationalStatesA27() {
|
|
46
|
+
return [
|
|
47
|
+
{
|
|
48
|
+
operationalStateId: RvcOperationalState.OperationalState.Stopped,
|
|
49
|
+
operationalStateLabel: 'Stopped',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
operationalStateId: RvcOperationalState.OperationalState.Running,
|
|
53
|
+
operationalStateLabel: 'Running',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
operationalStateId: RvcOperationalState.OperationalState.Paused,
|
|
57
|
+
operationalStateLabel: 'Paused',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
operationalStateId: RvcOperationalState.OperationalState.Error,
|
|
61
|
+
operationalStateLabel: 'Error',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
operationalStateId: RvcOperationalState.OperationalState.SeekingCharger,
|
|
65
|
+
operationalStateLabel: 'SeekingCharger',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
operationalStateId: RvcOperationalState.OperationalState.Charging,
|
|
69
|
+
operationalStateLabel: 'Charging',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
operationalStateId: RvcOperationalState.OperationalState.Docked,
|
|
73
|
+
operationalStateLabel: 'Docked',
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { MopWaterFlowA27, VacuumSuctionPowerA27 } from './a27.js';
|
|
2
|
+
export function getCurrentCleanModeA27(fan_power, water_box_mode) {
|
|
3
|
+
if (!fan_power || !water_box_mode)
|
|
4
|
+
return undefined;
|
|
5
|
+
if (fan_power == VacuumSuctionPowerA27.Custom || water_box_mode == MopWaterFlowA27.Custom)
|
|
6
|
+
return 8;
|
|
7
|
+
if (fan_power == VacuumSuctionPowerA27.Off)
|
|
8
|
+
return 5;
|
|
9
|
+
if (water_box_mode == MopWaterFlowA27.Off)
|
|
10
|
+
return 6;
|
|
11
|
+
else
|
|
12
|
+
return 7;
|
|
13
|
+
}
|
|
14
|
+
export function getCurrentCleanModeFromFanPowerA27(fan_power) {
|
|
15
|
+
if (!fan_power)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (fan_power == VacuumSuctionPowerA27.Custom)
|
|
18
|
+
return 8;
|
|
19
|
+
if (fan_power == VacuumSuctionPowerA27.Off)
|
|
20
|
+
return 5;
|
|
21
|
+
else
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export function getCurrentCleanModeFromWaterBoxModeA27(water_box_mode) {
|
|
25
|
+
if (!water_box_mode)
|
|
26
|
+
return undefined;
|
|
27
|
+
if (water_box_mode == MopWaterFlowA27.Custom)
|
|
28
|
+
return 8;
|
|
29
|
+
if (water_box_mode == MopWaterFlowA27.Off)
|
|
30
|
+
return 6;
|
|
31
|
+
else
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
@@ -3,10 +3,13 @@ import { getOperationalStatesA187 } from '../behaviors/roborock.vacuum/QREVO_EDG
|
|
|
3
3
|
import { getDefaultOperationalStates } from '../behaviors/roborock.vacuum/default/initalData.js';
|
|
4
4
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
5
5
|
import { VacuumErrorCode } from '../roborockCommunication/Zenum/vacuumAndDockErrorCode.js';
|
|
6
|
+
import { getOperationalStatesA27 } from '../behaviors/roborock.vacuum/S7_MAXV/initalData.js';
|
|
6
7
|
export function getOperationalStates(model) {
|
|
7
8
|
switch (model) {
|
|
8
9
|
case DeviceModel.QREVO_EDGE_5V1:
|
|
9
10
|
return getOperationalStatesA187();
|
|
11
|
+
case DeviceModel.S7_MAXV:
|
|
12
|
+
return getOperationalStatesA27();
|
|
10
13
|
default:
|
|
11
14
|
return getDefaultOperationalStates();
|
|
12
15
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { getSupportedCleanModesA187 } from '../behaviors/roborock.vacuum/QREVO_EDGE_5V1/initalData.js';
|
|
2
2
|
import { getDefaultSupportedCleanModes } from '../behaviors/roborock.vacuum/default/initalData.js';
|
|
3
3
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
4
|
+
import { getSupportedCleanModesA27 } from '../behaviors/roborock.vacuum/S7_MAXV/initalData.js';
|
|
4
5
|
export function getSupportedCleanModes(model) {
|
|
5
6
|
switch (model) {
|
|
6
7
|
case DeviceModel.QREVO_EDGE_5V1:
|
|
7
8
|
return getSupportedCleanModesA187();
|
|
9
|
+
case DeviceModel.S7_MAXV:
|
|
10
|
+
return getSupportedCleanModesA27();
|
|
8
11
|
default:
|
|
9
12
|
return getDefaultSupportedCleanModes();
|
|
10
13
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getSupportedRunModesA187 } from '../behaviors/roborock.vacuum/QREVO_EDGE_5V1/initalData.js';
|
|
2
2
|
import { getDefaultSupportedRunModes } from '../behaviors/roborock.vacuum/default/initalData.js';
|
|
3
3
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
4
|
+
import { getSupportedRunModesA27 } from '../behaviors/roborock.vacuum/S7_MAXV/initalData.js';
|
|
4
5
|
export function getRunningMode(model, modeTag) {
|
|
5
6
|
if (!model || !modeTag)
|
|
6
7
|
return null;
|
|
@@ -12,6 +13,8 @@ export function getSupportedRunModes(model) {
|
|
|
12
13
|
switch (model) {
|
|
13
14
|
case DeviceModel.QREVO_EDGE_5V1:
|
|
14
15
|
return getSupportedRunModesA187();
|
|
16
|
+
case DeviceModel.S7_MAXV:
|
|
17
|
+
return getSupportedRunModesA27();
|
|
15
18
|
default:
|
|
16
19
|
return getDefaultSupportedRunModes();
|
|
17
20
|
}
|
package/dist/platform.js
CHANGED
|
@@ -19,7 +19,6 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
19
19
|
platformRunner;
|
|
20
20
|
devices;
|
|
21
21
|
serialNumber;
|
|
22
|
-
whiteList;
|
|
23
22
|
constructor(matterbridge, log, config) {
|
|
24
23
|
super(matterbridge, log, config);
|
|
25
24
|
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.0.4')) {
|
|
@@ -32,8 +31,6 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
32
31
|
config.blackList = [];
|
|
33
32
|
if (config.enableExperimentalFeature === undefined)
|
|
34
33
|
config.enableExperimentalFeature = false;
|
|
35
|
-
this.whiteList = config.whiteList;
|
|
36
|
-
config.whiteList = [];
|
|
37
34
|
this.clientManager = new ClientManager(this.log);
|
|
38
35
|
this.devices = new Map();
|
|
39
36
|
}
|
|
@@ -74,15 +71,16 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
74
71
|
const devices = await this.roborockService.listDevices(username);
|
|
75
72
|
this.log.notice('Initializing - devices: ', debugStringify(devices));
|
|
76
73
|
let vacuum = undefined;
|
|
77
|
-
if (this.whiteList.length > 0) {
|
|
78
|
-
const firstDUID = this.whiteList[0];
|
|
79
|
-
|
|
74
|
+
if (this.config.whiteList.length > 0) {
|
|
75
|
+
const firstDUID = this.config.whiteList[0];
|
|
76
|
+
const duid = firstDUID.split('-')[1];
|
|
77
|
+
vacuum = devices.find((d) => d.duid == duid);
|
|
80
78
|
}
|
|
81
79
|
else {
|
|
82
80
|
vacuum = devices.find((d) => isSupportedDevice(d.data.model));
|
|
83
81
|
}
|
|
84
82
|
if (!vacuum) {
|
|
85
|
-
this.log.error('Initializing: No
|
|
83
|
+
this.log.error('Initializing: No device found');
|
|
86
84
|
return;
|
|
87
85
|
}
|
|
88
86
|
await this.roborockService.initializeMessageClient(username, vacuum, userData);
|
|
@@ -93,6 +91,11 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
93
91
|
}
|
|
94
92
|
async onConfigure() {
|
|
95
93
|
await super.onConfigure();
|
|
94
|
+
if (this.config.enableExperimentalFeature) {
|
|
95
|
+
const cleanModeSettings = this.config.cleanModeSettings;
|
|
96
|
+
this.log.notice(`Experimental Feature has been enable`);
|
|
97
|
+
this.log.notice(`cleanModeSettings ${debugStringify(cleanModeSettings)}`);
|
|
98
|
+
}
|
|
96
99
|
const self = this;
|
|
97
100
|
this.rvcInterval = setInterval(async () => {
|
|
98
101
|
self.platformRunner?.requestHomeData();
|
|
@@ -110,11 +113,15 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
110
113
|
this.log.error('Initializing: No supported devices found');
|
|
111
114
|
return;
|
|
112
115
|
}
|
|
116
|
+
let cleanModeSettings = undefined;
|
|
117
|
+
if (this.config.enableExperimentalFeature) {
|
|
118
|
+
cleanModeSettings = this.config.cleanModeSettings;
|
|
119
|
+
}
|
|
113
120
|
const self = this;
|
|
114
121
|
await this.roborockService.initializeMessageClientForLocal(vacuum);
|
|
115
122
|
const roomMap = await this.platformRunner.getRoomMapFromDevice(vacuum);
|
|
116
123
|
this.log.debug('Initializing - roomMap: ', debugStringify(roomMap));
|
|
117
|
-
const behaviorHandler = configurateBehavior(vacuum.data.model, vacuum.duid, this.roborockService, this.log);
|
|
124
|
+
const behaviorHandler = configurateBehavior(vacuum.data.model, vacuum.duid, this.roborockService, cleanModeSettings, this.log);
|
|
118
125
|
this.roborockService.setSupportedAreas(vacuum.duid, getSupportedAreas(vacuum.rooms, roomMap, this.log));
|
|
119
126
|
this.robot = new RoborockVacuumCleaner(username, vacuum, roomMap, this.log);
|
|
120
127
|
this.robot.configurateHandler(behaviorHandler);
|
|
@@ -63,24 +63,29 @@ export class MessageProcessor {
|
|
|
63
63
|
const request = new RequestMessage(def);
|
|
64
64
|
return this.client.send(duid, request);
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.logger?.warn('XXXXXXX: ', debugStringify(response));
|
|
69
|
-
return response;
|
|
66
|
+
getCustomMessage(duid, def) {
|
|
67
|
+
return this.client.get(duid, def);
|
|
70
68
|
}
|
|
71
69
|
async findMyRobot(duid) {
|
|
72
70
|
const request = new RequestMessage({ method: 'find_me' });
|
|
73
71
|
return this.client.send(duid, request);
|
|
74
72
|
}
|
|
75
|
-
async changeCleanMode(duid, suctionPower, waterFlow, mopRoute) {
|
|
76
|
-
this.logger?.notice(`Change clean mode for ${duid} to suctionPower: ${suctionPower}, waterFlow: ${waterFlow}`);
|
|
73
|
+
async changeCleanMode(duid, suctionPower, waterFlow, mopRoute, distance_off) {
|
|
74
|
+
this.logger?.notice(`Change clean mode for ${duid} to suctionPower: ${suctionPower}, waterFlow: ${waterFlow}, mopRoute: ${mopRoute}, distance_off: ${distance_off}`);
|
|
75
|
+
const currentMopMode = await this.getCustomMessage(duid, new RequestMessage({ method: 'get_custom_mode' }));
|
|
76
|
+
if (currentMopMode == 110) {
|
|
77
|
+
await this.client.send(duid, new RequestMessage({ method: 'set_mop_mode', params: [302] }));
|
|
78
|
+
}
|
|
77
79
|
if (mopRoute && mopRoute != 0) {
|
|
78
80
|
await this.client.send(duid, new RequestMessage({ method: 'set_mop_mode', params: [mopRoute] }));
|
|
79
81
|
}
|
|
80
82
|
if (suctionPower && suctionPower != 0) {
|
|
81
83
|
await this.client.send(duid, new RequestMessage({ method: 'set_custom_mode', params: [suctionPower] }));
|
|
82
84
|
}
|
|
83
|
-
if (waterFlow && waterFlow != 0) {
|
|
85
|
+
if (waterFlow && waterFlow == 207 && distance_off && distance_off != 0) {
|
|
86
|
+
await this.client.send(duid, new RequestMessage({ method: 'set_water_box_custom_mode', params: { 'water_box_mode': waterFlow, 'distance_off': distance_off } }));
|
|
87
|
+
}
|
|
88
|
+
else if (waterFlow && waterFlow != 0) {
|
|
84
89
|
await this.client.send(duid, new RequestMessage({ method: 'set_water_box_custom_mode', params: [waterFlow] }));
|
|
85
90
|
}
|
|
86
91
|
}
|
package/dist/roborockService.js
CHANGED
|
@@ -48,9 +48,9 @@ export default class RoborockService {
|
|
|
48
48
|
getSupportedAreas(duid) {
|
|
49
49
|
return this.supportedAreas.get(duid);
|
|
50
50
|
}
|
|
51
|
-
async changeCleanMode(duid, { suctionPower, waterFlow, mopRoute }) {
|
|
51
|
+
async changeCleanMode(duid, { suctionPower, waterFlow, distance_off, mopRoute }) {
|
|
52
52
|
this.logger.notice('changeCleanMode');
|
|
53
|
-
return this.messageProcessor?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute);
|
|
53
|
+
return this.messageProcessor?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute, distance_off);
|
|
54
54
|
}
|
|
55
55
|
async startClean(duid) {
|
|
56
56
|
const areas = this.supportedAreas.get(duid);
|
|
@@ -89,6 +89,9 @@ export default class RoborockService {
|
|
|
89
89
|
this.logger.debug('customGetInSecure-message', method);
|
|
90
90
|
return this.getMessageProcessor()?.getCustomMessage(duid, new RequestMessage({ method, secure: true }));
|
|
91
91
|
}
|
|
92
|
+
async customSend(duid, request) {
|
|
93
|
+
return this.getMessageProcessor()?.sendCustomMessage(duid, request);
|
|
94
|
+
}
|
|
92
95
|
stopService() {
|
|
93
96
|
if (this.messageClient) {
|
|
94
97
|
this.messageClient.disconnect();
|
package/dist/rvc.js
CHANGED
|
@@ -10,7 +10,8 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
|
|
|
10
10
|
const cleanModes = getSupportedCleanModes(device.data.model);
|
|
11
11
|
const supportedRunModes = getSupportedRunModes(device.data.model);
|
|
12
12
|
const supportedAreas = getSupportedAreas(device.rooms, roomMap, log);
|
|
13
|
-
|
|
13
|
+
const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
|
|
14
|
+
super(deviceName, device.duid, supportedRunModes[0].mode, supportedRunModes, cleanModes[0].mode, cleanModes, undefined, undefined, RvcOperationalState.OperationalState.Docked, getOperationalStates(device.data.model), supportedAreas, undefined, supportedAreas[0].areaId);
|
|
14
15
|
this.username = username;
|
|
15
16
|
this.device = device;
|
|
16
17
|
this.rrHomeId = device.rrHomeId;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { getCurrentCleanModeA187, getCurrentCleanModeFromFanPowerA187, getCurrentCleanModeFromWaterBoxModeA187 } from '../behaviors/roborock.vacuum/QREVO_EDGE_5V1/runtimes.js';
|
|
2
|
+
import { getCurrentCleanModeA27, getCurrentCleanModeFromFanPowerA27, getCurrentCleanModeFromWaterBoxModeA27 } from '../behaviors/roborock.vacuum/S7_MAXV/runtimes.js';
|
|
2
3
|
import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
|
|
3
4
|
export function getCurrentCleanModeFunc(model) {
|
|
4
5
|
switch (model) {
|
|
5
6
|
case DeviceModel.QREVO_EDGE_5V1: {
|
|
6
7
|
return getCurrentCleanModeA187;
|
|
7
8
|
}
|
|
9
|
+
case DeviceModel.S7_MAXV: {
|
|
10
|
+
return getCurrentCleanModeA27;
|
|
11
|
+
}
|
|
8
12
|
default:
|
|
9
13
|
return (_, __) => undefined;
|
|
10
14
|
}
|
|
@@ -14,6 +18,9 @@ export function getCurrentCleanModeFromFanPowerFunc(model) {
|
|
|
14
18
|
case DeviceModel.QREVO_EDGE_5V1: {
|
|
15
19
|
return getCurrentCleanModeFromFanPowerA187;
|
|
16
20
|
}
|
|
21
|
+
case DeviceModel.S7_MAXV: {
|
|
22
|
+
return getCurrentCleanModeFromFanPowerA27;
|
|
23
|
+
}
|
|
17
24
|
default:
|
|
18
25
|
return (_) => undefined;
|
|
19
26
|
}
|
|
@@ -23,6 +30,9 @@ export function getCurrentCleanModeFromWaterBoxModeFunc(model) {
|
|
|
23
30
|
case DeviceModel.QREVO_EDGE_5V1: {
|
|
24
31
|
return getCurrentCleanModeFromWaterBoxModeA187;
|
|
25
32
|
}
|
|
33
|
+
case DeviceModel.S7_MAXV: {
|
|
34
|
+
return getCurrentCleanModeFromWaterBoxModeA27;
|
|
35
|
+
}
|
|
26
36
|
default:
|
|
27
37
|
return (_) => undefined;
|
|
28
38
|
}
|