matterbridge-roborock-vacuum-plugin 1.1.0-rc16 → 1.1.0-rc18
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 +13 -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 +16 -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 = enableMultipleMap ? index + 100 : room.id;
|
|
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,9 @@ 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) ?? segment_id;
|
|
107
|
+
this.platform.log.notice(`AreaId: ${areaId}, segment_id: ${segment_id}`);
|
|
108
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
|
|
106
109
|
}
|
|
107
110
|
if (segment_id == -1) {
|
|
108
111
|
const isTargetMappedArea = currentMappedAreas?.some((x) => x.areaId == target_segment_id);
|
|
@@ -111,7 +114,9 @@ export class PlatformRunner {
|
|
|
111
114
|
if (target_segment_id !== -1 && isTargetMappedArea) {
|
|
112
115
|
this.platform.log.debug(`RoomMap: ${roomMap ? debugStringify(roomMap) : 'undefined'}`);
|
|
113
116
|
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
|
-
|
|
117
|
+
const areaId = roomIndexMap?.getAreaId(target_segment_id) ?? target_room_id;
|
|
118
|
+
this.platform.log.notice(`AreaId: ${areaId}, target_segment_id: ${target_segment_id}`);
|
|
119
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
if (target_segment_id == -1 && segment_id == -1) {
|
|
@@ -222,11 +227,12 @@ export class PlatformRunner {
|
|
|
222
227
|
platform.log.notice(`Received additional properties for robot ${duid}: ${debugStringify(data)}`);
|
|
223
228
|
const propCode = data.dps[Protocol.additional_props];
|
|
224
229
|
platform.log.debug(`DPS for additional properties: ${propCode}, AdditionalPropCode: ${AdditionalPropCode[propCode]}`);
|
|
230
|
+
const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap) ?? false;
|
|
225
231
|
if (propCode === AdditionalPropCode.map_change) {
|
|
226
232
|
platform.log.notice('------------------------ get roomData ----------------------------');
|
|
227
233
|
const roomMap = await getRoomMapFromDevice(robot.device, platform);
|
|
228
234
|
platform.log.notice('------------------------ Room map updated ------------------------');
|
|
229
|
-
const supportedAreas = getSupportedAreas(robot.device.rooms, roomMap, platform.log);
|
|
235
|
+
const { supportedAreas, supportedMaps, roomIndexMap } = getSupportedAreas(robot.device.rooms, roomMap, enableMultipleMap, platform.log);
|
|
230
236
|
platform.log.notice(`Supported areas: ${debugStringify(supportedAreas)}`);
|
|
231
237
|
platform.log.notice('------------------------ Supported areas updated ------------------');
|
|
232
238
|
platform.roborockService?.setSupportedAreas(duid, supportedAreas);
|
|
@@ -234,6 +240,10 @@ export class PlatformRunner {
|
|
|
234
240
|
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedAreas', supportedAreas, platform.log);
|
|
235
241
|
robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
|
|
236
242
|
robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
|
|
243
|
+
if (enableMultipleMap) {
|
|
244
|
+
platform.roborockService?.setSupportedAreaIndexMap(duid, roomIndexMap);
|
|
245
|
+
robot.updateAttribute(ServiceArea.Cluster.id, 'supportedMaps', supportedMaps, platform.log);
|
|
246
|
+
}
|
|
237
247
|
}
|
|
238
248
|
break;
|
|
239
249
|
}
|
|
@@ -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-rc18",
|
|
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-rc18 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
|
+
}
|