@switchbot/homebridge-switchbot 5.0.0-beta.7 → 5.0.0-beta.70
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 +15 -0
- package/README.md +45 -3
- package/config.schema.json +871 -13754
- package/dist/devices-hap/airpurifier.d.ts.map +1 -1
- package/dist/devices-hap/airpurifier.js +12 -6
- package/dist/devices-hap/airpurifier.js.map +1 -1
- package/dist/devices-hap/blindtilt.js +3 -3
- package/dist/devices-hap/bot.d.ts.map +1 -1
- package/dist/devices-hap/bot.js +16 -5
- package/dist/devices-hap/bot.js.map +1 -1
- package/dist/devices-hap/ceilinglight.d.ts.map +1 -1
- package/dist/devices-hap/ceilinglight.js +13 -7
- package/dist/devices-hap/ceilinglight.js.map +1 -1
- package/dist/devices-hap/colorbulb.d.ts.map +1 -1
- package/dist/devices-hap/colorbulb.js +49 -9
- package/dist/devices-hap/colorbulb.js.map +1 -1
- package/dist/devices-hap/contact.js +3 -3
- package/dist/devices-hap/curtain.js +2 -2
- package/dist/devices-hap/curtain.js.map +1 -1
- package/dist/devices-hap/device.d.ts +18 -8
- package/dist/devices-hap/device.d.ts.map +1 -1
- package/dist/devices-hap/device.js +141 -69
- package/dist/devices-hap/device.js.map +1 -1
- package/dist/devices-hap/fan.d.ts.map +1 -1
- package/dist/devices-hap/fan.js +12 -6
- package/dist/devices-hap/fan.js.map +1 -1
- package/dist/devices-hap/hub.d.ts.map +1 -1
- package/dist/devices-hap/hub.js +6 -5
- package/dist/devices-hap/hub.js.map +1 -1
- package/dist/devices-hap/humidifier.d.ts +5 -0
- package/dist/devices-hap/humidifier.d.ts.map +1 -1
- package/dist/devices-hap/humidifier.js +92 -4
- package/dist/devices-hap/humidifier.js.map +1 -1
- package/dist/devices-hap/iosensor.d.ts.map +1 -1
- package/dist/devices-hap/iosensor.js +36 -21
- package/dist/devices-hap/iosensor.js.map +1 -1
- package/dist/devices-hap/lightstrip.d.ts.map +1 -1
- package/dist/devices-hap/lightstrip.js +38 -8
- package/dist/devices-hap/lightstrip.js.map +1 -1
- package/dist/devices-hap/lock.d.ts.map +1 -1
- package/dist/devices-hap/lock.js +14 -6
- package/dist/devices-hap/lock.js.map +1 -1
- package/dist/devices-hap/meter.d.ts.map +1 -1
- package/dist/devices-hap/meter.js +6 -5
- package/dist/devices-hap/meter.js.map +1 -1
- package/dist/devices-hap/meterplus.d.ts.map +1 -1
- package/dist/devices-hap/meterplus.js +6 -5
- package/dist/devices-hap/meterplus.js.map +1 -1
- package/dist/devices-hap/meterpro.d.ts.map +1 -1
- package/dist/devices-hap/meterpro.js +7 -6
- package/dist/devices-hap/meterpro.js.map +1 -1
- package/dist/devices-hap/motion.js +3 -3
- package/dist/devices-hap/plug.d.ts.map +1 -1
- package/dist/devices-hap/plug.js +11 -6
- package/dist/devices-hap/plug.js.map +1 -1
- package/dist/devices-hap/relayswitch.js +3 -3
- package/dist/devices-hap/robotvacuumcleaner.d.ts.map +1 -1
- package/dist/devices-hap/robotvacuumcleaner.js +13 -6
- package/dist/devices-hap/robotvacuumcleaner.js.map +1 -1
- package/dist/devices-hap/waterdetector.js +3 -3
- package/dist/devices-matter/BaseMatterAccessory.d.ts +27 -0
- package/dist/devices-matter/BaseMatterAccessory.d.ts.map +1 -1
- package/dist/devices-matter/BaseMatterAccessory.js +169 -5
- package/dist/devices-matter/BaseMatterAccessory.js.map +1 -1
- package/dist/devices-matter/ColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorLightAccessory.js +12 -12
- package/dist/devices-matter/ColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.js +5 -7
- package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +1 -1
- package/dist/devices-matter/DimmableLightAccessory.js +9 -9
- package/dist/devices-matter/DimmableLightAccessory.js.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.js +14 -15
- package/dist/devices-matter/ExtendedColorLightAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffLightAccessory.js +8 -16
- package/dist/devices-matter/OnOffLightAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.d.ts +2 -0
- package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +1 -1
- package/dist/devices-matter/OnOffOutletAccessory.js +10 -7
- package/dist/devices-matter/OnOffOutletAccessory.js.map +1 -1
- package/dist/devices-matter/OnOffSwitchAccessory.js +2 -2
- package/dist/devices-matter/OnOffSwitchAccessory.js.map +1 -1
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts +36 -43
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +1 -1
- package/dist/devices-matter/RoboticVacuumAccessory.js +478 -268
- package/dist/devices-matter/RoboticVacuumAccessory.js.map +1 -1
- package/dist/devices-matter/VenetianBlindAccessory.d.ts +6 -6
- package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +1 -1
- package/dist/devices-matter/VenetianBlindAccessory.js.map +1 -1
- package/dist/devices-matter/WindowBlindAccessory.d.ts +5 -5
- package/dist/devices-matter/WindowBlindAccessory.d.ts.map +1 -1
- package/dist/devices-matter/WindowBlindAccessory.js +57 -6
- package/dist/devices-matter/WindowBlindAccessory.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +219 -19
- package/dist/homebridge-ui/server.js +0 -31
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -9
- package/dist/index.js.map +1 -1
- package/dist/irdevice/irdevice.d.ts +11 -10
- package/dist/irdevice/irdevice.d.ts.map +1 -1
- package/dist/irdevice/irdevice.js +76 -35
- package/dist/irdevice/irdevice.js.map +1 -1
- package/dist/platform-hap.d.ts +26 -15
- package/dist/platform-hap.d.ts.map +1 -1
- package/dist/platform-hap.js +333 -153
- package/dist/platform-hap.js.map +1 -1
- package/dist/platform-matter.d.ts +93 -6
- package/dist/platform-matter.d.ts.map +1 -1
- package/dist/platform-matter.js +1878 -229
- package/dist/platform-matter.js.map +1 -1
- package/dist/settings.d.ts +75 -7
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/dist/test/apiRequestTracker.test.d.ts +2 -0
- package/dist/test/apiRequestTracker.test.d.ts.map +1 -0
- package/dist/test/apiRequestTracker.test.js +392 -0
- package/dist/test/apiRequestTracker.test.js.map +1 -0
- package/dist/test/hap/device-webhook-context.test.d.ts +2 -0
- package/dist/test/hap/device-webhook-context.test.d.ts.map +1 -0
- package/dist/test/hap/device-webhook-context.test.js +128 -0
- package/dist/test/hap/device-webhook-context.test.js.map +1 -0
- package/dist/test/hap/platform-hap.logging.test.d.ts +2 -0
- package/dist/test/hap/platform-hap.logging.test.d.ts.map +1 -0
- package/dist/test/hap/platform-hap.logging.test.js +33 -0
- package/dist/test/hap/platform-hap.logging.test.js.map +1 -0
- package/dist/test/hap/platform-hap.test.d.ts +2 -0
- package/dist/test/hap/platform-hap.test.d.ts.map +1 -0
- package/dist/test/hap/platform-hap.test.js +62 -0
- package/dist/test/hap/platform-hap.test.js.map +1 -0
- package/dist/test/helpers/platform-fixtures.d.ts +9 -0
- package/dist/test/helpers/platform-fixtures.d.ts.map +1 -0
- package/dist/test/helpers/platform-fixtures.js +30 -0
- package/dist/test/helpers/platform-fixtures.js.map +1 -0
- package/dist/test/homebridge-ui/server.test.d.ts +2 -0
- package/dist/test/homebridge-ui/server.test.d.ts.map +1 -0
- package/dist/test/homebridge-ui/server.test.js +445 -0
- package/dist/test/homebridge-ui/server.test.js.map +1 -0
- package/dist/{index.test.d.ts.map → test/index.test.d.ts.map} +1 -1
- package/dist/test/index.test.js +19 -0
- package/dist/test/index.test.js.map +1 -0
- package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts +2 -0
- package/dist/test/matter/devices-matter/baseMatterAccessory.test.d.ts.map +1 -0
- package/dist/test/matter/devices-matter/baseMatterAccessory.test.js +71 -0
- package/dist/test/matter/devices-matter/baseMatterAccessory.test.js.map +1 -0
- package/dist/test/matter/platform-matter.additional.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.additional.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.additional.test.js +35 -0
- package/dist/test/matter/platform-matter.additional.test.js.map +1 -0
- package/dist/test/matter/platform-matter.bleparse.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.bleparse.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.bleparse.test.js +43 -0
- package/dist/test/matter/platform-matter.bleparse.test.js.map +1 -0
- package/dist/test/matter/platform-matter.cleanup.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.cleanup.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.cleanup.test.js +70 -0
- package/dist/test/matter/platform-matter.cleanup.test.js.map +1 -0
- package/dist/test/matter/platform-matter.keepstale.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.keepstale.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.keepstale.test.js +27 -0
- package/dist/test/matter/platform-matter.keepstale.test.js.map +1 -0
- package/dist/test/matter/platform-matter.logging.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.logging.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.logging.test.js +29 -0
- package/dist/test/matter/platform-matter.logging.test.js.map +1 -0
- package/dist/test/matter/platform-matter.mapping.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.mapping.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.mapping.test.js +43 -0
- package/dist/test/matter/platform-matter.mapping.test.js.map +1 -0
- package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.openapi-mapping.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.openapi-mapping.test.js +84 -0
- package/dist/test/matter/platform-matter.openapi-mapping.test.js.map +1 -0
- package/dist/test/matter/platform-matter.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.test.js +117 -0
- package/dist/test/matter/platform-matter.test.js.map +1 -0
- package/dist/test/matter/platform-matter.unregister.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.unregister.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.unregister.test.js +30 -0
- package/dist/test/matter/platform-matter.unregister.test.js.map +1 -0
- package/dist/test/matter/platform-matter.webhook.test.d.ts +2 -0
- package/dist/test/matter/platform-matter.webhook.test.d.ts.map +1 -0
- package/dist/test/matter/platform-matter.webhook.test.js +46 -0
- package/dist/test/matter/platform-matter.webhook.test.js.map +1 -0
- package/dist/test/utils.test.d.ts +2 -0
- package/dist/test/utils.test.d.ts.map +1 -0
- package/dist/test/utils.test.js +95 -0
- package/dist/test/utils.test.js.map +1 -0
- package/dist/test/verifyconfig.test.d.ts.map +1 -0
- package/dist/{verifyconfig.test.js → test/verifyconfig.test.js} +2 -2
- package/dist/test/verifyconfig.test.js.map +1 -0
- package/dist/utils.d.ts +204 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +713 -33
- package/dist/utils.js.map +1 -1
- package/docs/assets/highlight.css +14 -0
- package/docs/assets/main.js +2 -2
- package/docs/index.html +31 -2
- package/docs/variables/default.html +1 -1
- package/package.json +15 -15
- package/src/devices-hap/airpurifier.ts +11 -6
- package/src/devices-hap/blindtilt.ts +3 -3
- package/src/devices-hap/bot.ts +15 -5
- package/src/devices-hap/ceilinglight.ts +12 -7
- package/src/devices-hap/colorbulb.ts +46 -10
- package/src/devices-hap/contact.ts +3 -3
- package/src/devices-hap/curtain.ts +2 -2
- package/src/devices-hap/device.ts +149 -70
- package/src/devices-hap/fan.ts +11 -6
- package/src/devices-hap/hub.ts +6 -5
- package/src/devices-hap/humidifier.ts +97 -4
- package/src/devices-hap/iosensor.ts +36 -21
- package/src/devices-hap/lightstrip.ts +35 -8
- package/src/devices-hap/lock.ts +13 -6
- package/src/devices-hap/meter.ts +6 -5
- package/src/devices-hap/meterplus.ts +6 -5
- package/src/devices-hap/meterpro.ts +7 -6
- package/src/devices-hap/motion.ts +3 -3
- package/src/devices-hap/plug.ts +10 -6
- package/src/devices-hap/relayswitch.ts +3 -3
- package/src/devices-hap/robotvacuumcleaner.ts +12 -6
- package/src/devices-hap/waterdetector.ts +3 -3
- package/src/devices-matter/BaseMatterAccessory.ts +176 -5
- package/src/devices-matter/ColorLightAccessory.ts +12 -12
- package/src/devices-matter/ColorTemperatureLightAccessory.ts +5 -7
- package/src/devices-matter/DimmableLightAccessory.ts +9 -9
- package/src/devices-matter/ExtendedColorLightAccessory.ts +14 -15
- package/src/devices-matter/OnOffLightAccessory.ts +8 -16
- package/src/devices-matter/OnOffOutletAccessory.ts +12 -7
- package/src/devices-matter/OnOffSwitchAccessory.ts +2 -2
- package/src/devices-matter/RoboticVacuumAccessory.ts +529 -315
- package/src/devices-matter/VenetianBlindAccessory.ts +5 -5
- package/src/devices-matter/WindowBlindAccessory.ts +53 -10
- package/src/homebridge-ui/public/index.html +219 -19
- package/src/homebridge-ui/server.ts +0 -34
- package/src/index.ts +4 -10
- package/src/irdevice/irdevice.ts +74 -35
- package/src/platform-hap.ts +365 -169
- package/src/platform-matter.ts +1923 -230
- package/src/settings.ts +78 -3
- package/src/test/apiRequestTracker.test.ts +417 -0
- package/src/test/hap/device-webhook-context.test.ts +136 -0
- package/src/test/hap/platform-hap.logging.test.ts +36 -0
- package/src/test/hap/platform-hap.test.ts +70 -0
- package/src/test/helpers/platform-fixtures.ts +33 -0
- package/src/test/homebridge-ui/server.test.ts +486 -0
- package/src/test/index.test.ts +24 -0
- package/src/test/matter/devices-matter/baseMatterAccessory.test.ts +88 -0
- package/src/test/matter/platform-matter.additional.test.ts +44 -0
- package/src/test/matter/platform-matter.bleparse.test.ts +47 -0
- package/src/test/matter/platform-matter.cleanup.test.ts +86 -0
- package/src/test/matter/platform-matter.keepstale.test.ts +37 -0
- package/src/test/matter/platform-matter.logging.test.ts +33 -0
- package/src/test/matter/platform-matter.mapping.test.ts +57 -0
- package/src/test/matter/platform-matter.openapi-mapping.test.ts +109 -0
- package/src/test/matter/platform-matter.test.ts +144 -0
- package/src/test/matter/platform-matter.unregister.test.ts +39 -0
- package/src/test/matter/platform-matter.webhook.test.ts +54 -0
- package/src/test/utils.test.ts +96 -0
- package/src/{verifyconfig.test.ts → test/verifyconfig.test.ts} +12 -11
- package/src/utils.ts +777 -36
- package/dist/index.test.js +0 -14
- package/dist/index.test.js.map +0 -1
- package/dist/verifyconfig.test.d.ts.map +0 -1
- package/dist/verifyconfig.test.js.map +0 -1
- package/src/index.test.ts +0 -19
- /package/dist/{index.test.d.ts → test/index.test.d.ts} +0 -0
- /package/dist/{verifyconfig.test.d.ts → test/verifyconfig.test.d.ts} +0 -0
|
@@ -1,75 +1,93 @@
|
|
|
1
|
-
|
|
1
|
+
//
|
|
2
2
|
import { BaseMatterAccessory } from './BaseMatterAccessory.js';
|
|
3
|
+
function detectModelFromContext(ctx) {
|
|
4
|
+
const t = ctx?.deviceType?.trim();
|
|
5
|
+
switch (t) {
|
|
6
|
+
case 'Robot Vacuum Cleaner S1':
|
|
7
|
+
return 'S1';
|
|
8
|
+
case 'Robot Vacuum Cleaner S1 Plus':
|
|
9
|
+
return 'S1 Plus';
|
|
10
|
+
case 'Robot Vacuum Cleaner S1 Pro':
|
|
11
|
+
return 'S1 Pro';
|
|
12
|
+
case 'Robot Vacuum Cleaner S1 Mini':
|
|
13
|
+
return 'S1 Mini';
|
|
14
|
+
case 'WoSweeper':
|
|
15
|
+
return 'WoSweeper';
|
|
16
|
+
case 'WoSweeperMini':
|
|
17
|
+
return 'WoSweeperMini';
|
|
18
|
+
case 'K10+':
|
|
19
|
+
return 'K10+';
|
|
20
|
+
case 'K10+ Pro':
|
|
21
|
+
return 'K10+ Pro';
|
|
22
|
+
case 'Robot Vacuum Cleaner K10+ Pro Combo':
|
|
23
|
+
case 'K10+ Pro Combo':
|
|
24
|
+
return 'K10+ Pro Combo';
|
|
25
|
+
case 'Robot Vacuum Cleaner S10':
|
|
26
|
+
return 'S10';
|
|
27
|
+
case 'Robot Vacuum Cleaner S20':
|
|
28
|
+
case 'S20':
|
|
29
|
+
return 'S20';
|
|
30
|
+
case 'Robot Vacuum Cleaner K11+':
|
|
31
|
+
case 'K11+':
|
|
32
|
+
return 'K11+';
|
|
33
|
+
case 'Robot Vacuum Cleaner K20 Plus Pro':
|
|
34
|
+
case 'K20+ Pro':
|
|
35
|
+
return 'K20+ Pro';
|
|
36
|
+
default:
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function capabilitiesFor(model) {
|
|
41
|
+
// Defaults: conservative basic vac
|
|
42
|
+
if (!model) {
|
|
43
|
+
return { pause: false, resume: false, cleanAction: 'vacuum-only', suctionKind: 'powLevel-0-3', waterLevel: false };
|
|
44
|
+
}
|
|
45
|
+
// Basic vacuum models (S1 family, WoSweeper family, K10 family without Combo)
|
|
46
|
+
if (model === 'S1' || model === 'S1 Plus' || model === 'S1 Pro' || model === 'S1 Mini'
|
|
47
|
+
|| model === 'WoSweeper' || model === 'WoSweeperMini'
|
|
48
|
+
|| model === 'K10+' || model === 'K10+ Pro') {
|
|
49
|
+
return { pause: false, resume: false, cleanAction: 'vacuum-only', suctionKind: 'powLevel-0-3', waterLevel: false };
|
|
50
|
+
}
|
|
51
|
+
// K10+ Pro Combo: vacuum or mop, fanLevel, no waterLevel
|
|
52
|
+
if (model === 'K10+ Pro Combo') {
|
|
53
|
+
return { pause: true, resume: false, cleanAction: 'vacuum-or-mop', suctionKind: 'fanLevel-1-4', waterLevel: false };
|
|
54
|
+
}
|
|
55
|
+
// S10/S20: vacuum or vacuum+mop combo, fanLevel, waterLevel, plus advanced commands
|
|
56
|
+
if (model === 'S10' || model === 'S20') {
|
|
57
|
+
return {
|
|
58
|
+
pause: true,
|
|
59
|
+
resume: false,
|
|
60
|
+
cleanAction: 'vacuum-or-vacmop',
|
|
61
|
+
suctionKind: 'fanLevel-1-4',
|
|
62
|
+
waterLevel: true,
|
|
63
|
+
advancedCommands: {
|
|
64
|
+
setVolume: true,
|
|
65
|
+
selfClean: true,
|
|
66
|
+
addWaterForHumi: true,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// K11+/K20+ Pro: vacuum or mop, fanLevel, waterLevel, volume control
|
|
71
|
+
return {
|
|
72
|
+
pause: true,
|
|
73
|
+
resume: false,
|
|
74
|
+
cleanAction: 'vacuum-or-mop',
|
|
75
|
+
suctionKind: 'fanLevel-1-4',
|
|
76
|
+
waterLevel: true,
|
|
77
|
+
advancedCommands: {
|
|
78
|
+
setVolume: true,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
3
82
|
export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
4
|
-
|
|
83
|
+
// Track current high-level preferences that affect OpenAPI payloads
|
|
84
|
+
currentCleanAction = 'vacuum';
|
|
85
|
+
currentFanLevel = 2;
|
|
86
|
+
capabilities;
|
|
5
87
|
constructor(api, log, opts) {
|
|
6
88
|
const serialNumber = opts?.serialNumber ?? 'VACUUM-001';
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
status: 0,
|
|
10
|
-
order: 0,
|
|
11
|
-
description: 'Battery',
|
|
12
|
-
batPercentRemaining: 100,
|
|
13
|
-
batChargeLevel: 2,
|
|
14
|
-
batReplaceability: 1,
|
|
15
|
-
},
|
|
16
|
-
rvcRunMode: {
|
|
17
|
-
supportedModes: [
|
|
18
|
-
{ label: 'Idle', mode: 0, modeTags: [{ value: 16384 }] },
|
|
19
|
-
{ label: 'Cleaning', mode: 1, modeTags: [{ value: 16385 }] },
|
|
20
|
-
{ label: 'Mapping', mode: 2, modeTags: [{ value: 16386 }] },
|
|
21
|
-
],
|
|
22
|
-
currentMode: 0,
|
|
23
|
-
},
|
|
24
|
-
rvcCleanMode: {
|
|
25
|
-
supportedModes: [
|
|
26
|
-
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
27
|
-
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
28
|
-
{ label: 'Vacuum & Mop', mode: 2, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
29
|
-
{ label: 'Deep Clean', mode: 3, modeTags: [{ value: 16384 }] },
|
|
30
|
-
{ label: 'Deep Vacuum', mode: 4, modeTags: [{ value: 16384 }, { value: 16385 }] },
|
|
31
|
-
{ label: 'Deep Mop', mode: 5, modeTags: [{ value: 16384 }, { value: 16386 }] },
|
|
32
|
-
{ label: 'Quick Clean', mode: 6, modeTags: [{ value: 1 }, { value: 16385 }] },
|
|
33
|
-
{ label: 'Max Clean', mode: 7, modeTags: [{ value: 7 }, { value: 16385 }] },
|
|
34
|
-
{ label: 'Min Clean', mode: 8, modeTags: [{ value: 6 }, { value: 16385 }] },
|
|
35
|
-
{ label: 'Quiet Vacuum', mode: 9, modeTags: [{ value: 2 }, { value: 16385 }] },
|
|
36
|
-
{ label: 'Quiet Mop', mode: 10, modeTags: [{ value: 2 }, { value: 16386 }] },
|
|
37
|
-
{ label: 'Night Mode', mode: 11, modeTags: [{ value: 8 }, { value: 16385 }] },
|
|
38
|
-
{ label: 'Eco Vacuum', mode: 12, modeTags: [{ value: 4 }, { value: 16385 }] },
|
|
39
|
-
{ label: 'Eco Mop', mode: 13, modeTags: [{ value: 4 }, { value: 16386 }] },
|
|
40
|
-
{ label: 'Auto', mode: 14, modeTags: [{ value: 0 }, { value: 16385 }] },
|
|
41
|
-
],
|
|
42
|
-
currentMode: 0,
|
|
43
|
-
},
|
|
44
|
-
rvcOperationalState: {
|
|
45
|
-
operationalStateList: [
|
|
46
|
-
{ operationalStateId: 0 },
|
|
47
|
-
{ operationalStateId: 1 },
|
|
48
|
-
{ operationalStateId: 2 },
|
|
49
|
-
{ operationalStateId: 3 },
|
|
50
|
-
{ operationalStateId: 64 },
|
|
51
|
-
{ operationalStateId: 65 },
|
|
52
|
-
{ operationalStateId: 66 },
|
|
53
|
-
],
|
|
54
|
-
operationalState: 66,
|
|
55
|
-
},
|
|
56
|
-
serviceArea: {
|
|
57
|
-
supportedMaps: [],
|
|
58
|
-
supportedAreas: [
|
|
59
|
-
{ areaId: 0, mapId: null, areaInfo: { locationInfo: { locationName: 'Living Room', floorNumber: 0, areaType: 7 }, landmarkInfo: null } },
|
|
60
|
-
{ areaId: 1, mapId: null, areaInfo: { locationInfo: { locationName: 'Kitchen', floorNumber: 0, areaType: 10 }, landmarkInfo: null } },
|
|
61
|
-
{ areaId: 2, mapId: null, areaInfo: { locationInfo: { locationName: 'Bedroom', floorNumber: 0, areaType: 2 }, landmarkInfo: null } },
|
|
62
|
-
{ areaId: 3, mapId: null, areaInfo: { locationInfo: { locationName: 'Bathroom', floorNumber: 0, areaType: 6 }, landmarkInfo: null } },
|
|
63
|
-
],
|
|
64
|
-
selectedAreas: [0, 1, 2, 3],
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
const handlers = opts?.handlers ?? {
|
|
68
|
-
rvcRunMode: { changeToMode: async (request) => this.handleChangeRunMode(request) },
|
|
69
|
-
rvcCleanMode: { changeToMode: async (request) => this.handleChangeCleanMode(request) },
|
|
70
|
-
rvcOperationalState: { pause: async () => this.handlePause(), stop: async () => this.handleStop(), start: async () => this.handleStart(), resume: async () => this.handleResume(), goHome: async () => this.handleGoHome() },
|
|
71
|
-
serviceArea: { selectAreas: async (request) => this.handleSelectAreas(request), skipArea: async (request) => this.handleSkipArea(request) },
|
|
72
|
-
};
|
|
89
|
+
const model = detectModelFromContext(opts?.context);
|
|
90
|
+
const capabilities = capabilitiesFor(model);
|
|
73
91
|
super(api, log, {
|
|
74
92
|
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
75
93
|
displayName: opts?.displayName ?? 'Robot Vacuum',
|
|
@@ -79,188 +97,331 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
79
97
|
model: opts?.model ?? 'HB-MATTER-VACUUM-ROBOTIC',
|
|
80
98
|
firmwareRevision: opts?.firmwareRevision ?? '2.0.0',
|
|
81
99
|
hardwareRevision: opts?.hardwareRevision ?? '1.0.0',
|
|
82
|
-
clusters
|
|
83
|
-
|
|
84
|
-
|
|
100
|
+
clusters: {
|
|
101
|
+
rvcRunMode: {
|
|
102
|
+
supportedModes: [
|
|
103
|
+
{ label: 'Idle', mode: 0, modeTags: [{ value: 16384 }] },
|
|
104
|
+
{ label: 'Cleaning', mode: 1, modeTags: [{ value: 16385 }] },
|
|
105
|
+
],
|
|
106
|
+
currentMode: 0,
|
|
107
|
+
},
|
|
108
|
+
rvcCleanMode: (() => {
|
|
109
|
+
switch (model) {
|
|
110
|
+
case 'K10':
|
|
111
|
+
return {
|
|
112
|
+
supportedModes: [
|
|
113
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
114
|
+
],
|
|
115
|
+
currentMode: 0,
|
|
116
|
+
};
|
|
117
|
+
case 'Robot Vacuum Cleaner S1':
|
|
118
|
+
case 'Robot Vacuum Cleaner S1 Plus':
|
|
119
|
+
return {
|
|
120
|
+
supportedModes: [
|
|
121
|
+
{ label: 'Quiet', mode: 0, modeTags: [{ value: 2 }] },
|
|
122
|
+
{ label: 'Standard', mode: 1, modeTags: [{ value: 16384 }] },
|
|
123
|
+
{ label: 'Strong', mode: 2, modeTags: [{ value: 7 }] },
|
|
124
|
+
{ label: 'MAX', mode: 3, modeTags: [{ value: 8 }] },
|
|
125
|
+
],
|
|
126
|
+
currentMode: 1,
|
|
127
|
+
};
|
|
128
|
+
case 'Mini Robot Vacuum K10+':
|
|
129
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
130
|
+
case 'K10+ Pro Combo':
|
|
131
|
+
return {
|
|
132
|
+
supportedModes: [
|
|
133
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
134
|
+
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
135
|
+
{ label: 'Sweep & Mop', mode: 2, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
136
|
+
],
|
|
137
|
+
currentMode: 0,
|
|
138
|
+
};
|
|
139
|
+
case 'Multitasking Household Robot K20+ Pro':
|
|
140
|
+
return {
|
|
141
|
+
supportedModes: [
|
|
142
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
143
|
+
{ label: 'Vacuum & Mop', mode: 1, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
144
|
+
{ label: 'Deep Clean', mode: 2, modeTags: [{ value: 16384 }] },
|
|
145
|
+
],
|
|
146
|
+
currentMode: 0,
|
|
147
|
+
};
|
|
148
|
+
case 'Floor Cleaning Robot S10':
|
|
149
|
+
case 'Floor Cleaning Robot S20':
|
|
150
|
+
return {
|
|
151
|
+
supportedModes: [
|
|
152
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
153
|
+
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
154
|
+
],
|
|
155
|
+
currentMode: 0,
|
|
156
|
+
};
|
|
157
|
+
case 'Robot Vacuum K11+':
|
|
158
|
+
return {
|
|
159
|
+
supportedModes: [
|
|
160
|
+
{ label: 'Quiet', mode: 0, modeTags: [{ value: 2 }] },
|
|
161
|
+
{ label: 'Standard', mode: 1, modeTags: [{ value: 16384 }] },
|
|
162
|
+
{ label: 'Strong', mode: 2, modeTags: [{ value: 7 }] },
|
|
163
|
+
{ label: 'MAX', mode: 3, modeTags: [{ value: 8 }] },
|
|
164
|
+
{ label: 'Deep Clean', mode: 4, modeTags: [{ value: 16384 }, { value: 16385 }] },
|
|
165
|
+
],
|
|
166
|
+
currentMode: 1,
|
|
167
|
+
};
|
|
168
|
+
default:
|
|
169
|
+
return {
|
|
170
|
+
supportedModes: [
|
|
171
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
172
|
+
{ label: 'Vacuum & Mop', mode: 1, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
173
|
+
{ label: 'Deep Clean', mode: 2, modeTags: [{ value: 16384 }] },
|
|
174
|
+
],
|
|
175
|
+
currentMode: 0,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
})(),
|
|
179
|
+
rvcOperationalState: {
|
|
180
|
+
operationalStateList: [
|
|
181
|
+
{ operationalStateId: 0 }, // Stopped
|
|
182
|
+
{ operationalStateId: 1 }, // Running
|
|
183
|
+
{ operationalStateId: 2 }, // Paused
|
|
184
|
+
{ operationalStateId: 3 }, // Error
|
|
185
|
+
{ operationalStateId: 64 }, // Seeking Charger
|
|
186
|
+
{ operationalStateId: 65 }, // Charging
|
|
187
|
+
{ operationalStateId: 66 }, // Docked
|
|
188
|
+
{ operationalStateId: 67 }, // In Remote Control
|
|
189
|
+
{ operationalStateId: 68 }, // In Dust Collecting
|
|
190
|
+
],
|
|
191
|
+
operationalState: 66,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
handlers: (() => {
|
|
195
|
+
const opHandlers = {
|
|
196
|
+
stop: async () => this.handleStop(),
|
|
197
|
+
start: async () => this.handleStart(),
|
|
198
|
+
goHome: async () => this.handleGoHome(),
|
|
199
|
+
// Always register resume handler, log warning if not supported
|
|
200
|
+
resume: async () => {
|
|
201
|
+
if (capabilities.resume) {
|
|
202
|
+
await this.handleResume();
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
this.logWarn(`Resume operation is not supported for model: ${this.model}`);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
if (capabilities.pause) {
|
|
210
|
+
opHandlers.pause = async () => this.handlePause();
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
rvcRunMode: { changeToMode: async (request) => this.handleChangeRunMode(request) },
|
|
214
|
+
rvcCleanMode: { changeToMode: async (request) => this.handleChangeCleanMode(request) },
|
|
215
|
+
rvcOperationalState: opHandlers,
|
|
216
|
+
};
|
|
217
|
+
})(),
|
|
218
|
+
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}), deviceType: opts?.context?.deviceType },
|
|
85
219
|
});
|
|
220
|
+
this.capabilities = capabilities;
|
|
86
221
|
this.logInfo('initialized and ready.');
|
|
87
222
|
}
|
|
88
223
|
async handleChangeRunMode(request) {
|
|
89
224
|
this.logInfo(`ChangeToMode (run) request received: ${JSON.stringify(request)}`);
|
|
90
225
|
const { newMode } = request;
|
|
91
|
-
const modeStr = ['Idle', 'Cleaning', '
|
|
92
|
-
this.logInfo(`
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
226
|
+
const modeStr = ['Idle', 'Cleaning', 'Returning to Dock'][newMode] || `Unknown (mode=${newMode})`;
|
|
227
|
+
this.logInfo(`Changing run mode to: ${modeStr}`);
|
|
228
|
+
switch (this.model) {
|
|
229
|
+
case 'Robot Vacuum Cleaner S1':
|
|
230
|
+
case 'Robot Vacuum Cleaner S1 Plus': {
|
|
231
|
+
if (newMode === 1) {
|
|
232
|
+
await this.handleStart();
|
|
233
|
+
}
|
|
234
|
+
else if (newMode === 0) {
|
|
235
|
+
await this.handleGoHome();
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case 'Mini Robot Vacuum K10+':
|
|
240
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
241
|
+
case 'K10+ Pro Combo': {
|
|
242
|
+
if (newMode === 1) {
|
|
243
|
+
await this.handleStart();
|
|
244
|
+
}
|
|
245
|
+
else if (newMode === 2) {
|
|
246
|
+
await this.handleDock();
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
case 'Multitasking Household Robot K20+ Pro': {
|
|
251
|
+
if (newMode === 1) {
|
|
252
|
+
await this.handleStart();
|
|
253
|
+
}
|
|
254
|
+
else if (newMode === 0) {
|
|
255
|
+
await this.handleGoHome();
|
|
256
|
+
}
|
|
257
|
+
else if (newMode === 2) {
|
|
258
|
+
await this.handlePause();
|
|
259
|
+
}
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
case 'Floor Cleaning Robot S10':
|
|
263
|
+
case 'Floor Cleaning Robot S20': {
|
|
264
|
+
if (newMode === 1) {
|
|
265
|
+
await this.handleStart();
|
|
266
|
+
}
|
|
267
|
+
else if (newMode === 0) {
|
|
268
|
+
await this.handleGoHome();
|
|
269
|
+
}
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
case 'Robot Vacuum K11+': {
|
|
273
|
+
if (newMode === 1) {
|
|
274
|
+
await this.handleStart();
|
|
275
|
+
}
|
|
276
|
+
else if (newMode === 0) {
|
|
277
|
+
await this.handleGoHome();
|
|
278
|
+
}
|
|
279
|
+
else if (newMode === 2) {
|
|
280
|
+
await this.handleDock();
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
default:
|
|
285
|
+
this.logWarn(`Run mode change not supported for model: ${this.model}`);
|
|
120
286
|
}
|
|
121
287
|
}
|
|
122
288
|
async handleChangeCleanMode(request) {
|
|
123
289
|
this.logInfo(`ChangeToMode (clean) request received: ${JSON.stringify(request)}`);
|
|
124
290
|
const { newMode } = request;
|
|
125
|
-
|
|
126
|
-
'Vacuum'
|
|
127
|
-
'
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
'
|
|
135
|
-
'
|
|
136
|
-
'
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
291
|
+
switch (this.model) {
|
|
292
|
+
case 'Robot Vacuum Cleaner S1':
|
|
293
|
+
case 'Robot Vacuum Cleaner S1 Plus': {
|
|
294
|
+
const mapPowS1 = ['Quiet', 'Standard', 'Strong', 'MAX'];
|
|
295
|
+
const labelS1 = mapPowS1[newMode] ?? `Unknown (${newMode})`;
|
|
296
|
+
this.logInfo(`Changing suction level to: ${labelS1}`);
|
|
297
|
+
await this.sendOpenAPICommand('PowLevel', String(newMode));
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
case 'Mini Robot Vacuum K10+':
|
|
301
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
302
|
+
case 'K10+ Pro Combo': {
|
|
303
|
+
const mapPowK10 = ['Vacuum', 'Mop', 'Sweep & Mop'];
|
|
304
|
+
const labelK10 = mapPowK10[newMode] ?? `Unknown (${newMode})`;
|
|
305
|
+
this.logInfo(`Changing cleaning mode to: ${labelK10}`);
|
|
306
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode));
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
case 'Multitasking Household Robot K20+ Pro': {
|
|
310
|
+
const mapPowK20 = ['Vacuum', 'Vacuum & Mop', 'Deep Clean'];
|
|
311
|
+
const labelK20 = mapPowK20[newMode] ?? `Unknown (${newMode})`;
|
|
312
|
+
this.logInfo(`Changing cleaning mode to: ${labelK20}`);
|
|
313
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode));
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
case 'Floor Cleaning Robot S10':
|
|
317
|
+
case 'Floor Cleaning Robot S20': {
|
|
318
|
+
const mapPowS10 = ['Vacuum', 'Mop'];
|
|
319
|
+
const labelS10 = mapPowS10[newMode] ?? `Unknown (${newMode})`;
|
|
320
|
+
this.logInfo(`Changing cleaning mode to: ${labelS10}`);
|
|
321
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode));
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
case 'Robot Vacuum K11+': {
|
|
325
|
+
const mapPowK11 = ['Quiet', 'Standard', 'Strong', 'MAX', 'Deep Clean'];
|
|
326
|
+
const labelK11 = mapPowK11[newMode] ?? `Unknown (${newMode})`;
|
|
327
|
+
this.logInfo(`Changing suction level to: ${labelK11}`);
|
|
328
|
+
await this.sendOpenAPICommand('PowLevel', String(newMode));
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
default:
|
|
332
|
+
this.logWarn(`Clean mode change not supported for model: ${this.model}`);
|
|
333
|
+
}
|
|
145
334
|
}
|
|
146
335
|
async handlePause() {
|
|
147
336
|
this.logInfo('pausing.');
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
337
|
+
try {
|
|
338
|
+
this.logInfo(`[OpenAPI] Sending pause command`);
|
|
339
|
+
await this.sendOpenAPICommand('pause');
|
|
340
|
+
this.logInfo(`[OpenAPI] pause command sent`);
|
|
341
|
+
}
|
|
342
|
+
catch (e) {
|
|
343
|
+
this.logWarn(`OpenAPI pause failed: ${String(e?.message ?? e)}`);
|
|
344
|
+
}
|
|
345
|
+
this.updateOperationalState(2);
|
|
151
346
|
}
|
|
152
347
|
async handleStop() {
|
|
153
348
|
this.logInfo('stopping.');
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
349
|
+
try {
|
|
350
|
+
if (this.capabilities.cleanAction === 'vacuum-only' && this.capabilities.suctionKind === 'powLevel-0-3') {
|
|
351
|
+
this.logInfo(`[OpenAPI] Sending stop command`);
|
|
352
|
+
await this.sendOpenAPICommand('stop');
|
|
353
|
+
this.logInfo(`[OpenAPI] stop command sent`);
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
this.logInfo(`[OpenAPI] Sending pause command (for stop)`);
|
|
357
|
+
await this.sendOpenAPICommand('pause');
|
|
358
|
+
this.logInfo(`[OpenAPI] pause command sent (for stop)`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch (e) {
|
|
362
|
+
this.logWarn(`OpenAPI stop/pause failed: ${String(e?.message ?? e)}`);
|
|
363
|
+
}
|
|
364
|
+
this.updateRunMode(0);
|
|
365
|
+
this.updateOperationalState(0);
|
|
158
366
|
}
|
|
159
367
|
async handleStart() {
|
|
160
|
-
this.logInfo('starting
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
368
|
+
this.logInfo('starting clean.');
|
|
369
|
+
try {
|
|
370
|
+
if (this.capabilities.cleanAction === 'vacuum-only' && this.capabilities.suctionKind === 'powLevel-0-3') {
|
|
371
|
+
this.logInfo(`[OpenAPI] Sending start command`);
|
|
372
|
+
await this.sendOpenAPICommand('start');
|
|
373
|
+
this.logInfo(`[OpenAPI] start command sent`);
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const action = this.currentCleanAction === 'vacuum_mop' ? 'sweep_mop' : this.currentCleanAction;
|
|
377
|
+
const param = { action, param: { fanLevel: this.currentFanLevel } };
|
|
378
|
+
if (this.capabilities.waterLevel) {
|
|
379
|
+
param.param.waterLevel = 1;
|
|
380
|
+
}
|
|
381
|
+
this.logInfo(`[OpenAPI] Sending startClean: ${JSON.stringify(param)}`);
|
|
382
|
+
await this.sendOpenAPICommand('startClean', JSON.stringify(param));
|
|
383
|
+
this.logInfo(`[OpenAPI] startClean command sent: ${JSON.stringify(param)}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
catch (e) {
|
|
387
|
+
this.logWarn(`OpenAPI start/startClean failed: ${String(e?.message ?? e)}`);
|
|
388
|
+
}
|
|
389
|
+
this.updateRunMode(1);
|
|
390
|
+
this.updateOperationalState(1);
|
|
173
391
|
}
|
|
174
392
|
async handleResume() {
|
|
175
|
-
this.logInfo('
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}, 10000);
|
|
187
|
-
this.activeTimers.push(completionTimer);
|
|
393
|
+
this.logInfo('resume requested.');
|
|
394
|
+
try {
|
|
395
|
+
this.logInfo(`[OpenAPI] Sending resume command`);
|
|
396
|
+
await this.sendOpenAPICommand('resume');
|
|
397
|
+
this.logInfo(`[OpenAPI] resume command sent`);
|
|
398
|
+
}
|
|
399
|
+
catch (e) {
|
|
400
|
+
this.logWarn(`OpenAPI resume failed: ${String(e?.message ?? e)}`);
|
|
401
|
+
}
|
|
402
|
+
this.updateRunMode(1);
|
|
403
|
+
this.updateOperationalState(1);
|
|
188
404
|
}
|
|
189
405
|
async handleGoHome() {
|
|
190
|
-
this.logInfo('
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
this.
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
async handleSelectAreas(request) {
|
|
203
|
-
this.logInfo(`SelectAreas request received: ${JSON.stringify(request)}`);
|
|
204
|
-
const { newAreas } = request;
|
|
205
|
-
const areaNames = newAreas.map((id) => ['Living Room', 'Kitchen', 'Bedroom', 'Bathroom'][id] || `Area ${id}`);
|
|
206
|
-
this.logInfo(`selecting areas: ${areaNames.join(', ')}`);
|
|
207
|
-
// TODO: await myVacuumAPI.selectAreas(newAreas)
|
|
208
|
-
}
|
|
209
|
-
async handleSkipArea(request) {
|
|
210
|
-
this.logInfo(`SkipArea request received: ${JSON.stringify(request)}`);
|
|
211
|
-
const { skippedArea } = request;
|
|
212
|
-
const areaName = ['Living Room', 'Kitchen', 'Bedroom', 'Bathroom'][skippedArea] || `Area ${skippedArea}`;
|
|
213
|
-
this.logInfo(`skipping area: ${areaName}`);
|
|
214
|
-
// TODO: await myVacuumAPI.skipArea(skippedArea)
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Helper method to clear all active timers
|
|
218
|
-
*/
|
|
219
|
-
clearTimers() {
|
|
220
|
-
this.activeTimers.forEach(timer => clearTimeout(timer));
|
|
221
|
-
this.activeTimers = [];
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Helper method to initiate return to dock sequence
|
|
225
|
-
* Can be called synchronously from other handlers
|
|
226
|
-
*/
|
|
227
|
-
returnToDock() {
|
|
228
|
-
this.logInfo('initiating return to dock sequence.');
|
|
229
|
-
// Defer ALL state updates to ensure handler completes first
|
|
230
|
-
setImmediate(() => {
|
|
231
|
-
// Start seeking charger directly (skip intermediate Stopped state)
|
|
232
|
-
this.updateOperationalState(64); // Seeking Charger
|
|
233
|
-
// After 5 seconds, start charging
|
|
234
|
-
const chargingTimer = setTimeout(() => {
|
|
235
|
-
this.logInfo('reached dock, now charging.');
|
|
236
|
-
this.updateOperationalState(65); // Charging
|
|
237
|
-
// After 3 more seconds, fully docked
|
|
238
|
-
const dockedTimer = setTimeout(() => {
|
|
239
|
-
this.logInfo('fully charged and docked.');
|
|
240
|
-
this.updateOperationalState(66); // Docked
|
|
241
|
-
}, 3000);
|
|
242
|
-
this.activeTimers.push(dockedTimer);
|
|
243
|
-
}, 5000);
|
|
244
|
-
this.activeTimers.push(chargingTimer);
|
|
245
|
-
});
|
|
406
|
+
this.logInfo('returning to dock.');
|
|
407
|
+
try {
|
|
408
|
+
this.logInfo(`[OpenAPI] Sending dock command`);
|
|
409
|
+
await this.sendOpenAPICommand('dock');
|
|
410
|
+
this.logInfo(`[OpenAPI] dock command sent`);
|
|
411
|
+
}
|
|
412
|
+
catch (e) {
|
|
413
|
+
this.logWarn(`OpenAPI dock failed: ${String(e?.message ?? e)}`);
|
|
414
|
+
}
|
|
415
|
+
this.updateRunMode(0);
|
|
416
|
+
this.updateOperationalState(64);
|
|
246
417
|
}
|
|
247
|
-
/**
|
|
248
|
-
* Update Methods - Use these to update the vacuum state from your API/device
|
|
249
|
-
*
|
|
250
|
-
* Since this is a platform accessory, state updates work immediately after registration.
|
|
251
|
-
*/
|
|
252
418
|
updateOperationalState(state) {
|
|
253
419
|
this.updateState('rvcOperationalState', { operationalState: state });
|
|
254
420
|
const states = [
|
|
255
421
|
'Stopped',
|
|
256
422
|
'Running',
|
|
257
423
|
'Paused',
|
|
258
|
-
|
|
259
|
-
null,
|
|
260
|
-
null,
|
|
261
|
-
null,
|
|
262
|
-
null,
|
|
263
|
-
...Array.from({ length: 56 }).fill(null),
|
|
424
|
+
...Array.from({ length: 61 }).fill(null),
|
|
264
425
|
'Seeking Charger',
|
|
265
426
|
'Charging',
|
|
266
427
|
'Docked',
|
|
@@ -269,66 +430,115 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
269
430
|
}
|
|
270
431
|
updateRunMode(mode) {
|
|
271
432
|
this.updateState('rvcRunMode', { currentMode: mode });
|
|
272
|
-
const modes = ['Idle', 'Cleaning'
|
|
433
|
+
const modes = ['Idle', 'Cleaning'];
|
|
273
434
|
this.logInfo(`run mode updated to: ${modes[mode] || `Unknown (${mode})`}`);
|
|
274
435
|
}
|
|
275
436
|
updateCleanMode(mode) {
|
|
276
437
|
this.updateState('rvcCleanMode', { currentMode: mode });
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
'Mop',
|
|
280
|
-
'Vacuum & Mop',
|
|
281
|
-
'Deep Clean',
|
|
282
|
-
'Deep Vacuum',
|
|
283
|
-
'Deep Mop',
|
|
284
|
-
'Quick Clean',
|
|
285
|
-
'Max Clean',
|
|
286
|
-
'Min Clean',
|
|
287
|
-
'Quiet Vacuum',
|
|
288
|
-
'Quiet Mop',
|
|
289
|
-
'Night Mode',
|
|
290
|
-
'Eco Vacuum',
|
|
291
|
-
'Eco Mop',
|
|
292
|
-
'Auto',
|
|
293
|
-
];
|
|
294
|
-
this.logInfo(`clean mode updated to: ${modes[mode] || `Unknown (${mode})`}`);
|
|
438
|
+
const label = mode === 0 ? 'Vacuum' : mode === 1 ? 'Mop' : mode === 2 ? 'Vacuum & Mop' : 'Unknown';
|
|
439
|
+
this.logInfo(`clean mode updated to: ${label}`);
|
|
295
440
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
441
|
+
/**
|
|
442
|
+
* Update battery percentage (no PowerSource cluster for this device type)
|
|
443
|
+
*/
|
|
444
|
+
async updateBatteryPercentage(percentageOrBatPercentRemaining) {
|
|
445
|
+
const isBatPercent = Number(percentageOrBatPercentRemaining) > 100;
|
|
446
|
+
const percentage = isBatPercent
|
|
447
|
+
? Math.max(0, Math.min(100, Math.round(Number(percentageOrBatPercentRemaining) / 2)))
|
|
448
|
+
: Math.max(0, Math.min(100, Math.round(Number(percentageOrBatPercentRemaining))));
|
|
449
|
+
let chargeLevel = 0; // Ok
|
|
450
|
+
if (percentage < 20) {
|
|
451
|
+
chargeLevel = 2; // Critical
|
|
452
|
+
}
|
|
453
|
+
else if (percentage < 40) {
|
|
454
|
+
chargeLevel = 1; // Warning
|
|
455
|
+
}
|
|
456
|
+
this.logInfo(`battery status: ${percentage}% (${chargeLevel === 0 ? 'Ok' : chargeLevel === 1 ? 'Warning' : 'Critical'})`);
|
|
457
|
+
if (this.context) {
|
|
458
|
+
this.context.batteryPercentage = percentage;
|
|
459
|
+
this.context.batteryChargeLevel = chargeLevel;
|
|
460
|
+
}
|
|
300
461
|
}
|
|
301
|
-
|
|
302
|
-
this.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
this.
|
|
462
|
+
async handleDock() {
|
|
463
|
+
this.logInfo('Docking the vacuum.');
|
|
464
|
+
try {
|
|
465
|
+
this.logInfo('[OpenAPI] Sending dock command');
|
|
466
|
+
await this.sendOpenAPICommand('dock');
|
|
467
|
+
this.logInfo('[OpenAPI] Dock command sent successfully');
|
|
468
|
+
this.updateRunMode(0); // Set to Idle after docking
|
|
469
|
+
this.updateOperationalState(64); // Seeking Charger state
|
|
306
470
|
}
|
|
307
|
-
|
|
308
|
-
this.
|
|
471
|
+
catch (error) {
|
|
472
|
+
this.logWarn(`Docking failed: ${String(error?.message ?? error)}`);
|
|
309
473
|
}
|
|
310
474
|
}
|
|
311
|
-
|
|
312
|
-
this.
|
|
313
|
-
|
|
475
|
+
async handleServiceArea() {
|
|
476
|
+
this.logWarn(`Service area functionality is not supported for model: ${this.model}`);
|
|
477
|
+
// Placeholder for potential future support.
|
|
314
478
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
479
|
+
async simulateCleaningSequence() {
|
|
480
|
+
this.logInfo('Starting cleaning sequence simulation.');
|
|
481
|
+
this.updateOperationalState(1); // Set to Running
|
|
482
|
+
setTimeout(async () => {
|
|
483
|
+
this.logInfo('Cleaning sequence timer expired. Requesting device status update.');
|
|
484
|
+
try {
|
|
485
|
+
const status = await this.requestDeviceStatus();
|
|
486
|
+
if (status && status.operationalState) {
|
|
487
|
+
this.logInfo(`Device status found: ${status.operationalState}`);
|
|
488
|
+
this.updateOperationalState(status.operationalState);
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
this.logWarn('Device status not found. Setting operational state to Stopped.');
|
|
492
|
+
this.updateOperationalState(0); // Default to Stopped
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
this.logWarn(`Failed to fetch device status: ${String(error?.message ?? error)}`);
|
|
497
|
+
this.updateOperationalState(0); // Default to Stopped
|
|
498
|
+
}
|
|
499
|
+
}, 5000); // Simulate a 5-second cleaning sequence
|
|
500
|
+
}
|
|
501
|
+
async simulateDockingSequence() {
|
|
502
|
+
this.logInfo('Starting docking sequence simulation.');
|
|
503
|
+
this.updateOperationalState(64); // Set to Seeking Charger
|
|
504
|
+
setTimeout(async () => {
|
|
505
|
+
this.logInfo('Docking sequence timer expired. Requesting device status update.');
|
|
506
|
+
try {
|
|
507
|
+
const status = await this.requestDeviceStatus();
|
|
508
|
+
if (status && status.operationalState) {
|
|
509
|
+
this.logInfo(`Device status found: ${status.operationalState}`);
|
|
510
|
+
this.updateOperationalState(status.operationalState);
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
this.logWarn('Device status not found. Setting operational state to Docked.');
|
|
514
|
+
this.updateOperationalState(66); // Default to Docked
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
this.logWarn(`Failed to fetch device status: ${String(error?.message ?? error)}`);
|
|
519
|
+
this.updateOperationalState(66); // Default to Docked
|
|
520
|
+
}
|
|
521
|
+
}, 5000); // Simulate a 5-second docking sequence
|
|
522
|
+
}
|
|
523
|
+
async requestDeviceStatus() {
|
|
524
|
+
this.logInfo('Requesting device status from OpenAPI.');
|
|
525
|
+
try {
|
|
526
|
+
const response = await this.sendOpenAPICommand('getDeviceStatus');
|
|
527
|
+
this.logInfo(`Device status response: ${JSON.stringify(response)}`);
|
|
528
|
+
return response;
|
|
326
529
|
}
|
|
327
|
-
|
|
328
|
-
|
|
530
|
+
catch (error) {
|
|
531
|
+
this.logWarn(`Failed to request device status: ${String(error?.message ?? error)}`);
|
|
532
|
+
return null;
|
|
329
533
|
}
|
|
330
|
-
|
|
331
|
-
|
|
534
|
+
}
|
|
535
|
+
async startCleaningSimulation() {
|
|
536
|
+
this.logInfo('Initiating cleaning simulation.');
|
|
537
|
+
await this.simulateCleaningSequence();
|
|
538
|
+
}
|
|
539
|
+
async startDockingSimulation() {
|
|
540
|
+
this.logInfo('Initiating docking simulation.');
|
|
541
|
+
await this.simulateDockingSequence();
|
|
332
542
|
}
|
|
333
543
|
}
|
|
334
544
|
//# sourceMappingURL=RoboticVacuumAccessory.js.map
|