homebridge-lib 5.3.2 → 5.5.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/cli/json.js CHANGED
@@ -12,6 +12,10 @@
12
12
  const homebridgeLib = require('../index')
13
13
 
14
14
  const fs = require('fs')
15
+ const util = require('util')
16
+ const zlib = require('zlib')
17
+
18
+ const gunzip = util.promisify(zlib.unzip)
15
19
 
16
20
  const { b, u } = homebridgeLib.CommandLineTool
17
21
 
@@ -21,26 +25,59 @@ const help = `JSON formatter.
21
25
  Usage: ${usage}
22
26
 
23
27
  By default, ${b('json')} reads JSON from stdin, formats it, and prints it to stdout.
24
- The following parameters modify this behaviour:
25
- ${b('-h')} Print this help and exit.
26
- ${b('-V')} Print version and exit.
27
- ${b('-s')} Sort object key/value pairs alphabetically on key.
28
- ${b('-n')} Do not include spaces nor newlines in output.
29
- ${b('-j')} Output JSON array of objects for each key/value pair.
30
- Each object contains two key/value pairs: key "keys" with an array
31
- of keys as value and key "value" with the value as value.
32
- ${b('-u')} Output JSON array of objects for each key/value pair.
33
- Each object contains one key/value pair: the path (concatenated
34
- keys separated by '/') as key and the value as value.
35
- ${b('-a')} Output path:value in plain text instead of JSON.
36
- ${b('-t')} Limit output to top-level key/values.
37
- ${b('-p')} ${u('path')} Limit output to key/values under ${u('path')}. Set top level below ${u('path')}.
38
- ${b('-d')} ${u('depth')} Limit output to levels above ${u('depth')}.
39
- ${b('-l')} Limit output to leaf (non-array, non-object) key/values.
40
- ${b('-k')} Limit output to keys. With ${b('-u')} output JSON array of paths.
41
- ${b('-v')} Limit output to values. With ${b('-u')} output JSON array of values.
42
- ${b('-c')} ${u('string')} Read JSON from ${u('string')} instead of from stdin.
43
- ${u('file')} Read JSON from ${u('file')} instead of from stdin.`
28
+
29
+ Parameters:
30
+ ${b('-h')}, ${b('--help')}
31
+ Print this help and exit.
32
+
33
+ ${b('-V')}, ${b('--version')}
34
+ Print version and exit.
35
+
36
+ ${b('-s')}, ${b('--sortKeys')}
37
+ Sort object key/value pairs alphabetically on key.
38
+
39
+ ${b('-n')}, ${b('--noWhiteSpace')}
40
+ Do not include spaces nor newlines in output.
41
+
42
+ ${b('-j')}, ${b('--jsonArray')}
43
+ Output JSON array of objects for each key/value pair.
44
+ Each object contains two key/value pairs:
45
+ - key ${b('keys')} with an array of keys as value;
46
+ - key ${b('value')} with the value as value.
47
+
48
+ ${b('-u')}, ${b('--joinKeys')}
49
+ Output JSON array of objects for each key/value pair.
50
+ Each object contains one key/value pair:
51
+ the path (concatenated keys separated by ${b('/')} as key and the value as value.
52
+
53
+ ${b('-a')}, ${b('--ascii')}
54
+ Output ${u('path')}${b(':')}${u('value')} in plain text instead of JSON.
55
+
56
+ ${b('-t')}, ${b('--topOnly')}
57
+ Limit output to top-level key/values.
58
+
59
+ ${b('-p')} ${u('path')}, ${b('--fromPath=')}${u('path')}
60
+ Limit output to key/values under ${u('path')}. Set top level below ${u('path')}.
61
+
62
+ ${b('-d')} ${u('depth')}, ${b('--maxDepth=')}${u('depth')}
63
+ Limit output to levels above ${u('depth')}.
64
+
65
+ ${b('-l')}, ${b('--leavesOnly')}
66
+ Limit output to leaf (non-array, non-object) key/values.
67
+
68
+ ${b('-k')}, ${b('--keysOnly')}
69
+ Limit output to keys. With ${b('-u')} output JSON array of paths.
70
+
71
+ ${b('-v')}, ${b('--valuesOnly')}
72
+ Limit output to values. With ${b('-u')} output JSON array of values.
73
+
74
+ ${b('-c')} ${u('string')}, ${b('--string=')}${u('string')}
75
+ Read JSON from ${u('string')} instead of from stdin.
76
+
77
+ ${u('file')}
78
+ Read JSON from ${u('file')} instead of from stdin.
79
+ When the file name ends in ${b('.gz')}, it is assumed to be a gzip file and
80
+ uncompressed automatically.`
44
81
 
45
82
  class Main extends homebridgeLib.CommandLineTool {
46
83
  constructor () {
@@ -110,9 +147,11 @@ class Main extends homebridgeLib.CommandLineTool {
110
147
  this.error(error)
111
148
  }
112
149
  })
113
- this.fileList.forEach((file) => {
150
+ this.fileList.forEach(async (file) => {
114
151
  try {
115
- const s = fs.readFileSync(file === '-' ? 0 : file, 'utf8')
152
+ const s = file.endsWith('.gz')
153
+ ? await gunzip(fs.readFileSync(file))
154
+ : fs.readFileSync(file === '-' ? 0 : file, 'utf8')
116
155
  this.processString(s)
117
156
  } catch (error) {
118
157
  this.error(error)
@@ -172,12 +172,8 @@ class AdaptiveLighting {
172
172
  * @param {integer} ct - The IID of the _Color Temperature_ characteristic.
173
173
  */
174
174
  constructor (bri, ct) {
175
- this.bri = bri instanceof homebridgeLib.CharacteristicDelegate
176
- ? bri._characteristic.iid
177
- : bri
178
- this.ct = ct instanceof homebridgeLib.CharacteristicDelegate
179
- ? ct._characteristic.iid
180
- : ct
175
+ this._bri = bri
176
+ this._ct = ct
181
177
  this._active = false
182
178
  }
183
179
 
@@ -187,6 +183,24 @@ class AdaptiveLighting {
187
183
  */
188
184
  get active () { return this._control != null }
189
185
 
186
+ get briIid () {
187
+ if (this._briIid == null) {
188
+ this._briIid = this._bri instanceof homebridgeLib.CharacteristicDelegate
189
+ ? this._bri._characteristic.iid
190
+ : this._bri
191
+ }
192
+ return this._briIid
193
+ }
194
+
195
+ get ctIid () {
196
+ if (this._ctIid == null) {
197
+ this._ctIid = this._ct instanceof homebridgeLib.CharacteristicDelegate
198
+ ? this._ct._characteristic.iid
199
+ : this._ct
200
+ }
201
+ return this._ctIid
202
+ }
203
+
190
204
  /** Deactivtate adaptive lighting.
191
205
  */
192
206
  deactivate () {
@@ -199,12 +213,12 @@ class AdaptiveLighting {
199
213
  generateConfiguration () {
200
214
  return Buffer.concat([
201
215
  tlvFromBuffer(1, Buffer.concat([
202
- tlvFromUInt(1, this.bri),
216
+ tlvFromUInt(1, this.briIid),
203
217
  tlvFromUInt(2, 1)
204
218
  ])),
205
219
  tlvFromNull(0),
206
220
  tlvFromBuffer(1, Buffer.concat([
207
- tlvFromUInt(1, this.ct),
221
+ tlvFromUInt(1, this.ctIid),
208
222
  tlvFromUInt(2, 2)
209
223
  ]))
210
224
  ]).toString('base64')
@@ -212,7 +226,7 @@ class AdaptiveLighting {
212
226
 
213
227
  _generateControl () {
214
228
  return tlvFromBuffer(1, Buffer.concat([
215
- tlvFromUInt(1, this.ct),
229
+ tlvFromUInt(1, this.ctIid),
216
230
  tlvFromBuffer(2, Buffer.concat([
217
231
  tlvFromHexString(1, this._control.transitionParameters['2.1.2.1']),
218
232
  tlvFromUInt(2, this._startTime - epoch),
@@ -266,11 +280,11 @@ class AdaptiveLighting {
266
280
  value = parseTlv('2', buf)
267
281
  }
268
282
  const control = value.colorTemperature
269
- if (control.iid != null && control.iid !== this.ct) {
283
+ if (control.iid != null && control.iid !== this.ctIid) {
270
284
  throw new Error('%d: bad ColorTemperature iid', control.iid)
271
285
  }
272
286
  if (control.curve != null) {
273
- if (control.curve.adjustmentIid !== this.bri) {
287
+ if (control.curve.adjustmentIid !== this.briIid) {
274
288
  throw new Error('%d: bad Brightness iid', control.curve.adjustmentIid)
275
289
  }
276
290
  this._control = control
@@ -274,7 +274,7 @@ class CharacteristicDelegate extends homebridgeLib.Delegate {
274
274
  break
275
275
  }
276
276
  }
277
- return { value: value, s: s }
277
+ return { value, s }
278
278
  }
279
279
 
280
280
  /** Value of associated Characteristic.
package/lib/Colour.js CHANGED
@@ -109,7 +109,7 @@ class Colour {
109
109
  case 4: r = x + m; g = m; b = C + m; break
110
110
  case 5: r = C + m; g = m; b = x + m; break
111
111
  }
112
- return { r: r, g: g, b: b }
112
+ return { r, g, b }
113
113
  }
114
114
 
115
115
  /** Convert {@link Colour.RGB RGB} to {@link Colour.HSV HSV}.
@@ -201,11 +201,7 @@ See ${this._packageJson.homepage.split('#')[0]} for more info.
201
201
  parameter (key, callback, optional = false) {
202
202
  key = homebridgeLib.OptionParser.toString('key', key, true)
203
203
  callback = homebridgeLib.OptionParser.toFunction('callback', callback)
204
- this._callbacks.parameters.push({
205
- key: key,
206
- callback: callback,
207
- optional: optional
208
- })
204
+ this._callbacks.parameters.push({ key, callback, optional })
209
205
  return this
210
206
  }
211
207
 
package/lib/HttpClient.js CHANGED
@@ -349,14 +349,14 @@ class HttpClient extends events.EventEmitter {
349
349
  const requestId = ++this.__requestId
350
350
  const url = this.__params.url + (resource === '/' ? '' : resource) +
351
351
  this.__params.suffix + suffix
352
- const options = Object.assign({ method: method }, this.__options)
352
+ const options = Object.assign({ method }, this.__options)
353
353
  const requestInfo = Object.assign({
354
354
  name: this.name,
355
355
  id: requestId,
356
- method: method,
357
- resource: resource,
358
- body: body,
359
- url: url
356
+ method,
357
+ resource,
358
+ body,
359
+ url
360
360
  }, info)
361
361
  const request = this._http.request(url, options)
362
362
  request
@@ -185,9 +185,9 @@ class JsonFormatter {
185
185
  obj[`/${keys.join('/')}`] = value
186
186
  return obj
187
187
  } else {
188
- if (this.options.keysOnly) { return { keys: keys } }
189
- if (this.options.valuesOnly) { return { value: value } }
190
- return { keys: keys, value: value }
188
+ if (this.options.keysOnly) { return { keys } }
189
+ if (this.options.valuesOnly) { return { value } }
190
+ return { keys, value }
191
191
  }
192
192
  })
193
193
  if (this.options.ascii) {
package/lib/Platform.js CHANGED
@@ -12,10 +12,12 @@ const fs = require('fs')
12
12
  const http = require('http')
13
13
  const semver = require('semver')
14
14
  const util = require('util')
15
+ const zlib = require('zlib')
15
16
 
16
17
  const libPackageJson = require('../package.json')
17
18
 
18
19
  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}$/
20
+ const gzip = util.promisify(zlib.gzip)
19
21
 
20
22
  const context = {
21
23
  libName: libPackageJson.name,
@@ -114,6 +116,12 @@ class Platform extends homebridgeLib.Delegate {
114
116
 
115
117
  get Characteristics () { return context.Characteristics }
116
118
 
119
+ /** Content of the plugin's package.json file.
120
+ * @type {object}
121
+ * @readonly
122
+ */
123
+ get packageJson () { return context.packageJson }
124
+
117
125
  /** Create a new instance of the platform plugin.
118
126
  *
119
127
  * Called by Homebridge when initialising the plugin from `config.json`.
@@ -210,6 +218,39 @@ class Platform extends homebridgeLib.Delegate {
210
218
  }
211
219
  }
212
220
 
221
+ /** Create a debug dump file.
222
+ *
223
+ * The dump file is a gzipped json file containing
224
+ * - The hardware and software environment of the server running Homebridge;
225
+ * - The versions of the plugin and of homebridge-lib;
226
+ * - The contents of config.json;
227
+ * - Any plugin-specific information.
228
+ *
229
+ * The file is created in the Homebridge user directory, and named after
230
+ * the plugin.
231
+ * @param {*} dumpInfo - Plugin-specific information.
232
+ */
233
+ async createDumpFile (dumpInfo = {}) {
234
+ const result = {
235
+ hardware: this.systemInfo.hwInfo.prettyName,
236
+ os: this.systemInfo.osInfo.prettyName,
237
+ node: context.nodeVersion,
238
+ homebridge: context.homebridgeVersion
239
+ }
240
+ result[this._pluginName] = this._pluginVersion
241
+ result[context.libName] = context.libVersion
242
+ result.configJson = this._configJson
243
+ const filename = this._homebridge.user.storagePath() + '/' +
244
+ this._pluginName + '.json.gz'
245
+ try {
246
+ const data = await gzip(JSON.stringify(Object.assign(result, dumpInfo)))
247
+ await fs.promises.writeFile(filename, data)
248
+ this.log('created debug dump file %s', filename)
249
+ } catch (error) {
250
+ this.error('%s: %s', filename, error)
251
+ }
252
+ }
253
+
213
254
  // Write `cachedAccessories` to disk.
214
255
  _flushCachedAccessories () {
215
256
  this.debug('flush cachedAccessories')
@@ -237,7 +278,7 @@ class Platform extends homebridgeLib.Delegate {
237
278
 
238
279
  if (beat % context.checkInterval === 0) {
239
280
  this._checkLatest(this._pluginName, this._pluginVersion)
240
- this._checkLatest(context.libName, context.libVersion)
281
+ // this._checkLatest(context.libName, context.libVersion)
241
282
  }
242
283
 
243
284
  /** Emitted every second.
@@ -431,10 +472,10 @@ class Platform extends homebridgeLib.Delegate {
431
472
  this._accessories[id] = accessory
432
473
  accessory.displayName = name
433
474
  accessory.context = {
434
- className: className,
435
- version: version,
436
- id: id,
437
- name: name,
475
+ className,
476
+ version,
477
+ id,
478
+ name,
438
479
  logLevel: this.logLevel,
439
480
  context: {}
440
481
  }
@@ -94,7 +94,7 @@ class PropertyDelegate extends homebridgeLib.Delegate {
94
94
 
95
95
  validate (value) {
96
96
  // Todo: check value against type.
97
- return { value: value, s: '' }
97
+ return { value, s: '' }
98
98
  }
99
99
 
100
100
  /** Value of associated Characteristic.
package/lib/SystemInfo.js CHANGED
@@ -150,19 +150,19 @@ class SystemInfo extends events.EventEmitter {
150
150
  gpioMask = 0x03E6CF93 // 0-1, 4, 7-11, 14-15, 17-18, 21-25
151
151
  }
152
152
  return {
153
- gpioMask: gpioMask,
153
+ gpioMask,
154
154
  gpioMaskSerial: (1 << 15) | (1 << 14),
155
- id: id,
155
+ id,
156
156
  isRpi: true,
157
- manufacturer: manufacturer,
158
- memory: memory,
159
- model: model,
160
- modelRevision: modelRevision,
157
+ manufacturer,
158
+ memory,
159
+ model,
160
+ modelRevision,
161
161
  prettyName: [
162
162
  'Raspberry Pi', model, modelRevision, '(' + memory + ')'
163
163
  ].join(' '),
164
164
  powerLed: !(['A', 'B', 'Zero', 'Zero W', 'Zero 2 W'].includes(model)),
165
- processor: processor,
165
+ processor,
166
166
  revision: homebridgeLib.toHexString(revision, 6),
167
167
  usbPower: ['B+', '2B', '3B', '3B+'].includes(model)
168
168
  }
@@ -249,13 +249,7 @@ class SystemInfo extends events.EventEmitter {
249
249
  }
250
250
  }
251
251
  }
252
- return {
253
- name: name,
254
- platform: platform,
255
- prettyName: prettyName,
256
- version: version,
257
- versionName: versionName
258
- }
252
+ return { name, platform, prettyName, version, versionName }
259
253
  }
260
254
 
261
255
  /** Extract Apple Mac hardware info from `system_profiler` command.
@@ -315,15 +309,15 @@ class SystemInfo extends events.EventEmitter {
315
309
  this.emit('error', error)
316
310
  }
317
311
  return {
318
- id: id,
312
+ id,
319
313
  isMac: true,
320
314
  manufacturer: 'Apple Inc.',
321
- memory: memory,
322
- model: model,
323
- nCores: nCores,
315
+ memory,
316
+ model,
317
+ nCores,
324
318
  prettyName: prettyName || model,
325
- processor: processor,
326
- revision: revision
319
+ processor,
320
+ revision
327
321
  }
328
322
  }
329
323
 
@@ -361,13 +355,13 @@ class SystemInfo extends events.EventEmitter {
361
355
  }
362
356
  const versionName = macOsInfo.versionNames[v] // e.g. 'Monterey'
363
357
  return {
364
- build: build,
358
+ build,
365
359
  catalina: semver.gte(version, '10.15.0'),
366
- name: name,
360
+ name,
367
361
  platform: process.platform,
368
362
  prettyName: [name, versionName, version, '(' + build + ')'].join(' '),
369
- version: version,
370
- versionName: versionName
363
+ version,
364
+ versionName
371
365
  }
372
366
  }
373
367
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Library for homebridge plugins",
4
4
  "author": "Erik Baauw",
5
5
  "license": "Apache-2.0",
6
- "version": "5.3.2",
6
+ "version": "5.5.0",
7
7
  "keywords": [
8
8
  "homekit",
9
9
  "homebridge"
@@ -21,14 +21,14 @@
21
21
  "upnp": "cli/upnp.js"
22
22
  },
23
23
  "engines": {
24
- "homebridge": "^1.4.0",
25
- "node": "^16.14.2"
24
+ "homebridge": "^1.4.1",
25
+ "node": "^16.15.0"
26
26
  },
27
27
  "dependencies": {
28
28
  "@homebridge/plugin-ui-utils": "~0.0.19",
29
29
  "bonjour-hap": "^3.6.3",
30
30
  "chalk": "^4.1.2",
31
- "semver": "^7.3.5"
31
+ "semver": "^7.3.7"
32
32
  },
33
33
  "scripts": {
34
34
  "prepare": "standard && mocha && rm -rf out && jsdoc -c jsdoc.json",