matterbridge-roborock-vacuum-plugin 1.1.1-rc05 → 1.1.1-rc07

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/model/roomIndexMap.js +2 -2
  2. package/dist/platform.js +2 -2
  3. package/dist/roborockService.js +1 -1
  4. package/matterbridge-roborock-vacuum-plugin.config.json +1 -1
  5. package/matterbridge-roborock-vacuum-plugin.schema.json +1 -1
  6. package/package.json +1 -1
  7. package/src/behaviors/roborock.vacuum/default/default.ts +9 -5
  8. package/src/behaviors/roborock.vacuum/default/runtimes.ts +2 -2
  9. package/src/behaviors/roborock.vacuum/smart/runtimes.ts +2 -1
  10. package/src/behaviors/roborock.vacuum/smart/smart.ts +2 -2
  11. package/src/initialData/getSupportedAreas.ts +25 -13
  12. package/src/model/CloudMessageModel.ts +6 -8
  13. package/src/model/ExperimentalFeatureSetting.ts +32 -24
  14. package/src/model/roomIndexMap.ts +6 -4
  15. package/src/platform.ts +4 -4
  16. package/src/roborockCommunication/Zmodel/batteryMessage.ts +3 -1
  17. package/src/roborockCommunication/Zmodel/device.ts +18 -22
  18. package/src/roborockCommunication/Zmodel/map.ts +6 -1
  19. package/src/roborockCommunication/Zmodel/messageResult.ts +9 -7
  20. package/src/roborockCommunication/Zmodel/roomInfo.ts +6 -1
  21. package/src/roborockCommunication/Zmodel/scene.ts +6 -4
  22. package/src/roborockCommunication/Zmodel/userData.ts +8 -6
  23. package/src/roborockCommunication/broadcast/messageProcessor.ts +3 -2
  24. package/src/roborockCommunication/broadcast/model/dps.ts +6 -4
  25. package/src/roborockCommunication/broadcast/model/messageContext.ts +7 -1
  26. package/src/roborockCommunication/helper/messageSerializer.ts +6 -1
  27. package/src/roborockService.ts +14 -8
  28. package/src/rvc.ts +5 -1
  29. package/src/share/runtimeHelper.ts +2 -1
  30. package/src/tests/runtimes/handleHomeDataMessage.test.ts +2 -1
  31. package/src/tests/runtimes/handleLocalMessage.test.ts +6 -1
@@ -4,8 +4,8 @@ export class RoomIndexMap {
4
4
  constructor(roomMap) {
5
5
  this.indexMap = roomMap;
6
6
  this.roomMap = new Map();
7
- for (const [areaId, { roomId, mapId }] of roomMap.entries()) {
8
- this.roomMap.set(`${roomId}:${mapId}`, areaId);
7
+ for (const [areaId, r] of roomMap.entries()) {
8
+ this.roomMap.set(`${r.roomId}:${r.mapId}`, areaId);
9
9
  }
10
10
  }
11
11
  getAreaId(roomId, mapId) {
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.2.2')) {
30
- throw new Error(`This plugin requires Matterbridge version >= "3.2.2". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`);
29
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.3.6')) {
30
+ throw new Error(`This plugin requires Matterbridge version >= "3.3.6". 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)
@@ -97,7 +97,7 @@ export default class RoborockService {
97
97
  }
98
98
  async changeCleanMode(duid, { suctionPower, waterFlow, distance_off, mopRoute }) {
99
99
  this.logger.notice('RoborockService - changeCleanMode');
100
- return this.getMessageProcessor(duid)?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute, distance_off);
100
+ return this.getMessageProcessor(duid)?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute ?? 0, distance_off);
101
101
  }
102
102
  async startClean(duid) {
103
103
  const supportedRooms = this.supportedAreas.get(duid) ?? [];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "matterbridge-roborock-vacuum-plugin",
3
3
  "type": "DynamicPlatform",
4
- "version": "1.1.1-rc05",
4
+ "version": "1.1.1-rc07",
5
5
  "whiteList": [],
6
6
  "blackList": [],
7
7
  "useInterval": true,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "title": "Matterbridge Roborock Vacuum Plugin",
3
- "description": "matterbridge-roborock-vacuum-plugin v. 1.1.1-rc05 by https://github.com/RinDevJunior",
3
+ "description": "matterbridge-roborock-vacuum-plugin v. 1.1.1-rc07 by https://github.com/RinDevJunior",
4
4
  "type": "object",
5
5
  "required": ["username", "password"],
6
6
  "properties": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge-roborock-vacuum-plugin",
3
- "version": "1.1.1-rc05",
3
+ "version": "1.1.1-rc07",
4
4
  "description": "Matterbridge Roborock Vacuum Plugin",
5
5
  "author": "https://github.com/RinDevJunior",
6
6
  "license": "MIT",
@@ -79,7 +79,14 @@ export const RvcCleanMode: Record<number, string> = {
79
79
  [99]: 'Go Vacation',
80
80
  };
81
81
 
82
- export const CleanSetting: Record<number, { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number }> = {
82
+ export interface CleanModeSetting {
83
+ suctionPower: number;
84
+ waterFlow: number;
85
+ distance_off: number;
86
+ mopRoute: number | undefined;
87
+ }
88
+
89
+ export const CleanSetting: Record<number, CleanModeSetting> = {
83
90
  [5]: { suctionPower: VacuumSuctionPower.Balanced, waterFlow: MopWaterFlow.Medium, distance_off: 0, mopRoute: MopRoute.Standard }, // 'Vac & Mop Default'
84
91
  [6]: { suctionPower: VacuumSuctionPower.Balanced, waterFlow: MopWaterFlow.Medium, distance_off: 0, mopRoute: MopRoute.Fast }, // 'Vac & Mop Quick'
85
92
 
@@ -192,10 +199,7 @@ export function setDefaultCommandHandler(
192
199
  });
193
200
  }
194
201
 
195
- export const getSettingFromCleanMode = (
196
- activity: string,
197
- cleanModeSettings?: CleanModeSettings,
198
- ): { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number } | undefined => {
202
+ export const getSettingFromCleanMode = (activity: string, cleanModeSettings?: CleanModeSettings): CleanModeSetting | undefined => {
199
203
  switch (activity) {
200
204
  case 'Mop: Default': {
201
205
  const mopSetting = cleanModeSettings?.mopping;
@@ -1,6 +1,6 @@
1
- import { CleanSetting, MopRoute, MopWaterFlow, VacuumSuctionPower } from './default.js';
1
+ import { CleanModeSetting, CleanSetting, MopRoute, MopWaterFlow, VacuumSuctionPower } from './default.js';
2
2
 
3
- export function getCurrentCleanModeDefault(setting: { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number | undefined }): number | undefined {
3
+ export function getCurrentCleanModeDefault(setting: CleanModeSetting): number | undefined {
4
4
  if (!setting || typeof setting !== 'object') {
5
5
  return undefined;
6
6
  }
@@ -1,7 +1,8 @@
1
+ import { CleanModeSetting } from '../default/default.js';
1
2
  import { getCurrentCleanModeDefault } from '../default/runtimes.js';
2
3
  import { MopRouteSmart, MopWaterFlowSmart, VacuumSuctionPowerSmart } from './smart.js';
3
4
 
4
- export function getCurrentCleanModeSmart(setting: { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number | undefined }): number | undefined {
5
+ export function getCurrentCleanModeSmart(setting: CleanModeSetting): number | undefined {
5
6
  if (!setting || typeof setting !== 'object') {
6
7
  return undefined;
7
8
  }
@@ -3,7 +3,7 @@ import { AnsiLogger, debugStringify } from 'matterbridge/logger';
3
3
  import { BehaviorDeviceGeneric, BehaviorRoborock, DeviceCommands } from '../../BehaviorDeviceGeneric.js';
4
4
  import RoborockService from '../../../roborockService.js';
5
5
  import { CleanModeSettings } from '../../../model/ExperimentalFeatureSetting.js';
6
- import { RvcCleanMode as DefaultRvcCleanMode, CleanSetting as DefaultCleanSetting, getSettingFromCleanMode, RvcRunMode } from '../default/default.js';
6
+ import { RvcCleanMode as DefaultRvcCleanMode, CleanSetting as DefaultCleanSetting, getSettingFromCleanMode, RvcRunMode, CleanModeSetting } from '../default/default.js';
7
7
 
8
8
  export interface EndpointCommandsSmart extends DeviceCommands {
9
9
  selectAreas: (newAreas: number[] | undefined) => MaybePromise;
@@ -61,7 +61,7 @@ export const RvcCleanMode: Record<number, string> = {
61
61
  };
62
62
 
63
63
  // { suctionPower: [ 102 ], waterFlow: 200, distance_off: 0, mopRoute: [ 102 ] }
64
- export const CleanSetting: Record<number, { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number }> = {
64
+ export const CleanSetting: Record<number, CleanModeSetting> = {
65
65
  [4]: { suctionPower: 0, waterFlow: 0, distance_off: 0, mopRoute: MopRouteSmart.Smart }, // 'Smart Plan'
66
66
  ...DefaultCleanSetting,
67
67
  };
@@ -5,12 +5,13 @@ import { Room } from '../roborockCommunication/Zmodel/room.js';
5
5
  import { randomInt } from 'node:crypto';
6
6
  import { RoomIndexMap } from '../model/roomIndexMap.js';
7
7
 
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
+ export interface SupportedAreasResult {
9
+ supportedAreas: ServiceArea.Area[];
10
+ supportedMaps: ServiceArea.Map[];
11
+ roomIndexMap: RoomIndexMap;
12
+ }
13
+
14
+ export function getSupportedAreas(vacuumRooms: Room[], roomMap: RoomMap | undefined, enableMultipleMap = false, log?: AnsiLogger): SupportedAreasResult {
14
15
  log?.debug('getSupportedAreas-vacuum room', debugStringify(vacuumRooms));
15
16
  log?.debug('getSupportedAreas-roomMap', roomMap ? debugStringify(roomMap) : 'undefined');
16
17
 
@@ -80,9 +81,14 @@ export function getSupportedAreas(
80
81
  };
81
82
  }
82
83
 
84
+ interface SupportedArea {
85
+ areaId: number;
86
+ mapId: number;
87
+ }
88
+
83
89
  function findDuplicatedAreaIds(areas: ServiceArea.Area[], log?: AnsiLogger): boolean {
84
90
  const seen = new Set<string>();
85
- const duplicates: { areaId: number; mapId: number }[] = [];
91
+ const duplicates: SupportedArea[] = [];
86
92
 
87
93
  for (const area of areas) {
88
94
  const key = `${area.areaId}=${area.mapId}`;
@@ -101,12 +107,18 @@ function findDuplicatedAreaIds(areas: ServiceArea.Area[], log?: AnsiLogger): boo
101
107
  return duplicates.length > 0;
102
108
  }
103
109
 
104
- function processValidData(
105
- enableMultipleMap: boolean,
106
- vacuumRooms: Room[],
107
- roomMap?: RoomMap,
108
- ): { supportedAreas: ServiceArea.Area[]; indexMap: Map<number, { roomId: number; mapId: number | null }> } {
109
- const indexMap = new Map<number, { roomId: number; mapId: number | null }>();
110
+ export interface MapInfo {
111
+ roomId: number;
112
+ mapId: number | null;
113
+ }
114
+
115
+ interface ProcessedData {
116
+ supportedAreas: ServiceArea.Area[];
117
+ indexMap: Map<number, MapInfo>;
118
+ }
119
+
120
+ function processValidData(enableMultipleMap: boolean, vacuumRooms: Room[], roomMap?: RoomMap): ProcessedData {
121
+ const indexMap = new Map<number, MapInfo>();
110
122
  const supportedAreas: ServiceArea.Area[] =
111
123
  roomMap?.rooms !== undefined && roomMap.rooms.length > 0
112
124
  ? roomMap.rooms.map((room, index) => {
@@ -1,13 +1,11 @@
1
1
  import { CloudMessageResult } from '../roborockCommunication/Zmodel/messageResult.js';
2
2
 
3
+ interface CloudMessageDpsEntry {
4
+ id: number;
5
+ result: CloudMessageResult[];
6
+ }
7
+
3
8
  export interface CloudMessageModel {
4
9
  duid: string;
5
- dps: Record<
6
- string,
7
- | number
8
- | {
9
- id: number;
10
- result: CloudMessageResult[];
11
- }
12
- >;
10
+ dps: Record<string, number | CloudMessageDpsEntry>;
13
11
  }
@@ -1,34 +1,42 @@
1
+ export interface AdvancedFeature {
2
+ showRoutinesAsRoom: boolean;
3
+ includeDockStationStatus: boolean;
4
+ forceRunAtDefault: boolean;
5
+ useVacationModeToSendVacuumToDock: boolean;
6
+ enableServerMode: boolean;
7
+ alwaysExecuteAuthentication: boolean;
8
+ enableMultipleMap: boolean;
9
+ }
10
+
1
11
  export interface ExperimentalFeatureSetting {
2
12
  enableExperimentalFeature: boolean;
3
- advancedFeature: {
4
- showRoutinesAsRoom: boolean;
5
- includeDockStationStatus: boolean;
6
- forceRunAtDefault: boolean;
7
- useVacationModeToSendVacuumToDock: boolean;
8
- enableServerMode: boolean;
9
- alwaysExecuteAuthentication: boolean;
10
- enableMultipleMap: boolean;
11
- };
13
+ advancedFeature: AdvancedFeature;
12
14
  cleanModeSettings: CleanModeSettings;
13
15
  }
14
16
 
17
+ interface VacuumingCleanModeSetting {
18
+ fanMode: 'Balanced' | string;
19
+ mopRouteMode: 'Standard' | string;
20
+ }
21
+
22
+ interface MoppingCleanModeSetting {
23
+ waterFlowMode: 'Medium' | string;
24
+ mopRouteMode: 'Standard' | string;
25
+ distanceOff?: number;
26
+ }
27
+
28
+ interface VacMopCleanModeSetting {
29
+ fanMode: 'Balanced' | string;
30
+ waterFlowMode: 'Medium' | string;
31
+ mopRouteMode: 'Standard' | string;
32
+ distanceOff?: number;
33
+ }
34
+
15
35
  export interface CleanModeSettings {
16
36
  enableCleanModeMapping: boolean;
17
- vacuuming?: {
18
- fanMode: 'Balanced' | string;
19
- mopRouteMode: 'Standard' | string;
20
- };
21
- mopping?: {
22
- waterFlowMode: 'Medium' | string;
23
- mopRouteMode: 'Standard' | string;
24
- distanceOff?: number;
25
- };
26
- vacmop?: {
27
- fanMode: 'Balanced' | string;
28
- waterFlowMode: 'Medium' | string;
29
- mopRouteMode: 'Standard' | string;
30
- distanceOff?: number;
31
- };
37
+ vacuuming?: VacuumingCleanModeSetting;
38
+ mopping?: MoppingCleanModeSetting;
39
+ vacmop?: VacMopCleanModeSetting;
32
40
  }
33
41
 
34
42
  export function createDefaultExperimentalFeatureSetting(): ExperimentalFeatureSetting {
@@ -1,12 +1,14 @@
1
+ import { MapInfo } from '../initialData/getSupportedAreas.js';
2
+
1
3
  export class RoomIndexMap {
2
- public indexMap: Map<number, { roomId: number; mapId: number | null }>;
4
+ public indexMap: Map<number, MapInfo>;
3
5
  public roomMap: Map<string, number>;
4
6
 
5
- constructor(roomMap: Map<number, { roomId: number; mapId: number | null }>) {
7
+ constructor(roomMap: Map<number, MapInfo>) {
6
8
  this.indexMap = roomMap;
7
9
  this.roomMap = new Map();
8
- for (const [areaId, { roomId, mapId }] of roomMap.entries()) {
9
- this.roomMap.set(`${roomId}:${mapId}`, areaId);
10
+ for (const [areaId, r] of roomMap.entries()) {
11
+ this.roomMap.set(`${r.roomId}:${r.mapId}`, areaId);
10
12
  }
11
13
  }
12
14
 
package/src/platform.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Matterbridge, MatterbridgeDynamicPlatform, PlatformConfig } from 'matterbridge';
1
+ import { PlatformMatterbridge, MatterbridgeDynamicPlatform, PlatformConfig } from 'matterbridge';
2
2
  import * as axios from 'axios';
3
3
  import { AnsiLogger, debugStringify, LogLevel } from 'matterbridge/logger';
4
4
  import RoborockService from './roborockService.js';
@@ -29,13 +29,13 @@ export class RoborockMatterbridgePlatform extends MatterbridgeDynamicPlatform {
29
29
  persist: NodePersist.LocalStorage;
30
30
  rrHomeId: number | undefined;
31
31
 
32
- constructor(matterbridge: Matterbridge, log: AnsiLogger, config: PlatformConfig) {
32
+ constructor(matterbridge: PlatformMatterbridge, log: AnsiLogger, config: PlatformConfig) {
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.2.2')) {
36
+ if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.3.6')) {
37
37
  throw new Error(
38
- `This plugin requires Matterbridge version >= "3.2.2". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version in the frontend.`,
38
+ `This plugin requires Matterbridge version >= "3.3.6". 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);
@@ -11,4 +11,6 @@ export interface DeviceErrorMessage {
11
11
  errorCode: VacuumErrorCode;
12
12
  }
13
13
 
14
- export type DeviceStatusNotify = { duid: string } & DeviceStatus & CloudMessageResult;
14
+ export interface DeviceStatusNotify extends DeviceStatus, CloudMessageResult {
15
+ duid: string;
16
+ }
@@ -3,6 +3,22 @@ import { Room } from './room.js';
3
3
  import { Scene } from './scene.js';
4
4
  import { UserData } from './userData.js';
5
5
 
6
+ export interface DeviceData {
7
+ id: string;
8
+ firmwareVersion: string;
9
+ serialNumber: string;
10
+ model: string;
11
+ category: string;
12
+ batteryLevel: number;
13
+ }
14
+
15
+ interface DeviceInformation {
16
+ userData: UserData;
17
+ localKey: string;
18
+ pv: string;
19
+ model?: string;
20
+ }
21
+
6
22
  export interface Device {
7
23
  duid: string;
8
24
  name: string;
@@ -15,40 +31,20 @@ export interface Device {
15
31
 
16
32
  activeTime: number;
17
33
  createTime: number;
18
-
19
34
  localKey: string;
20
35
 
21
36
  /** The protocol version of the robot. */
22
37
  pv: string;
23
38
  online: boolean;
24
-
25
39
  productId: string;
26
-
27
40
  rrHomeId: number;
28
-
29
41
  /** The firmware version of the robot. */
30
42
  fv: string;
31
43
 
32
44
  deviceStatus: Record<string, number>;
33
45
  rooms: Room[];
34
-
35
46
  schema: DeviceSchema[];
36
-
37
- data: {
38
- id: string;
39
- firmwareVersion: string;
40
- serialNumber: string;
41
- model: string;
42
- category: string;
43
- batteryLevel: number;
44
- };
45
-
46
- store?: {
47
- userData: UserData;
48
- localKey: string;
49
- pv: string;
50
- model?: string;
51
- };
52
-
47
+ data: DeviceData;
48
+ store?: DeviceInformation;
53
49
  scenes?: Scene[];
54
50
  }
@@ -1,10 +1,15 @@
1
+ interface MapBackupInformation {
2
+ mapFlag: number;
3
+ add_time: number;
4
+ }
5
+
1
6
  export interface MapInformation {
2
7
  mapFlag: number;
3
8
  add_time: number;
4
9
  length: number;
5
10
  name: string;
6
11
  rooms?: RoomInformation[] | undefined;
7
- bak_maps: { mapFlag: number; add_time: number }[];
12
+ bak_maps: MapBackupInformation[];
8
13
  }
9
14
 
10
15
  export interface RoomInformation {
@@ -54,17 +54,19 @@ export interface CloudMessageResult {
54
54
  repeat?: number;
55
55
  kct?: number;
56
56
  subdivision_sets?: number;
57
- cleaning_info?: {
58
- target_segment_id: number;
59
- segment_id: number;
60
- fan_power: number;
61
- water_box_status: number;
62
- mop_mode: number;
63
- };
57
+ cleaning_info?: CleanInformation;
64
58
  exit_dock?: number;
65
59
  seq_type?: number;
66
60
  }
67
61
 
62
+ interface CleanInformation {
63
+ target_segment_id: number;
64
+ segment_id: number;
65
+ fan_power: number;
66
+ water_box_status: number;
67
+ mop_mode: number;
68
+ }
69
+
68
70
  export enum CarpetCleanMode {
69
71
  Avoid = 0,
70
72
  Ignore = 2,
@@ -1,8 +1,13 @@
1
1
  import decodeComponent from '../helper/nameDecoder.js';
2
2
  import { Room } from './room.js';
3
3
 
4
+ interface RoomEntry {
5
+ id: number;
6
+ name: string | undefined;
7
+ }
8
+
4
9
  export class RoomInfo {
5
- readonly rooms: { id: number; name: string | undefined }[] = [];
10
+ readonly rooms: RoomEntry[] = [];
6
11
 
7
12
  constructor(roomInfo: Room[], roomData: number[][]) {
8
13
  this.rooms = roomData
@@ -7,12 +7,14 @@ export class Scene {
7
7
  type: string | undefined;
8
8
  }
9
9
 
10
+ interface ActionInformation {
11
+ type: string;
12
+ items: SceneItem[];
13
+ }
14
+
10
15
  export interface SceneParam {
11
16
  triggers: unknown[];
12
- action: {
13
- type: string;
14
- items: SceneItem[];
15
- };
17
+ action: ActionInformation;
16
18
  matchType: string;
17
19
  }
18
20
 
@@ -10,15 +10,17 @@ export interface UserData {
10
10
  rriot: Rriot;
11
11
  }
12
12
 
13
+ interface r {
14
+ r: string;
15
+ a: string;
16
+ m: string;
17
+ l: string;
18
+ }
19
+
13
20
  export interface Rriot {
14
21
  u: string;
15
22
  s: string;
16
23
  h: string;
17
24
  k: string;
18
- r: {
19
- r: string;
20
- a: string;
21
- m: string;
22
- l: string;
23
- };
25
+ r: r;
24
26
  }
@@ -6,6 +6,7 @@ import { RequestMessage } from './model/requestMessage.js';
6
6
  import { DeviceStatus } from '../Zmodel/deviceStatus.js';
7
7
  import { Client } from './client.js';
8
8
  import { NetworkInfo } from '../Zmodel/networkInfo.js';
9
+ import { CleanModeSetting } from '../../behaviors/roborock.vacuum/default/default.js';
9
10
 
10
11
  export class MessageProcessor {
11
12
  private readonly client: Client;
@@ -108,7 +109,7 @@ export class MessageProcessor {
108
109
  return this.client.get(duid, request);
109
110
  }
110
111
 
111
- public async getCleanModeData(duid: string): Promise<{ suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number }> {
112
+ public async getCleanModeData(duid: string): Promise<CleanModeSetting> {
112
113
  const currentMopMode = await this.getCustomMessage(duid, new RequestMessage({ method: 'get_mop_mode' }));
113
114
  const suctionPowerRaw = await this.getCustomMessage(duid, new RequestMessage({ method: 'get_custom_mode' }));
114
115
  const waterFlowRaw = await this.getCustomMessage(duid, new RequestMessage({ method: 'get_water_box_custom_mode' }));
@@ -145,7 +146,7 @@ export class MessageProcessor {
145
146
  waterFlow: waterFlow,
146
147
  distance_off: distance_off,
147
148
  mopRoute: mopRoute,
148
- };
149
+ } satisfies CleanModeSetting;
149
150
  }
150
151
 
151
152
  public async changeCleanMode(duid: string, suctionPower: number, waterFlow: number, mopRoute: number, distance_off: number): Promise<void> {
@@ -1,11 +1,13 @@
1
+ interface Security {
2
+ endpoint: string;
3
+ nonce: string;
4
+ }
5
+
1
6
  export interface DpsPayload {
2
7
  id: number;
3
8
  method?: string;
4
9
  params?: unknown[] | Record<string, unknown> | undefined;
5
- security?: {
6
- endpoint: string;
7
- nonce: string;
8
- };
10
+ security?: Security;
9
11
  result: unknown;
10
12
  }
11
13
 
@@ -2,9 +2,15 @@ import { randomBytes, randomInt } from 'node:crypto';
2
2
  import * as CryptoUtils from '../../helper/cryptoHelper.js';
3
3
  import { UserData } from '../../Zmodel/userData.js';
4
4
 
5
+ interface DeviceInfo {
6
+ localKey: string;
7
+ protocolVersion: string;
8
+ nonce: number | undefined;
9
+ }
10
+
5
11
  export class MessageContext {
6
12
  private readonly endpoint: string;
7
- private readonly devices = new Map<string, { localKey: string; protocolVersion: string; nonce: number | undefined }>();
13
+ private readonly devices = new Map<string, DeviceInfo>();
8
14
  public readonly nonce: number;
9
15
  public readonly serializeNonce: Buffer;
10
16
 
@@ -7,6 +7,11 @@ import { MessageContext } from '../broadcast/model/messageContext.js';
7
7
  import { AnsiLogger } from 'matterbridge/logger';
8
8
  import { Protocol } from '../broadcast/model/protocol.js';
9
9
 
10
+ interface SerializeResult {
11
+ messageId: number;
12
+ buffer: Buffer<ArrayBufferLike>;
13
+ }
14
+
10
15
  export class MessageSerializer {
11
16
  private readonly context: MessageContext;
12
17
  private readonly logger: AnsiLogger;
@@ -18,7 +23,7 @@ export class MessageSerializer {
18
23
  this.logger = logger;
19
24
  }
20
25
 
21
- public serialize(duid: string, request: RequestMessage): { messageId: number; buffer: Buffer<ArrayBufferLike> } {
26
+ public serialize(duid: string, request: RequestMessage): SerializeResult {
22
27
  const messageId = request.messageId;
23
28
  const buffer = this.buildBuffer(duid, messageId, request);
24
29
  return { messageId: messageId, buffer: buffer };
@@ -26,8 +26,17 @@ import { ServiceArea } from 'matterbridge/matter/clusters';
26
26
  import { LocalNetworkClient } from './roborockCommunication/broadcast/client/LocalNetworkClient.js';
27
27
  import { RoomIndexMap } from './model/roomIndexMap.js';
28
28
  import { DpsPayload } from './roborockCommunication/broadcast/model/dps.js';
29
+ import { CleanModeSetting } from './behaviors/roborock.vacuum/default/default.js';
29
30
  export type Factory<A, T> = (logger: AnsiLogger, arg: A) => T;
30
31
 
32
+ interface MapRoomResponse {
33
+ vacuumRoom?: number;
34
+ }
35
+
36
+ interface Security {
37
+ nonce: number;
38
+ }
39
+
31
40
  export default class RoborockService {
32
41
  private loginApi: RoborockAuthenticateApi;
33
42
  private logger: AnsiLogger;
@@ -130,7 +139,7 @@ export default class RoborockService {
130
139
  return this.supportedAreaIndexMaps.get(duid);
131
140
  }
132
141
 
133
- public async getCleanModeData(duid: string): Promise<{ suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number }> {
142
+ public async getCleanModeData(duid: string): Promise<CleanModeSetting> {
134
143
  this.logger.notice('RoborockService - getCleanModeData');
135
144
  const data = await this.getMessageProcessor(duid)?.getCleanModeData(duid);
136
145
  if (!data) {
@@ -140,7 +149,7 @@ export default class RoborockService {
140
149
  }
141
150
 
142
151
  public async getRoomIdFromMap(duid: string): Promise<number | undefined> {
143
- const data = (await this.customGet(duid, new RequestMessage({ method: 'get_map_v1' }))) as { vacuumRoom?: number };
152
+ const data = (await this.customGet(duid, new RequestMessage({ method: 'get_map_v1' }))) as MapRoomResponse;
144
153
  return data?.vacuumRoom;
145
154
  }
146
155
 
@@ -153,12 +162,9 @@ export default class RoborockService {
153
162
  });
154
163
  }
155
164
 
156
- public async changeCleanMode(
157
- duid: string,
158
- { suctionPower, waterFlow, distance_off, mopRoute }: { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number },
159
- ): Promise<void> {
165
+ public async changeCleanMode(duid: string, { suctionPower, waterFlow, distance_off, mopRoute }: CleanModeSetting): Promise<void> {
160
166
  this.logger.notice('RoborockService - changeCleanMode');
161
- return this.getMessageProcessor(duid)?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute, distance_off);
167
+ return this.getMessageProcessor(duid)?.changeCleanMode(duid, suctionPower, waterFlow, mopRoute ?? 0, distance_off);
162
168
  }
163
169
 
164
170
  public async startClean(duid: string): Promise<void> {
@@ -497,7 +503,7 @@ export default class RoborockService {
497
503
 
498
504
  if (message instanceof ResponseMessage && message.contain(Protocol.hello_response)) {
499
505
  const dps = message.dps[Protocol.hello_response] as DpsPayload;
500
- const result = dps.result as { nonce: number };
506
+ const result = dps.result as Security;
501
507
  self.messageClient?.updateNonce(message.duid, result.nonce);
502
508
  }
503
509
  },
package/src/rvc.ts CHANGED
@@ -8,6 +8,10 @@ import { ModeBase, RvcOperationalState, ServiceArea } from 'matterbridge/matter/
8
8
  import { ExperimentalFeatureSetting } from './model/ExperimentalFeatureSetting.js';
9
9
  import { DockingStationStatus } from './model/DockingStationStatus.js';
10
10
 
11
+ interface IdentifyCommandRequest {
12
+ identifyTime?: number;
13
+ }
14
+
11
15
  export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
12
16
  username: string | undefined;
13
17
  device: Device;
@@ -64,7 +68,7 @@ export class RoborockVacuumCleaner extends RoboticVacuumCleaner {
64
68
  public configurateHandler(behaviorHandler: BehaviorFactoryResult): void {
65
69
  this.addCommandHandler('identify', async ({ request, cluster, attributes, endpoint }) => {
66
70
  this.log.info(`Identify command received for endpoint ${endpoint}, cluster ${cluster}, attributes ${debugStringify(attributes)}, request: ${JSON.stringify(request)}`);
67
- behaviorHandler.executeCommand('playSoundToLocate', (request as { identifyTime?: number }).identifyTime ?? 0);
71
+ behaviorHandler.executeCommand('playSoundToLocate', (request as IdentifyCommandRequest).identifyTime ?? 0);
68
72
  });
69
73
 
70
74
  this.addCommandHandler('selectAreas', async ({ request }) => {
@@ -1,8 +1,9 @@
1
+ import { CleanModeSetting } from '../behaviors/roborock.vacuum/default/default.js';
1
2
  import { getCurrentCleanModeDefault } from '../behaviors/roborock.vacuum/default/runtimes.js';
2
3
  import { getCurrentCleanModeSmart } from '../behaviors/roborock.vacuum/smart/runtimes.js';
3
4
  import { DeviceModel } from '../roborockCommunication/Zmodel/deviceModel.js';
4
5
 
5
- export type CleanModeFunc = (setting: { suctionPower: number; waterFlow: number; distance_off: number; mopRoute: number | undefined }) => number | undefined;
6
+ export type CleanModeFunc = (setting: CleanModeSetting) => number | undefined;
6
7
 
7
8
  export function getCurrentCleanModeFunc(model: string, forceRunAtDefault: boolean): CleanModeFunc {
8
9
  if (forceRunAtDefault) {
@@ -1,3 +1,4 @@
1
+ import { DeviceData } from '../../roborockCommunication/Zmodel/device';
1
2
  import { updateFromHomeData } from '../../runtimes/handleHomeDataMessage';
2
3
  import { homeData } from '../testData/mockData';
3
4
  import { PowerSource, RvcRunMode } from 'matterbridge/matter/clusters';
@@ -7,7 +8,7 @@ const mockUpdateAttribute = jest.fn();
7
8
  const duid = 'test-duid';
8
9
  const robot = {
9
10
  updateAttribute: mockUpdateAttribute,
10
- device: { data: { model: 'test-model' } as { model: string } | undefined },
11
+ device: { data: { model: 'test-model' } as DeviceData | undefined },
11
12
  dockStationStatus: {},
12
13
  };
13
14
  const platform = {
@@ -196,7 +196,7 @@ describe('handleLocalMessage -- FF OFF', () => {
196
196
  [4, 4],
197
197
  ]),
198
198
 
199
- getAreaId(roomId: number): { roomId: number; mapId: number } | undefined {
199
+ getAreaId(roomId: number): Area | undefined {
200
200
  const index = this.roomMap.get(roomId);
201
201
  if (index === undefined) {
202
202
  return undefined;
@@ -220,3 +220,8 @@ describe('handleLocalMessage -- FF OFF', () => {
220
220
  expect(mockUpdateAttribute).toHaveBeenCalledWith(ServiceArea.Cluster.id, 'currentArea', 4, mockLog);
221
221
  });
222
222
  });
223
+
224
+ interface Area {
225
+ roomId: number;
226
+ mapId: number;
227
+ }