@switchbot/homebridge-switchbot 5.0.0-beta.63 → 5.0.0-beta.65
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/config.schema.json +9 -4
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts +7 -0
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +1 -1
- package/dist/devices-matter/RoboticVacuumAccessory.js +272 -87
- package/dist/devices-matter/RoboticVacuumAccessory.js.map +1 -1
- package/dist/settings.d.ts +17 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js.map +1 -1
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/devices-matter/RoboticVacuumAccessory.ts +269 -82
- package/src/settings.ts +17 -1
- package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.d.ts +0 -2
- package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.d.ts.map +0 -1
- package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.js +0 -366
- package/dist/test/matter/devices-matter/roboticVacuumAccessory.test.js.map +0 -1
- package/src/test/matter/devices-matter/roboticVacuumAccessory.test.ts +0 -453
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=></span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/
|
|
1
|
+
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=></span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/f7041b5fa47c90b445909ecea8a760a4366b2e4f/src/index.ts#L13">index.ts:13</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@switchbot/homebridge-switchbot",
|
|
3
3
|
"displayName": "SwitchBot",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "5.0.0-beta.
|
|
5
|
+
"version": "5.0.0-beta.65",
|
|
6
6
|
"description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.",
|
|
7
7
|
"author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
|
|
8
8
|
"contributors": [
|
|
@@ -180,32 +180,74 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
180
180
|
currentMode: 0,
|
|
181
181
|
},
|
|
182
182
|
rvcCleanMode: (() => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
183
|
+
switch (model as string) {
|
|
184
|
+
case 'K10':
|
|
185
|
+
return {
|
|
186
|
+
supportedModes: [
|
|
187
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
188
|
+
],
|
|
189
|
+
currentMode: 0,
|
|
190
|
+
}
|
|
191
|
+
case 'Robot Vacuum Cleaner S1':
|
|
192
|
+
case 'Robot Vacuum Cleaner S1 Plus':
|
|
193
|
+
return {
|
|
194
|
+
supportedModes: [
|
|
195
|
+
{ label: 'Quiet', mode: 0, modeTags: [{ value: 2 }] },
|
|
196
|
+
{ label: 'Standard', mode: 1, modeTags: [{ value: 16384 }] },
|
|
197
|
+
{ label: 'Strong', mode: 2, modeTags: [{ value: 7 }] },
|
|
198
|
+
{ label: 'MAX', mode: 3, modeTags: [{ value: 8 }] },
|
|
199
|
+
],
|
|
200
|
+
currentMode: 1,
|
|
201
|
+
}
|
|
202
|
+
case 'Mini Robot Vacuum K10+':
|
|
203
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
204
|
+
case 'K10+ Pro Combo':
|
|
205
|
+
return {
|
|
206
|
+
supportedModes: [
|
|
207
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
208
|
+
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
209
|
+
{ label: 'Sweep & Mop', mode: 2, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
210
|
+
],
|
|
211
|
+
currentMode: 0,
|
|
212
|
+
}
|
|
213
|
+
case 'Multitasking Household Robot K20+ Pro':
|
|
214
|
+
return {
|
|
215
|
+
supportedModes: [
|
|
216
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
217
|
+
{ label: 'Vacuum & Mop', mode: 1, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
218
|
+
{ label: 'Deep Clean', mode: 2, modeTags: [{ value: 16384 }] },
|
|
219
|
+
],
|
|
220
|
+
currentMode: 0,
|
|
221
|
+
}
|
|
222
|
+
case 'Floor Cleaning Robot S10':
|
|
223
|
+
case 'Floor Cleaning Robot S20':
|
|
224
|
+
return {
|
|
225
|
+
supportedModes: [
|
|
226
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
227
|
+
{ label: 'Mop', mode: 1, modeTags: [{ value: 16386 }] },
|
|
228
|
+
],
|
|
229
|
+
currentMode: 0,
|
|
230
|
+
}
|
|
231
|
+
case 'Robot Vacuum K11+':
|
|
232
|
+
return {
|
|
233
|
+
supportedModes: [
|
|
234
|
+
{ label: 'Quiet', mode: 0, modeTags: [{ value: 2 }] },
|
|
235
|
+
{ label: 'Standard', mode: 1, modeTags: [{ value: 16384 }] },
|
|
236
|
+
{ label: 'Strong', mode: 2, modeTags: [{ value: 7 }] },
|
|
237
|
+
{ label: 'MAX', mode: 3, modeTags: [{ value: 8 }] },
|
|
238
|
+
{ label: 'Deep Clean', mode: 4, modeTags: [{ value: 16384 }, { value: 16385 }] },
|
|
239
|
+
],
|
|
240
|
+
currentMode: 1,
|
|
241
|
+
}
|
|
242
|
+
default:
|
|
243
|
+
return {
|
|
244
|
+
supportedModes: [
|
|
245
|
+
{ label: 'Vacuum', mode: 0, modeTags: [{ value: 16385 }] },
|
|
246
|
+
{ label: 'Vacuum & Mop', mode: 1, modeTags: [{ value: 16385 }, { value: 16386 }] },
|
|
247
|
+
{ label: 'Deep Clean', mode: 2, modeTags: [{ value: 16384 }] },
|
|
248
|
+
],
|
|
249
|
+
currentMode: 0,
|
|
250
|
+
}
|
|
209
251
|
}
|
|
210
252
|
})(),
|
|
211
253
|
rvcOperationalState: {
|
|
@@ -213,9 +255,12 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
213
255
|
{ operationalStateId: 0 }, // Stopped
|
|
214
256
|
{ operationalStateId: 1 }, // Running
|
|
215
257
|
{ operationalStateId: 2 }, // Paused
|
|
258
|
+
{ operationalStateId: 3 }, // Error
|
|
216
259
|
{ operationalStateId: 64 }, // Seeking Charger
|
|
217
260
|
{ operationalStateId: 65 }, // Charging
|
|
218
261
|
{ operationalStateId: 66 }, // Docked
|
|
262
|
+
{ operationalStateId: 67 }, // In Remote Control
|
|
263
|
+
{ operationalStateId: 68 }, // In Dust Collecting
|
|
219
264
|
],
|
|
220
265
|
operationalState: 66,
|
|
221
266
|
},
|
|
@@ -225,13 +270,18 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
225
270
|
stop: async () => this.handleStop(),
|
|
226
271
|
start: async () => this.handleStart(),
|
|
227
272
|
goHome: async () => this.handleGoHome(),
|
|
273
|
+
// Always register resume handler, log warning if not supported
|
|
274
|
+
resume: async () => {
|
|
275
|
+
if (capabilities.resume) {
|
|
276
|
+
await this.handleResume()
|
|
277
|
+
} else {
|
|
278
|
+
this.logWarn(`Resume operation is not supported for model: ${this.model}`)
|
|
279
|
+
}
|
|
280
|
+
},
|
|
228
281
|
}
|
|
229
282
|
if (capabilities.pause) {
|
|
230
283
|
opHandlers.pause = async () => this.handlePause()
|
|
231
284
|
}
|
|
232
|
-
if (capabilities.resume) {
|
|
233
|
-
opHandlers.resume = async () => this.handleResume()
|
|
234
|
-
}
|
|
235
285
|
return {
|
|
236
286
|
rvcRunMode: { changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeRunMode(request) },
|
|
237
287
|
rvcCleanMode: { changeToMode: async (request: MatterRequests.ChangeToMode) => this.handleChangeCleanMode(request) },
|
|
@@ -248,58 +298,110 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
248
298
|
private async handleChangeRunMode(request: MatterRequests.ChangeToMode): Promise<void> {
|
|
249
299
|
this.logInfo(`ChangeToMode (run) request received: ${JSON.stringify(request)}`)
|
|
250
300
|
const { newMode } = request
|
|
251
|
-
const modeStr = ['Idle', 'Cleaning'][newMode] || `Unknown (mode=${newMode})`
|
|
252
|
-
this.logInfo(`
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
301
|
+
const modeStr = ['Idle', 'Cleaning', 'Returning to Dock'][newMode] || `Unknown (mode=${newMode})`
|
|
302
|
+
this.logInfo(`Changing run mode to: ${modeStr}`)
|
|
303
|
+
|
|
304
|
+
switch (this.model) {
|
|
305
|
+
case 'Robot Vacuum Cleaner S1':
|
|
306
|
+
case 'Robot Vacuum Cleaner S1 Plus': {
|
|
307
|
+
if (newMode === 1) {
|
|
308
|
+
await this.handleStart()
|
|
309
|
+
} else if (newMode === 0) {
|
|
310
|
+
await this.handleGoHome()
|
|
311
|
+
}
|
|
312
|
+
break
|
|
313
|
+
}
|
|
314
|
+
case 'Mini Robot Vacuum K10+':
|
|
315
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
316
|
+
case 'K10+ Pro Combo': {
|
|
317
|
+
if (newMode === 1) {
|
|
318
|
+
await this.handleStart()
|
|
319
|
+
} else if (newMode === 2) {
|
|
320
|
+
await this.handleDock()
|
|
321
|
+
}
|
|
322
|
+
break
|
|
323
|
+
}
|
|
324
|
+
case 'Multitasking Household Robot K20+ Pro': {
|
|
325
|
+
if (newMode === 1) {
|
|
326
|
+
await this.handleStart()
|
|
327
|
+
} else if (newMode === 0) {
|
|
328
|
+
await this.handleGoHome()
|
|
329
|
+
} else if (newMode === 2) {
|
|
330
|
+
await this.handlePause()
|
|
331
|
+
}
|
|
332
|
+
break
|
|
333
|
+
}
|
|
334
|
+
case 'Floor Cleaning Robot S10':
|
|
335
|
+
case 'Floor Cleaning Robot S20': {
|
|
336
|
+
if (newMode === 1) {
|
|
337
|
+
await this.handleStart()
|
|
338
|
+
} else if (newMode === 0) {
|
|
339
|
+
await this.handleGoHome()
|
|
340
|
+
}
|
|
341
|
+
break
|
|
342
|
+
}
|
|
343
|
+
case 'Robot Vacuum K11+': {
|
|
344
|
+
if (newMode === 1) {
|
|
345
|
+
await this.handleStart()
|
|
346
|
+
} else if (newMode === 0) {
|
|
347
|
+
await this.handleGoHome()
|
|
348
|
+
} else if (newMode === 2) {
|
|
349
|
+
await this.handleDock()
|
|
350
|
+
}
|
|
351
|
+
break
|
|
352
|
+
}
|
|
353
|
+
default:
|
|
354
|
+
this.logWarn(`Run mode change not supported for model: ${this.model}`)
|
|
257
355
|
}
|
|
258
356
|
}
|
|
259
357
|
|
|
260
358
|
private async handleChangeCleanMode(request: MatterRequests.ChangeToMode): Promise<void> {
|
|
261
359
|
this.logInfo(`ChangeToMode (clean) request received: ${JSON.stringify(request)}`)
|
|
262
360
|
const { newMode } = request
|
|
263
|
-
if (this.capabilities.cleanAction === 'vacuum-only') {
|
|
264
|
-
const mapPow = ['Quiet', 'Standard', 'Strong', 'MAX'] as const
|
|
265
|
-
const label = mapPow[newMode] ?? `Unknown (${newMode})`
|
|
266
|
-
this.logInfo(`changing suction level to: ${label}`)
|
|
267
|
-
if (this.capabilities.suctionKind === 'powLevel-0-3') {
|
|
268
|
-
try {
|
|
269
|
-
this.logInfo(`[OpenAPI] Sending PowLevel: ${newMode}`)
|
|
270
|
-
await this.sendOpenAPICommand('PowLevel', String(newMode))
|
|
271
|
-
this.logInfo(`[OpenAPI] PowLevel command sent: ${newMode}`)
|
|
272
|
-
} catch (e: any) {
|
|
273
|
-
this.logWarn(`OpenAPI PowLevel failed: ${String(e?.message ?? e)}`)
|
|
274
|
-
}
|
|
275
|
-
} else if (this.capabilities.suctionKind === 'fanLevel-1-4') {
|
|
276
|
-
this.currentFanLevel = (Math.min(3, Math.max(0, Number(newMode))) + 1) as 1 | 2 | 3 | 4
|
|
277
|
-
try {
|
|
278
|
-
this.logInfo(`[OpenAPI] Sending changeParam fanLevel: ${this.currentFanLevel}`)
|
|
279
|
-
await this.sendOpenAPICommand('changeParam', JSON.stringify({ fanLevel: this.currentFanLevel }))
|
|
280
|
-
this.logInfo(`[OpenAPI] changeParam command sent: fanLevel=${this.currentFanLevel}`)
|
|
281
|
-
} catch (e: any) {
|
|
282
|
-
this.logWarn(`OpenAPI changeParam(fanLevel) failed: ${String(e?.message ?? e)}`)
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
this.updateCleanMode(newMode)
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
361
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
362
|
+
switch (this.model) {
|
|
363
|
+
case 'Robot Vacuum Cleaner S1':
|
|
364
|
+
case 'Robot Vacuum Cleaner S1 Plus': {
|
|
365
|
+
const mapPowS1 = ['Quiet', 'Standard', 'Strong', 'MAX'] as const
|
|
366
|
+
const labelS1 = mapPowS1[newMode] ?? `Unknown (${newMode})`
|
|
367
|
+
this.logInfo(`Changing suction level to: ${labelS1}`)
|
|
368
|
+
await this.sendOpenAPICommand('PowLevel', String(newMode))
|
|
369
|
+
break
|
|
370
|
+
}
|
|
371
|
+
case 'Mini Robot Vacuum K10+':
|
|
372
|
+
case 'Mini Robot Vacuum K10+ Pro':
|
|
373
|
+
case 'K10+ Pro Combo': {
|
|
374
|
+
const mapPowK10 = ['Vacuum', 'Mop', 'Sweep & Mop'] as const
|
|
375
|
+
const labelK10 = mapPowK10[newMode] ?? `Unknown (${newMode})`
|
|
376
|
+
this.logInfo(`Changing cleaning mode to: ${labelK10}`)
|
|
377
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode))
|
|
378
|
+
break
|
|
379
|
+
}
|
|
380
|
+
case 'Multitasking Household Robot K20+ Pro': {
|
|
381
|
+
const mapPowK20 = ['Vacuum', 'Vacuum & Mop', 'Deep Clean'] as const
|
|
382
|
+
const labelK20 = mapPowK20[newMode] ?? `Unknown (${newMode})`
|
|
383
|
+
this.logInfo(`Changing cleaning mode to: ${labelK20}`)
|
|
384
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode))
|
|
385
|
+
break
|
|
386
|
+
}
|
|
387
|
+
case 'Floor Cleaning Robot S10':
|
|
388
|
+
case 'Floor Cleaning Robot S20': {
|
|
389
|
+
const mapPowS10 = ['Vacuum', 'Mop'] as const
|
|
390
|
+
const labelS10 = mapPowS10[newMode] ?? `Unknown (${newMode})`
|
|
391
|
+
this.logInfo(`Changing cleaning mode to: ${labelS10}`)
|
|
392
|
+
await this.sendOpenAPICommand('CleanMode', String(newMode))
|
|
393
|
+
break
|
|
394
|
+
}
|
|
395
|
+
case 'Robot Vacuum K11+': {
|
|
396
|
+
const mapPowK11 = ['Quiet', 'Standard', 'Strong', 'MAX', 'Deep Clean'] as const
|
|
397
|
+
const labelK11 = mapPowK11[newMode] ?? `Unknown (${newMode})`
|
|
398
|
+
this.logInfo(`Changing suction level to: ${labelK11}`)
|
|
399
|
+
await this.sendOpenAPICommand('PowLevel', String(newMode))
|
|
400
|
+
break
|
|
401
|
+
}
|
|
402
|
+
default:
|
|
403
|
+
this.logWarn(`Clean mode change not supported for model: ${this.model}`)
|
|
296
404
|
}
|
|
297
|
-
|
|
298
|
-
const label = newMode === 0 ? 'Vacuum' : 'Vacuum & Mop'
|
|
299
|
-
this.currentCleanAction = newMode === 0 ? 'vacuum' : 'vacuum_mop'
|
|
300
|
-
this.logInfo(`changing clean action to: ${label}`)
|
|
301
|
-
this.logInfo(`[OpenAPI] (no command sent for cleanAction change, just updating state)`)
|
|
302
|
-
this.updateCleanMode(newMode)
|
|
303
405
|
}
|
|
304
406
|
|
|
305
407
|
private async handlePause(): Promise<void> {
|
|
@@ -359,7 +461,15 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
359
461
|
|
|
360
462
|
private async handleResume(): Promise<void> {
|
|
361
463
|
this.logInfo('resume requested.')
|
|
362
|
-
|
|
464
|
+
try {
|
|
465
|
+
this.logInfo(`[OpenAPI] Sending resume command`)
|
|
466
|
+
await this.sendOpenAPICommand('resume')
|
|
467
|
+
this.logInfo(`[OpenAPI] resume command sent`)
|
|
468
|
+
} catch (e: any) {
|
|
469
|
+
this.logWarn(`OpenAPI resume failed: ${String(e?.message ?? e)}`)
|
|
470
|
+
}
|
|
471
|
+
this.updateRunMode(1)
|
|
472
|
+
this.updateOperationalState(1)
|
|
363
473
|
}
|
|
364
474
|
|
|
365
475
|
private async handleGoHome(): Promise<void> {
|
|
@@ -397,14 +507,7 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
397
507
|
|
|
398
508
|
public updateCleanMode(mode: number): void {
|
|
399
509
|
this.updateState('rvcCleanMode', { currentMode: mode })
|
|
400
|
-
|
|
401
|
-
if (this.capabilities.cleanAction === 'vacuum-only') {
|
|
402
|
-
label = ['Quiet', 'Standard', 'Strong', 'MAX'][mode] || label
|
|
403
|
-
} else if (this.capabilities.cleanAction === 'vacuum-or-mop') {
|
|
404
|
-
label = ['Vacuum', 'Mop'][mode] || label
|
|
405
|
-
} else {
|
|
406
|
-
label = ['Vacuum', 'Vacuum & Mop'][mode] || label
|
|
407
|
-
}
|
|
510
|
+
const label = mode === 0 ? 'Vacuum' : mode === 1 ? 'Mop' : mode === 2 ? 'Vacuum & Mop' : 'Unknown'
|
|
408
511
|
this.logInfo(`clean mode updated to: ${label}`)
|
|
409
512
|
}
|
|
410
513
|
|
|
@@ -431,4 +534,88 @@ export class RoboticVacuumAccessory extends BaseMatterAccessory {
|
|
|
431
534
|
;(this.context as any).batteryChargeLevel = chargeLevel
|
|
432
535
|
}
|
|
433
536
|
}
|
|
537
|
+
|
|
538
|
+
private async handleDock(): Promise<void> {
|
|
539
|
+
this.logInfo('Docking the vacuum.')
|
|
540
|
+
try {
|
|
541
|
+
this.logInfo('[OpenAPI] Sending dock command')
|
|
542
|
+
await this.sendOpenAPICommand('dock')
|
|
543
|
+
this.logInfo('[OpenAPI] Dock command sent successfully')
|
|
544
|
+
this.updateRunMode(0) // Set to Idle after docking
|
|
545
|
+
this.updateOperationalState(64) // Seeking Charger state
|
|
546
|
+
} catch (error: any) {
|
|
547
|
+
this.logWarn(`Docking failed: ${String(error?.message ?? error)}`)
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private async handleServiceArea(): Promise<void> {
|
|
552
|
+
this.logWarn(`Service area functionality is not supported for model: ${this.model}`)
|
|
553
|
+
// Placeholder for potential future support.
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
private async simulateCleaningSequence(): Promise<void> {
|
|
557
|
+
this.logInfo('Starting cleaning sequence simulation.')
|
|
558
|
+
this.updateOperationalState(1) // Set to Running
|
|
559
|
+
|
|
560
|
+
setTimeout(async () => {
|
|
561
|
+
this.logInfo('Cleaning sequence timer expired. Requesting device status update.')
|
|
562
|
+
try {
|
|
563
|
+
const status = await this.requestDeviceStatus()
|
|
564
|
+
if (status && status.operationalState) {
|
|
565
|
+
this.logInfo(`Device status found: ${status.operationalState}`)
|
|
566
|
+
this.updateOperationalState(status.operationalState)
|
|
567
|
+
} else {
|
|
568
|
+
this.logWarn('Device status not found. Setting operational state to Stopped.')
|
|
569
|
+
this.updateOperationalState(0) // Default to Stopped
|
|
570
|
+
}
|
|
571
|
+
} catch (error: any) {
|
|
572
|
+
this.logWarn(`Failed to fetch device status: ${String(error?.message ?? error)}`)
|
|
573
|
+
this.updateOperationalState(0) // Default to Stopped
|
|
574
|
+
}
|
|
575
|
+
}, 5000) // Simulate a 5-second cleaning sequence
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private async simulateDockingSequence(): Promise<void> {
|
|
579
|
+
this.logInfo('Starting docking sequence simulation.')
|
|
580
|
+
this.updateOperationalState(64) // Set to Seeking Charger
|
|
581
|
+
|
|
582
|
+
setTimeout(async () => {
|
|
583
|
+
this.logInfo('Docking sequence timer expired. Requesting device status update.')
|
|
584
|
+
try {
|
|
585
|
+
const status = await this.requestDeviceStatus()
|
|
586
|
+
if (status && status.operationalState) {
|
|
587
|
+
this.logInfo(`Device status found: ${status.operationalState}`)
|
|
588
|
+
this.updateOperationalState(status.operationalState)
|
|
589
|
+
} else {
|
|
590
|
+
this.logWarn('Device status not found. Setting operational state to Docked.')
|
|
591
|
+
this.updateOperationalState(66) // Default to Docked
|
|
592
|
+
}
|
|
593
|
+
} catch (error: any) {
|
|
594
|
+
this.logWarn(`Failed to fetch device status: ${String(error?.message ?? error)}`)
|
|
595
|
+
this.updateOperationalState(66) // Default to Docked
|
|
596
|
+
}
|
|
597
|
+
}, 5000) // Simulate a 5-second docking sequence
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
private async requestDeviceStatus(): Promise<{ operationalState?: number } | null> {
|
|
601
|
+
this.logInfo('Requesting device status from OpenAPI.')
|
|
602
|
+
try {
|
|
603
|
+
const response = await this.sendOpenAPICommand('getDeviceStatus')
|
|
604
|
+
this.logInfo(`Device status response: ${JSON.stringify(response)}`)
|
|
605
|
+
return response
|
|
606
|
+
} catch (error: any) {
|
|
607
|
+
this.logWarn(`Failed to request device status: ${String(error?.message ?? error)}`)
|
|
608
|
+
return null
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
public async startCleaningSimulation(): Promise<void> {
|
|
613
|
+
this.logInfo('Initiating cleaning simulation.')
|
|
614
|
+
await this.simulateCleaningSequence()
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
public async startDockingSimulation(): Promise<void> {
|
|
618
|
+
this.logInfo('Initiating docking simulation.')
|
|
619
|
+
await this.simulateDockingSequence()
|
|
620
|
+
}
|
|
434
621
|
}
|
package/src/settings.ts
CHANGED
|
@@ -88,11 +88,27 @@ export interface options {
|
|
|
88
88
|
* When false (default), reset at UTC midnight. Default: false.
|
|
89
89
|
*/
|
|
90
90
|
dailyApiResetAtLocalMidnight?: boolean
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* When true, resets the daily API request counter to zero. This is useful for testing purposes.
|
|
93
|
+
*/
|
|
94
|
+
resetDailyApiCounter?: boolean
|
|
95
|
+
/**
|
|
96
|
+
* When set, configures the batch refresh rate (in milliseconds) for Matter devices. Default: 5000 ms.
|
|
97
|
+
*/
|
|
92
98
|
matterBatchRefreshRate?: number
|
|
99
|
+
/**
|
|
100
|
+
* When true, enables batch processing for Matter devices. Default: false.
|
|
101
|
+
*/
|
|
93
102
|
matterBatchConcurrency?: number
|
|
103
|
+
/**
|
|
104
|
+
* When true, enables batch processing for Matter devices. Default: false.
|
|
105
|
+
*/
|
|
94
106
|
matterBatchEnabled?: boolean
|
|
107
|
+
/**
|
|
108
|
+
* When set, adds a random delay (jitter) to batch requests to avoid thundering herd problems.
|
|
109
|
+
*/
|
|
95
110
|
matterBatchJitter?: number
|
|
111
|
+
newFeatureEnabled?: boolean
|
|
96
112
|
};
|
|
97
113
|
|
|
98
114
|
export type devicesConfig = botConfig | relaySwitch1Config | relaySwitch1PMConfig | meterConfig | meterProConfig | indoorOutdoorSensorConfig | humidifierConfig | curtainConfig | blindTiltConfig | contactConfig | motionConfig | waterDetectorConfig | plugConfig | colorBulbConfig | stripLightConfig | ceilingLightConfig | lockConfig | hubConfig
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"roboticVacuumAccessory.test.d.ts","sourceRoot":"","sources":["../../../../src/test/matter/devices-matter/roboticVacuumAccessory.test.ts"],"names":[],"mappings":""}
|