homebridge-lib 5.2.3-0 → 5.3.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.
- package/index.js +7 -0
- package/lib/CommandLineTool.js +30 -2
- package/lib/Platform.js +112 -9
- package/lib/UiServer.js +237 -0
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -196,6 +196,13 @@ class homebridgeLib {
|
|
|
196
196
|
*/
|
|
197
197
|
static get SystemInfo () { return require('./lib/SystemInfo') }
|
|
198
198
|
|
|
199
|
+
/** Server for dynamic configuration settings through Homebridge UI.
|
|
200
|
+
* <br>See {@link UiServer}.
|
|
201
|
+
* @type {Class}
|
|
202
|
+
* @memberof module:homebridgeLib
|
|
203
|
+
*/
|
|
204
|
+
static get UiServer () { return require('./lib/UiServer') }
|
|
205
|
+
|
|
199
206
|
/** Universal Plug and Play client.
|
|
200
207
|
* <br>See {@link UpnpClient}.
|
|
201
208
|
* @type {Class}
|
package/lib/CommandLineTool.js
CHANGED
|
@@ -150,8 +150,9 @@ class CommandLineTool {
|
|
|
150
150
|
return !!this._options.debug
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
/** Usage string.
|
|
154
|
+
* @type {string}
|
|
155
|
+
*/
|
|
155
156
|
get usage () { return this._usage }
|
|
156
157
|
set usage (usage) {
|
|
157
158
|
this._usage = usage
|
|
@@ -167,6 +168,9 @@ class CommandLineTool {
|
|
|
167
168
|
// ===== Logging =============================================================
|
|
168
169
|
|
|
169
170
|
/** Print debug message to stderr.
|
|
171
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
172
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
173
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
170
174
|
*/
|
|
171
175
|
debug (format, ...args) {
|
|
172
176
|
if (this._options.debug) {
|
|
@@ -175,12 +179,18 @@ class CommandLineTool {
|
|
|
175
179
|
}
|
|
176
180
|
|
|
177
181
|
/** Print error message to stderr.
|
|
182
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
183
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
184
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
178
185
|
*/
|
|
179
186
|
error (format, ...args) {
|
|
180
187
|
this._log({ label: 'error', chalk: chalk.bold.red }, format, ...args)
|
|
181
188
|
}
|
|
182
189
|
|
|
183
190
|
/** Print error message to stderr and abort program.
|
|
191
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
192
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
193
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
184
194
|
*/
|
|
185
195
|
async fatal (format, ...args) {
|
|
186
196
|
this._log({ label: 'fatal', chalk: chalk.bold.red }, format, ...args)
|
|
@@ -195,24 +205,36 @@ class CommandLineTool {
|
|
|
195
205
|
}
|
|
196
206
|
|
|
197
207
|
/** Print log message to stderr.
|
|
208
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
209
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
210
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
198
211
|
*/
|
|
199
212
|
log (format, ...args) {
|
|
200
213
|
this._log({}, format, ...args)
|
|
201
214
|
}
|
|
202
215
|
|
|
203
216
|
/** Print log message continuation to stderr.
|
|
217
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
218
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
219
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
204
220
|
*/
|
|
205
221
|
logc (format, ...args) {
|
|
206
222
|
this._log({ noLabel: true }, format, ...args)
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
/** Print message to stdout.
|
|
226
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
227
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
228
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
210
229
|
*/
|
|
211
230
|
print (format, ...args) {
|
|
212
231
|
this._log({ noLabel: true, stdout: true }, format, ...args)
|
|
213
232
|
}
|
|
214
233
|
|
|
215
234
|
/** Print verbose debug message to stderr.
|
|
235
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
236
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
237
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
216
238
|
*/
|
|
217
239
|
vdebug (format, ...args) {
|
|
218
240
|
if (this._options.vdebug) {
|
|
@@ -221,6 +243,9 @@ class CommandLineTool {
|
|
|
221
243
|
}
|
|
222
244
|
|
|
223
245
|
/** Print very verbose debug message to stderr.
|
|
246
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
247
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
248
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
224
249
|
*/
|
|
225
250
|
vvdebug (format, ...args) {
|
|
226
251
|
if (this._options.vvdebug) {
|
|
@@ -229,6 +254,9 @@ class CommandLineTool {
|
|
|
229
254
|
}
|
|
230
255
|
|
|
231
256
|
/** Print warning message to stderr.
|
|
257
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
258
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
259
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
232
260
|
*/
|
|
233
261
|
warn (format, ...args) {
|
|
234
262
|
this._log({ label: 'warning', chalk: chalk.yellow }, format, ...args)
|
package/lib/Platform.js
CHANGED
|
@@ -9,8 +9,10 @@ const homebridgeLib = require('../index')
|
|
|
9
9
|
|
|
10
10
|
const events = require('events')
|
|
11
11
|
const fs = require('fs')
|
|
12
|
+
const http = require('http')
|
|
12
13
|
const semver = require('semver')
|
|
13
14
|
const util = require('util')
|
|
15
|
+
|
|
14
16
|
const libPackageJson = require('../package.json')
|
|
15
17
|
|
|
16
18
|
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}$/
|
|
@@ -37,7 +39,8 @@ const context = {
|
|
|
37
39
|
* the plugin through Homebridge;
|
|
38
40
|
* - Persist HomeKit accessories across Homebridge restarts;
|
|
39
41
|
* - Support for device polling by providing a heartbeat;
|
|
40
|
-
* - Support for UPnP device discovery
|
|
42
|
+
* - Support for UPnP device discovery;
|
|
43
|
+
* - Support dynamic configuration through the Homebridge UI.
|
|
41
44
|
* @abstract
|
|
42
45
|
* @extends Delegate
|
|
43
46
|
*/
|
|
@@ -172,11 +175,7 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
172
175
|
this.log('os: %s', this.systemInfo.osInfo.prettyName)
|
|
173
176
|
this._heartbeatStart = new Date()
|
|
174
177
|
setTimeout(() => { this._beat(-1) }, 1000)
|
|
175
|
-
this.on('exit', () => {
|
|
176
|
-
this.debug('flush cachedAccessories')
|
|
177
|
-
this._homebridge.updatePlatformAccessories()
|
|
178
|
-
this.log('goodbye')
|
|
179
|
-
})
|
|
178
|
+
this.on('exit', () => { this._flushCachedAccessories() })
|
|
180
179
|
|
|
181
180
|
const n = Object.keys(this._accessories).length
|
|
182
181
|
if (n > 0) {
|
|
@@ -188,7 +187,13 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
188
187
|
if (this.listenerCount('upnpDeviceFound') > 0) {
|
|
189
188
|
this._upnpMonitor.search()
|
|
190
189
|
}
|
|
190
|
+
if (typeof this.onUiRequest === 'function') {
|
|
191
|
+
try {
|
|
192
|
+
await this._createUiServer()
|
|
193
|
+
} catch (error) { this.error(error) }
|
|
194
|
+
}
|
|
191
195
|
await events.once(this, 'initialised')
|
|
196
|
+
this._flushCachedAccessories()
|
|
192
197
|
for (const id in this._accessories) {
|
|
193
198
|
if (this._accessoryDelegates[id] == null) {
|
|
194
199
|
const accessory = this._accessories[id]
|
|
@@ -205,6 +210,12 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
205
210
|
}
|
|
206
211
|
}
|
|
207
212
|
|
|
213
|
+
// Write `cachedAccessories` to disk.
|
|
214
|
+
_flushCachedAccessories () {
|
|
215
|
+
this.debug('flush cachedAccessories')
|
|
216
|
+
this._homebridge.updatePlatformAccessories()
|
|
217
|
+
}
|
|
218
|
+
|
|
208
219
|
// Called every second.
|
|
209
220
|
_beat (beat) {
|
|
210
221
|
beat += 1
|
|
@@ -221,9 +232,7 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
221
232
|
}, 1000 - drift)
|
|
222
233
|
|
|
223
234
|
if (beat % context.saveInterval === 30) {
|
|
224
|
-
|
|
225
|
-
this.debug('flush cachedAccessories')
|
|
226
|
-
this._homebridge.updatePlatformAccessories()
|
|
235
|
+
this._flushCachedAccessories()
|
|
227
236
|
}
|
|
228
237
|
|
|
229
238
|
if (beat % context.checkInterval === 0) {
|
|
@@ -255,6 +264,9 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
255
264
|
this._shuttingDown = true
|
|
256
265
|
this.removeAllListeners('upnpDeviceAlive')
|
|
257
266
|
this.removeAllListeners('upnpDeviceFound')
|
|
267
|
+
if (this._ui != null && this._ui.abortController != null) {
|
|
268
|
+
this._ui.abortController.abort()
|
|
269
|
+
}
|
|
258
270
|
for (const id in this._accessoryDelegates) {
|
|
259
271
|
/** Emitted when Homebridge is shutting down.
|
|
260
272
|
*
|
|
@@ -545,6 +557,97 @@ class Platform extends homebridgeLib.Delegate {
|
|
|
545
557
|
})
|
|
546
558
|
}
|
|
547
559
|
|
|
560
|
+
// ===== Dynamic Configuration through Homebridge UI =========================
|
|
561
|
+
|
|
562
|
+
/** Handler for requests from the Homebridge Plugin UI Server.
|
|
563
|
+
* @function Platform#onUiRequest
|
|
564
|
+
* @async
|
|
565
|
+
* @abstract
|
|
566
|
+
* @param {string} method - The request method.
|
|
567
|
+
* @param {string} resource - The request resource.
|
|
568
|
+
* @param {*} body - The request body.
|
|
569
|
+
* @returns {*} - The response body.
|
|
570
|
+
*/
|
|
571
|
+
|
|
572
|
+
// Create HTTP server for Homebridge Plugin UI Settings.
|
|
573
|
+
async _createUiServer () {
|
|
574
|
+
this._ui = {}
|
|
575
|
+
this._ui.server = new http.Server()
|
|
576
|
+
this._ui.server
|
|
577
|
+
.on('listening', () => {
|
|
578
|
+
this._ui.port = this._ui.server.address().port
|
|
579
|
+
this.log('ui server: listening on http://127.0.0.1:%d/', this._ui.port)
|
|
580
|
+
for (const id in this._accessoryDelegates) {
|
|
581
|
+
this._accessoryDelegates[id]._context.uiPort = this._ui.port
|
|
582
|
+
}
|
|
583
|
+
})
|
|
584
|
+
.on('error', (error) => { this.error(error) })
|
|
585
|
+
.on('close', () => {
|
|
586
|
+
this.debug('ui server: closed port %d', this._ui.port)
|
|
587
|
+
})
|
|
588
|
+
.on('request', async (request, response) => {
|
|
589
|
+
let buffer = ''
|
|
590
|
+
request.on('data', (data) => { buffer += data })
|
|
591
|
+
request.on('end', async () => {
|
|
592
|
+
try {
|
|
593
|
+
if (buffer !== '') {
|
|
594
|
+
try {
|
|
595
|
+
request.body = JSON.parse(buffer)
|
|
596
|
+
} catch (error) {
|
|
597
|
+
this.log(
|
|
598
|
+
'ui request %s: %s %s %s', ++this._ui.requestId,
|
|
599
|
+
request.method, request.url, buffer
|
|
600
|
+
)
|
|
601
|
+
this.warn('ui request %d: %s', this._ui.requestId, error.message)
|
|
602
|
+
response.writeHead(400) // Bad Request
|
|
603
|
+
response.end()
|
|
604
|
+
return
|
|
605
|
+
}
|
|
606
|
+
this.debug(
|
|
607
|
+
'ui request %s: %s %s %j', ++this._ui.requestId,
|
|
608
|
+
request.method, request.url, request.body
|
|
609
|
+
)
|
|
610
|
+
} else {
|
|
611
|
+
this.debug(
|
|
612
|
+
'ui request %s: %s %s', ++this._ui.requestId,
|
|
613
|
+
request.method, request.url
|
|
614
|
+
)
|
|
615
|
+
}
|
|
616
|
+
const { status, body } =
|
|
617
|
+
request.method === 'GET' && request.url === '/ping'
|
|
618
|
+
? { status: 200, body: 'pong' }
|
|
619
|
+
: await this.onUiRequest(
|
|
620
|
+
request.method, request.url, request.body
|
|
621
|
+
)
|
|
622
|
+
this.debug(
|
|
623
|
+
'ui request %d: %d %s', this._ui.requestId,
|
|
624
|
+
status, http.STATUS_CODES[status]
|
|
625
|
+
)
|
|
626
|
+
if (status === 200) {
|
|
627
|
+
this.vdebug('ui request %d: response: %j', this._ui.requestId, body)
|
|
628
|
+
response.writeHead(status, { 'Content-Type': 'application/json' })
|
|
629
|
+
response.end(JSON.stringify(body))
|
|
630
|
+
} else {
|
|
631
|
+
response.writeHead(status)
|
|
632
|
+
response.end()
|
|
633
|
+
}
|
|
634
|
+
} catch (error) {
|
|
635
|
+
this.warn('ui request %d: %s', this._ui.requestId, error)
|
|
636
|
+
response.writeHead(500) // Internal Server Error
|
|
637
|
+
response.end()
|
|
638
|
+
}
|
|
639
|
+
})
|
|
640
|
+
})
|
|
641
|
+
this._ui.abortController = new AbortController() // eslint-disable-line no-undef
|
|
642
|
+
this._ui.requestId = 0
|
|
643
|
+
this._ui.server.listen({
|
|
644
|
+
port: 0,
|
|
645
|
+
host: '127.0.0.1',
|
|
646
|
+
signal: this._ui.abortController.signal
|
|
647
|
+
})
|
|
648
|
+
await events.once(this._ui.server, 'listening')
|
|
649
|
+
}
|
|
650
|
+
|
|
548
651
|
// ===== Logging =============================================================
|
|
549
652
|
|
|
550
653
|
// Do the heavy lifting for debug(), error(), fatal(), log(), and warn(),
|
package/lib/UiServer.js
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// homebridge-deconz/homebridge-lib/UiServer.js
|
|
2
|
+
//
|
|
3
|
+
// Library for Homebridge plugins.
|
|
4
|
+
// Copyright © 2022 Erik Baauw. All rights reserved.
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
HomebridgePluginUiServer // , RequestError
|
|
10
|
+
} = require('@homebridge/plugin-ui-utils')
|
|
11
|
+
const { HttpClient, formatError } = require('../index')
|
|
12
|
+
const chalk = require('chalk')
|
|
13
|
+
const fs = require('fs/promises')
|
|
14
|
+
const path = require('path')
|
|
15
|
+
const util = require('util')
|
|
16
|
+
|
|
17
|
+
/** Server for handling Homebridge Plugin UI requests.
|
|
18
|
+
*
|
|
19
|
+
* See {@link https://github.com/homebridge/plugin-ui-utils plugin-ui-utils}.
|
|
20
|
+
*
|
|
21
|
+
* The Homebridge Plugin UI Server runs in a separate process, which is spawned
|
|
22
|
+
* by the Homebridge UI when the plugin _Settings_ are opened.
|
|
23
|
+
* It implements an {@link HttpClient} to connect to the HTTP server provided
|
|
24
|
+
* by {@link Platform} to change plugin settings dynamically.
|
|
25
|
+
*
|
|
26
|
+
* `UiServer` implemensts the following requests, which are documented as events:
|
|
27
|
+
* - {@link UiServer#event:get get} - Send a GET request to the plugin instance.
|
|
28
|
+
* - {@link UiServer#event:put put} - Send a put request to the plugin instance.
|
|
29
|
+
* - {@link UiServer#event:cachedAccessories cachedAccessories} - Get the
|
|
30
|
+
* cachedAccessories for a (child) bridge instance.
|
|
31
|
+
* @extends HomebridgePluginUiServer
|
|
32
|
+
*/
|
|
33
|
+
class UiServer extends HomebridgePluginUiServer {
|
|
34
|
+
constructor () {
|
|
35
|
+
super()
|
|
36
|
+
this.clients = {}
|
|
37
|
+
|
|
38
|
+
/** Do a GET request to the plugin instance.
|
|
39
|
+
* @event UiServer#get
|
|
40
|
+
* @type {object}
|
|
41
|
+
* @property {integer} uiPort - The port of the plugin instance UI server.
|
|
42
|
+
* @property {string} resource - The requested resource.
|
|
43
|
+
* @returns {*} - The response body.
|
|
44
|
+
*/
|
|
45
|
+
this.onRequest('get', async (params) => {
|
|
46
|
+
try {
|
|
47
|
+
const { uiPort, path } = params
|
|
48
|
+
const client = this._getClient(uiPort)
|
|
49
|
+
const { body } = await client.get(path)
|
|
50
|
+
return body
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (!(error instanceof HttpClient.HttpError)) {
|
|
53
|
+
this.error(error)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
/** Do a PUT request to the plugin instance.
|
|
59
|
+
* @event UiServer#put
|
|
60
|
+
* @param {object}
|
|
61
|
+
* @property {integer} uiPort - The port of the plugin instance UI server.
|
|
62
|
+
* @property {string} resource - The requested resource.
|
|
63
|
+
* @property {*} body - The body of the request.
|
|
64
|
+
* @returns {HttpResponse} - The response.
|
|
65
|
+
*/
|
|
66
|
+
this.onRequest('put', async (params) => {
|
|
67
|
+
try {
|
|
68
|
+
const { uiPort, path, body } = params
|
|
69
|
+
const client = this._getClient(uiPort)
|
|
70
|
+
const response = await client.put(path, JSON.stringify(body))
|
|
71
|
+
return response
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (!(error instanceof HttpClient.HttpError)) {
|
|
74
|
+
this.error(error)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
/** Get the cached accessories for a single (child) bridge instance.
|
|
80
|
+
*
|
|
81
|
+
* This endpoint is needed because `homebridge.getCachedAccessories()` from
|
|
82
|
+
* `plugin-ui-utils` doesn't indicate to which child bridge an accessory
|
|
83
|
+
* belongs.
|
|
84
|
+
* @event UiServer#cachedAccessories
|
|
85
|
+
* @type {object}
|
|
86
|
+
* @property {?string} username - The virtual MAC address of the child
|
|
87
|
+
* bridge. Use `null` for the main bridge.
|
|
88
|
+
* @returns {Object} cachedAccessories - The cached accessories.
|
|
89
|
+
*/
|
|
90
|
+
this.onRequest('cachedAccessories', async (params) => {
|
|
91
|
+
try {
|
|
92
|
+
const { username } = params
|
|
93
|
+
let fileName = 'cachedAccessories'
|
|
94
|
+
if (username != null) {
|
|
95
|
+
fileName += '.' + username.replace(/:/g, '').toUpperCase()
|
|
96
|
+
}
|
|
97
|
+
const fullFileName = path.join(
|
|
98
|
+
this.homebridgeStoragePath,
|
|
99
|
+
'accessories',
|
|
100
|
+
fileName
|
|
101
|
+
)
|
|
102
|
+
const json = await fs.readFile(fullFileName)
|
|
103
|
+
const cachedAccessories = JSON.parse(json)
|
|
104
|
+
return cachedAccessories
|
|
105
|
+
} catch (error) {
|
|
106
|
+
this.error(error)
|
|
107
|
+
}
|
|
108
|
+
return []
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_getClient (uiPort) {
|
|
113
|
+
if (this.clients[uiPort] == null) {
|
|
114
|
+
this.clients[uiPort] = new HttpClient({
|
|
115
|
+
host: 'localhost:' + uiPort,
|
|
116
|
+
json: true,
|
|
117
|
+
keepAlive: true
|
|
118
|
+
})
|
|
119
|
+
this.clients[uiPort]
|
|
120
|
+
.on('error', (error) => {
|
|
121
|
+
this.warn('request %d: %s', error.request.id, error)
|
|
122
|
+
})
|
|
123
|
+
.on('request', (request) => {
|
|
124
|
+
if (request.body == null) {
|
|
125
|
+
this.debug(
|
|
126
|
+
'request %d: %s %s', request.id, request.method, request.resource
|
|
127
|
+
)
|
|
128
|
+
} else {
|
|
129
|
+
this.debug(
|
|
130
|
+
'request %d: %s %s %j', request.id,
|
|
131
|
+
request.method, request.resource, request.body
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
.on('response', (response) => {
|
|
136
|
+
this.vdebug(
|
|
137
|
+
'request %d: response: %j', response.request.id, response.body
|
|
138
|
+
)
|
|
139
|
+
this.debug(
|
|
140
|
+
'request %d: %s %s', response.request.id,
|
|
141
|
+
response.statusCode, response.statusMessage
|
|
142
|
+
)
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
return this.clients[uiPort]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ===== Logging =============================================================
|
|
149
|
+
|
|
150
|
+
/** Print debug message to stdout.
|
|
151
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
152
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
153
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
154
|
+
*/
|
|
155
|
+
debug (format, ...args) {
|
|
156
|
+
this._log({ chalk: chalk.grey }, format, ...args)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Print error message to stdout.
|
|
160
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
161
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
162
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
163
|
+
*/
|
|
164
|
+
error (format, ...args) {
|
|
165
|
+
this._log({ label: 'error', chalk: chalk.bold.red }, format, ...args)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Print log message to stdout.
|
|
169
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
170
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
171
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
172
|
+
*/
|
|
173
|
+
log (format, ...args) {
|
|
174
|
+
this._log({}, format, ...args)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Print verbose debug message to stdout.
|
|
178
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
179
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
180
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
181
|
+
*/
|
|
182
|
+
vdebug (format, ...args) {
|
|
183
|
+
this._log({ chalk: chalk.grey }, format, ...args)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Print very verbose debug message to stdout.
|
|
187
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
188
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
189
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
190
|
+
*/
|
|
191
|
+
vvdebug (format, ...args) {
|
|
192
|
+
this._log({ chalk: chalk.grey }, format, ...args)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Print warning message to stdout.
|
|
196
|
+
* @param {string|Error} format - The printf-style message or an instance of
|
|
197
|
+
* [Error](https://nodejs.org/dist/latest-v14.x/docs/api/errors.html#errors_class_error).
|
|
198
|
+
* @param {...string} args - Arguments to the printf-style message.
|
|
199
|
+
*/
|
|
200
|
+
warn (format, ...args) {
|
|
201
|
+
this._log({ label: 'warning', chalk: chalk.yellow }, format, ...args)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Do the heavy lifting for debug(), error(), fatal(), log(), and warn(),
|
|
205
|
+
// taking into account the options, and errors vs exceptions.
|
|
206
|
+
_log (params = {}, ...args) {
|
|
207
|
+
const output = process.stdout
|
|
208
|
+
let message = ''
|
|
209
|
+
|
|
210
|
+
// If last argument is Error convert it to string.
|
|
211
|
+
if (args.length > 0) {
|
|
212
|
+
let lastArg = args.pop()
|
|
213
|
+
if (lastArg instanceof Error) {
|
|
214
|
+
lastArg = formatError(lastArg, true)
|
|
215
|
+
}
|
|
216
|
+
args.push(lastArg)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Format message.
|
|
220
|
+
if (args[0] == null) {
|
|
221
|
+
message = ''
|
|
222
|
+
} else if (typeof args[0] === 'string') {
|
|
223
|
+
message = util.format(...args)
|
|
224
|
+
} else {
|
|
225
|
+
message = util.format('%o', ...args)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Handle colours.
|
|
229
|
+
if (params.chalk != null) {
|
|
230
|
+
message = params.chalk(message)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
output.write(message)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
module.exports = UiServer
|
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.
|
|
6
|
+
"version": "5.3.1",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"homekit",
|
|
9
9
|
"homebridge"
|
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"homebridge": "^1.4.0",
|
|
25
|
-
"node": "^16.14.
|
|
25
|
+
"node": "^16.14.2"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@homebridge/plugin-ui-utils": "~0.0.19",
|
|
28
29
|
"bonjour-hap": "^3.6.3",
|
|
29
30
|
"chalk": "^4.1.2",
|
|
30
31
|
"semver": "^7.3.5"
|