matterbridge-roborock-vacuum-plugin 1.1.0-rc16 → 1.1.0-rc17
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/dist/helper.js +23 -20
- package/dist/initialData/getSupportedAreas.js +85 -46
- package/dist/model/ExperimentalFeatureSetting.js +1 -0
- package/dist/model/RoomMap.js +8 -3
- package/dist/model/roomIndexMap.js +17 -0
- package/dist/platform.js +5 -3
- package/dist/platformRunner.js +11 -3
- package/dist/roborockCommunication/Zmodel/mapInfo.js +2 -3
- package/dist/roborockService.js +10 -1
- package/dist/rvc.js +5 -2
- package/matterbridge-roborock-vacuum-plugin.config.json +4 -3
- package/matterbridge-roborock-vacuum-plugin.schema.json +42 -10
- package/package.json +1 -1
- package/src/helper.ts +27 -24
- package/src/initialData/getSupportedAreas.ts +112 -50
- package/src/model/ExperimentalFeatureSetting.ts +2 -0
- package/src/model/RoomMap.ts +17 -3
- package/src/model/roomIndexMap.ts +20 -0
- package/src/platform.ts +6 -3
- package/src/platformRunner.ts +15 -3
- package/src/roborockCommunication/Zmodel/map.ts +1 -1
- package/src/roborockCommunication/Zmodel/mapInfo.ts +11 -10
- package/src/roborockService.ts +16 -1
- package/src/rvc.ts +7 -2
- package/src/tests/helper.test.ts +47 -47
- package/src/tests/initialData/getSupportedAreas.test.ts +80 -7
- package/src/tests/platformRunner2.test.ts +108 -1
- package/src/tests/roborockService.test.ts +11 -0
- package/web-for-testing/package-lock.json +14 -12
- package/web-for-testing/package.json +1 -1
- package/web-for-testing/src/accountStore.ts +0 -10
package/dist/helper.js
CHANGED
|
@@ -27,6 +27,7 @@ export function isStatusUpdate(result) {
|
|
|
27
27
|
}
|
|
28
28
|
export async function getRoomMap(duid, platform) {
|
|
29
29
|
const robot = platform.robots.get(duid);
|
|
30
|
+
const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature.enableMultipleMap) ?? false;
|
|
30
31
|
if (robot === undefined) {
|
|
31
32
|
platform.log.error(`Error6: Robot with DUID ${duid} not found`);
|
|
32
33
|
return undefined;
|
|
@@ -35,44 +36,46 @@ export async function getRoomMap(duid, platform) {
|
|
|
35
36
|
return undefined;
|
|
36
37
|
const rooms = robot.device.rooms ?? [];
|
|
37
38
|
if (robot.roomInfo === undefined) {
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const mapInfo = await platform.roborockService.getMapInformation(robot.device.duid);
|
|
40
|
+
if (mapInfo && mapInfo.allRooms && mapInfo.allRooms.length > 0) {
|
|
41
|
+
platform.log.info(`getRoomMap - mapInfo: ${debugStringify(mapInfo.allRooms)}`);
|
|
42
|
+
robot.roomInfo = new RoomMap(mapInfo.allRooms, rooms, mapInfo.maps, enableMultipleMap);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
if (robot.roomInfo === undefined) {
|
|
45
|
-
const
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
robot.roomInfo
|
|
46
|
+
const roomData = await platform.roborockService.getRoomMappings(robot.device.duid);
|
|
47
|
+
if (roomData !== undefined && roomData.length > 0) {
|
|
48
|
+
const roomDataMap = roomData.map((r) => ({ id: r[0], iot_name_id: String(r[1]), globalId: r[1], tag: r[2], mapId: 0, displayName: undefined }));
|
|
49
|
+
robot.roomInfo = new RoomMap(roomDataMap, rooms, [], enableMultipleMap);
|
|
50
|
+
return robot.roomInfo;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
return robot.roomInfo;
|
|
53
54
|
}
|
|
54
55
|
export async function getRoomMapFromDevice(device, platform) {
|
|
55
56
|
const rooms = device?.rooms ?? [];
|
|
57
|
+
const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature.enableMultipleMap) ?? false;
|
|
56
58
|
platform.log.notice('-------------------------------------------0--------------------------------------------------------');
|
|
57
59
|
platform.log.notice(`getRoomMapFromDevice - device.rooms: ${debugStringify(rooms)}`);
|
|
58
60
|
if (device && platform.roborockService) {
|
|
59
|
-
const roomData = await platform.roborockService.getRoomMappings(device.duid);
|
|
60
|
-
if (roomData !== undefined && roomData.length > 0) {
|
|
61
|
-
platform.log.notice(`getRoomMapFromDevice - roomData: ${debugStringify(roomData ?? [])}`);
|
|
62
|
-
const roomMap = new RoomMap(roomData ?? [], rooms);
|
|
63
|
-
platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
|
|
64
|
-
platform.log.notice('-------------------------------------------1--------------------------------------------------------');
|
|
65
|
-
return roomMap;
|
|
66
|
-
}
|
|
67
61
|
const mapInfo = await platform.roborockService.getMapInformation(device.duid);
|
|
68
62
|
platform.log.notice(`getRoomMapFromDevice - mapInfo: ${mapInfo ? debugStringify(mapInfo) : 'undefined'}`);
|
|
69
63
|
if (mapInfo && mapInfo.allRooms && mapInfo.allRooms.length > 0) {
|
|
70
|
-
const roomDataMap = mapInfo.allRooms
|
|
71
|
-
const roomMap = new RoomMap(roomDataMap, rooms);
|
|
64
|
+
const roomDataMap = mapInfo.allRooms;
|
|
65
|
+
const roomMap = new RoomMap(roomDataMap, rooms, mapInfo.maps, enableMultipleMap);
|
|
72
66
|
platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
|
|
73
67
|
platform.log.notice('-------------------------------------------2--------------------------------------------------------');
|
|
74
68
|
return roomMap;
|
|
75
69
|
}
|
|
70
|
+
const roomData = await platform.roborockService.getRoomMappings(device.duid);
|
|
71
|
+
if (roomData !== undefined && roomData.length > 0) {
|
|
72
|
+
platform.log.notice(`getRoomMapFromDevice - roomData: ${debugStringify(roomData ?? [])}`);
|
|
73
|
+
const roomDataMap = roomData.map((r) => ({ id: r[0], iot_name_id: String(r[1]), globalId: r[1], tag: r[2], mapId: 0, displayName: undefined }));
|
|
74
|
+
const roomMap = new RoomMap(roomDataMap ?? [], rooms, [], enableMultipleMap);
|
|
75
|
+
platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
|
|
76
|
+
platform.log.notice('-------------------------------------------1--------------------------------------------------------');
|
|
77
|
+
return roomMap;
|
|
78
|
+
}
|
|
76
79
|
}
|
|
77
|
-
return new RoomMap([], rooms);
|
|
80
|
+
return new RoomMap([], rooms, [], enableMultipleMap);
|
|
78
81
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { debugStringify } from 'matterbridge/logger';
|
|
2
2
|
import { randomInt } from 'node:crypto';
|
|
3
|
-
|
|
3
|
+
import { RoomIndexMap } from '../model/roomIndexMap.js';
|
|
4
|
+
export function getSupportedAreas(vacuumRooms, roomMap, enableMultipleMap = false, log) {
|
|
4
5
|
log?.debug('getSupportedAreas-vacuum room', debugStringify(vacuumRooms));
|
|
5
6
|
log?.debug('getSupportedAreas-roomMap', roomMap ? debugStringify(roomMap) : 'undefined');
|
|
6
7
|
const noVacuumRooms = !vacuumRooms || vacuumRooms.length === 0;
|
|
@@ -12,70 +13,108 @@ export function getSupportedAreas(vacuumRooms, roomMap, log) {
|
|
|
12
13
|
if (noRoomMap) {
|
|
13
14
|
log?.error('No room map found');
|
|
14
15
|
}
|
|
15
|
-
return [
|
|
16
|
-
{
|
|
17
|
-
areaId: 1,
|
|
18
|
-
mapId: null,
|
|
19
|
-
areaInfo: {
|
|
20
|
-
locationInfo: {
|
|
21
|
-
locationName: 'Unknown',
|
|
22
|
-
floorNumber: null,
|
|
23
|
-
areaType: null,
|
|
24
|
-
},
|
|
25
|
-
landmarkInfo: null,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
|
-
const supportedAreas = roomMap.rooms.map((room) => {
|
|
31
|
-
const locationName = room.displayName ?? vacuumRooms.find((r) => r.id === room.globalId || r.id === room.id)?.name ?? `Unknown Room ${randomInt(1000, 9999)}`;
|
|
32
16
|
return {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
17
|
+
supportedAreas: [
|
|
18
|
+
{
|
|
19
|
+
areaId: 1,
|
|
20
|
+
mapId: null,
|
|
21
|
+
areaInfo: {
|
|
22
|
+
locationInfo: {
|
|
23
|
+
locationName: 'Unknown',
|
|
24
|
+
floorNumber: null,
|
|
25
|
+
areaType: null,
|
|
26
|
+
},
|
|
27
|
+
landmarkInfo: null,
|
|
28
|
+
},
|
|
40
29
|
},
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
],
|
|
31
|
+
supportedMaps: [],
|
|
32
|
+
roomIndexMap: new RoomIndexMap(new Map([[1, { roomId: 1, mapId: null }]])),
|
|
43
33
|
};
|
|
44
|
-
}
|
|
45
|
-
|
|
34
|
+
}
|
|
35
|
+
const { supportedAreas, indexMap } = processValidData(enableMultipleMap, vacuumRooms, roomMap);
|
|
46
36
|
const duplicated = findDuplicatedAreaIds(supportedAreas, log);
|
|
47
37
|
if (duplicated) {
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
38
|
+
return {
|
|
39
|
+
supportedAreas: [
|
|
40
|
+
{
|
|
41
|
+
areaId: 2,
|
|
42
|
+
mapId: null,
|
|
43
|
+
areaInfo: {
|
|
44
|
+
locationInfo: {
|
|
45
|
+
locationName: 'Unknown - Duplicated Areas Found',
|
|
46
|
+
floorNumber: null,
|
|
47
|
+
areaType: null,
|
|
48
|
+
},
|
|
49
|
+
landmarkInfo: null,
|
|
57
50
|
},
|
|
58
|
-
landmarkInfo: null,
|
|
59
51
|
},
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
],
|
|
53
|
+
supportedMaps: [],
|
|
54
|
+
roomIndexMap: new RoomIndexMap(new Map([[2, { roomId: 2, mapId: null }]])),
|
|
55
|
+
};
|
|
62
56
|
}
|
|
63
|
-
|
|
57
|
+
const supportedMaps = getSupportedMaps(enableMultipleMap, supportedAreas, roomMap);
|
|
58
|
+
log?.debug('getSupportedAreas - supportedAreas', debugStringify(supportedAreas));
|
|
59
|
+
log?.debug('getSupportedAreas - supportedMaps', debugStringify(supportedMaps));
|
|
60
|
+
const roomIndexMap = new RoomIndexMap(indexMap);
|
|
61
|
+
return {
|
|
62
|
+
supportedAreas,
|
|
63
|
+
supportedMaps,
|
|
64
|
+
roomIndexMap,
|
|
65
|
+
};
|
|
64
66
|
}
|
|
65
67
|
function findDuplicatedAreaIds(areas, log) {
|
|
66
68
|
const seen = new Set();
|
|
67
69
|
const duplicates = [];
|
|
68
70
|
for (const area of areas) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
const key = `${area.areaId}=${area.mapId}`;
|
|
72
|
+
if (seen.has(key)) {
|
|
73
|
+
duplicates.push({ areaId: area.areaId, mapId: area.mapId ?? 0 });
|
|
71
74
|
}
|
|
72
75
|
else {
|
|
73
|
-
seen.add(
|
|
76
|
+
seen.add(key);
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
79
|
if (duplicates.length > 0 && log) {
|
|
77
|
-
const duplicated = areas.filter((
|
|
80
|
+
const duplicated = areas.filter(({ areaId, mapId }) => duplicates.some((y) => y.areaId === areaId && y.mapId === (mapId ?? 0)));
|
|
78
81
|
log.error(`Duplicated areaId(s) found: ${debugStringify(duplicated)}`);
|
|
79
82
|
}
|
|
80
83
|
return duplicates.length > 0;
|
|
81
84
|
}
|
|
85
|
+
function processValidData(enableMultipleMap, vacuumRooms, roomMap) {
|
|
86
|
+
const indexMap = new Map();
|
|
87
|
+
const supportedAreas = roomMap?.rooms !== undefined && roomMap.rooms.length > 0
|
|
88
|
+
? roomMap.rooms.map((room, index) => {
|
|
89
|
+
const locationName = room.displayName ?? vacuumRooms.find((r) => r.id === room.globalId || r.id === room.id)?.name ?? `Unknown Room ${randomInt(1000, 9999)}`;
|
|
90
|
+
const areaId = index + 100;
|
|
91
|
+
const mapId = enableMultipleMap ? (room.mapId ?? null) : null;
|
|
92
|
+
indexMap.set(areaId, { roomId: room.id, mapId: room.mapId ?? null });
|
|
93
|
+
return {
|
|
94
|
+
areaId: areaId,
|
|
95
|
+
mapId: mapId,
|
|
96
|
+
areaInfo: {
|
|
97
|
+
locationInfo: {
|
|
98
|
+
locationName: locationName,
|
|
99
|
+
floorNumber: room.mapId ?? null,
|
|
100
|
+
areaType: null,
|
|
101
|
+
},
|
|
102
|
+
landmarkInfo: null,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
})
|
|
106
|
+
: [];
|
|
107
|
+
return {
|
|
108
|
+
supportedAreas,
|
|
109
|
+
indexMap,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function getSupportedMaps(enableMultipleMap, supportedAreas, roomMap) {
|
|
113
|
+
if (enableMultipleMap) {
|
|
114
|
+
return (roomMap?.mapInfo?.map((map) => ({
|
|
115
|
+
mapId: map.id,
|
|
116
|
+
name: map.name ?? `Map ${map.id}`,
|
|
117
|
+
})) ?? []);
|
|
118
|
+
}
|
|
119
|
+
return [];
|
|
120
|
+
}
|
package/dist/model/RoomMap.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
export class RoomMap {
|
|
2
2
|
rooms;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
mapInfo;
|
|
4
|
+
constructor(roomData, rooms, mapInfo, enableMultipleMap) {
|
|
5
|
+
const mapid = mapInfo[0]?.id ?? 0;
|
|
6
|
+
const roomDataTmp = enableMultipleMap ? roomData : roomData.filter((room) => room.mapId === undefined || room.mapId === mapid);
|
|
7
|
+
this.rooms = roomDataTmp.map(({ id, globalId, tag, mapId }) => {
|
|
5
8
|
const room = rooms.find((r) => Number(r.id) === Number(globalId) || Number(r.id) === Number(id));
|
|
6
9
|
return {
|
|
7
10
|
id,
|
|
8
11
|
globalId: globalId !== undefined ? Number(globalId) : undefined,
|
|
9
12
|
displayName: room?.name,
|
|
10
|
-
alternativeId: `${id}${
|
|
13
|
+
alternativeId: `${id}${tag}`,
|
|
14
|
+
mapId,
|
|
11
15
|
};
|
|
12
16
|
});
|
|
17
|
+
this.mapInfo = mapInfo;
|
|
13
18
|
}
|
|
14
19
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class RoomIndexMap {
|
|
2
|
+
indexMap;
|
|
3
|
+
roomMap;
|
|
4
|
+
constructor(roomMap) {
|
|
5
|
+
this.indexMap = roomMap;
|
|
6
|
+
this.roomMap = new Map();
|
|
7
|
+
for (const [areaId, { roomId }] of roomMap.entries()) {
|
|
8
|
+
this.roomMap.set(roomId, areaId);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
getAreaId(roomId) {
|
|
12
|
+
return this.roomMap.get(roomId);
|
|
13
|
+
}
|
|
14
|
+
getRoomId(areaId) {
|
|
15
|
+
return this.indexMap.get(areaId)?.roomId;
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/platform.js
CHANGED
|
@@ -26,8 +26,8 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
26
26
|
rrHomeId;
|
|
27
27
|
constructor(matterbridge, log, config) {
|
|
28
28
|
super(matterbridge, log, config);
|
|
29
|
-
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.
|
|
30
|
-
throw new Error(`This plugin requires Matterbridge version >= "3.1.
|
|
29
|
+
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.8')) {
|
|
30
|
+
throw new Error(`This plugin requires Matterbridge version >= "3.1.8". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
|
|
31
31
|
}
|
|
32
32
|
this.log.info('Initializing platform:', this.config.name);
|
|
33
33
|
if (config.whiteList === undefined)
|
|
@@ -165,8 +165,10 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
|
|
|
165
165
|
const roomMap = await getRoomMapFromDevice(vacuum, this);
|
|
166
166
|
this.log.debug('Initializing - roomMap: ', debugStringify(roomMap));
|
|
167
167
|
const behaviorHandler = configurateBehavior(vacuum.data.model, vacuum.duid, this.roborockService, this.cleanModeSettings, this.enableExperimentalFeature?.advancedFeature?.forceRunAtDefault ?? false, this.log);
|
|
168
|
-
const
|
|
168
|
+
const enableMultipleMap = this.enableExperimentalFeature?.enableExperimentalFeature && this.enableExperimentalFeature.advancedFeature?.enableMultipleMap;
|
|
169
|
+
const { supportedAreas, roomIndexMap } = getSupportedAreas(vacuum.rooms, roomMap, enableMultipleMap, this.log);
|
|
169
170
|
this.roborockService.setSupportedAreas(vacuum.duid, supportedAreas);
|
|
171
|
+
this.roborockService.setSupportedAreaIndexMap(vacuum.duid, roomIndexMap);
|
|
170
172
|
let routineAsRoom = [];
|
|
171
173
|
if (this.enableExperimentalFeature?.enableExperimentalFeature && this.enableExperimentalFeature.advancedFeature?.showRoutinesAsRoom) {
|
|
172
174
|
routineAsRoom = getSupportedScenes(vacuum.scenes, this.log);
|
package/dist/platformRunner.js
CHANGED
|
@@ -93,6 +93,7 @@ export class PlatformRunner {
|
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
95
|
const currentMappedAreas = this.platform.roborockService?.getSupportedAreas(duid);
|
|
96
|
+
const roomIndexMap = this.platform.roborockService?.getSupportedAreasIndexMap(duid);
|
|
96
97
|
const roomMap = await getRoomMap(duid, this.platform);
|
|
97
98
|
const segment_id = data.cleaning_info?.segment_id ?? -1;
|
|
98
99
|
const target_segment_id = data.cleaning_info?.target_segment_id ?? -1;
|
|
@@ -102,7 +103,8 @@ export class PlatformRunner {
|
|
|
102
103
|
if (segment_id !== -1 && isMappedArea) {
|
|
103
104
|
this.platform.log.debug(`RoomMap: ${roomMap ? debugStringify(roomMap) : 'undefined'}`);
|
|
104
105
|
this.platform.log.debug(`Part1: CurrentRoom: ${segment_id}, room name: ${roomMap?.rooms.find((x) => x.id === segment_id || x.alternativeId === segment_id.toString())?.displayName ?? 'unknown'}`);
|
|
105
|
-
|
|
106
|
+
const areaId = roomIndexMap?.getAreaId(segment_id) ?? null;
|
|
107
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
|
|
106
108
|
}
|
|
107
109
|
if (segment_id == -1) {
|
|
108
110
|
const isTargetMappedArea = currentMappedAreas?.some((x) => x.areaId == target_segment_id);
|
|
@@ -111,7 +113,8 @@ export class PlatformRunner {
|
|
|
111
113
|
if (target_segment_id !== -1 && isTargetMappedArea) {
|
|
112
114
|
this.platform.log.debug(`RoomMap: ${roomMap ? debugStringify(roomMap) : 'undefined'}`);
|
|
113
115
|
this.platform.log.debug(`Part2: TargetRoom: ${target_segment_id}, room name: ${roomMap?.rooms.find((x) => x.id === target_segment_id || x.alternativeId === segment_id.toString())?.displayName ?? 'unknown'}`);
|
|
114
|
-
|
|
116
|
+
const areaId = roomIndexMap?.getAreaId(target_segment_id) ?? null;
|
|
117
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
if (target_segment_id == -1 && segment_id == -1) {
|
|
@@ -222,11 +225,12 @@ export class PlatformRunner {
|
|
|
222
225
|
platform.log.notice(`Received additional properties for robot ${duid}: ${debugStringify(data)}`);
|
|
223
226
|
const propCode = data.dps[Protocol.additional_props];
|
|
224
227
|
platform.log.debug(`DPS for additional properties: ${propCode}, AdditionalPropCode: ${AdditionalPropCode[propCode]}`);
|
|
228
|
+
const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap) ?? false;
|
|
225
229
|
if (propCode === AdditionalPropCode.map_change) {
|
|
226
230
|
platform.log.notice('------------------------ get roomData ----------------------------');
|
|
227
231
|
const roomMap = await getRoomMapFromDevice(robot.device, platform);
|
|
228
232
|
platform.log.notice('------------------------ Room map updated ------------------------');
|
|
229
|
-
const supportedAreas = getSupportedAreas(robot.device.rooms, roomMap, platform.log);
|
|
233
|
+
const { supportedAreas, supportedMaps, roomIndexMap } = getSupportedAreas(robot.device.rooms, roomMap, enableMultipleMap, platform.log);
|
|
230
234
|
platform.log.notice(`Supported areas: ${debugStringify(supportedAreas)}`);
|
|
231
235
|
platform.log.notice('------------------------ Supported areas updated ------------------');
|
|
232
236
|
platform.roborockService?.setSupportedAreas(duid, supportedAreas);
|
|
@@ -234,6 +238,10 @@ export class PlatformRunner {
|
|
|
234
238
|
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedAreas', supportedAreas, platform.log);
|
|
235
239
|
robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
|
|
236
240
|
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
|
|
241
|
+
if (enableMultipleMap) {
|
|
242
|
+
platform.roborockService?.setSupportedAreaIndexMap(duid, roomIndexMap);
|
|
243
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedMaps', supportedMaps, platform.log);
|
|
244
|
+
}
|
|
237
245
|
}
|
|
238
246
|
break;
|
|
239
247
|
}
|
|
@@ -4,14 +4,14 @@ export class MapInfo {
|
|
|
4
4
|
allRooms = [];
|
|
5
5
|
constructor(multimap) {
|
|
6
6
|
this.maps = multimap.map_info.map((mapInfo) => {
|
|
7
|
-
const rooms = mapInfo.rooms
|
|
7
|
+
const rooms = mapInfo.rooms?.map((room) => ({
|
|
8
8
|
id: room.id,
|
|
9
9
|
globalId: parseInt(room.iot_name_id),
|
|
10
10
|
iot_name_id: room.iot_name_id,
|
|
11
11
|
tag: room.tag,
|
|
12
12
|
displayName: room.iot_name,
|
|
13
13
|
mapId: mapInfo.mapFlag,
|
|
14
|
-
}));
|
|
14
|
+
})) ?? [];
|
|
15
15
|
this.allRooms.push(...rooms);
|
|
16
16
|
return {
|
|
17
17
|
id: mapInfo.mapFlag,
|
|
@@ -19,7 +19,6 @@ export class MapInfo {
|
|
|
19
19
|
rooms,
|
|
20
20
|
};
|
|
21
21
|
});
|
|
22
|
-
this.allRooms = this.allRooms.filter((room, index, self) => index === self.findIndex((r) => r.globalId === room.globalId));
|
|
23
22
|
}
|
|
24
23
|
getById(id) {
|
|
25
24
|
return this.maps.find((m) => m.id === id)?.name;
|
package/dist/roborockService.js
CHANGED
|
@@ -22,6 +22,7 @@ export default class RoborockService {
|
|
|
22
22
|
supportedAreas = new Map();
|
|
23
23
|
supportedRoutines = new Map();
|
|
24
24
|
selectedAreas = new Map();
|
|
25
|
+
supportedAreaIndexMaps = new Map();
|
|
25
26
|
vacuumNeedAPIV3 = ['roborock.vacuum.ss07'];
|
|
26
27
|
constructor(authenticateApiSupplier = (logger) => new RoborockAuthenticateApi(logger), iotApiSupplier = (logger, ud) => new RoborockIoTApi(ud, logger), refreshInterval, clientManager, logger) {
|
|
27
28
|
this.logger = logger;
|
|
@@ -52,7 +53,9 @@ export default class RoborockService {
|
|
|
52
53
|
}
|
|
53
54
|
setSelectedAreas(duid, selectedAreas) {
|
|
54
55
|
this.logger.debug('RoborockService - setSelectedAreas', selectedAreas);
|
|
55
|
-
this.
|
|
56
|
+
const roomIds = selectedAreas.map((areaId) => this.supportedAreaIndexMaps.get(duid)?.getRoomId(areaId)) ?? [];
|
|
57
|
+
this.logger.debug('RoborockService - setSelectedAreas - roomIds', roomIds);
|
|
58
|
+
this.selectedAreas.set(duid, roomIds.filter((id) => id !== undefined).map((id) => id));
|
|
56
59
|
}
|
|
57
60
|
getSelectedAreas(duid) {
|
|
58
61
|
return this.selectedAreas.get(duid) ?? [];
|
|
@@ -60,12 +63,18 @@ export default class RoborockService {
|
|
|
60
63
|
setSupportedAreas(duid, supportedAreas) {
|
|
61
64
|
this.supportedAreas.set(duid, supportedAreas);
|
|
62
65
|
}
|
|
66
|
+
setSupportedAreaIndexMap(duid, indexMap) {
|
|
67
|
+
this.supportedAreaIndexMaps.set(duid, indexMap);
|
|
68
|
+
}
|
|
63
69
|
setSupportedScenes(duid, routineAsRooms) {
|
|
64
70
|
this.supportedRoutines.set(duid, routineAsRooms);
|
|
65
71
|
}
|
|
66
72
|
getSupportedAreas(duid) {
|
|
67
73
|
return this.supportedAreas.get(duid);
|
|
68
74
|
}
|
|
75
|
+
getSupportedAreasIndexMap(duid) {
|
|
76
|
+
return this.supportedAreaIndexMaps.get(duid);
|
|
77
|
+
}
|
|
69
78
|
async getCleanModeData(duid) {
|
|
70
79
|
this.logger.notice('RoborockService - getCleanModeData');
|
|
71
80
|
const data = await this.getMessageProcessor(duid)?.getCleanModeData(duid);
|
package/dist/rvc.js
CHANGED
|
@@ -9,14 +9,17 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
|
|
|
9
9
|
constructor(username, device, roomMap, routineAsRoom, enableExperimentalFeature, log) {
|
|
10
10
|
const cleanModes = getSupportedCleanModes(device.data.model, enableExperimentalFeature);
|
|
11
11
|
const supportedRunModes = getSupportedRunModes();
|
|
12
|
-
const
|
|
12
|
+
const enableMultipleMap = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableMultipleMap;
|
|
13
|
+
const { supportedAreas, supportedMaps } = getSupportedAreas(device.rooms, roomMap, enableMultipleMap, log);
|
|
14
|
+
const supportedAreaAndRoutines = [...supportedAreas, ...routineAsRoom];
|
|
13
15
|
const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
|
|
14
16
|
log.debug(`Creating RoborockVacuumCleaner for device: ${deviceName}, model: ${device.data.model}, forceRunAtDefault: ${enableExperimentalFeature?.advancedFeature?.forceRunAtDefault}`);
|
|
15
17
|
log.debug(`Supported Clean Modes: ${JSON.stringify(cleanModes)}`);
|
|
16
18
|
log.debug(`Supported Run Modes: ${JSON.stringify(supportedRunModes)}`);
|
|
17
19
|
log.debug(`Supported Areas: ${JSON.stringify(supportedAreas)}`);
|
|
20
|
+
log.debug(`Supported Maps: ${JSON.stringify(supportedMaps)}`);
|
|
18
21
|
const bridgeMode = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableServerMode ? 'server' : undefined;
|
|
19
|
-
super(deviceName, device.duid, bridgeMode, supportedRunModes[0].mode, supportedRunModes, cleanModes[0].mode, cleanModes, undefined, undefined, RvcOperationalState.OperationalState.Docked, getOperationalStates(),
|
|
22
|
+
super(deviceName, device.duid, bridgeMode, supportedRunModes[0].mode, supportedRunModes, cleanModes[0].mode, cleanModes, undefined, undefined, RvcOperationalState.OperationalState.Docked, getOperationalStates(), supportedAreaAndRoutines, undefined, supportedAreas[0].areaId, supportedMaps);
|
|
20
23
|
this.username = username;
|
|
21
24
|
this.device = device;
|
|
22
25
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-roborock-vacuum-plugin",
|
|
3
3
|
"type": "DynamicPlatform",
|
|
4
|
-
"version": "1.1.0-
|
|
4
|
+
"version": "1.1.0-rc17",
|
|
5
5
|
"whiteList": [],
|
|
6
6
|
"blackList": [],
|
|
7
7
|
"useInterval": true,
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"forceRunAtDefault": false,
|
|
14
14
|
"useVacationModeToSendVacuumToDock": false,
|
|
15
15
|
"enableServerMode": false,
|
|
16
|
-
"alwaysExecuteAuthentication": false
|
|
16
|
+
"alwaysExecuteAuthentication": false,
|
|
17
|
+
"enableMultipleMap": false
|
|
17
18
|
},
|
|
18
19
|
"cleanModeSettings": {
|
|
19
20
|
"enableCleanModeMapping": false,
|
|
@@ -37,4 +38,4 @@
|
|
|
37
38
|
"debug": true,
|
|
38
39
|
"unregisterOnShutdown": false,
|
|
39
40
|
"enableExperimentalFeature": false
|
|
40
|
-
}
|
|
41
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "Matterbridge Roborock Vacuum Plugin",
|
|
3
|
-
"description": "matterbridge-roborock-vacuum-plugin v. 1.1.0-
|
|
3
|
+
"description": "matterbridge-roborock-vacuum-plugin v. 1.1.0-rc17 by https://github.com/RinDevJunior",
|
|
4
4
|
"type": "object",
|
|
5
|
-
"required": [
|
|
5
|
+
"required": [
|
|
6
|
+
"username",
|
|
7
|
+
"password"
|
|
8
|
+
],
|
|
6
9
|
"properties": {
|
|
7
10
|
"name": {
|
|
8
11
|
"description": "Plugin name",
|
|
@@ -57,7 +60,9 @@
|
|
|
57
60
|
"const": true
|
|
58
61
|
}
|
|
59
62
|
},
|
|
60
|
-
"required": [
|
|
63
|
+
"required": [
|
|
64
|
+
"enableExperimentalFeature"
|
|
65
|
+
]
|
|
61
66
|
},
|
|
62
67
|
"then": {
|
|
63
68
|
"properties": {
|
|
@@ -94,6 +99,11 @@
|
|
|
94
99
|
"description": "Always execute authentication on startup.",
|
|
95
100
|
"type": "boolean",
|
|
96
101
|
"default": false
|
|
102
|
+
},
|
|
103
|
+
"enableMultipleMap": {
|
|
104
|
+
"description": "Enable multiple maps support.",
|
|
105
|
+
"type": "boolean",
|
|
106
|
+
"default": false
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
},
|
|
@@ -114,7 +124,9 @@
|
|
|
114
124
|
"const": true
|
|
115
125
|
}
|
|
116
126
|
},
|
|
117
|
-
"required": [
|
|
127
|
+
"required": [
|
|
128
|
+
"enableCleanModeMapping"
|
|
129
|
+
]
|
|
118
130
|
},
|
|
119
131
|
"then": {
|
|
120
132
|
"properties": {
|
|
@@ -159,7 +171,9 @@
|
|
|
159
171
|
"default": 25
|
|
160
172
|
}
|
|
161
173
|
},
|
|
162
|
-
"required": [
|
|
174
|
+
"required": [
|
|
175
|
+
"distanceOff"
|
|
176
|
+
]
|
|
163
177
|
}
|
|
164
178
|
}
|
|
165
179
|
]
|
|
@@ -196,7 +210,9 @@
|
|
|
196
210
|
"default": 25
|
|
197
211
|
}
|
|
198
212
|
},
|
|
199
|
-
"required": [
|
|
213
|
+
"required": [
|
|
214
|
+
"distanceOff"
|
|
215
|
+
]
|
|
200
216
|
}
|
|
201
217
|
}
|
|
202
218
|
]
|
|
@@ -226,20 +242,36 @@
|
|
|
226
242
|
"fanMode": {
|
|
227
243
|
"type": "string",
|
|
228
244
|
"description": "Suction power mode to use (e.g., 'Quiet', 'Balanced', 'Turbo', 'Max', 'MaxPlus').",
|
|
229
|
-
"enum": [
|
|
245
|
+
"enum": [
|
|
246
|
+
"Quiet",
|
|
247
|
+
"Balanced",
|
|
248
|
+
"Turbo",
|
|
249
|
+
"Max",
|
|
250
|
+
"MaxPlus"
|
|
251
|
+
],
|
|
230
252
|
"default": "Balanced"
|
|
231
253
|
},
|
|
232
254
|
"waterFlowMode": {
|
|
233
255
|
"type": "string",
|
|
234
256
|
"description": "Water flow mode to use (e.g., 'Low', 'Medium', 'High', 'CustomizeWithDistanceOff').",
|
|
235
|
-
"enum": [
|
|
257
|
+
"enum": [
|
|
258
|
+
"Low",
|
|
259
|
+
"Medium",
|
|
260
|
+
"High",
|
|
261
|
+
"CustomizeWithDistanceOff"
|
|
262
|
+
],
|
|
236
263
|
"default": "Medium"
|
|
237
264
|
},
|
|
238
265
|
"mopRouteMode": {
|
|
239
266
|
"type": "string",
|
|
240
267
|
"description": "Mop route intensity to use (e.g., 'Standard', 'Deep', 'DeepPlus', 'Fast').",
|
|
241
|
-
"enum": [
|
|
268
|
+
"enum": [
|
|
269
|
+
"Standard",
|
|
270
|
+
"Deep",
|
|
271
|
+
"DeepPlus",
|
|
272
|
+
"Fast"
|
|
273
|
+
],
|
|
242
274
|
"default": "Standard"
|
|
243
275
|
}
|
|
244
276
|
}
|
|
245
|
-
}
|
|
277
|
+
}
|