homebridge-roborock-vacuum2 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +65 -0
  4. package/ROADMAP.md +28 -0
  5. package/config.schema.json +48 -0
  6. package/dist/crypto.js +62 -0
  7. package/dist/crypto.js.map +1 -0
  8. package/dist/index.js +10 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/logger.js +39 -0
  11. package/dist/logger.js.map +1 -0
  12. package/dist/platform.js +221 -0
  13. package/dist/platform.js.map +1 -0
  14. package/dist/settings.js +8 -0
  15. package/dist/settings.js.map +1 -0
  16. package/dist/types.js +3 -0
  17. package/dist/types.js.map +1 -0
  18. package/dist/ui/index.js +311 -0
  19. package/dist/ui/index.js.map +1 -0
  20. package/dist/vacuum_accessory.js +262 -0
  21. package/dist/vacuum_accessory.js.map +1 -0
  22. package/homebridge-roborock-vacuum.code-workspace +7 -0
  23. package/homebridge-ui/public/index.html +72 -0
  24. package/homebridge-ui/public/index.js +344 -0
  25. package/homebridge-ui/public/styles.css +275 -0
  26. package/homebridge-ui/server.js +3 -0
  27. package/package.json +67 -0
  28. package/roborockLib/data/roborock.clientID +4 -0
  29. package/roborockLib/i18n/de/translations.json +188 -0
  30. package/roborockLib/i18n/en/translations.json +208 -0
  31. package/roborockLib/i18n/es/translations.json +188 -0
  32. package/roborockLib/i18n/fr/translations.json +188 -0
  33. package/roborockLib/i18n/it/translations.json +188 -0
  34. package/roborockLib/i18n/nl/translations.json +188 -0
  35. package/roborockLib/i18n/pl/translations.json +188 -0
  36. package/roborockLib/i18n/pt/translations.json +188 -0
  37. package/roborockLib/i18n/ru/translations.json +188 -0
  38. package/roborockLib/i18n/uk/translations.json +188 -0
  39. package/roborockLib/i18n/zh-cn/translations.json +188 -0
  40. package/roborockLib/lib/RRMapParser.js +447 -0
  41. package/roborockLib/lib/deviceFeatures.js +1222 -0
  42. package/roborockLib/lib/localConnector.js +390 -0
  43. package/roborockLib/lib/map/map.html +110 -0
  44. package/roborockLib/lib/map/zones.js +713 -0
  45. package/roborockLib/lib/message.js +434 -0
  46. package/roborockLib/lib/messageQueueHandler.js +97 -0
  47. package/roborockLib/lib/roborockAuth.js +147 -0
  48. package/roborockLib/lib/roborockPackageHelper.js +116 -0
  49. package/roborockLib/lib/roborock_mqtt_connector.js +474 -0
  50. package/roborockLib/lib/sniffing/mitmproxy_roborock.py +300 -0
  51. package/roborockLib/lib/vacuum.js +542 -0
  52. package/roborockLib/roborockAPI.js +1964 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## 1.2.2
4
+ - **New Feature**: Dynamic Scene Switch Management
5
+ - Automatically create HomeKit switch buttons for each device's available scenes
6
+ - Scene switches named after scene names with momentary switch behavior
7
+ - Automatically add/remove corresponding switch buttons when scenes change
8
+ - Execute corresponding scenes when switches are pressed, with error handling and status feedback
9
+ - Synchronize scene switches when HomeData is updated
10
+ - **Improvement**: Refactored scene API methods, separated scene fetching and device filtering functionality
11
+ - **Fix**: Resolved recursive call issue in scene methods
12
+
13
+ ## 1.0.15
14
+ - Fix Roborock Saros 10R Status issue
15
+
16
+ ## 1.0.6
17
+ - Support new model
18
+
19
+ ## 1.0.0
20
+
21
+ - First version.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018-2019 Nico Hartung
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # homebridge-roborock-vacuum
2
+
3
+ ![Roborock Vacuum in Home App](https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/40/21/71/40217177-c879-f670-bd01-c93acfabc31e/AppIcon-0-0-1x_U007emarketing-0-8-0-85-220.png/460x0w.webp)
4
+
5
+ A Homebridge plugin to integrate your Roborock vacuum cleaner with Apple HomeKit, allowing you to control it via the Home app and Siri.
6
+
7
+ ## Introduction
8
+
9
+ `homebridge-roborock-vacuum` brings your Roborock vacuum cleaner into Apple HomeKit. Using your Roborock app account credentials, this plugin automatically detects your vacuum, enabling you to control it directly from the Home app on your iPhone, iPad, or Mac, or with Siri voice commands.
10
+
11
+ This plugin is inspired by and adapted from the [ioBroker.roborock](https://github.com/copystring/ioBroker.roborock) project by copystring.
12
+
13
+ ## Features
14
+
15
+ - **Automatic Device Detection**: No need to manually find or enter your vacuum's device ID.
16
+ - **Start/Stop Cleaning**: Begin or end cleaning sessions.
17
+
18
+ ## The supported robots are:
19
+
20
+ Roborock S4
21
+ Roborock S4 Max
22
+ Roborock S5 Max
23
+ Roborock S6
24
+ Roborock S6 Pure
25
+ Roborock S6 MaxV
26
+ Roborock S7
27
+ Roborock S7 MaxV (Ultra)
28
+ Roborock Q7
29
+ Roborock Q7 Max
30
+ Roborock S7 Pro Ultra
31
+ Roborock S7 Max Ultra
32
+ Roborock S8
33
+ Roborock S8 Pro Ultra
34
+ Roborock Q Revo
35
+ Roborock Q8 Max
36
+ Roborock Q5 Pro
37
+ Roborock Q Revo Pro
38
+ Roborock Qrevo S
39
+ Roborock Qrevo Curve
40
+ Roborock Saros 10
41
+ Roborock (roborock.vacuum.a95)
42
+ Roborock (roborock.vacuum.a159)
43
+ Roborock (roborock.vacuum.ss07)
44
+
45
+
46
+ ## Requirements
47
+
48
+ Before installing, ensure you have:
49
+
50
+ - A Roborock vacuum cleaner compatible with the Roborock app.
51
+ - A Roborock app account (email and password).
52
+ - [Homebridge](https://github.com/homebridge/homebridge) installed on a server (e.g., Raspberry Pi).
53
+ - Node.js and npm installed on your Homebridge server.
54
+
55
+ ## Installation
56
+
57
+ Follow these steps to install the plugin:
58
+
59
+ 1. **Install Homebridge** (if not already installed):
60
+ - Refer to the official [Homebridge installation guide](https://github.com/homebridge/homebridge#installation).
61
+
62
+ 2. **Install the Plugin**:
63
+ - Open a terminal and run:
64
+ ```bash
65
+ npm install -g homebridge-roborock-vacuum
package/ROADMAP.md ADDED
@@ -0,0 +1,28 @@
1
+ # Homebridge Roborock Vacuum 2 Roadmap
2
+
3
+ ## Worth Doing Now
4
+
5
+ - Add diagnostics for model resolution, `localKey` presence, and local-vs-cloud readiness in the admin UI.
6
+ - Persist enough discovery data to inspect failures after startup.
7
+ - Harden model lookup so new Roborock API shapes do not immediately become `unknown`.
8
+ - Add targeted tests around discovery parsing, payload normalization, and command transport fallback.
9
+ - Keep CI validating both Homebridge `1.11.x` and `2.0.0-beta`.
10
+
11
+ ## Worth Doing Soon
12
+
13
+ - Add an explicit per-device transport status view that shows `local`, `cloud fallback`, or `unknown`.
14
+ - Add clearer logs for `localKey` missing, model lookup mismatches, and unsupported attributes.
15
+ - Improve support for recently reported models such as Saros 10, Q5 Max+, QX Revo Plus, and Q10 S5+.
16
+ - Reduce brittle model-specific switches by moving feature detection toward schema/capability-based logic.
17
+
18
+ ## Worth Evaluating Carefully
19
+
20
+ - Optional manual overrides for model mapping when Roborock metadata is incomplete.
21
+ - Manual local-IP diagnostics or reconnect tools in the UI.
22
+ - A small telemetry/debug export for users opening issue reports.
23
+
24
+ ## Probably Not Worth It
25
+
26
+ - Rewriting the transport stack from scratch.
27
+ - Fork-only divergence without tests or observability.
28
+ - Large UI redesign before operational visibility is in place.
@@ -0,0 +1,48 @@
1
+ {
2
+ "pluginAlias": "RoborockVacuumPlatform",
3
+ "pluginType": "platform",
4
+ "singular": true,
5
+ "customUi": true,
6
+ "customUiPath": "./homebridge-ui",
7
+ "schema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "email": {
11
+ "title": "Email",
12
+ "type": "string",
13
+ "format": "email",
14
+ "description": "Roborock account email"
15
+ },
16
+ "password": {
17
+ "title": "Password",
18
+ "type": "string",
19
+ "placeholder": "Password",
20
+ "description": "Roborock account password"
21
+ },
22
+ "encryptedToken": {
23
+ "title": "Encrypted Token",
24
+ "type": "string",
25
+ "description": "Encrypted Roborock session data (managed by the UI)",
26
+ "readOnly": true
27
+ },
28
+ "skipDevices": {
29
+ "title": "Skip Devices",
30
+ "type": "string",
31
+ "description": "Comma-separated device IDs to skip"
32
+ },
33
+ "baseURL": {
34
+ "type": "string",
35
+ "default": "https://usiot.roborock.com",
36
+ "description": "Roborock API endpoint: https://usiot.roborock.com (US), https://euiot.roborock.com (EU), https://cniot.roborock.com (CN), https://api.roborock.com (Asia)"
37
+ }
38
+ ,
39
+ "debugMode": {
40
+ "title": "Debug Mode",
41
+ "description": "When enabled, debug messages will be written to the log.",
42
+ "type": "boolean",
43
+ "default": false
44
+ }
45
+ },
46
+ "required": ["email"]
47
+ }
48
+ }
package/dist/crypto.js ADDED
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.encryptSession = encryptSession;
7
+ exports.decryptSession = decryptSession;
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const KEY_FILENAME = 'roborock.token.key';
12
+ function loadOrCreateKey(storagePath) {
13
+ const keyPath = path_1.default.join(storagePath, KEY_FILENAME);
14
+ try {
15
+ const existing = fs_1.default.readFileSync(keyPath);
16
+ if (existing.length === 32) {
17
+ return existing;
18
+ }
19
+ }
20
+ catch (error) {
21
+ // Ignore and create a new key.
22
+ }
23
+ const key = crypto_1.default.randomBytes(32);
24
+ fs_1.default.mkdirSync(storagePath, { recursive: true });
25
+ fs_1.default.writeFileSync(keyPath, key, { mode: 0o600 });
26
+ return key;
27
+ }
28
+ function encryptSession(session, storagePath) {
29
+ const key = loadOrCreateKey(storagePath);
30
+ const iv = crypto_1.default.randomBytes(12);
31
+ const cipher = crypto_1.default.createCipheriv('aes-256-gcm', key, iv);
32
+ const plaintext = Buffer.from(JSON.stringify(session), 'utf8');
33
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
34
+ const tag = cipher.getAuthTag();
35
+ const payload = {
36
+ iv: iv.toString('base64'),
37
+ tag: tag.toString('base64'),
38
+ data: ciphertext.toString('base64'),
39
+ };
40
+ return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64');
41
+ }
42
+ function decryptSession(encrypted, storagePath) {
43
+ if (!encrypted) {
44
+ return null;
45
+ }
46
+ try {
47
+ const key = loadOrCreateKey(storagePath);
48
+ const raw = Buffer.from(encrypted, 'base64').toString('utf8');
49
+ const payload = JSON.parse(raw);
50
+ const iv = Buffer.from(payload.iv, 'base64');
51
+ const tag = Buffer.from(payload.tag, 'base64');
52
+ const ciphertext = Buffer.from(payload.data, 'base64');
53
+ const decipher = crypto_1.default.createDecipheriv('aes-256-gcm', key, iv);
54
+ decipher.setAuthTag(tag);
55
+ const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('utf8');
56
+ return JSON.parse(plaintext);
57
+ }
58
+ catch (error) {
59
+ return null;
60
+ }
61
+ }
62
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const platform_1 = __importDefault(require("./platform"));
6
+ const settings_1 = require("./settings");
7
+ module.exports = (api) => {
8
+ api.registerPlatform(settings_1.PLATFORM_NAME, platform_1.default);
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AACA,0DAA0C;AAC1C,yCAA2C;AAK3C,iBAAS,CAAC,GAAQ,EAAE,EAAE;IACpB,GAAG,CAAC,gBAAgB,CAAC,wBAAa,EAAE,kBAAgB,CAAC,CAAC;AACxD,CAAC,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * Decorates the Homebridge logger to only log debug messages when debug mode is enabled.
5
+ */
6
+ class RoborockPlatformLogger {
7
+ constructor(logger, debugMode) {
8
+ this.logger = logger;
9
+ this.debugMode = debugMode;
10
+ }
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ debug(...messages) {
13
+ if (this.debugMode) {
14
+ for (let i = 0; i < messages.length; i++) {
15
+ this.logger.debug(messages[i]);
16
+ }
17
+ }
18
+ }
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ info(...messages) {
21
+ for (let i = 0; i < messages.length; i++) {
22
+ this.logger.info(messages[i]);
23
+ }
24
+ }
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ warn(...messages) {
27
+ for (let i = 0; i < messages.length; i++) {
28
+ this.logger.warn(messages[i]);
29
+ }
30
+ }
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ error(...messages) {
33
+ for (let i = 0; i < messages.length; i++) {
34
+ this.logger.error(messages[i]);
35
+ }
36
+ }
37
+ }
38
+ exports.default = RoborockPlatformLogger;
39
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;AAEA;;GAEG;AACH,MAAqB,sBAAsB;IACzC,YACmB,MAAc,EACd,SAAkB;QADlB,WAAM,GAAN,MAAM,CAAQ;QACd,cAAS,GAAT,SAAS,CAAS;IAClC,CAAC;IAEJ,8DAA8D;IAC9D,KAAK,CAAC,GAAG,QAAe;QACtB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,GAAG,QAAe;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,GAAG,QAAe;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IAEA,8DAA8D;IAC9D,KAAK,CAAC,GAAG,QAAe;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;CACF;AAnCD,yCAmCC"}
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const vacuum_accessory_1 = __importDefault(require("./vacuum_accessory"));
7
+ const logger_1 = __importDefault(require("./logger"));
8
+ const settings_1 = require("./settings");
9
+ const crypto_1 = require("./crypto");
10
+ const DEP0040_CODE = "DEP0040";
11
+ let dep0040FilterInstalled = false;
12
+ function installDeprecationWarningFilter() {
13
+ if (dep0040FilterInstalled) {
14
+ return;
15
+ }
16
+ dep0040FilterInstalled = true;
17
+ const originalEmitWarning = process.emitWarning.bind(process);
18
+ let dep0040Logged = false;
19
+ process.emitWarning = ((warning, type, code, ctor) => {
20
+ const warningCode = typeof warning === "object" && warning !== null && "code" in warning
21
+ ? String(warning.code)
22
+ : code;
23
+ if (warningCode === DEP0040_CODE) {
24
+ if (!dep0040Logged) {
25
+ dep0040Logged = true;
26
+ process.stderr.write("[Roborock Vacuum] Suppressed Node.js DEP0040 warning from upstream dependency.\n");
27
+ }
28
+ return;
29
+ }
30
+ originalEmitWarning(warning, type, code, ctor);
31
+ });
32
+ }
33
+ installDeprecationWarningFilter();
34
+ const Roborock = require("../roborockLib/roborockAPI").Roborock;
35
+ /**
36
+ * Roborock App Platform Plugin for Homebridge
37
+ * Based on https://github.com/homebridge/homebridge-plugin-template
38
+ */
39
+ class RoborockPlatform {
40
+ /**
41
+ * This constructor is where you should parse the user config
42
+ * and discover/register accessories with Homebridge.
43
+ *
44
+ * @param logger Homebridge logger
45
+ * @param config Homebridge platform config
46
+ * @param api Homebridge API
47
+ */
48
+ constructor(homebridgeLogger, config, api) {
49
+ this.api = api;
50
+ this.Service = this.api.hap.Service;
51
+ this.Characteristic = this.api.hap.Characteristic;
52
+ // Used to track restored cached accessories
53
+ this.accessories = [];
54
+ this.vacuums = [];
55
+ this.platformConfig = config;
56
+ // Initialise logging utility
57
+ this.log = new logger_1.default(homebridgeLogger, this.platformConfig.debugMode);
58
+ // Create Roborock App communication module
59
+ const username = this.platformConfig.email;
60
+ const password = this.platformConfig.password;
61
+ const baseURL = this.platformConfig.baseURL;
62
+ const debugMode = this.platformConfig.debugMode;
63
+ const storagePath = this.api.user.storagePath();
64
+ const decryptedSession = this.platformConfig.encryptedToken
65
+ ? (0, crypto_1.decryptSession)(this.platformConfig.encryptedToken, storagePath)
66
+ : null;
67
+ this.roborockAPI = new Roborock({
68
+ username: username,
69
+ password: password,
70
+ debug: debugMode,
71
+ baseURL: baseURL,
72
+ log: this.log,
73
+ userData: decryptedSession,
74
+ storagePath: storagePath,
75
+ });
76
+ /**
77
+ * When this event is fired it means Homebridge has restored all cached accessories from disk.
78
+ * Dynamic Platform plugins should only register new accessories after this event was fired,
79
+ * in order to ensure they weren't added to homebridge already. This event can also be used
80
+ * to start discovery of new accessories.
81
+ */
82
+ this.api.on("didFinishLaunching" /* APIEvent.DID_FINISH_LAUNCHING */, () => {
83
+ this.log.debug("Finished launching and restored cached accessories.");
84
+ this.configurePlugin();
85
+ });
86
+ this.api.on("shutdown" /* APIEvent.SHUTDOWN */, () => {
87
+ this.log.debug("Shutting down...");
88
+ if (this.roborockAPI) {
89
+ this.roborockAPI.stopService();
90
+ }
91
+ });
92
+ }
93
+ async configurePlugin() {
94
+ await this.loginAndDiscoverDevices();
95
+ }
96
+ async loginAndDiscoverDevices() {
97
+ if (!this.platformConfig.email) {
98
+ this.log.error("Email is not configured - aborting plugin start. " +
99
+ "Please set the field `email` in your config and restart Homebridge.");
100
+ return;
101
+ }
102
+ if (!this.platformConfig.password && !this.platformConfig.encryptedToken) {
103
+ this.log.error("Password is not configured - aborting plugin start. " +
104
+ "Please set `password` or complete login in the Config UI.");
105
+ return;
106
+ }
107
+ const self = this;
108
+ self.roborockAPI.setDeviceNotify(function (id, homeData) {
109
+ self.log.debug(`${id} notifyDeviceUpdater:${JSON.stringify(homeData)}`);
110
+ for (const vacuum of self.vacuums) {
111
+ vacuum.notifyDeviceUpdater(id, homeData);
112
+ }
113
+ });
114
+ self.roborockAPI.startService(function () {
115
+ self.log.info("Service started");
116
+ //call the discoverDevices function
117
+ self.discoverDevices();
118
+ });
119
+ }
120
+ /**
121
+ * This function is invoked when Homebridge restores cached accessories from disk at startup.
122
+ * It should be used to set up event handlers for characteristics and update respective values.
123
+ */
124
+ configureAccessory(accessory) {
125
+ this.log.info(`Loading accessory '${accessory.displayName}' from cache.`);
126
+ // Store restored accessory in the cached accessories list
127
+ // remove duplicates accessories
128
+ try {
129
+ const existingAccessory = this.accessories.find((a) => a.UUID === accessory.UUID);
130
+ if (existingAccessory) {
131
+ this.log.info(`Removing duplicate accessory '${existingAccessory.displayName}' from cache.`);
132
+ this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [
133
+ existingAccessory,
134
+ ]);
135
+ }
136
+ }
137
+ catch (e) {
138
+ this.log.error("Error loading accessory from cache: " + e);
139
+ }
140
+ this.accessories.push(accessory);
141
+ }
142
+ isSupportedDevice(model) {
143
+ return typeof model === "string" && model.startsWith("roborock.vacuum.");
144
+ }
145
+ /**
146
+ * Fetches all of the user's devices from Roborock App and sets up handlers.
147
+ *
148
+ * Accessories must only be registered once. Previously created accessories
149
+ * must not be registered again to prevent "duplicate UUID" errors.
150
+ */
151
+ async discoverDevices() {
152
+ this.log.info("Discovering vacuum devices...");
153
+ try {
154
+ const self = this;
155
+ if (self.roborockAPI.isInited()) {
156
+ self.roborockAPI.getVacuumList().forEach(function (device) {
157
+ var duid = device.duid;
158
+ var name = device.name;
159
+ var model = self.roborockAPI.getProductAttribute(duid, "model");
160
+ if (!self.isSupportedDevice(model)) {
161
+ self.log.info(`Device '${name}' (${duid}) is not supported (model '${model || "unknown"}').`);
162
+ return;
163
+ }
164
+ const uuid = self.api.hap.uuid.generate(device.duid);
165
+ const existingAccessory = self.accessories.find((accessory) => accessory.UUID === uuid);
166
+ if (existingAccessory !== undefined) {
167
+ self.log.info(`Restoring accessory '${existingAccessory.displayName}' ` +
168
+ `(${uuid}) from cache.`);
169
+ // If you need to update the accessory.context then you should run
170
+ // `api.updatePlatformAccessories`. eg.:
171
+ existingAccessory.context = duid;
172
+ self.api.updatePlatformAccessories([existingAccessory]);
173
+ // Create the accessory handler for the restored accessory
174
+ self.createRoborockAccessory(existingAccessory);
175
+ }
176
+ else {
177
+ // The accessory already exists, so we need to create it
178
+ self.log.info(`Adding accessory '${name}' (${uuid}).`);
179
+ // The accessory does not yet exist, so we need to create it
180
+ const accessory = new self.api.platformAccessory(name, uuid);
181
+ // Store a copy of the device object in the `accessory.context` property,
182
+ // which can be used to store any data about the accessory you may need.
183
+ accessory.context = duid;
184
+ // Create the accessory handler for the newly create accessory
185
+ // this is imported from `platformAccessory.ts`
186
+ self.createRoborockAccessory(accessory);
187
+ // Link the accessory to your platform
188
+ self.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [
189
+ accessory,
190
+ ]);
191
+ }
192
+ });
193
+ }
194
+ // At this point, we set up all devices from Roborock App, but we did not unregister
195
+ // cached devices that do not exist on the Roborock App account anymore.
196
+ for (const cachedAccessory of this.accessories) {
197
+ if (cachedAccessory.context) {
198
+ const vacuum = self.roborockAPI.getVacuumDeviceData(cachedAccessory.context);
199
+ if (vacuum === undefined) {
200
+ // This cached devices does not exist on the Roborock App account (anymore).
201
+ this.log.info(`Removing accessory '${cachedAccessory.displayName}' (${cachedAccessory.context}) ` +
202
+ "because it does not exist on the Roborock account anymore.");
203
+ this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [
204
+ cachedAccessory,
205
+ ]);
206
+ }
207
+ }
208
+ }
209
+ }
210
+ catch (error) {
211
+ this.log.error("An error occurred during device discovery. " +
212
+ "Turn on debug mode for more information.");
213
+ this.log.debug(error);
214
+ }
215
+ }
216
+ createRoborockAccessory(accessory) {
217
+ this.vacuums.push(new vacuum_accessory_1.default(this, accessory));
218
+ }
219
+ }
220
+ exports.default = RoborockPlatform;
221
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLATFORM_NAME = exports.PLUGIN_NAME = void 0;
4
+ // Name of the plugin (must match the `name` of the package.json).
5
+ exports.PLUGIN_NAME = 'homebridge-roborock-vacuum';
6
+ // The platform the plugin creates (see config.json).
7
+ exports.PLATFORM_NAME = 'RoborockVacuumPlatform';
8
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":";;;AAAA,kEAAkE;AACrD,QAAA,WAAW,GAAG,4BAA4B,CAAC;AAExD,qDAAqD;AACxC,QAAA,aAAa,GAAG,wBAAwB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}