@homebridge-plugins/homebridge-ecovacs 7.3.0 → 7.4.0

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 CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to `@homebridge-plugins/homebridge-ecovacs` will be documented in this file.
4
4
 
5
+ ## v7.4.0 (2026-04-05)
6
+
7
+ ### Changes
8
+
9
+ - dependency updates
10
+ - remove support for node v20
11
+ - fix: shallow copy default config/device objects
12
+ - fix: correct poll interval config access
13
+ - fix: remove extra brace in clean update log
14
+ - fix: move accessory null check before first use
15
+ - fix: clear cache after updateValue calls, not before
16
+ - fix: correct error message for predefined area failures
17
+ - fix: guard `refreshIntervals` in `pluginShutdown`
18
+ - fix: use logDebug for `GetChargeState` in `externalReadyUpdate`
19
+ - fix: use object over sparse array for virtual boundaries
20
+ - fix: remove unused `refreshTime` config
21
+ - fix: use `trim()` in `parseError` stack trace cleanup
22
+
5
23
  ## v7.3.0 (2026-02-16)
6
24
 
7
25
  ### Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
  <span align="center">
5
5
 
6
- # homebridge-ecovacs
6
+ ## homebridge-ecovacs
7
7
 
8
8
  Homebridge plugin to integrate Ecovacs Deebot or Yeedi devices into HomeKit
9
9
 
@@ -27,7 +27,7 @@ Homebridge plugin to integrate Ecovacs Deebot or Yeedi devices into HomeKit
27
27
  ### Prerequisites
28
28
 
29
29
  - To use this plugin, you will need to already have:
30
- - [Node](https://nodejs.org): latest version of `v20`, `v22` or `v24` - any other major version is not supported.
30
+ - [Node](https://nodejs.org): latest version of `v22` or `v24` - any other major version is not supported.
31
31
  - [Homebridge](https://homebridge.io): `v1.6` - refer to link for more information and installation instructions.
32
32
 
33
33
  ### Setup
@@ -700,7 +700,7 @@
700
700
  "type": "fieldset",
701
701
  "title": "Optional Settings",
702
702
  "expandable": true,
703
- "items": ["disableDeviceLogging", "refreshTime"]
703
+ "items": ["disableDeviceLogging"]
704
704
  },
705
705
  {
706
706
  "key": "devices",
package/lib/platform.js CHANGED
@@ -57,7 +57,7 @@ export default class {
57
57
  }
58
58
 
59
59
  // Apply the user's configuration
60
- this.config = platformConsts.defaultConfig
60
+ this.config = { ...platformConsts.defaultConfig }
61
61
  this.applyUserConfig(config)
62
62
 
63
63
  // Create further variables needed by the plugin
@@ -136,7 +136,7 @@ export default class {
136
136
  logRemove(`${key}.${id}`)
137
137
  return
138
138
  }
139
- this.deviceConf[id] = platformConsts.defaultDevice
139
+ this.deviceConf[id] = { ...platformConsts.defaultDevice }
140
140
  entries.forEach((subEntry) => {
141
141
  const [k, v] = subEntry
142
142
  switch (k) {
@@ -417,7 +417,7 @@ export default class {
417
417
  // A function that is called when the plugin fails to load or Homebridge restarts
418
418
  try {
419
419
  // Stop the refresh intervals
420
- Object.keys(this.refreshIntervals).forEach((id) => {
420
+ Object.keys(this.refreshIntervals || {}).forEach((id) => {
421
421
  clearInterval(this.refreshIntervals[id])
422
422
  })
423
423
 
@@ -458,13 +458,13 @@ export default class {
458
458
  // Get the cached accessory or add to Homebridge if it doesn't exist
459
459
  const accessory = devicesInHB.get(uuid) || this.addAccessory(loadedDevice)
460
460
 
461
- accessory.context.rawConfig = this.deviceConf?.[device.did] || platformConsts.defaultDevice
462
-
463
461
  // Final check the accessory now exists in Homebridge
464
462
  if (!accessory) {
465
463
  throw new Error(platformLang.accNotFound)
466
464
  }
467
465
 
466
+ accessory.context.rawConfig = this.deviceConf?.[device.did] || platformConsts.defaultDevice
467
+
468
468
  // Sort out some logging functions per accessory
469
469
  if (this.isBeta) {
470
470
  accessory.log = msg => this.log('[%s] %s.', accessory.displayName, msg)
@@ -487,21 +487,6 @@ export default class {
487
487
  accessory.context.isOnline = false
488
488
  accessory.context.lastMsg = ''
489
489
 
490
- // Remove the existing cache values from the context
491
- // accessory.context.cacheClean
492
- // accessory.context.cacheCharge
493
- // accessory.context.cacheAirDrying
494
- // accessory.context.cacheSpeed
495
- // accessory.context.cacheBattery
496
- const cacheKeys = [
497
- 'cacheClean',
498
- 'cacheCharge',
499
- 'cacheAirDrying',
500
- 'cacheSpeed',
501
- 'cacheBattery',
502
- ]
503
- cacheKeys.forEach(key => delete accessory.context[key])
504
-
505
490
  // Add the 'clean' switch service if it doesn't already exist
506
491
  const cleanService = accessory.getService('Clean') || accessory.addService(this.hapServ.Switch, 'Clean', 'clean')
507
492
  if (!cleanService.testCharacteristic(this.hapChar.ConfiguredName)) {
@@ -618,6 +603,16 @@ export default class {
618
603
  accessory.logDebug('no air drying available or not configured')
619
604
  }
620
605
 
606
+ // Remove the existing cache values from the context now that services have been updated
607
+ const cacheKeys = [
608
+ 'cacheClean',
609
+ 'cacheCharge',
610
+ 'cacheAirDrying',
611
+ 'cacheSpeed',
612
+ 'cacheBattery',
613
+ ]
614
+ cacheKeys.forEach(key => delete accessory.context[key])
615
+
621
616
  // TrueDetect service
622
617
  if (accessory.context.rawConfig.supportTrueDetect) {
623
618
  // Custom Eve characteristic like MaxSpeed
@@ -744,16 +739,16 @@ export default class {
744
739
  if (vbs) {
745
740
  accessory.logDebug(`MapVirtualBoundaries: ${JSON.stringify(vbs)}`)
746
741
  const vbsCombined = [...vbs.mapVirtualWalls, ...vbs.mapNoMopZones]
747
- const virtualBoundaryArray = []
748
- Object.keys(vbsCombined).forEach((key) => {
749
- virtualBoundaryArray[vbsCombined[key].mapVirtualBoundaryID] = vbsCombined[key]
742
+ const virtualBoundaryMap = {}
743
+ vbsCombined.forEach((vb) => {
744
+ virtualBoundaryMap[vb.mapVirtualBoundaryID] = vb
750
745
  })
751
- Object.keys(virtualBoundaryArray).forEach((key) => {
746
+ Object.values(virtualBoundaryMap).forEach((vb) => {
752
747
  accessory.control.run(
753
748
  'GetVirtualBoundaryInfo',
754
749
  vbs.mapID,
755
- virtualBoundaryArray[key].mapVirtualBoundaryID,
756
- virtualBoundaryArray[key].mapVirtualBoundaryType,
750
+ vb.mapVirtualBoundaryID,
751
+ vb.mapVirtualBoundaryType,
757
752
  )
758
753
  })
759
754
  }
@@ -770,7 +765,7 @@ export default class {
770
765
 
771
766
  // Refresh the current state of all the accessories
772
767
  this.refreshAccessory(accessory)
773
- const { pollInterval } = accessory.context.rawConfig[device] || platformConsts.defaultValues
768
+ const { pollInterval } = accessory.context.rawConfig || platformConsts.defaultValues
774
769
  if (pollInterval > 0) {
775
770
  this.refreshIntervals[device.did] = setInterval(() => {
776
771
  devicesInHB.get(this.api.hap.uuid.generate(device.did)).control?.refresh()
@@ -956,7 +951,7 @@ export default class {
956
951
  const order = value ? `Clean${accessory.context.commandSuffix}` : 'Stop'
957
952
 
958
953
  // Log the update
959
- accessory.log(`${platformLang.curCleaning} [${value ? platformLang.cleaning : platformLang.stop}}]`)
954
+ accessory.log(`${platformLang.curCleaning} [${value ? platformLang.cleaning : platformLang.stop}]`)
960
955
 
961
956
  // Send the command
962
957
  accessory.logDebug(`${platformLang.sendCmd} [${order}]`)
@@ -1096,7 +1091,7 @@ export default class {
1096
1091
  }, 2000)
1097
1092
  } catch (err) {
1098
1093
  // Catch any errors during the process
1099
- accessory.logWarn(`${platformLang.speedFail} ${parseError(err, [platformLang.errNotInit, platformLang.errNotReady])}`)
1094
+ accessory.logWarn(`${platformLang.cleanFail} ${parseError(err, [platformLang.errNotInit, platformLang.errNotReady])}`)
1100
1095
 
1101
1096
  // Throw a 'no response' error and set a timeout to revert this after 2 seconds
1102
1097
  setTimeout(() => {
@@ -1220,7 +1215,7 @@ export default class {
1220
1215
  accessory.logDebug(`${platformLang.sendCmd} [GetBatteryState]`)
1221
1216
  accessory.control.run('GetBatteryState')
1222
1217
 
1223
- accessory.log(`${platformLang.sendCmd} [GetChargeState]`)
1218
+ accessory.logDebug(`${platformLang.sendCmd} [GetChargeState]`)
1224
1219
  accessory.control.run('GetChargeState')
1225
1220
 
1226
1221
  accessory.logDebug(`${platformLang.sendCmd} [GetCleanState${accessory.context.commandSuffix}]`)
@@ -6,7 +6,6 @@ export default {
6
6
  username: '',
7
7
  password: '',
8
8
  disableDeviceLogging: false,
9
- refreshTime: 120,
10
9
  devices: [],
11
10
  platform: 'Deebot',
12
11
  },
@@ -3,7 +3,7 @@ function parseError(err, hideStack = []) {
3
3
  if (err?.stack?.length > 0 && !hideStack.includes(err.message)) {
4
4
  const stack = err.stack.split('\n')
5
5
  if (stack[1]) {
6
- toReturn += stack[1].replace(' ', '')
6
+ toReturn += stack[1].trim()
7
7
  }
8
8
  }
9
9
  return toReturn
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "displayName": "Homebridge Ecovacs",
4
4
  "alias": "Deebot",
5
5
  "type": "module",
6
- "version": "7.3.0",
6
+ "version": "7.4.0",
7
7
  "description": "Homebridge plugin to integrate Ecovacs Deebot/Yeedi devices into HomeKit.",
8
8
  "author": {
9
9
  "name": "bwp91",
@@ -54,7 +54,7 @@
54
54
  "main": "lib/index.js",
55
55
  "engines": {
56
56
  "homebridge": "^1.6.0 || ^2.0.0-beta.0",
57
- "node": "^20 || ^22 || ^24"
57
+ "node": "^22 || ^24"
58
58
  },
59
59
  "scripts": {
60
60
  "lint": "eslint . --max-warnings=0",
@@ -62,20 +62,21 @@
62
62
  "postinstall": "patch-package"
63
63
  },
64
64
  "dependencies": {
65
- "@homebridge/plugin-ui-utils": "^2.2.0",
65
+ "@homebridge/plugin-ui-utils": "^2.2.3",
66
66
  "ecovacs-deebot": "^0.9.6-beta.12",
67
67
  "patch-package": "^8.0.1"
68
68
  },
69
69
  "devDependencies": {
70
- "@antfu/eslint-config": "^7.4.3"
70
+ "@antfu/eslint-config": "^8.0.0"
71
71
  },
72
72
  "overrides": {
73
73
  "ecovacs-deebot": {
74
- "axios": "^1.13.5",
74
+ "@xmldom/xmldom": "^0.9.9",
75
+ "axios": "^1.14.0",
75
76
  "canvas": {
76
77
  ".": "^2.11.1",
77
78
  "@mapbox/node-pre-gyp": {
78
- "tar": "^7.5.9"
79
+ "tar": "^7.5.13"
79
80
  }
80
81
  },
81
82
  "simple-xmpp": {