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/src/helper.ts CHANGED
@@ -3,6 +3,7 @@ import { RoomMap } from './model/RoomMap.js';
3
3
  import { RoborockMatterbridgePlatform } from './platform.js';
4
4
  import { Device } from './roborockCommunication/index.js';
5
5
  import { CloudMessageResult } from './roborockCommunication/Zmodel/messageResult.js';
6
+ import { MapRoom } from './roborockCommunication/Zmodel/mapInfo.js';
6
7
 
7
8
  export function getVacuumProperty(device: Device, property: string): number | undefined {
8
9
  if (device) {
@@ -39,6 +40,7 @@ export function isStatusUpdate(result: unknown): boolean {
39
40
 
40
41
  export async function getRoomMap(duid: string, platform: RoborockMatterbridgePlatform): Promise<RoomMap | undefined> {
41
42
  const robot = platform.robots.get(duid);
43
+ const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature.enableMultipleMap) ?? false;
42
44
  if (robot === undefined) {
43
45
  platform.log.error(`Error6: Robot with DUID ${duid} not found`);
44
46
  return undefined;
@@ -47,21 +49,21 @@ export async function getRoomMap(duid: string, platform: RoborockMatterbridgePla
47
49
  if (platform.roborockService === undefined) return undefined;
48
50
 
49
51
  const rooms = robot.device.rooms ?? [];
50
- if (robot.roomInfo === undefined) {
51
- const roomData = await platform.roborockService.getRoomMappings(robot.device.duid);
52
- if (roomData !== undefined && roomData.length > 0) {
53
- robot.roomInfo = new RoomMap(roomData ?? [], rooms);
54
- return robot.roomInfo;
55
- }
56
- }
57
52
 
58
53
  if (robot.roomInfo === undefined) {
59
54
  const mapInfo = await platform.roborockService.getMapInformation(robot.device.duid);
60
55
  if (mapInfo && mapInfo.allRooms && mapInfo.allRooms.length > 0) {
61
- platform.log.error(`getRoomMap - mapInfo: ${debugStringify(mapInfo.allRooms)}`);
56
+ platform.log.info(`getRoomMap - mapInfo: ${debugStringify(mapInfo.allRooms)}`);
57
+ robot.roomInfo = new RoomMap(mapInfo.allRooms, rooms, mapInfo.maps, enableMultipleMap);
58
+ }
59
+ }
62
60
 
63
- const roomDataMap = mapInfo.allRooms.map((r) => [r.id, parseInt(r.iot_name_id), r.tag] as [number, number, number]);
64
- robot.roomInfo = new RoomMap(roomDataMap, rooms);
61
+ if (robot.roomInfo === undefined) {
62
+ const roomData = await platform.roborockService.getRoomMappings(robot.device.duid);
63
+ if (roomData !== undefined && roomData.length > 0) {
64
+ const roomDataMap: MapRoom[] = roomData.map((r) => ({ id: r[0], iot_name_id: String(r[1]), globalId: r[1], tag: r[2], mapId: 0, displayName: undefined }));
65
+ robot.roomInfo = new RoomMap(roomDataMap, rooms, [], enableMultipleMap);
66
+ return robot.roomInfo;
65
67
  }
66
68
  }
67
69
 
@@ -70,35 +72,36 @@ export async function getRoomMap(duid: string, platform: RoborockMatterbridgePla
70
72
 
71
73
  export async function getRoomMapFromDevice(device: Device, platform: RoborockMatterbridgePlatform): Promise<RoomMap> {
72
74
  const rooms = device?.rooms ?? [];
75
+ const enableMultipleMap = (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature.enableMultipleMap) ?? false;
73
76
 
74
77
  platform.log.notice('-------------------------------------------0--------------------------------------------------------');
75
78
  platform.log.notice(`getRoomMapFromDevice - device.rooms: ${debugStringify(rooms)}`);
76
79
 
77
80
  if (device && platform.roborockService) {
78
- const roomData = await platform.roborockService.getRoomMappings(device.duid);
79
- if (roomData !== undefined && roomData.length > 0) {
80
- platform.log.notice(`getRoomMapFromDevice - roomData: ${debugStringify(roomData ?? [])}`);
81
-
82
- const roomMap = new RoomMap(roomData ?? [], rooms);
83
-
84
- platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
85
- platform.log.notice('-------------------------------------------1--------------------------------------------------------');
86
- return roomMap;
87
- }
88
-
89
81
  const mapInfo = await platform.roborockService.getMapInformation(device.duid);
90
82
  platform.log.notice(`getRoomMapFromDevice - mapInfo: ${mapInfo ? debugStringify(mapInfo) : 'undefined'}`);
91
83
 
92
84
  if (mapInfo && mapInfo.allRooms && mapInfo.allRooms.length > 0) {
93
- const roomDataMap = mapInfo.allRooms.map((r) => [r.id, parseInt(r.iot_name_id), r.tag] as [number, number, number]);
85
+ const roomDataMap = mapInfo.allRooms; // .map((r) => [r.id, parseInt(r.iot_name_id), r.tag, r.mapId] as [number, number, number, number]);
94
86
 
95
- const roomMap = new RoomMap(roomDataMap, rooms);
87
+ const roomMap = new RoomMap(roomDataMap, rooms, mapInfo.maps, enableMultipleMap);
96
88
 
97
89
  platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
98
90
  platform.log.notice('-------------------------------------------2--------------------------------------------------------');
99
91
  return roomMap;
100
92
  }
93
+
94
+ const roomData = await platform.roborockService.getRoomMappings(device.duid);
95
+ if (roomData !== undefined && roomData.length > 0) {
96
+ platform.log.notice(`getRoomMapFromDevice - roomData: ${debugStringify(roomData ?? [])}`);
97
+ const roomDataMap: MapRoom[] = roomData.map((r) => ({ id: r[0], iot_name_id: String(r[1]), globalId: r[1], tag: r[2], mapId: 0, displayName: undefined }));
98
+ const roomMap = new RoomMap(roomDataMap ?? [], rooms, [], enableMultipleMap);
99
+
100
+ platform.log.notice(`getRoomMapFromDevice - roomMap: ${debugStringify(roomMap)}`);
101
+ platform.log.notice('-------------------------------------------1--------------------------------------------------------');
102
+ return roomMap;
103
+ }
101
104
  }
102
105
 
103
- return new RoomMap([], rooms);
106
+ return new RoomMap([], rooms, [], enableMultipleMap);
104
107
  }
@@ -3,8 +3,14 @@ import { ServiceArea } from 'matterbridge/matter/clusters';
3
3
  import { RoomMap } from '../model/RoomMap.js';
4
4
  import { Room } from '../roborockCommunication/Zmodel/room.js';
5
5
  import { randomInt } from 'node:crypto';
6
+ import { RoomIndexMap } from '../model/roomIndexMap.js';
6
7
 
7
- export function getSupportedAreas(vacuumRooms: Room[], roomMap: RoomMap | undefined, log?: AnsiLogger): ServiceArea.Area[] {
8
+ export function getSupportedAreas(
9
+ vacuumRooms: Room[],
10
+ roomMap: RoomMap | undefined,
11
+ enableMultipleMap = false,
12
+ log?: AnsiLogger,
13
+ ): { supportedAreas: ServiceArea.Area[]; supportedMaps: ServiceArea.Map[]; roomIndexMap: RoomIndexMap } {
8
14
  log?.debug('getSupportedAreas-vacuum room', debugStringify(vacuumRooms));
9
15
  log?.debug('getSupportedAreas-roomMap', roomMap ? debugStringify(roomMap) : 'undefined');
10
16
 
@@ -18,79 +24,135 @@ export function getSupportedAreas(vacuumRooms: Room[], roomMap: RoomMap | undefi
18
24
  if (noRoomMap) {
19
25
  log?.error('No room map found');
20
26
  }
21
- return [
22
- {
23
- areaId: 1,
24
- mapId: null,
25
- areaInfo: {
26
- locationInfo: {
27
- locationName: 'Unknown',
28
- floorNumber: null,
29
- areaType: null,
30
- },
31
- landmarkInfo: null,
32
- },
33
- },
34
- ];
35
- }
36
-
37
- const supportedAreas: ServiceArea.Area[] = roomMap.rooms.map((room) => {
38
- const locationName = room.displayName ?? vacuumRooms.find((r) => r.id === room.globalId || r.id === room.id)?.name ?? `Unknown Room ${randomInt(1000, 9999)}`;
39
27
 
40
28
  return {
41
- areaId: room.id,
42
- mapId: null,
43
- areaInfo: {
44
- locationInfo: {
45
- locationName,
46
- floorNumber: null,
47
- areaType: null,
29
+ supportedAreas: [
30
+ {
31
+ areaId: 1,
32
+ mapId: null,
33
+ areaInfo: {
34
+ locationInfo: {
35
+ locationName: 'Unknown',
36
+ floorNumber: null,
37
+ areaType: null,
38
+ },
39
+ landmarkInfo: null,
40
+ },
48
41
  },
49
- landmarkInfo: null,
50
- },
42
+ ],
43
+ supportedMaps: [],
44
+ roomIndexMap: new RoomIndexMap(new Map([[1, { roomId: 1, mapId: null }]])),
51
45
  };
52
- });
53
-
54
- log?.debug('getSupportedAreas - supportedAreas', debugStringify(supportedAreas));
46
+ }
55
47
 
48
+ const { supportedAreas, indexMap } = processValidData(enableMultipleMap, vacuumRooms, roomMap);
56
49
  const duplicated = findDuplicatedAreaIds(supportedAreas, log);
57
50
 
58
51
  if (duplicated) {
59
- return [
60
- {
61
- areaId: 2,
62
- mapId: null,
63
- areaInfo: {
64
- locationInfo: {
65
- locationName: 'Unknown',
66
- floorNumber: null,
67
- areaType: null,
52
+ return {
53
+ supportedAreas: [
54
+ {
55
+ areaId: 2,
56
+ mapId: null,
57
+ areaInfo: {
58
+ locationInfo: {
59
+ locationName: 'Unknown - Duplicated Areas Found',
60
+ floorNumber: null,
61
+ areaType: null,
62
+ },
63
+ landmarkInfo: null,
68
64
  },
69
- landmarkInfo: null,
70
65
  },
71
- },
72
- ];
66
+ ],
67
+ supportedMaps: [],
68
+ roomIndexMap: new RoomIndexMap(new Map([[2, { roomId: 2, mapId: null }]])),
69
+ };
73
70
  }
74
71
 
75
- return supportedAreas;
72
+ const supportedMaps = getSupportedMaps(enableMultipleMap, supportedAreas, roomMap);
73
+
74
+ log?.debug('getSupportedAreas - supportedAreas', debugStringify(supportedAreas));
75
+ log?.debug('getSupportedAreas - supportedMaps', debugStringify(supportedMaps));
76
+ const roomIndexMap = new RoomIndexMap(indexMap);
77
+ return {
78
+ supportedAreas,
79
+ supportedMaps,
80
+ roomIndexMap,
81
+ };
76
82
  }
77
83
 
78
84
  function findDuplicatedAreaIds(areas: ServiceArea.Area[], log?: AnsiLogger): boolean {
79
- const seen = new Set<number>();
80
- const duplicates: number[] = [];
85
+ const seen = new Set<string>();
86
+ const duplicates: { areaId: number; mapId: number }[] = [];
81
87
 
82
88
  for (const area of areas) {
83
- if (seen.has(area.areaId)) {
84
- duplicates.push(area.areaId);
89
+ const key = `${area.areaId}=${area.mapId}`;
90
+ if (seen.has(key)) {
91
+ duplicates.push({ areaId: area.areaId, mapId: area.mapId ?? 0 });
85
92
  } else {
86
- seen.add(area.areaId);
93
+ seen.add(key);
87
94
  }
88
95
  }
89
96
 
90
97
  if (duplicates.length > 0 && log) {
91
- const duplicated = areas.filter((x) => duplicates.includes(x.areaId));
98
+ const duplicated = areas.filter(({ areaId, mapId }) => duplicates.some((y) => y.areaId === areaId && y.mapId === (mapId ?? 0)));
92
99
  log.error(`Duplicated areaId(s) found: ${debugStringify(duplicated)}`);
93
100
  }
94
101
 
95
102
  return duplicates.length > 0;
96
103
  }
104
+
105
+ function processValidData(
106
+ enableMultipleMap: boolean,
107
+ vacuumRooms: Room[],
108
+ roomMap?: RoomMap,
109
+ ): { supportedAreas: ServiceArea.Area[]; indexMap: Map<number, { roomId: number; mapId: number | null }> } {
110
+ const indexMap = new Map<number, { roomId: number; mapId: number | null }>();
111
+ const supportedAreas: ServiceArea.Area[] =
112
+ roomMap?.rooms !== undefined && roomMap.rooms.length > 0
113
+ ? roomMap.rooms.map((room, index) => {
114
+ const locationName = room.displayName ?? vacuumRooms.find((r) => r.id === room.globalId || r.id === room.id)?.name ?? `Unknown Room ${randomInt(1000, 9999)}`;
115
+
116
+ const areaId = enableMultipleMap ? index + 100 : room.id;
117
+ const mapId = enableMultipleMap ? (room.mapId ?? null) : null;
118
+
119
+ indexMap.set(areaId, { roomId: room.id, mapId: room.mapId ?? null });
120
+
121
+ return {
122
+ areaId: areaId,
123
+ mapId: mapId,
124
+ areaInfo: {
125
+ locationInfo: {
126
+ locationName: locationName, // `${locationName} - (${areaId}) - (${room.id}) - (${room.globalId})`,
127
+ floorNumber: room.mapId ?? null,
128
+ areaType: null,
129
+ },
130
+ landmarkInfo: null,
131
+ },
132
+ };
133
+ })
134
+ : [];
135
+
136
+ return {
137
+ supportedAreas,
138
+ indexMap,
139
+ };
140
+ }
141
+
142
+ function getSupportedMaps(enableMultipleMap: boolean, supportedAreas: ServiceArea.Area[], roomMap?: RoomMap): ServiceArea.Map[] {
143
+ if (enableMultipleMap) {
144
+ return (
145
+ roomMap?.mapInfo?.map((map) => ({
146
+ mapId: map.id,
147
+ name: map.name ?? `Map ${map.id}`,
148
+ })) ?? []
149
+ );
150
+ }
151
+
152
+ return [];
153
+
154
+ // return supportedAreas.map((area) => ({
155
+ // mapId: area.mapId ?? 0,
156
+ // name: `Map ${area.mapId ?? 0}`,
157
+ // }));
158
+ }
@@ -7,6 +7,7 @@ export interface ExperimentalFeatureSetting {
7
7
  useVacationModeToSendVacuumToDock: boolean;
8
8
  enableServerMode: boolean;
9
9
  alwaysExecuteAuthentication: boolean;
10
+ enableMultipleMap: boolean;
10
11
  };
11
12
  cleanModeSettings: CleanModeSettings;
12
13
  }
@@ -40,6 +41,7 @@ export function createDefaultExperimentalFeatureSetting(): ExperimentalFeatureSe
40
41
  useVacationModeToSendVacuumToDock: false,
41
42
  enableServerMode: false,
42
43
  alwaysExecuteAuthentication: false,
44
+ enableMultipleMap: false,
43
45
  },
44
46
  cleanModeSettings: {
45
47
  enableCleanModeMapping: false,
@@ -15,6 +15,7 @@ roomMap = {
15
15
  };
16
16
  */
17
17
 
18
+ import { MapRoom } from '../roborockCommunication/Zmodel/mapInfo.js';
18
19
  import { Room } from '../roborockCommunication/Zmodel/room.js';
19
20
 
20
21
  export interface RoomMapEntry {
@@ -22,21 +23,34 @@ export interface RoomMapEntry {
22
23
  globalId: number | undefined;
23
24
  displayName?: string;
24
25
  alternativeId: string;
26
+ mapId?: number;
27
+ }
28
+
29
+ export interface MapInfo {
30
+ id: number;
31
+ name: string | undefined;
25
32
  }
26
33
 
27
34
  export class RoomMap {
28
35
  readonly rooms: RoomMapEntry[];
36
+ readonly mapInfo?: MapInfo[];
29
37
 
30
- constructor(roomData: number[][], rooms: Room[]) {
31
- this.rooms = roomData.map(([id, globalId, altId]) => {
38
+ constructor(roomData: MapRoom[], rooms: Room[], mapInfo: MapInfo[], enableMultipleMap: boolean) {
39
+ const mapid = mapInfo[0]?.id ?? 0;
40
+ const roomDataTmp = enableMultipleMap ? roomData : roomData.filter((room) => room.mapId === undefined || room.mapId === mapid);
41
+
42
+ this.rooms = roomDataTmp.map(({ id, globalId, tag, mapId }) => {
32
43
  const room = rooms.find((r) => Number(r.id) === Number(globalId) || Number(r.id) === Number(id));
33
44
  return {
34
45
  id,
35
46
  globalId: globalId !== undefined ? Number(globalId) : undefined,
36
47
  displayName: room?.name,
37
- alternativeId: `${id}${altId}`,
48
+ alternativeId: `${id}${tag}`,
49
+ mapId,
38
50
  };
39
51
  });
52
+
53
+ this.mapInfo = mapInfo;
40
54
  }
41
55
 
42
56
  // Optionally, add utility methods for clarity
@@ -0,0 +1,20 @@
1
+ export class RoomIndexMap {
2
+ private indexMap: Map<number, { roomId: number; mapId: number | null }>;
3
+ private roomMap: Map<number, number>;
4
+
5
+ constructor(roomMap: Map<number, { roomId: number; mapId: number | null }>) {
6
+ this.indexMap = roomMap;
7
+ this.roomMap = new Map();
8
+ for (const [areaId, { roomId }] of roomMap.entries()) {
9
+ this.roomMap.set(roomId, areaId);
10
+ }
11
+ }
12
+
13
+ public getAreaId(roomId: number): number | undefined {
14
+ return this.roomMap.get(roomId);
15
+ }
16
+
17
+ public getRoomId(areaId: number): number | undefined {
18
+ return this.indexMap.get(areaId)?.roomId;
19
+ }
20
+ }
package/src/platform.ts CHANGED
@@ -33,9 +33,9 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
33
33
  super(matterbridge, log, config);
34
34
 
35
35
  // Verify that Matterbridge is the correct version
36
- if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.7')) {
36
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.1.8')) {
37
37
  throw new Error(
38
- `This plugin requires Matterbridge version >= "3.1.7". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`,
38
+ `This plugin requires Matterbridge version >= "3.1.8". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`,
39
39
  );
40
40
  }
41
41
  this.log.info('Initializing platform:', this.config.name);
@@ -244,8 +244,11 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
244
244
  this.log,
245
245
  );
246
246
 
247
- const supportedAreas = getSupportedAreas(vacuum.rooms, roomMap, this.log);
247
+ const enableMultipleMap = this.enableExperimentalFeature?.enableExperimentalFeature && this.enableExperimentalFeature.advancedFeature?.enableMultipleMap;
248
+
249
+ const { supportedAreas, roomIndexMap } = getSupportedAreas(vacuum.rooms, roomMap, enableMultipleMap, this.log);
248
250
  this.roborockService.setSupportedAreas(vacuum.duid, supportedAreas);
251
+ this.roborockService.setSupportedAreaIndexMap(vacuum.duid, roomIndexMap);
249
252
 
250
253
  let routineAsRoom: ServiceArea.Area[] = [];
251
254
  if (this.enableExperimentalFeature?.enableExperimentalFeature && this.enableExperimentalFeature.advancedFeature?.showRoutinesAsRoom) {
@@ -120,6 +120,7 @@ export class PlatformRunner {
120
120
  robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
121
121
  } else {
122
122
  const currentMappedAreas = this.platform.roborockService?.getSupportedAreas(duid);
123
+ const roomIndexMap = this.platform.roborockService?.getSupportedAreasIndexMap(duid);
123
124
  const roomMap = await getRoomMap(duid, this.platform);
124
125
 
125
126
  // Get current room from segment_id
@@ -135,7 +136,10 @@ export class PlatformRunner {
135
136
  this.platform.log.debug(
136
137
  `Part1: CurrentRoom: ${segment_id}, room name: ${roomMap?.rooms.find((x) => x.id === segment_id || x.alternativeId === segment_id.toString())?.displayName ?? 'unknown'}`,
137
138
  );
138
- robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', segment_id, platform.log);
139
+
140
+ const areaId = roomIndexMap?.getAreaId(segment_id) ?? segment_id;
141
+ this.platform.log.notice(`AreaId: ${areaId}, segment_id: ${segment_id}`);
142
+ robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
139
143
  }
140
144
 
141
145
  if (segment_id == -1) {
@@ -148,7 +152,9 @@ export class PlatformRunner {
148
152
  this.platform.log.debug(
149
153
  `Part2: TargetRoom: ${target_segment_id}, room name: ${roomMap?.rooms.find((x) => x.id === target_segment_id || x.alternativeId === segment_id.toString())?.displayName ?? 'unknown'}`,
150
154
  );
151
- robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', target_segment_id, platform.log);
155
+ const areaId = roomIndexMap?.getAreaId(target_segment_id) ?? target_room_id;
156
+ this.platform.log.notice(`AreaId: ${areaId}, target_segment_id: ${target_segment_id}`);
157
+ robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', areaId, platform.log);
152
158
  }
153
159
  }
154
160
 
@@ -284,6 +290,8 @@ export class PlatformRunner {
284
290
  platform.log.notice(`Received additional properties for robot ${duid}: ${debugStringify(data)}`);
285
291
  const propCode = data.dps[Protocol.additional_props] as number;
286
292
  platform.log.debug(`DPS for additional properties: ${propCode}, AdditionalPropCode: ${AdditionalPropCode[propCode]}`);
293
+ const enableMultipleMap =
294
+ (platform.enableExperimentalFeature?.enableExperimentalFeature && platform.enableExperimentalFeature?.advancedFeature?.enableMultipleMap) ?? false;
287
295
 
288
296
  if (propCode === AdditionalPropCode.map_change) {
289
297
  platform.log.notice('------------------------ get roomData ----------------------------');
@@ -291,7 +299,7 @@ export class PlatformRunner {
291
299
  const roomMap = await getRoomMapFromDevice(robot.device, platform);
292
300
 
293
301
  platform.log.notice('------------------------ Room map updated ------------------------');
294
- const supportedAreas = getSupportedAreas(robot.device.rooms, roomMap, platform.log);
302
+ const { supportedAreas, supportedMaps, roomIndexMap } = getSupportedAreas(robot.device.rooms, roomMap, enableMultipleMap, platform.log);
295
303
 
296
304
  platform.log.notice(`Supported areas: ${debugStringify(supportedAreas)}`);
297
305
  platform.log.notice('------------------------ Supported areas updated ------------------');
@@ -301,6 +309,11 @@ export class PlatformRunner {
301
309
  robot.updateAttribute(ServiceArea.Cluster.id, 'supportedAreas', supportedAreas, platform.log);
302
310
  robot.updateAttribute(ServiceArea.Cluster.id, 'selectedAreas', [], platform.log);
303
311
  robot.updateAttribute(ServiceArea.Cluster.id, 'currentArea', null, platform.log);
312
+
313
+ if (enableMultipleMap) {
314
+ platform.roborockService?.setSupportedAreaIndexMap(duid, roomIndexMap);
315
+ robot.updateAttribute(ServiceArea.Cluster.id, 'supportedMaps', supportedMaps, platform.log);
316
+ }
304
317
  }
305
318
  break;
306
319
  }
@@ -3,7 +3,7 @@ export interface MapInformation {
3
3
  add_time: number;
4
4
  length: number;
5
5
  name: string;
6
- rooms: RoomInformation[];
6
+ rooms?: RoomInformation[] | undefined;
7
7
  bak_maps: { mapFlag: number; add_time: number }[];
8
8
  }
9
9
 
@@ -7,7 +7,7 @@ export interface MapRoom {
7
7
  iot_name_id: string;
8
8
  tag: number;
9
9
  globalId?: number;
10
- displayName: string;
10
+ displayName?: string;
11
11
  mapId?: number;
12
12
  }
13
13
 
@@ -23,14 +23,15 @@ export class MapInfo {
23
23
 
24
24
  constructor(multimap: MultipleMap) {
25
25
  this.maps = multimap.map_info.map((mapInfo) => {
26
- const rooms: MapRoom[] = mapInfo.rooms.map((room: RoomInformation) => ({
27
- id: room.id,
28
- globalId: parseInt(room.iot_name_id),
29
- iot_name_id: room.iot_name_id,
30
- tag: room.tag,
31
- displayName: room.iot_name,
32
- mapId: mapInfo.mapFlag,
33
- }));
26
+ const rooms: MapRoom[] =
27
+ mapInfo.rooms?.map((room: RoomInformation) => ({
28
+ id: room.id,
29
+ globalId: parseInt(room.iot_name_id),
30
+ iot_name_id: room.iot_name_id,
31
+ tag: room.tag,
32
+ displayName: room.iot_name,
33
+ mapId: mapInfo.mapFlag,
34
+ })) ?? [];
34
35
 
35
36
  this.allRooms.push(...rooms);
36
37
  return {
@@ -40,7 +41,7 @@ export class MapInfo {
40
41
  };
41
42
  });
42
43
 
43
- this.allRooms = this.allRooms.filter((room, index, self) => index === self.findIndex((r) => r.globalId === room.globalId));
44
+ // this.allRooms = this.allRooms.filter((room, index, self) => index === self.findIndex((r) => r.globalId === room.globalId));
44
45
  }
45
46
 
46
47
  getById(id: number): string | undefined {
@@ -24,6 +24,7 @@ import {
24
24
  import type { AbstractMessageHandler, AbstractMessageListener, BatteryMessage, DeviceErrorMessage, DeviceStatusNotify, MultipleMap } from './roborockCommunication/index.js';
25
25
  import { ServiceArea } from 'matterbridge/matter/clusters';
26
26
  import { LocalNetworkClient } from './roborockCommunication/broadcast/client/LocalNetworkClient.js';
27
+ import { RoomIndexMap } from './model/roomIndexMap.js';
27
28
  export type Factory<A, T> = (logger: AnsiLogger, arg: A) => T;
28
29
 
29
30
  export default class RoborockService {
@@ -48,6 +49,7 @@ export default class RoborockService {
48
49
  private supportedAreas = new Map<string, ServiceArea.Area[]>();
49
50
  private supportedRoutines = new Map<string, ServiceArea.Area[]>();
50
51
  private selectedAreas = new Map<string, number[]>();
52
+ private supportedAreaIndexMaps = new Map<string, RoomIndexMap>();
51
53
 
52
54
  private readonly vacuumNeedAPIV3 = ['roborock.vacuum.ss07'];
53
55
 
@@ -95,7 +97,12 @@ export default class RoborockService {
95
97
 
96
98
  public setSelectedAreas(duid: string, selectedAreas: number[]): void {
97
99
  this.logger.debug('RoborockService - setSelectedAreas', selectedAreas);
98
- this.selectedAreas.set(duid, selectedAreas);
100
+ const roomIds = selectedAreas.map((areaId) => this.supportedAreaIndexMaps.get(duid)?.getRoomId(areaId)) ?? [];
101
+ this.logger.debug('RoborockService - setSelectedAreas - roomIds', roomIds);
102
+ this.selectedAreas.set(
103
+ duid,
104
+ roomIds.filter((id) => id !== undefined).map((id) => id),
105
+ );
99
106
  }
100
107
 
101
108
  public getSelectedAreas(duid: string): number[] {
@@ -106,6 +113,10 @@ export default class RoborockService {
106
113
  this.supportedAreas.set(duid, supportedAreas);
107
114
  }
108
115
 
116
+ public setSupportedAreaIndexMap(duid: string, indexMap: RoomIndexMap): void {
117
+ this.supportedAreaIndexMaps.set(duid, indexMap);
118
+ }
119
+
109
120
  public setSupportedScenes(duid: string, routineAsRooms: ServiceArea.Area[]) {
110
121
  this.supportedRoutines.set(duid, routineAsRooms);
111
122
  }
@@ -114,6 +125,10 @@ export default class RoborockService {
114
125
  return this.supportedAreas.get(duid);
115
126
  }
116
127
 
128
+ public getSupportedAreasIndexMap(duid: string): RoomIndexMap | undefined {
129
+ return this.supportedAreaIndexMaps.get(duid);
130
+ }
131
+
117
132
  public async getCleanModeData(duid: string): Promise<{ suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number }> {
118
133
  this.logger.notice('RoborockService - getCleanModeData');
119
134
  const data = await this.getMessageProcessor(duid)?.getCleanModeData(duid);
package/src/rvc.ts CHANGED
@@ -24,7 +24,10 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
24
24
  ) {
25
25
  const cleanModes = getSupportedCleanModes(device.data.model, enableExperimentalFeature);
26
26
  const supportedRunModes = getSupportedRunModes();
27
- const supportedAreas = [...getSupportedAreas(device.rooms, roomMap, log), ...routineAsRoom];
27
+ const enableMultipleMap = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableMultipleMap;
28
+
29
+ const { supportedAreas, supportedMaps } = getSupportedAreas(device.rooms, roomMap, enableMultipleMap, log);
30
+ const supportedAreaAndRoutines = [...supportedAreas, ...routineAsRoom];
28
31
  const deviceName = `${device.name}-${device.duid}`.replace(/\s+/g, '');
29
32
 
30
33
  log.debug(
@@ -33,6 +36,7 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
33
36
  log.debug(`Supported Clean Modes: ${JSON.stringify(cleanModes)}`);
34
37
  log.debug(`Supported Run Modes: ${JSON.stringify(supportedRunModes)}`);
35
38
  log.debug(`Supported Areas: ${JSON.stringify(supportedAreas)}`);
39
+ log.debug(`Supported Maps: ${JSON.stringify(supportedMaps)}`);
36
40
 
37
41
  const bridgeMode = enableExperimentalFeature?.enableExperimentalFeature && enableExperimentalFeature?.advancedFeature?.enableServerMode ? 'server' : undefined;
38
42
  super(
@@ -47,9 +51,10 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
47
51
  undefined, // phaseList
48
52
  RvcOperationalState.OperationalState.Docked, // operationalState
49
53
  getOperationalStates(), // operationalStateList
50
- supportedAreas, // supportedAreas
54
+ supportedAreaAndRoutines, // supportedAreas
51
55
  undefined, // selectedAreas
52
56
  supportedAreas[0].areaId, // currentArea
57
+ supportedMaps, // supportedMaps
53
58
  );
54
59
 
55
60
  this.username = username;