@homebridge-plugins/homebridge-wemo 7.2.3 → 7.3.1-beta.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,30 @@
2
2
 
3
3
  All notable changes to `@homebridge-plugins/homebridge-wemo` will be documented in this file.
4
4
 
5
+ ## v7.3.1 (Pending Release)
6
+
7
+ ### Changed
8
+
9
+ - fix: empty push in cached accessory tracking
10
+ - fix: wrong code in link bulb reverse lookup map
11
+ - fix: power diff always zero in insight devices
12
+ - fix: extra brace in purifier ionizer log output
13
+ - fix: serial number normalization mismatch in config
14
+ - fix: XML entity decode ordering for ampersands
15
+ - fix: incorrect unit casing in eve characteristic
16
+ - fix: fakegato unsubscribe removing wrong service
17
+ - fix: fakegato immediate callback missing averaging
18
+ - fix: string radix in fakegato toString call
19
+ - dependency updates + code lint fixes
20
+
21
+ ## v7.3.0 (2026-02-15)
22
+
23
+ ### Changes
24
+
25
+ - determine debug mode from `-D` flag
26
+ - updated dependencies
27
+ - updated dependencies + lint rules
28
+
5
29
  ## v7.2.3 (2025-12-05)
6
30
 
7
31
  ### Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
  <span align="center">
5
5
 
6
- # homebridge-wemo
6
+ ## homebridge-wemo
7
7
 
8
8
  Homebridge plugin to integrate Wemo devices into HomeKit
9
9
 
package/eslint.config.js CHANGED
@@ -8,29 +8,24 @@ export default antfu(
8
8
  rules: {
9
9
  'curly': ['error', 'multi-line'],
10
10
  'new-cap': 'off',
11
- 'jsdoc/check-alignment': 'warn',
12
- 'jsdoc/check-line-alignment': 'warn',
13
- 'jsdoc/require-returns-check': 0,
14
- 'jsdoc/require-returns-description': 0,
15
11
  'no-undef': 'error',
16
12
  'perfectionist/sort-exports': 'error',
17
13
  'perfectionist/sort-imports': [
18
14
  'error',
19
15
  {
20
16
  groups: [
21
- 'type',
22
- 'internal-type',
17
+ ['type-builtin', 'type-external', 'type-internal'],
18
+ ['type-parent', 'type-sibling', 'type-index'],
23
19
  'builtin',
24
20
  'external',
25
21
  'internal',
26
- ['parent-type', 'sibling-type', 'index-type'],
27
22
  ['parent', 'sibling', 'index'],
28
- 'object',
23
+ 'side-effect',
29
24
  'unknown',
30
25
  ],
31
26
  order: 'asc',
32
27
  type: 'natural',
33
- newlinesBetween: 'always',
28
+ newlinesBetween: 1,
34
29
  },
35
30
  ],
36
31
  'perfectionist/sort-named-exports': 'error',
@@ -45,4 +40,13 @@ export default antfu(
45
40
  },
46
41
  typescript: false,
47
42
  },
43
+ {
44
+ files: ['**/*.md'],
45
+ rules: {
46
+ 'perfectionist/sort-exports': 'off',
47
+ 'perfectionist/sort-imports': 'off',
48
+ 'perfectionist/sort-named-exports': 'off',
49
+ 'perfectionist/sort-named-imports': 'off',
50
+ },
51
+ },
48
52
  )
@@ -277,6 +277,9 @@ export default class {
277
277
  return
278
278
  }
279
279
 
280
+ // Calculate a difference from the last reading
281
+ const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
282
+
280
283
  // Update the power in watts cache
281
284
  this.cachePowerInWatts = powerInWatts
282
285
 
@@ -286,9 +289,6 @@ export default class {
286
289
  // Add the Eve wattage entry
287
290
  this.accessory.historyService.addEntry({ power: this.cachePowerInWatts })
288
291
 
289
- // Calculate a difference from the last reading
290
- const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
291
-
292
292
  // Don't continue with logging if the user has set a timeout between entries or a min difference between entries
293
293
  if (!this.skipTimeDiff && diff >= this.wattDiff) {
294
294
  // Log the change if appropriate
@@ -41,7 +41,7 @@ export default class {
41
41
  temperature: '30301',
42
42
  }
43
43
  this.linkCodesRev = {
44
- 10600: 'switch',
44
+ 10006: 'switch',
45
45
  10008: 'brightness',
46
46
  10300: 'color',
47
47
  30301: 'temperature',
@@ -334,7 +334,7 @@ export default class {
334
334
  this.accessory.context.cacheIonizerOn = value ? 1 : 0
335
335
 
336
336
  // Log the update if appropriate
337
- this.accessory.log(`${platformLang.curIon} [${value ? 'on' : 'off'}}]`)
337
+ this.accessory.log(`${platformLang.curIon} [${value ? 'on' : 'off'}]`)
338
338
  } catch (err) {
339
339
  const eText = parseError(err, [platformLang.timeout, platformLang.timeoutUnreach])
340
340
  this.accessory.logWarn(`${platformLang.cantCtl} ${eText}`)
@@ -282,6 +282,9 @@ export default class {
282
282
  return
283
283
  }
284
284
 
285
+ // Calculate a difference from the last reading
286
+ const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
287
+
285
288
  // Update the power in watts cache
286
289
  this.cachePowerInWatts = powerInWatts
287
290
 
@@ -291,9 +294,6 @@ export default class {
291
294
  // Add the Eve wattage entry
292
295
  this.accessory.historyService.addEntry({ power: this.cachePowerInWatts })
293
296
 
294
- // Calculate a difference from the last reading
295
- const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
296
-
297
297
  // Don't continue with logging if the user has set a timeout between entries or a min difference between entries
298
298
  if (!this.skipTimeDiff && diff >= this.wattDiff) {
299
299
  // Log the change if appropriate
@@ -240,6 +240,9 @@ export default class {
240
240
  return
241
241
  }
242
242
 
243
+ // Calculate a difference from the last reading
244
+ const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
245
+
243
246
  // Update the power in watts cache
244
247
  this.cachePowerInWatts = powerInWatts
245
248
 
@@ -249,9 +252,6 @@ export default class {
249
252
  // Add the Eve wattage entry
250
253
  this.accessory.historyService.addEntry({ power: this.cachePowerInWatts })
251
254
 
252
- // Calculate a difference from the last reading
253
- const diff = Math.abs(powerInWatts - this.cachePowerInWatts)
254
-
255
255
  // Don't continue with logging if the user has set a timeout between entries or a min difference between entries
256
256
  if (!this.skipTimeDiff && diff >= this.wattDiff) {
257
257
  // Log the change if appropriate
@@ -370,9 +370,9 @@ export default function (homebridge) {
370
370
  avrg: {},
371
371
  }
372
372
  for (const h in backLog) {
373
- if (Object.prototype.hasOwnProperty.call(backLog, h)) {
373
+ if (Object.hasOwn(backLog, h)) {
374
374
  for (const key in backLog[h]) {
375
- if (Object.prototype.hasOwnProperty.call(backLog[h], key) && key !== 'time') {
375
+ if (Object.hasOwn(backLog[h], key) && key !== 'time') {
376
376
  if (!calc.sum[key]) {
377
377
  calc.sum[key] = 0
378
378
  }
@@ -389,7 +389,7 @@ export default function (homebridge) {
389
389
  calc.avrg.time = Math.round(new Date().valueOf() / 1000)
390
390
 
391
391
  for (const key in previousAvrg) {
392
- if (Object.prototype.hasOwnProperty.call(previousAvrg, key) && key !== 'time') {
392
+ if (Object.hasOwn(previousAvrg, key) && key !== 'time') {
393
393
  if (!backLog.length || calc.avrg[key] === undefined) {
394
394
  calc.avrg[key] = previousAvrg[key]
395
395
  }
@@ -798,7 +798,7 @@ export default function (homebridge) {
798
798
  const substring = valHex.substring(4, 12)
799
799
  const valInt = Number.parseInt(substring, 16)
800
800
  const address = swap32(valInt)
801
- const hexAddress = address.toString('16')
801
+ const hexAddress = address.toString(16)
802
802
  this.log('[%s] FGH address req [%s].', this.accessoryName, hexAddress)
803
803
  this.sendHistory(address)
804
804
  }
@@ -71,7 +71,7 @@ export default class {
71
71
  '[%s] FGS write file [%s] [%s].',
72
72
  params.service.accessoryName,
73
73
  fileLoc,
74
- params.data.substr(1, 80),
74
+ params.data.substring(1, 81),
75
75
  )
76
76
  writer.storageHandler.writeFile(fileLoc, params.data, 'utf8', (...args) => {
77
77
  this.writing = false
@@ -39,7 +39,9 @@ export default class {
39
39
 
40
40
  unsubscribe(service) {
41
41
  const index = this._getSubscriberIndex(service)
42
- this.subscribedServices.splice(index, 1)
42
+ if (index !== -1) {
43
+ this.subscribedServices.splice(index, 1)
44
+ }
43
45
  if (this.subscribedServices.length === 0 && this.running) {
44
46
  this.stop()
45
47
  }
@@ -65,7 +67,7 @@ export default class {
65
67
  this.log('FGT executeCallbacks().')
66
68
  if (this.subscribedServices.length !== 0) {
67
69
  for (const s in this.subscribedServices) {
68
- if (Object.prototype.hasOwnProperty.call(this.subscribedServices, s)) {
70
+ if (Object.hasOwn(this.subscribedServices, s)) {
69
71
  const service = this.subscribedServices[s]
70
72
  if (typeof service.callback === 'function') {
71
73
  service.previousAvrg = service.callback({
@@ -83,8 +85,9 @@ export default class {
83
85
  executeImmediateCallback(service) {
84
86
  this.log('[%s] FGT executeImmediateCallback().', service.accessoryName)
85
87
  if (typeof service.callback === 'function' && service.backLog.length) {
86
- service.callback({
88
+ service.previousAvrg = service.callback({
87
89
  backLog: service.backLog,
90
+ previousAvrg: service.previousAvrg,
88
91
  timer: this,
89
92
  immediate: true,
90
93
  })
@@ -1,12 +1,13 @@
1
1
  // https://github.com/homebridge/HAP-NodeJS/blob/master/src/lib/util/uuid.ts
2
2
 
3
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
4
+ const shortRegex = /^[0-9a-f]{1,8}$/i
5
+
3
6
  function isValid(UUID) {
4
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
5
7
  return uuidRegex.test(UUID)
6
8
  }
7
9
 
8
10
  function toLongFormUUID(uuid, base = '-0000-1000-8000-0026BB765291') {
9
- const shortRegex = /^[0-9a-f]{1,8}$/i
10
11
  if (isValid(uuid)) {
11
12
  return uuid.toUpperCase()
12
13
  }
package/lib/platform.js CHANGED
@@ -24,6 +24,7 @@ const require = createRequire(import.meta.url)
24
24
  const plugin = require('../package.json')
25
25
 
26
26
  const devicesInHB = new Map()
27
+ const trailingSlashRegex = /\/\s*$/
27
28
 
28
29
  let listenerServer
29
30
  let cacheSerialsToConnect = []
@@ -40,7 +41,7 @@ export default class {
40
41
  try {
41
42
  this.api = api
42
43
  this.log = log
43
- this.isBeta = plugin.version.includes('beta')
44
+ this.isBeta = process.argv.includes('-D')
44
45
 
45
46
  // Configuration objects for accessories
46
47
  this.ignoredDevices = []
@@ -269,7 +270,7 @@ export default class {
269
270
  if (typeof v1 !== 'string' || v1 === '') {
270
271
  logIgnore(`${key}.${k1}`)
271
272
  }
272
- this.config.callbackOverride = v1.replace('http://', '').replace(/\/\s*$/, '')
273
+ this.config.callbackOverride = v1.replace('http://', '').replace(trailingSlashRegex, '')
273
274
  break
274
275
  case 'discover_opts':
275
276
  if (typeof v1 === 'object' && Object.keys(v1).length > 0) {
@@ -345,14 +346,6 @@ export default class {
345
346
  if (this.isBeta) {
346
347
  this.log.debug = this.log
347
348
  this.log.debugWarn = this.log.warn
348
-
349
- // Log that using a beta will generate a lot of debug logs
350
- if (this.isBeta) {
351
- const divide = '*'.repeat(platformLang.beta.length + 1) // don't forget the full stop (+1!)
352
- this.log.warn(divide)
353
- this.log.warn(`${platformLang.beta}.`)
354
- this.log.warn(divide)
355
- }
356
349
  } else {
357
350
  this.log.debug = () => {}
358
351
  this.log.debugWarn = () => {}
@@ -418,7 +411,7 @@ export default class {
418
411
 
419
412
  // Add the accessory to cache accessories to connect to if it isn't already
420
413
  if (!cacheSerialsToConnect.includes(accessory.context.serialNumber)) {
421
- cacheSerialsToConnect.push()
414
+ cacheSerialsToConnect.push(accessory.context.serialNumber)
422
415
  }
423
416
 
424
417
  // Update the changes to the accessory to the platform
@@ -794,7 +787,7 @@ export default class {
794
787
  cacheSerialsToConnect = cacheSerialsToConnect.filter(el => el !== device.serialNumber)
795
788
 
796
789
  // Obtain any user configured entry for this device
797
- const deviceConf = this.deviceConf[device.serialNumber] || {}
790
+ const deviceConf = this.deviceConf[parseSerialNumber(device.serialNumber)] || {}
798
791
 
799
792
  // Save context information for the plugin to use
800
793
  const listenerType = deviceConf.listenerType === 'http' ? 'http' : 'upnp'
@@ -79,7 +79,7 @@ export default class {
79
79
  super('Reset Total', uuids.resetTotal)
80
80
  this.setProps({
81
81
  format: api.hap.Formats.UINT32,
82
- unit: api.hap.Units.seconds,
82
+ unit: api.hap.Units.SECONDS,
83
83
  perms: [api.hap.Perms.PAIRED_READ, api.hap.Perms.NOTIFY, api.hap.Perms.PAIRED_WRITE],
84
84
  })
85
85
  this.value = this.getDefaultValue()
@@ -1,10 +1,10 @@
1
1
  function decodeXML(input) {
2
2
  return input
3
+ .replace(/&amp;/g, '&')
3
4
  .replace(/&lt;/g, '<')
4
5
  .replace(/&gt;/g, '>')
5
6
  .replace(/&quot;/g, '"')
6
7
  .replace(/&#039;/g, '\'')
7
- .replace(/&amp;/g, '&')
8
8
  }
9
9
 
10
10
  function generateRandomString(length) {
@@ -16,7 +16,7 @@ function generateRandomString(length) {
16
16
  return nonce
17
17
  }
18
18
 
19
- const hasProperty = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
19
+ const hasProperty = (obj, prop) => Object.hasOwn(obj, prop)
20
20
 
21
21
  function parseError(err, hideStack = []) {
22
22
  let toReturn = err.message
@@ -3,7 +3,6 @@ export default {
3
3
  accNotReady: 'has not been discovered yet so commands will fail',
4
4
  alDisabled: 'adaptive lighting disabled due to significant colour change',
5
5
  awaiting: 'The following devices have still not been initially found',
6
- beta: 'You are using a beta version of the plugin - you will experience more logging than normal',
7
6
  brand: 'Belkin Wemo',
8
7
  brightnessFail: 'could not obtain updated brightness as',
9
8
  cantCtl: 'sending update failed as',
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@homebridge-plugins/homebridge-wemo",
3
3
  "alias": "Wemo",
4
4
  "type": "module",
5
- "version": "7.2.3",
5
+ "version": "7.3.1-beta.0",
6
6
  "description": "Homebridge plugin to integrate Wemo devices into HomeKit.",
7
7
  "author": {
8
8
  "name": "bwp91",
@@ -55,15 +55,15 @@
55
55
  "lint:fix": "npm run lint -- --fix"
56
56
  },
57
57
  "dependencies": {
58
- "@homebridge/plugin-ui-utils": "^2.1.2",
59
- "axios": "^1.13.2",
58
+ "@homebridge/plugin-ui-utils": "^2.2.3",
59
+ "axios": "^1.14.0",
60
60
  "ip": "^2.0.1",
61
61
  "node-ssdp": "^4.0.1",
62
- "p-queue": "^9.0.1",
62
+ "p-queue": "^9.1.1",
63
63
  "xml2js": "^0.6.2",
64
64
  "xmlbuilder": "^15.1.1"
65
65
  },
66
66
  "devDependencies": {
67
- "@antfu/eslint-config": "^6.4.2"
67
+ "@antfu/eslint-config": "^8.0.0"
68
68
  }
69
69
  }