@homebridge-plugins/homebridge-sharkiq 2.0.0-beta.3 → 2.0.0-beta.30
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/CHANGELOG.md +19 -2
- package/README.md +41 -4
- package/config.schema.json +8 -26
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/devices/BaseMatterAccessory.d.ts +74 -0
- package/dist/devices/BaseMatterAccessory.d.ts.map +1 -0
- package/dist/devices/BaseMatterAccessory.js +210 -0
- package/dist/devices/BaseMatterAccessory.js.map +1 -0
- package/dist/devices/RoboticVacuumAccessory.d.ts +85 -0
- package/dist/devices/RoboticVacuumAccessory.d.ts.map +1 -0
- package/dist/devices/RoboticVacuumAccessory.js +944 -0
- package/dist/devices/RoboticVacuumAccessory.js.map +1 -0
- package/dist/devices/index.d.ts +9 -0
- package/dist/devices/index.d.ts.map +1 -0
- package/dist/devices/index.js +8 -0
- package/dist/devices/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/login.js +1 -1
- package/dist/login.js.map +1 -1
- package/dist/platform.d.ts +39 -16
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +196 -104
- package/dist/platform.js.map +1 -1
- package/dist/sharkiq-js/ayla_api.js.map +1 -1
- package/dist/sharkiq-js/room_encoding.d.ts +8 -0
- package/dist/sharkiq-js/room_encoding.d.ts.map +1 -0
- package/dist/sharkiq-js/room_encoding.js +35 -0
- package/dist/sharkiq-js/room_encoding.js.map +1 -0
- package/dist/sharkiq-js/sharkiq.d.ts.map +1 -1
- package/dist/sharkiq-js/sharkiq.js +3 -20
- package/dist/sharkiq-js/sharkiq.js.map +1 -1
- package/docs/assets/highlight.css +9 -2
- package/docs/index.html +35 -3
- package/docs/variables/default.html +2 -1
- package/package.json +15 -15
- package/dist/errorHandling.d.ts +0 -19
- package/dist/errorHandling.d.ts.map +0 -1
- package/dist/errorHandling.js +0 -27
- package/dist/errorHandling.js.map +0 -1
- package/dist/platformAccessory.d.ts +0 -33
- package/dist/platformAccessory.d.ts.map +0 -1
- package/dist/platformAccessory.js +0 -384
- package/dist/platformAccessory.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [2.0.0] (https://github.com/homebridge-plugins/homebridge-sharkiq/releases/tag/v2.0.0) (2025-XX-XX)
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
- This release is Matter-only. The plugin now publishes external Matter Robotic Vacuum Cleaner accessories and no longer publishes HAP platform accessories. If you need the legacy HAP behavior, continue using a pre-2.0 release or a branch that preserves the HAP path.
|
|
9
|
+
- Minimum required Homebridge: >= 2.0.0-alpha.28 (or later) with Matter support exposed via `api.matter`.
|
|
10
|
+
|
|
11
|
+
### What's Changed
|
|
12
|
+
- Converted plugin to Matter-only and added Matter external accessory publishing for Robotic Vacuum Cleaner devices.
|
|
13
|
+
- Added lifecycle wiring so accessories wait for READY before initial sync and polling.
|
|
14
|
+
- Added retry/backoff for critical Ayla API calls.
|
|
15
|
+
- Removed HAP-specific configuration options (invertDockedStatus, dockedUpdateInterval, enhancedVacuumMode).
|
|
16
|
+
|
|
17
|
+
**Full Changelog**: https://github.com/homebridge-plugins/homebridge-sharkiq/compare/v1.4.1...v2.0.0
|
|
18
|
+
|
|
19
|
+
## [1.4.1] (https://github.com/homebridge-plugins/homebridge-sharkiq/releases/tag/v1.4.1) (2025-XX-XX)
|
|
6
20
|
|
|
7
21
|
### What's Changed
|
|
8
22
|
- Fix ARM64 OAuth code handling for users with both email/password and OAuth code [#54](https://github.com/homebridge-plugins/homebridge-sharkiq/issues/54)
|
|
9
23
|
|
|
24
|
+
**Full Changelog**: https://github.com/homebridge-plugins/homebridge-sharkiq/compare/v1.4.0...v1.4.1
|
|
25
|
+
|
|
10
26
|
## [1.4.0](https://github.com/homebridge-plugins/homebridge-sharkiq/releases/tag/v1.4.0) (2025-07-17)
|
|
11
27
|
|
|
12
28
|
### What's Changes
|
|
@@ -14,4 +30,5 @@ All notable changes to this project will be documented in this file. This projec
|
|
|
14
30
|
- Fix JSON parsing errors in SharkIQ API responses [#44](https://github.com/homebridge-plugins/homebridge-sharkiq/pull/44) [@mmenanno](https://github.com/mmenanno)
|
|
15
31
|
- Housekeeping and updated dependencies.
|
|
16
32
|
|
|
17
|
-
**Full Changelog**: https://github.com/homebridge-plugins/homebridge-sharkiq/compare/v1.3.2...v1.4.0
|
|
33
|
+
**Full Changelog**: https://github.com/homebridge-plugins/homebridge-sharkiq/compare/v1.3.2...v1.4.0
|
|
34
|
+
|
package/README.md
CHANGED
|
@@ -39,10 +39,7 @@ Configure Homebridge. The config file for SharkIQ should include:
|
|
|
39
39
|
"[Shark Vacuum DSN]",
|
|
40
40
|
"..."
|
|
41
41
|
],
|
|
42
|
-
"europe": false
|
|
43
|
-
"invertDockedStatus": false,
|
|
44
|
-
"dockedUpdateInterval": 30000,
|
|
45
|
-
"enhancedVacuumMode": true
|
|
42
|
+
"europe": false
|
|
46
43
|
}
|
|
47
44
|
]
|
|
48
45
|
}
|
|
@@ -78,6 +75,15 @@ The `enhancedVacuumMode` option (enabled by default) provides improved vacuum be
|
|
|
78
75
|
|
|
79
76
|
## Homebridge 2.0.0+ Compatibility
|
|
80
77
|
|
|
78
|
+
This release of the plugin is Matter-only and requires a Homebridge runtime that exposes the Matter API.
|
|
79
|
+
Minimum tested Homebridge: 2.0.0-alpha.28 or later. If your Homebridge installation does not support Matter, this plugin will log an error and will not start.
|
|
80
|
+
|
|
81
|
+
This plugin uses Matter external accessories (Robotic Vacuum Cleaner) to integrate with the platform and no longer publishes HAP platform accessories.
|
|
82
|
+
|
|
83
|
+
If you rely on the legacy HAP (HomeKit) path, keep using an older plugin release or run this code from a separate branch — this release intentionally removes HAP fallback.
|
|
84
|
+
|
|
85
|
+
Compatibility notes and behavior:
|
|
86
|
+
|
|
81
87
|
This plugin is compatible with Homebridge 2.0.0-alpha.28 and later versions, providing enhanced vacuum functionality while maintaining compatibility with current HomeKit limitations:
|
|
82
88
|
|
|
83
89
|
- **Current Implementation**: Uses optimized FanV2 service with vacuum-specific behavior
|
|
@@ -109,3 +115,34 @@ Contributions would be very helpful to help this Homebridge plugin stay maintain
|
|
|
109
115
|
## Useful Links
|
|
110
116
|
|
|
111
117
|
- [SharkIQ Python](https://github.com/JeffResc/sharkiq/)
|
|
118
|
+
|
|
119
|
+
## Integration checklist — Matter
|
|
120
|
+
|
|
121
|
+
Follow these steps to verify Matter integration locally on a Homebridge instance that supports Matter (Homebridge >= 2.0.0-alpha.28):
|
|
122
|
+
|
|
123
|
+
1. Ensure your Homebridge runtime supports Matter and the `api.matter` external accessory API.
|
|
124
|
+
2. Configure the plugin in `config.json` with your Shark credentials or `oAuthCode` and do NOT include deprecated HAP-only options (the plugin is Matter-only).
|
|
125
|
+
3. Start Homebridge in a terminal and watch logs. You should see the plugin log the DSNs found on your account and then a "Publishing X robotic device(s) as external Matter accessories" message.
|
|
126
|
+
4. After publishing, Homebridge should emit READY/COMMISSIONED events for each accessory. The plugin will perform an initial sync and start polling.
|
|
127
|
+
5. From the Home app or a Matter controller, attempt these actions and verify the vacuum responds:
|
|
128
|
+
|
|
129
|
+
- Start / Stop cleaning
|
|
130
|
+
- Pause / Resume
|
|
131
|
+
- Go Home (return to dock)
|
|
132
|
+
- Select Areas (if your device supports area cleaning)
|
|
133
|
+
|
|
134
|
+
6. Observe plugin logs for successful API calls and state updates. Look for `Matter accessory ready` and `Performing initial device sync` log lines.
|
|
135
|
+
|
|
136
|
+
Quick troubleshooting:
|
|
137
|
+
|
|
138
|
+
- If you see "requires Homebridge with Matter support" in logs, update Homebridge to a Matter-enabled build.
|
|
139
|
+
- If actions fail, inspect network connectivity and plugin logs for Ayla API errors; the plugin now includes retries with exponential backoff for critical calls.
|
|
140
|
+
|
|
141
|
+
Optional: run the prepublish checks locally (lint, build, docs) to validate everything before publishing:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Run this in the project root (macOS / zsh)
|
|
145
|
+
npm run prepublishOnly
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
If you'd like, I can add a short automated script that validates a sample run (requires a Matter-enabled Homebridge instance and credentials).
|
package/config.schema.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"vacuums": {
|
|
31
31
|
"title": "SharkClean Vacuum Devicess",
|
|
32
32
|
"type": "array",
|
|
33
|
-
"required":
|
|
33
|
+
"required": false,
|
|
34
34
|
"items": {
|
|
35
35
|
"title": "SharkClean DSN",
|
|
36
36
|
"type": "string"
|
|
@@ -43,25 +43,14 @@
|
|
|
43
43
|
"required": false,
|
|
44
44
|
"default": false
|
|
45
45
|
},
|
|
46
|
-
"
|
|
47
|
-
"title": "
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"default": false
|
|
51
|
-
},
|
|
52
|
-
"dockedUpdateInterval": {
|
|
53
|
-
"title": "Docked Update Interval",
|
|
54
|
-
"type": "integer",
|
|
46
|
+
"pollInterval": {
|
|
47
|
+
"title": "Polling interval (seconds)",
|
|
48
|
+
"description": "How often to poll Shark devices for status updates. Set to 0 to disable polling.",
|
|
49
|
+
"type": "number",
|
|
55
50
|
"required": false,
|
|
56
|
-
"default":
|
|
57
|
-
},
|
|
58
|
-
"enhancedVacuumMode": {
|
|
59
|
-
"title": "Enhanced Vacuum Mode",
|
|
60
|
-
"type": "boolean",
|
|
61
|
-
"required": false,
|
|
62
|
-
"default": true,
|
|
63
|
-
"description": "Use improved power level mappings and vacuum-optimized behavior. Prepares for future robot vacuum service support."
|
|
51
|
+
"default": 30
|
|
64
52
|
}
|
|
53
|
+
|
|
65
54
|
}
|
|
66
55
|
},
|
|
67
56
|
"layout": [
|
|
@@ -113,14 +102,7 @@
|
|
|
113
102
|
}
|
|
114
103
|
]
|
|
115
104
|
},
|
|
116
|
-
"europe"
|
|
117
|
-
"invertDockedStatus",
|
|
118
|
-
"dockedUpdateInterval",
|
|
119
|
-
{
|
|
120
|
-
"type": "help",
|
|
121
|
-
"helpvalue": "<h5>Enhanced Vacuum Mode</h5><em class='primary-text'>Enables improved vacuum behavior with better power level mappings (25%=Eco, 50%=Normal, 100%=Max). This prepares your setup for future native HomeKit robot vacuum support.</em>"
|
|
122
|
-
},
|
|
123
|
-
"enhancedVacuumMode"
|
|
105
|
+
"europe"
|
|
124
106
|
]
|
|
125
107
|
}
|
|
126
108
|
]
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa;;;;;CAKhB,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa;;;;;CAKhB,CAAA;AAEV,eAAO,MAAM,QAAQ;;;;;;CAMX,CAAA"}
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,EAAE;IACP,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,EAAE;CACC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,CAAC;IACN,GAAG,EAAE,EAAE;IACP,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,EAAE;CACC,CAAA;AAEV,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,WAAW,EAAE,IAAI;IACjB,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,GAAG;IACxB,8BAA8B,EAAE,IAAI;IACpC,uBAAuB,EAAE,GAAG;CACpB,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Matter Accessory Class
|
|
3
|
+
*
|
|
4
|
+
* This base class implements the MatterAccessory interface and provides
|
|
5
|
+
* common functionality that all Matter devices can use.
|
|
6
|
+
*
|
|
7
|
+
* Individual device types should extend this class and call super() with
|
|
8
|
+
* the required configuration.
|
|
9
|
+
*/
|
|
10
|
+
import type { API, EndpointType, Logger, MatterAccessory } from 'homebridge';
|
|
11
|
+
export interface BaseMatterAccessoryConfig {
|
|
12
|
+
uuid: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
deviceType: EndpointType;
|
|
15
|
+
serialNumber: string;
|
|
16
|
+
manufacturer: string;
|
|
17
|
+
model: string;
|
|
18
|
+
firmwareRevision: string;
|
|
19
|
+
hardwareRevision: string;
|
|
20
|
+
context?: Record<string, unknown>;
|
|
21
|
+
clusters?: MatterAccessory['clusters'];
|
|
22
|
+
handlers?: MatterAccessory['handlers'];
|
|
23
|
+
parts?: MatterAccessory['parts'];
|
|
24
|
+
/** Optional mapping from legacy cluster names to supported cluster names. */
|
|
25
|
+
clusterNameMap?: Record<string, string>;
|
|
26
|
+
/** Enable translation behavior for legacy clusters like 'power' and 'diagnostics'. */
|
|
27
|
+
translateLegacyClusters?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Base class for all Matter accessories
|
|
31
|
+
* Implements the MatterAccessory interface and provides common methods
|
|
32
|
+
*/
|
|
33
|
+
export declare abstract class BaseMatterAccessory implements MatterAccessory {
|
|
34
|
+
/** In-memory cache for battery/charging state to suppress noisy logs */
|
|
35
|
+
protected lastBatteryLevel: number | null;
|
|
36
|
+
protected lastChargingStatus: boolean | null;
|
|
37
|
+
readonly uuid: string;
|
|
38
|
+
readonly displayName: string;
|
|
39
|
+
readonly deviceType: EndpointType;
|
|
40
|
+
readonly serialNumber: string;
|
|
41
|
+
readonly manufacturer: string;
|
|
42
|
+
readonly model: string;
|
|
43
|
+
readonly firmwareRevision: string;
|
|
44
|
+
readonly hardwareRevision: string;
|
|
45
|
+
readonly context: Record<string, unknown>;
|
|
46
|
+
readonly clusters?: MatterAccessory['clusters'];
|
|
47
|
+
readonly handlers?: MatterAccessory['handlers'];
|
|
48
|
+
readonly parts?: MatterAccessory['parts'];
|
|
49
|
+
/** Optional mapping table for legacy cluster names */
|
|
50
|
+
readonly clusterNameMap?: Record<string, string>;
|
|
51
|
+
/** Whether to translate legacy clusters (can be toggled at runtime via context.translateLegacyClusters) */
|
|
52
|
+
protected readonly translateLegacyClusters: boolean;
|
|
53
|
+
protected readonly api: API;
|
|
54
|
+
protected readonly log: Logger;
|
|
55
|
+
constructor(api: API, log: Logger, config: BaseMatterAccessoryConfig);
|
|
56
|
+
/**
|
|
57
|
+
* Update the accessory state
|
|
58
|
+
* Helper method to update cluster attributes
|
|
59
|
+
*/
|
|
60
|
+
protected updateState(cluster: string, attributes: Record<string, unknown>): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Log helper methods
|
|
63
|
+
*/
|
|
64
|
+
protected logInfo(message: string, ...args: unknown[]): void;
|
|
65
|
+
protected logError(message: string, ...args: unknown[]): void;
|
|
66
|
+
protected logDebug(message: string, ...args: unknown[]): void;
|
|
67
|
+
protected logWarn(message: string, ...args: unknown[]): void;
|
|
68
|
+
/**
|
|
69
|
+
* Convert this class instance to a plain MatterAccessory object
|
|
70
|
+
* This is what gets registered with Homebridge
|
|
71
|
+
*/
|
|
72
|
+
toAccessory(): MatterAccessory;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=BaseMatterAccessory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseMatterAccessory.d.ts","sourceRoot":"","sources":["../../src/devices/BaseMatterAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Matter Accessory Class
|
|
3
|
+
*
|
|
4
|
+
* This base class implements the MatterAccessory interface and provides
|
|
5
|
+
* common functionality that all Matter devices can use.
|
|
6
|
+
*
|
|
7
|
+
* Individual device types should extend this class and call super() with
|
|
8
|
+
* the required configuration.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Base class for all Matter accessories
|
|
12
|
+
* Implements the MatterAccessory interface and provides common methods
|
|
13
|
+
*/
|
|
14
|
+
export class BaseMatterAccessory {
|
|
15
|
+
/** In-memory cache for battery/charging state to suppress noisy logs */
|
|
16
|
+
lastBatteryLevel = null;
|
|
17
|
+
lastChargingStatus = null;
|
|
18
|
+
// Required MatterAccessory properties
|
|
19
|
+
uuid;
|
|
20
|
+
displayName;
|
|
21
|
+
deviceType;
|
|
22
|
+
serialNumber;
|
|
23
|
+
manufacturer;
|
|
24
|
+
model;
|
|
25
|
+
firmwareRevision;
|
|
26
|
+
hardwareRevision;
|
|
27
|
+
context;
|
|
28
|
+
clusters;
|
|
29
|
+
handlers;
|
|
30
|
+
parts;
|
|
31
|
+
/** Optional mapping table for legacy cluster names */
|
|
32
|
+
clusterNameMap;
|
|
33
|
+
/** Whether to translate legacy clusters (can be toggled at runtime via context.translateLegacyClusters) */
|
|
34
|
+
translateLegacyClusters;
|
|
35
|
+
// Protected properties available to child classes
|
|
36
|
+
api;
|
|
37
|
+
log;
|
|
38
|
+
constructor(api, log, config) {
|
|
39
|
+
this.api = api;
|
|
40
|
+
this.log = log;
|
|
41
|
+
// Set all required properties
|
|
42
|
+
this.uuid = config.uuid;
|
|
43
|
+
this.displayName = config.displayName;
|
|
44
|
+
this.deviceType = config.deviceType;
|
|
45
|
+
this.serialNumber = config.serialNumber;
|
|
46
|
+
this.manufacturer = config.manufacturer;
|
|
47
|
+
this.model = config.model;
|
|
48
|
+
this.firmwareRevision = config.firmwareRevision;
|
|
49
|
+
this.hardwareRevision = config.hardwareRevision;
|
|
50
|
+
this.clusters = config.clusters;
|
|
51
|
+
this.handlers = config.handlers;
|
|
52
|
+
this.parts = config.parts;
|
|
53
|
+
this.clusterNameMap = config.clusterNameMap || {};
|
|
54
|
+
this.translateLegacyClusters = typeof config.translateLegacyClusters === 'boolean' ? config.translateLegacyClusters : true;
|
|
55
|
+
// Set context with all metadata
|
|
56
|
+
this.context = {
|
|
57
|
+
serialNumber: this.serialNumber,
|
|
58
|
+
manufacturer: this.manufacturer,
|
|
59
|
+
model: this.model,
|
|
60
|
+
firmwareRevision: this.firmwareRevision,
|
|
61
|
+
hardwareRevision: this.hardwareRevision,
|
|
62
|
+
...config.context,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Update the accessory state
|
|
67
|
+
* Helper method to update cluster attributes
|
|
68
|
+
*/
|
|
69
|
+
async updateState(cluster, attributes) {
|
|
70
|
+
// First, allow a configured mapping from legacy cluster names to the
|
|
71
|
+
// clusters we actually registered. This supports older code paths that
|
|
72
|
+
// attempted to update clusters like 'power' or 'diagnostics'. The mapping
|
|
73
|
+
// is optional and can be provided per-accessory via config.
|
|
74
|
+
const mapped = (this.clusterNameMap && this.clusterNameMap[cluster]) || cluster;
|
|
75
|
+
// If the mapped cluster exists on this accessory and this is not a
|
|
76
|
+
// legacy cluster that requires translation, forward the update.
|
|
77
|
+
const isLegacy = cluster === 'power' || cluster === 'diagnostics';
|
|
78
|
+
if (this.clusters && (mapped in this.clusters) && !isLegacy) {
|
|
79
|
+
try {
|
|
80
|
+
await this.api.matter.updateAccessoryState(this.uuid, mapped, attributes);
|
|
81
|
+
this.log.debug(`[${this.displayName}] Updated ${mapped} state (from ${cluster}):`, attributes);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
// Matter may report the accessory as not registered when running
|
|
85
|
+
// in Child/Bridge configurations; surface as debug to avoid
|
|
86
|
+
// noisy stack traces while still recording the failure.
|
|
87
|
+
this.logDebug(`Failed to update ${mapped} state (from ${cluster}): ${e?.message || e}`);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Special-case handling for legacy clusters when no direct mapping exists.
|
|
92
|
+
// These translate a small set of commonly-updated attributes into updates
|
|
93
|
+
// against supported clusters (for vacuum devices we commonly support
|
|
94
|
+
// 'rvcOperationalState'). This avoids noisy "Behavior ID ... does not
|
|
95
|
+
// exist" errors while preserving useful state updates.
|
|
96
|
+
// Determine whether translations are enabled for this accessory at runtime.
|
|
97
|
+
const runtimeTranslate = typeof this.context.translateLegacyClusters === 'boolean'
|
|
98
|
+
? this.context.translateLegacyClusters
|
|
99
|
+
: this.translateLegacyClusters;
|
|
100
|
+
if (cluster === 'power') {
|
|
101
|
+
// batteryLevel and charging are informational. If charging is present
|
|
102
|
+
// and we have rvcOperationalState, translate charging->Charging(65)
|
|
103
|
+
// or not-charging->Docked(66). Also log battery percentage locally.
|
|
104
|
+
const batteryLevel = attributes.batteryLevel;
|
|
105
|
+
const charging = attributes.charging;
|
|
106
|
+
if (typeof batteryLevel === 'number') {
|
|
107
|
+
// Use in-memory cache to suppress noisy logs
|
|
108
|
+
const chargingBool = typeof charging === 'boolean' ? charging : (charging === 1);
|
|
109
|
+
const batteryChanged = this.lastBatteryLevel === null || this.lastBatteryLevel !== batteryLevel;
|
|
110
|
+
const chargingChanged = this.lastChargingStatus === null || this.lastChargingStatus !== chargingBool;
|
|
111
|
+
if (batteryChanged || chargingChanged) {
|
|
112
|
+
this.logInfo(`battery updated (via legacy 'power'): ${batteryLevel}%`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.logDebug(`legacy 'power' battery unchanged: ${batteryLevel}% (charging: ${String(chargingBool)})`);
|
|
116
|
+
}
|
|
117
|
+
// Always update the in-memory cache
|
|
118
|
+
this.lastBatteryLevel = batteryLevel;
|
|
119
|
+
this.lastChargingStatus = chargingBool;
|
|
120
|
+
}
|
|
121
|
+
if (runtimeTranslate && typeof charging !== 'undefined') {
|
|
122
|
+
// Choose the target cluster to update. Prefer an explicit mapping
|
|
123
|
+
// if provided, otherwise fall back to rvcOperationalState when
|
|
124
|
+
// available.
|
|
125
|
+
const target = (this.clusterNameMap && this.clusterNameMap[cluster]) || 'rvcOperationalState';
|
|
126
|
+
const targetExists = this.clusters && (target in this.clusters);
|
|
127
|
+
const rvcExists = this.clusters && ('rvcOperationalState' in this.clusters);
|
|
128
|
+
if (targetExists || rvcExists) {
|
|
129
|
+
const isCharging = charging === true || charging === 1;
|
|
130
|
+
const opState = isCharging ? 65 : 66;
|
|
131
|
+
const chosen = targetExists ? target : 'rvcOperationalState';
|
|
132
|
+
try {
|
|
133
|
+
await this.api.matter.updateAccessoryState(this.uuid, chosen, { operationalState: opState });
|
|
134
|
+
this.log.debug(`[${this.displayName}] Translated legacy 'power' charging=${String(charging)} -> ${chosen}=${opState}`);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
this.logDebug(`Failed to translate legacy 'power' charging=${String(charging)} -> ${chosen}: ${e?.message || e}`);
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const available = this.clusters ? Object.keys(this.clusters).join(', ') : '(none)';
|
|
143
|
+
this.logWarn(`Attempt to update legacy cluster 'power' but no mapping or supported target found. Available clusters: ${available}`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (cluster === 'diagnostics') {
|
|
147
|
+
// diagnostics commonly carries an errorCode. If present and non-zero,
|
|
148
|
+
// translate to rvcOperationalState Error (3) when supported.
|
|
149
|
+
const errorCode = attributes.errorCode;
|
|
150
|
+
if (runtimeTranslate && typeof errorCode === 'number' && errorCode > 0) {
|
|
151
|
+
const target = (this.clusterNameMap && this.clusterNameMap[cluster]) || 'rvcOperationalState';
|
|
152
|
+
const targetExists = this.clusters && (target in this.clusters);
|
|
153
|
+
const rvcExists = this.clusters && ('rvcOperationalState' in this.clusters);
|
|
154
|
+
if (targetExists || rvcExists) {
|
|
155
|
+
const chosen = targetExists ? target : 'rvcOperationalState';
|
|
156
|
+
try {
|
|
157
|
+
await this.api.matter.updateAccessoryState(this.uuid, chosen, { operationalState: 3 });
|
|
158
|
+
this.logWarn(`[${this.displayName}] Translated legacy 'diagnostics' errorCode=${errorCode} -> ${chosen}=3 (Error)`);
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
this.logDebug(`Failed to translate legacy 'diagnostics' errorCode=${errorCode} -> ${chosen}: ${e?.message || e}`);
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const available = this.clusters ? Object.keys(this.clusters).join(', ') : '(none)';
|
|
167
|
+
this.logDebug(`Attempt to update legacy cluster 'diagnostics' but no mapping or supported target found. Available clusters: ${available}`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
// Fallback: warn and skip unknown clusters to avoid Matter server errors.
|
|
171
|
+
const available = this.clusters ? Object.keys(this.clusters).join(', ') : '(none)';
|
|
172
|
+
this.logWarn(`Attempt to update unknown cluster '${cluster}' (mapped to '${mapped}'). Available clusters: ${available}`);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Log helper methods
|
|
176
|
+
*/
|
|
177
|
+
logInfo(message, ...args) {
|
|
178
|
+
this.log.info(`[${this.displayName}] ${message}`, ...args);
|
|
179
|
+
}
|
|
180
|
+
logError(message, ...args) {
|
|
181
|
+
this.log.error(`[${this.displayName}] ${message}`, ...args);
|
|
182
|
+
}
|
|
183
|
+
logDebug(message, ...args) {
|
|
184
|
+
this.log.debug(`[${this.displayName}] ${message}`, ...args);
|
|
185
|
+
}
|
|
186
|
+
logWarn(message, ...args) {
|
|
187
|
+
this.log.warn(`[${this.displayName}] ${message}`, ...args);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Convert this class instance to a plain MatterAccessory object
|
|
191
|
+
* This is what gets registered with Homebridge
|
|
192
|
+
*/
|
|
193
|
+
toAccessory() {
|
|
194
|
+
return {
|
|
195
|
+
uuid: this.uuid,
|
|
196
|
+
displayName: this.displayName,
|
|
197
|
+
deviceType: this.deviceType,
|
|
198
|
+
serialNumber: this.serialNumber,
|
|
199
|
+
manufacturer: this.manufacturer,
|
|
200
|
+
model: this.model,
|
|
201
|
+
firmwareRevision: this.firmwareRevision,
|
|
202
|
+
hardwareRevision: this.hardwareRevision,
|
|
203
|
+
context: this.context,
|
|
204
|
+
clusters: this.clusters,
|
|
205
|
+
handlers: this.handlers,
|
|
206
|
+
parts: this.parts,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=BaseMatterAccessory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BaseMatterAccessory.js","sourceRoot":"","sources":["../../src/devices/BaseMatterAccessory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Robotic Vacuum Cleaner Accessory Class
|
|
3
|
+
*
|
|
4
|
+
* This is a comprehensive example demonstrating all available features
|
|
5
|
+
* of the RoboticVacuumCleaner device type including:
|
|
6
|
+
* - Multiple run modes (Idle, Cleaning, Mapping)
|
|
7
|
+
* - Multiple clean modes (Vacuum, Mop, Vacuum & Mop, Deep Clean)
|
|
8
|
+
* - Operational state management with realistic transitions
|
|
9
|
+
* - Service area (room) support
|
|
10
|
+
*
|
|
11
|
+
* IMPORTANT: Platform Matter accessories
|
|
12
|
+
* =======================================
|
|
13
|
+
* This vacuum is registered as a platform accessory using
|
|
14
|
+
* api.matter.registerPlatformAccessories(), which works the same as HAP.
|
|
15
|
+
* Platform accessories are registered synchronously and are immediately ready for use.
|
|
16
|
+
*
|
|
17
|
+
* Demo behavior:
|
|
18
|
+
* - Start/Resume: Sets run mode to "Cleaning", runs for 15/10 seconds, then returns to dock
|
|
19
|
+
* - Return to dock: Immediately sets "Idle" mode, then Seeking (5s) → Charging (3s) → Docked
|
|
20
|
+
* - Stop: Immediately stops and resets to "Idle" mode
|
|
21
|
+
* - Pause: Cancels automatic completion timer, keeps "Cleaning" mode
|
|
22
|
+
*/
|
|
23
|
+
import type { API, Logger } from 'homebridge';
|
|
24
|
+
import type { SharkIqVacuum } from '../sharkiq-js/sharkiq.js';
|
|
25
|
+
import { BaseMatterAccessory } from './BaseMatterAccessory.js';
|
|
26
|
+
export declare class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
27
|
+
private activeTimers;
|
|
28
|
+
private lastRunMode;
|
|
29
|
+
protected lastBatteryLevel: number | null;
|
|
30
|
+
protected lastChargingStatus: boolean | null;
|
|
31
|
+
private lastOperationalState;
|
|
32
|
+
private lastRssi;
|
|
33
|
+
private lastSelectedAreas;
|
|
34
|
+
private lastCleanMode;
|
|
35
|
+
private readonly sharkDevice?;
|
|
36
|
+
private pollInterval?;
|
|
37
|
+
constructor(api: API, log: Logger, sharkDevice?: SharkIqVacuum, pollIntervalMs?: number);
|
|
38
|
+
/**
|
|
39
|
+
* Initialize cached runtime values from the Shark device wrapper where
|
|
40
|
+
* available, otherwise fall back to persisted accessory state exposed by the API.
|
|
41
|
+
*/
|
|
42
|
+
private initCachedState;
|
|
43
|
+
/**
|
|
44
|
+
* Persist a named cache value into accessory context and keep in-memory copy.
|
|
45
|
+
* This centralizes writes so callers only need to update the in-memory field
|
|
46
|
+
* and call this to persist to Homebridge accessory.context.
|
|
47
|
+
*/
|
|
48
|
+
private persistCache;
|
|
49
|
+
private startPolling;
|
|
50
|
+
private stopPolling;
|
|
51
|
+
private buildServiceAreaCluster;
|
|
52
|
+
private handleChangeRunMode;
|
|
53
|
+
private handleChangeCleanMode;
|
|
54
|
+
private handlePause;
|
|
55
|
+
private handleStop;
|
|
56
|
+
private handleStart;
|
|
57
|
+
private handleResume;
|
|
58
|
+
private handleGoHome;
|
|
59
|
+
private handleSelectAreas;
|
|
60
|
+
private handleSkipArea;
|
|
61
|
+
/**
|
|
62
|
+
* Helper method to clear all active timers
|
|
63
|
+
*/
|
|
64
|
+
private clearTimers;
|
|
65
|
+
/**
|
|
66
|
+
* Helper method to initiate return to dock sequence
|
|
67
|
+
* Can be called synchronously from other handlers
|
|
68
|
+
*/
|
|
69
|
+
private returnToDock;
|
|
70
|
+
/**
|
|
71
|
+
* Update Methods - Use these to update the vacuum state from your API/device
|
|
72
|
+
*
|
|
73
|
+
* Since this is a platform accessory, state updates work immediately after registration.
|
|
74
|
+
*/
|
|
75
|
+
updateOperationalState(state: number): void;
|
|
76
|
+
updateRunMode(mode: number): void;
|
|
77
|
+
updateCleanMode(mode: number): void;
|
|
78
|
+
updateSelectedAreas(areaIds: number[]): void;
|
|
79
|
+
updateCurrentArea(areaId: number | null): void;
|
|
80
|
+
updateProgress(progress: Array<{
|
|
81
|
+
areaId: number;
|
|
82
|
+
status: number;
|
|
83
|
+
}>): void;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=RoboticVacuumAccessory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoboticVacuumAccessory.d.ts","sourceRoot":"","sources":["../../src/devices/RoboticVacuumAccessory.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAkB,MAAM,YAAY,CAAA;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,qBAAa,sBAAuB,SAAQ,mBAAmB;IAC7D,OAAO,CAAC,YAAY,CAAuB;IAE3C,OAAO,CAAC,WAAW,CAAsB;IAEzC,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAO;IAChD,SAAS,CAAC,kBAAkB,EAAE,OAAO,GAAG,IAAI,CAAO;IAEnD,OAAO,CAAC,oBAAoB,CAAsB;IAElD,OAAO,CAAC,QAAQ,CAAsB;IAEtC,OAAO,CAAC,iBAAiB,CAAwB;IAEjD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAe;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAgB;gBAEzB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,aAAa,EAAE,cAAc,CAAC,EAAE,MAAM;IAmMvF;;;OAGG;IACH,OAAO,CAAC,eAAe;IAkJvB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,YAAY;IAwKpB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,uBAAuB;YAqCjB,mBAAmB;YAoDnB,qBAAqB;YA4BrB,WAAW;YAaX,UAAU;YAcV,WAAW;YA0BX,YAAY;YA0BZ,YAAY;YAuBZ,iBAAiB;YAsBjB,cAAc;IAQ5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;;OAGG;IACH,OAAO,CAAC,YAAY;IA0BpB;;;;OAIG;IAEI,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA2B3C,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmBjC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8BnC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAkC5C,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAU9C,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;CAIjF"}
|