homebridge-lib 8.0.0 → 8.0.1

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.
@@ -0,0 +1,12 @@
1
+ // homebridge-lib/lib/MdnsClient.js
2
+ //
3
+ // Library for Homebridge plugins.
4
+ // Copyright © 2020-2026 Erik Baauw. All rights reserved.
5
+
6
+ /** Multicat DNS (Bonjour) client.
7
+ * <br>See {@link MdnsClient}.
8
+ * @name MdnsClient
9
+ * @type {Class}
10
+ * @memberof module:homebridge-lib
11
+ */
12
+ export { MdnsClient } from 'hb-lib-tools/MdnsClient'
package/lib/Platform.js CHANGED
@@ -5,14 +5,11 @@
5
5
 
6
6
  import { once } from 'node:events'
7
7
  import { writeFile, unlink } from 'node:fs/promises'
8
- import { Server, STATUS_CODES } from 'node:http'
9
8
  import { createRequire } from 'node:module'
10
9
  import { format, promisify } from 'node:util'
11
- import zlib from 'node:zlib'
12
10
 
13
11
  import { HttpClient } from 'hb-lib-tools/HttpClient'
14
12
  import { SystemInfo } from 'hb-lib-tools/SystemInfo'
15
- import { UpnpClient } from 'hb-lib-tools/UpnpClient'
16
13
 
17
14
  import { Delegate } from 'homebridge-lib/Delegate'
18
15
  import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes'
@@ -25,15 +22,16 @@ const require = createRequire(import.meta.url)
25
22
  const libPackageJson = require('../package.json')
26
23
 
27
24
  const uuid = /^[0-9A-F]{8}-[0-9A-F]{4}-[1-5][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/
28
- const gzip = promisify(zlib.gzip)
25
+
26
+ let gzip
29
27
 
30
28
  const context = {
31
29
  libName: libPackageJson.name,
32
30
  libVersion: libPackageJson.version,
33
31
  nodeVersion: process.version.slice(1),
34
32
  recommendedNodeVersion: recommendedNodeVersion(libPackageJson),
35
- // recommendedHomebridgeVersion:
36
- // semver.minVersion(libPackageJson.engines.homebridge).toString(),
33
+ recommendedHomebridgeVersion:
34
+ semver.minVersion(libPackageJson.engines.homebridge).toString(),
37
35
  saveInterval: 3600,
38
36
  checkInterval: 7 * 24 * 3600,
39
37
  driftDebugThreshold: 250,
@@ -80,8 +78,8 @@ class Platform extends Delegate {
80
78
  context.homebridge = homebridge
81
79
  context.homebridgeVersion = homebridge.serverVersion
82
80
  context.PlatformAccessory = homebridge.platformAccessory
83
- context.recommendedHomebridgeVersion =
84
- semver.minVersion(libPackageJson.engines.homebridge).toString()
81
+ // context.recommendedHomebridgeVersion =
82
+ // semver.minVersion(libPackageJson.engines.homebridge).toString()
85
83
 
86
84
  const hap = {
87
85
  Services: {},
@@ -178,52 +176,41 @@ class Platform extends Delegate {
178
176
  )
179
177
  }
180
178
  this._myContext.platform = this
181
- this._identify()
179
+ this.#identify()
182
180
 
183
181
  this._homebridge
184
- .on('didFinishLaunching', this._main.bind(this))
185
- .on('shutdown', this._shutdown.bind(this))
186
- process.on('exit', this._exit.bind(this))
182
+ .on('didFinishLaunching', this.#main.bind(this))
183
+ .on('shutdown', this.#shutdown.bind(this))
184
+ process.on('exit', this.#exit.bind(this))
187
185
  }
188
186
 
189
187
  // ===== Main ================================================================
190
188
 
191
189
  // Main platform function.
192
190
  // Called by homebridge after restoring accessories from cache.
193
- async _main () {
191
+ async #main () {
194
192
  /** System information.
195
193
  * @type {SystemInfo}
196
194
  * @readonly
197
195
  */
198
- this.systemInfo = new SystemInfo()
199
- this.systemInfo
200
- .on('error', (error) => { this.warn(error) })
201
- .on('exec', (command) => { this.debug('exec: %s', command) })
202
- .on('readFile', (filename) => { this.debug('read file: %s', filename) })
196
+ this.systemInfo = new SystemInfo({ logger: this })
203
197
  await this.systemInfo.init()
204
198
  this.log('hardware: %s', this.systemInfo.hwInfo.prettyName)
205
199
  this.log('os: %s', this.systemInfo.osInfo.prettyName)
206
200
  this._heartbeatStart = new Date()
207
- setTimeout(() => { this._beat(-1) }, 1000)
208
- this.on('exit', () => { this._flushCachedAccessories() })
201
+ setTimeout(() => { this.#beat(-1) }, 1000)
209
202
 
210
203
  const n = Object.keys(this._accessories).length
211
204
  if (n > 0) {
212
205
  this.log('restored %d accessories from cache', n)
213
206
  }
214
- if (this.listenerCount('upnpDeviceAlive') > 0) {
215
- this._upnpMonitor.listen()
216
- }
217
- if (this.listenerCount('upnpDeviceFound') > 0) {
218
- this._upnpMonitor.search()
219
- }
220
207
  if (typeof this.onUiRequest === 'function') {
221
208
  try {
222
- await this._createUiServer()
209
+ await this.#createUiServer()
223
210
  } catch (error) { this.error(error) }
224
211
  }
225
212
  await once(this, 'initialised')
226
- this._flushCachedAccessories()
213
+ this.#flushCachedAccessories()
227
214
  for (const id in this._accessories) {
228
215
  if (this._accessoryDelegates[id] == null) {
229
216
  const accessory = this._accessories[id]
@@ -253,6 +240,10 @@ class Platform extends Delegate {
253
240
  * @param {*} dumpInfo - Plugin-specific information.
254
241
  */
255
242
  async createDumpFile (dumpInfo = {}) {
243
+ if (gzip == null) {
244
+ const zlib = await import('node:zlib')
245
+ gzip = promisify(zlib.gzip)
246
+ }
256
247
  const result = {
257
248
  hardware: this.systemInfo.hwInfo.prettyName,
258
249
  os: this.systemInfo.osInfo.prettyName,
@@ -274,13 +265,13 @@ class Platform extends Delegate {
274
265
  }
275
266
 
276
267
  // Write `cachedAccessories` to disk.
277
- _flushCachedAccessories () {
268
+ #flushCachedAccessories () {
278
269
  this.debug('flush cachedAccessories')
279
270
  this._homebridge.updatePlatformAccessories([])
280
271
  }
281
272
 
282
273
  // Called every second.
283
- _beat (beat) {
274
+ #beat (beat) {
284
275
  beat += 1
285
276
  const drift = new Date() - this._heartbeatStart - 1000 * (beat + 1)
286
277
  if (this._shuttingDown) {
@@ -295,16 +286,16 @@ class Platform extends Delegate {
295
286
  }
296
287
  }
297
288
  setTimeout(() => {
298
- this._beat(beat)
289
+ this.#beat(beat)
299
290
  }, drift < 1000 ? 1000 - drift : 1)
300
291
 
301
292
  if (beat % context.saveInterval === 30) {
302
- this._flushCachedAccessories()
293
+ this.#flushCachedAccessories()
303
294
  }
304
295
 
305
296
  if (beat % context.checkInterval === 0) {
306
- this._checkLatest(this._pluginName, this._pluginVersion)
307
- // this._checkLatest(context.libName, context.libVersion)
297
+ this.#checkLatest(this._pluginName, this._pluginVersion)
298
+ // this.#checkLatest(context.libName, context.libVersion)
308
299
  }
309
300
 
310
301
  /** Emitted every second.
@@ -324,46 +315,40 @@ class Platform extends Delegate {
324
315
  }
325
316
 
326
317
  // Called by homebridge when shutting down.
327
- _shutdown () {
318
+ #shutdown () {
328
319
  if (this._shuttingDown) {
329
320
  return
330
321
  }
331
322
  this._shuttingDown = true
332
- this.removeAllListeners('upnpDeviceAlive')
333
- this.removeAllListeners('upnpDeviceFound')
334
323
  if (this._ui?.abortController != null) {
335
324
  this._ui.abortController.abort()
336
325
  }
337
326
  for (const id in this._accessoryDelegates) {
338
327
  /** Emitted when Homebridge is shutting down.
339
328
  *
340
- * On receiving this event, the plugin should cleanup (close connections,
341
- * flush peristent storage, ...).
329
+ * On receiving this event, the accessory delegate should cleanup
330
+ * (close connections, flush peristent storage, ...).
342
331
  * @event AccessoryDelegate#shutdown
343
332
  */
344
333
  this._accessoryDelegates[id].emit('shutdown')
345
334
  }
346
335
  /** Emitted when Homebridge is shutting down.
347
336
  *
348
- * On receiving this event, the plugin should cleanup (close connections,
349
- * flush peristent storage, ...).
337
+ * On receiving this event, the plugin should cleanup
338
+ * (close connections, flush peristent storage, ...).
350
339
  * @event Platform#shutdown
351
340
  */
352
341
  this.emit('shutdown')
353
342
  }
354
343
 
355
344
  // Called by NodeJS when process is exiting.
356
- _exit () {
357
- /** Emitted when Homebridge is exiting.
358
- *
359
- * Note: asynchronous calls made when handling this event will not be executed.
360
- * @event Platform#exit
361
- */
362
- this.emit('exit')
345
+ #exit () {
346
+ this.#flushCachedAccessories()
347
+ this.log('goodbye')
363
348
  }
364
349
 
365
350
  // Issue an identity message.
366
- _identify () {
351
+ #identify () {
367
352
  this.log(
368
353
  '%s v%s, node v%s, homebridge v%s, %s v%s',
369
354
  this._pluginName, this._pluginVersion, context.nodeVersion,
@@ -388,7 +373,7 @@ class Platform extends Delegate {
388
373
  }
389
374
 
390
375
  // Check the NPM registry for the latest version of this plugin.
391
- async _checkLatest (name, version) {
376
+ async #checkLatest (name, version) {
392
377
  try {
393
378
  if (this.npmRegistry == null) {
394
379
  this.npmRegistry = new HttpClient({
@@ -534,60 +519,6 @@ class Platform extends Delegate {
534
519
  delete this._accessories[id]
535
520
  }
536
521
 
537
- // ===== UPnP Device Discovery ===============================================
538
-
539
- /** Configure UPnP discovery.
540
- *
541
- * @param {!object} config - ...
542
- * @param {?string} config.class - Filter on UPnP device class.
543
- * Default `upnp:rootdevice`. Use `ssdp:all` for all device classes.
544
- * @param {?string} config.host - UPnP address and port.
545
- * Default: `239.255.255.250:1900`.
546
- * @param {function} config.filter - Filter on UPnP message content.
547
- * The function takes the message as argument and returns a boolean.
548
- * Default: `(message) => { return true }`, return all messages.
549
- * @param {integer} config.timeout - Timeout (in seconds) for UPnP search.
550
- * Default: `5`.
551
- */
552
- upnpConfig (config) {
553
- if (this._upnpMonitor != null) {
554
- throw new SyntaxError('upnpConfig(): already called')
555
- }
556
- this._upnpMonitor = new UpnpClient(config)
557
- this._upnpMonitor
558
- .on('error', (error) => {
559
- this.error('upnp: error')
560
- this.error(error)
561
- })
562
- .on('listening', (host) => {
563
- this.debug('upnp: listening on %s', host)
564
- })
565
- .on('searching', (host) => {
566
- this.debug('upnp: searching on %s', host)
567
- })
568
- .on('searchDone', () => {
569
- this.debug('upnp: search done')
570
- })
571
- .on('deviceAlive', (address, message) => {
572
- // this.debug('upnp: device %s is alive: %j', address, message)
573
- /** Emitted when a UPnP device sends an alive message.
574
- * @event Platform#upnpDeviceAlive
575
- * @param {string} address - The device's IP address.
576
- * @param {object} message - The contents of the alive message.
577
- */
578
- this.emit('upnpDeviceAlive', address, message)
579
- })
580
- .on('deviceFound', (address, message) => {
581
- // this.debug('upnp: found device %s: %j', address, message)
582
- /** Emitted when a UPnP device responds to a search request.
583
- * @event Platform#upnpDeviceFound
584
- * @param {string} address - The device's IP address.
585
- * @param {object} message - The contents of the search response message.
586
- */
587
- this.emit('upnpDeviceFound', address, message)
588
- })
589
- }
590
-
591
522
  // ===== Dynamic Configuration through Homebridge UI =========================
592
523
 
593
524
  /** Handler for requests from the Homebridge Plugin UI Server.
@@ -601,7 +532,8 @@ class Platform extends Delegate {
601
532
  */
602
533
 
603
534
  // Create HTTP server for Homebridge Plugin UI Settings.
604
- async _createUiServer () {
535
+ async #createUiServer () {
536
+ const { Server, STATUS_CODES } = await import('node:http')
605
537
  this._ui = {}
606
538
  this._ui.server = new Server()
607
539
  this._ui.server
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "ebaauw"
7
7
  ],
8
8
  "license": "Apache-2.0",
9
- "version": "8.0.0",
9
+ "version": "8.0.1",
10
10
  "keywords": [
11
11
  "homekit",
12
12
  "homebridge"
@@ -29,12 +29,12 @@
29
29
  "upnp": "cli/upnp.js"
30
30
  },
31
31
  "engines": {
32
- "homebridge": "^1.11.4||^2.0.0-beta",
33
- "node": "24.14.1||^24||^22||^20"
32
+ "homebridge": "^2.0.0",
33
+ "node": "24.15.0||^24||^22"
34
34
  },
35
35
  "dependencies": {
36
36
  "@homebridge/plugin-ui-utils": "~2.2.3",
37
- "hb-lib-tools": "~3.0.0"
37
+ "hb-lib-tools": "~3.0.4"
38
38
  },
39
39
  "scripts": {
40
40
  "prepare": "standard && rm -rf out && jsdoc -c jsdoc.json",
package/lib/Bonjour.js DELETED
@@ -1,12 +0,0 @@
1
- // homebridge-lib/lib/Bonjour.js
2
- //
3
- // Library for Homebridge plugins.
4
- // Copyright © 2020-2026 Erik Baauw. All rights reserved.
5
-
6
- /** Return the `Bonjour` class from [`bonjour-hap`](https://github.com/homebridge/bonjour),
7
- * so plugins don't have to list this as a separate dependency.
8
- * @name Bonjour
9
- * @type {Class}
10
- * @memberof module:homebridge-lib
11
- */
12
- export { Bonjour } from 'hb-lib-tools/Bonjour'