homebridge-lib 5.3.1 → 5.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/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)
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,
@@ -210,6 +212,39 @@ class Platform extends homebridgeLib.Delegate {
210
212
  }
211
213
  }
212
214
 
215
+ /** Create a debug dump file.
216
+ *
217
+ * The dump file is a gzipped json file containing
218
+ * - The hardware and software environment of the server running Homebridge;
219
+ * - The versions of the plugin and of homebridge-lib;
220
+ * - The contents of config.json;
221
+ * - Any plugin-specific information.
222
+ *
223
+ * The file is created in the Homebridge user directory, and named after
224
+ * the plugin.
225
+ * @param {*} dumpInfo - Plugin-specific information.
226
+ */
227
+ async createDumpFile (dumpInfo = {}) {
228
+ const result = {
229
+ hardware: this.systemInfo.hwInfo.prettyName,
230
+ os: this.systemInfo.osInfo.prettyName,
231
+ node: context.nodeVersion,
232
+ homebridge: context.homebridgeVersion
233
+ }
234
+ result[this._pluginName] = this._pluginVersion
235
+ result[context.libName] = context.libVersion
236
+ result.configJson = this._configJson
237
+ const filename = this._homebridge.user.storagePath() + '/' +
238
+ this._pluginName + '.json.gz'
239
+ try {
240
+ const data = await gzip(JSON.stringify(Object.assign(result, dumpInfo)))
241
+ await fs.promises.writeFile(filename, data)
242
+ this.log('created debug dump file %s', filename)
243
+ } catch (error) {
244
+ this.error('%s: %s', filename, error)
245
+ }
246
+ }
247
+
213
248
  // Write `cachedAccessories` to disk.
214
249
  _flushCachedAccessories () {
215
250
  this.debug('flush cachedAccessories')
@@ -237,7 +272,7 @@ class Platform extends homebridgeLib.Delegate {
237
272
 
238
273
  if (beat % context.checkInterval === 0) {
239
274
  this._checkLatest(this._pluginName, this._pluginVersion)
240
- this._checkLatest(context.libName, context.libVersion)
275
+ // this._checkLatest(context.libName, context.libVersion)
241
276
  }
242
277
 
243
278
  /** Emitted every second.
package/lib/SystemInfo.js CHANGED
@@ -293,29 +293,26 @@ class SystemInfo extends events.EventEmitter {
293
293
  }
294
294
  }
295
295
  }
296
- text = await this.exec(
297
- 'plutil', '-convert', 'json', '-o', '-',
298
- process.env.HOME + '/Library/Preferences/com.apple.SystemProfiler.plist'
299
- )
300
- const s = JSON.parse(text)['CPU Names']
301
- if (s != null) {
302
- // This is empty on my MacBook Pro (14-inch, 2021).
303
- for (const key of Object.keys(s)) {
304
- if (key.startsWith(id.slice(-4))) {
305
- prettyName = s[key]
296
+ try {
297
+ if (process.arch === 'x64') { // Intel
298
+ text = await this.exec(
299
+ 'plutil', '-p',
300
+ process.env.HOME + '/Library/Preferences/com.apple.SystemProfiler.plist'
301
+ )
302
+ const regexp = RegExp('"' + id.slice(-4) + '.*" => "(.*)"')
303
+ const a = regexp.exec(text)
304
+ if (a[1] != null) {
305
+ prettyName = a[1]
306
+ }
307
+ } else { // Apple silicon
308
+ text = await this.execShell('ioreg -l | grep product-description')
309
+ const a = /"product-description" = <"([^"]*)">/.exec(text)
310
+ if (a != null) {
311
+ prettyName = a[1]
306
312
  }
307
313
  }
308
- } else {
309
- // text = await this.exec(
310
- // 'ioreg', '-c', 'IOPlatformDevice', '-d', '4', '-n', 'product'
311
- // )
312
- text = await this.execShell('ioreg -l | grep product-description')
313
- // This is empty on my Intel Macs - I think the key is registered for
314
- // running iPad apps on Apple chips.
315
- const a = /"product-description" = <"([^"]*)">/.exec(text)
316
- if (a != null) {
317
- prettyName = a[1]
318
- }
314
+ } catch (error) {
315
+ this.emit('error', error)
319
316
  }
320
317
  return {
321
318
  id: id,
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.1",
6
+ "version": "5.4.0",
7
7
  "keywords": [
8
8
  "homekit",
9
9
  "homebridge"
@@ -28,7 +28,7 @@
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",