homebridge-lib 6.3.7 → 6.3.8
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/README.md +1 -6
- package/cli/hap.js +2 -2
- package/cli/json.js +2 -2
- package/cli/sysinfo.js +2 -2
- package/cli/upnp.js +2 -2
- package/index.js +41 -105
- package/lib/AccessoryDelegate.js +1 -1
- package/lib/AdaptiveLighting.js +3 -3
- package/lib/Delegate.js +2 -1
- package/lib/EveHomeKitTypes.js +2 -2
- package/lib/MyHomeKitTypes.js +2 -2
- package/lib/Platform.js +7 -5
- package/lib/ServiceDelegate/AccessoryInformation.js +1 -3
- package/lib/ServiceDelegate/Battery.js +1 -3
- package/lib/ServiceDelegate/Dummy.js +1 -3
- package/lib/ServiceDelegate/History.js +6 -11
- package/lib/ServiceDelegate/ServiceLabel.js +1 -3
- package/lib/UiServer.js +1 -2
- package/package.json +4 -6
- package/lib/Colour.js +0 -323
- package/lib/CommandLineParser.js +0 -311
- package/lib/CommandLineTool.js +0 -328
- package/lib/HapTool.js +0 -92
- package/lib/HttpClient.js +0 -478
- package/lib/JsonFormatter.js +0 -200
- package/lib/JsonTool.js +0 -166
- package/lib/OptionParser.js +0 -886
- package/lib/SysinfoTool.js +0 -79
- package/lib/SystemInfo.js +0 -522
- package/lib/UpnpClient.js +0 -217
- package/lib/UpnpTool.js +0 -148
package/lib/Colour.js
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
// homebridge-lib/lib/Colour.js
|
|
2
|
-
//
|
|
3
|
-
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2016-2023 Erik Baauw. All rights reserved.
|
|
5
|
-
|
|
6
|
-
'use strict'
|
|
7
|
-
|
|
8
|
-
// Return point in color gamut closest to p.
|
|
9
|
-
function closestInGamut (p, gamut) {
|
|
10
|
-
// Return cross product of two points.
|
|
11
|
-
function crossProduct (p1, p2) {
|
|
12
|
-
return p1.x * p2.y - p1.y * p2.x
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Return distance between two points.
|
|
16
|
-
function distance (p1, p2) {
|
|
17
|
-
const dx = p1.x - p2.x
|
|
18
|
-
const dy = p1.y - p2.y
|
|
19
|
-
return Math.sqrt(dx * dx + dy * dy)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Return point on line a,b closest to p.
|
|
23
|
-
function closest (a, b, p) {
|
|
24
|
-
const ap = { x: p.x - a.x, y: p.y - a.y }
|
|
25
|
-
const ab = { x: b.x - a.x, y: b.y - a.y }
|
|
26
|
-
let t = (ap.x * ab.x + ap.y * ab.y) / (ab.x * ab.x + ab.y * ab.y)
|
|
27
|
-
t = t < 0.0 ? 0.0 : t > 1.0 ? 1.0 : t
|
|
28
|
-
return { x: a.x + t * ab.x, y: a.y + t * ab.y }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const r = { x: gamut.r[0], y: gamut.r[1] }
|
|
32
|
-
const g = { x: gamut.g[0], y: gamut.g[1] }
|
|
33
|
-
const b = { x: gamut.b[0], y: gamut.b[1] }
|
|
34
|
-
const v1 = { x: g.x - r.x, y: g.y - r.y }
|
|
35
|
-
const v2 = { x: b.x - r.x, y: b.y - r.y }
|
|
36
|
-
const v = crossProduct(v1, v2)
|
|
37
|
-
const q = { x: p.x - r.x, y: p.y - r.y }
|
|
38
|
-
const s = crossProduct(q, v2) / v
|
|
39
|
-
const t = crossProduct(v1, q) / v
|
|
40
|
-
if (s >= 0.0 && t >= 0.0 && s + t <= 1.0) {
|
|
41
|
-
return p
|
|
42
|
-
}
|
|
43
|
-
const pRG = closest(r, g, p)
|
|
44
|
-
const pGB = closest(g, b, p)
|
|
45
|
-
const pBR = closest(b, r, p)
|
|
46
|
-
const dRG = distance(p, pRG)
|
|
47
|
-
const dGB = distance(p, pGB)
|
|
48
|
-
const dBR = distance(p, pBR)
|
|
49
|
-
let min = dRG
|
|
50
|
-
p = pRG
|
|
51
|
-
if (dGB < min) {
|
|
52
|
-
min = dGB
|
|
53
|
-
p = pGB
|
|
54
|
-
}
|
|
55
|
-
if (dBR < min) {
|
|
56
|
-
p = pBR
|
|
57
|
-
}
|
|
58
|
-
return p
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Colour conversions.
|
|
62
|
-
* @class
|
|
63
|
-
* @hideconstructor
|
|
64
|
-
*/
|
|
65
|
-
class Colour {
|
|
66
|
-
/** [sRGB](https://en.wikipedia.org/wiki/SRGB) colour in
|
|
67
|
-
* [HSV](https://en.wikipedia.org/wiki/HSL_and_HSV).
|
|
68
|
-
* @typedef
|
|
69
|
-
* @property {integer} h - Hue, between 0˚ and 360˚.
|
|
70
|
-
* @property {integer} s - Saturation, between 0% and 100%.
|
|
71
|
-
* @property {integer} v - Value, between 0% and 100%.
|
|
72
|
-
*/
|
|
73
|
-
static get HSV () {}
|
|
74
|
-
|
|
75
|
-
/** [sRGB](https://en.wikipedia.org/wiki/SRGB) colour in
|
|
76
|
-
* [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model).
|
|
77
|
-
* @typedef
|
|
78
|
-
* @property {number} r - Red, between 0.0 and 1.0.
|
|
79
|
-
* @property {number} g - Green, between 0.0 and 1.0.
|
|
80
|
-
* @property {number} b - Blue, between 0.0 and 1.0.
|
|
81
|
-
*/
|
|
82
|
-
static get RGB () {}
|
|
83
|
-
|
|
84
|
-
/** Convert {@link Colour.HSV HSV} to {@link Colour.RGB RGB}.
|
|
85
|
-
*
|
|
86
|
-
* See [HSL and HSV](https://en.wikipedia.org/wiki/HSL_and_HSV).
|
|
87
|
-
* @param {integer} h - Hue, between 0˚ and 360˚.
|
|
88
|
-
* @param {integer} s - Saturation, between 0% and 100%.
|
|
89
|
-
* @param {integer} [v=100] - Value, between 0% and 100%.
|
|
90
|
-
* @return {RGB} rgb - The corresponding {@link Colour.RGB RGB} value.
|
|
91
|
-
*/
|
|
92
|
-
static hsvToRgb (h, s, v = 100) {
|
|
93
|
-
h /= 60.0
|
|
94
|
-
s /= 100.0
|
|
95
|
-
v /= 100.0
|
|
96
|
-
const C = v * s
|
|
97
|
-
const m = v - C
|
|
98
|
-
let x = (h % 2) - 1.0
|
|
99
|
-
if (x < 0) {
|
|
100
|
-
x = -x
|
|
101
|
-
}
|
|
102
|
-
x = C * (1.0 - x)
|
|
103
|
-
let r, g, b
|
|
104
|
-
switch (Math.floor(h) % 6) {
|
|
105
|
-
case 0: r = C + m; g = x + m; b = m; break
|
|
106
|
-
case 1: r = x + m; g = C + m; b = m; break
|
|
107
|
-
case 2: r = m; g = C + m; b = x + m; break
|
|
108
|
-
case 3: r = m; g = x + m; b = C + m; break
|
|
109
|
-
case 4: r = x + m; g = m; b = C + m; break
|
|
110
|
-
case 5: r = C + m; g = m; b = x + m; break
|
|
111
|
-
}
|
|
112
|
-
return { r, g, b }
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** Convert {@link Colour.RGB RGB} to {@link Colour.HSV HSV}.
|
|
116
|
-
*
|
|
117
|
-
* See [HSL and HSV](https://en.wikipedia.org/wiki/HSL_and_HSV).
|
|
118
|
-
* @param {number} r - Red, between 0.0 and 1.0.
|
|
119
|
-
* @param {number} g - Green, between 0.0 and 1.0.
|
|
120
|
-
* @param {number} b - Blue, between 0.0 and 1.0.
|
|
121
|
-
* @return {HSV} hsv - The corresponding {@link Colour.HSV HSV} value.
|
|
122
|
-
*/
|
|
123
|
-
static rgbToHsv (r, g, b) {
|
|
124
|
-
const M = Math.max(r, g, b)
|
|
125
|
-
const m = Math.min(r, g, b)
|
|
126
|
-
const C = M - m
|
|
127
|
-
const S = (M === 0.0) ? 0.0 : C / M
|
|
128
|
-
let H
|
|
129
|
-
switch (M) {
|
|
130
|
-
case m:
|
|
131
|
-
H = 0.0
|
|
132
|
-
break
|
|
133
|
-
case r:
|
|
134
|
-
H = (g - b) / C
|
|
135
|
-
if (H < 0) {
|
|
136
|
-
H += 6.0
|
|
137
|
-
}
|
|
138
|
-
break
|
|
139
|
-
case g:
|
|
140
|
-
H = (b - r) / C
|
|
141
|
-
H += 2.0
|
|
142
|
-
break
|
|
143
|
-
case b:
|
|
144
|
-
H = (r - g) / C
|
|
145
|
-
H += 4.0
|
|
146
|
-
break
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
h: Math.round(H * 60.0),
|
|
150
|
-
s: Math.round(S * 100.0),
|
|
151
|
-
v: Math.round(M * 100.0)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** Colour [gamut](https://en.wikipedia.org/wiki/Gamut).
|
|
156
|
-
* @typedef
|
|
157
|
-
* @property {number[]} r - `xy` coordinates for red,
|
|
158
|
-
* x, y between 0.0000 and 1.0000.
|
|
159
|
-
* @property {number[]} g - `xy` coordinates for green,
|
|
160
|
-
* x, y between 0.0000 and 1.0000..
|
|
161
|
-
* @property {number[]} b - `xy` coordinates for blue,
|
|
162
|
-
* x, y between 0.0000 and 1.0000.
|
|
163
|
-
*/
|
|
164
|
-
static get Gamut () {}
|
|
165
|
-
|
|
166
|
-
/** Default gamut.
|
|
167
|
-
* @type {Gamut}
|
|
168
|
-
* @readonly
|
|
169
|
-
*/
|
|
170
|
-
static get defaultGamut () {
|
|
171
|
-
// Safe default gamut taking into account:
|
|
172
|
-
// - The maximum value for CurrentX and CurrentY, 65279 (0xfeff),
|
|
173
|
-
// as defined by the ZCL spec;
|
|
174
|
-
// - A potential division by zero error for CurrentY, when translating the
|
|
175
|
-
// xy values back to hue/sat.
|
|
176
|
-
return {
|
|
177
|
-
r: [0.9961, 0.0001],
|
|
178
|
-
g: [0, 0.9961],
|
|
179
|
-
b: [0, 0.0001]
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** Transform [sRGB](https://en.wikipedia.org/wiki/SRGB)
|
|
184
|
-
* {@link Colour.HSV HSV} to
|
|
185
|
-
* [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space) `xy`.
|
|
186
|
-
*
|
|
187
|
-
* See [Hue developer portal](https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/).
|
|
188
|
-
* @param {integer} h - Hue, between 0˚ and 360˚.
|
|
189
|
-
* @param {integer} s - Saturation, between 0% and 100%.
|
|
190
|
-
* @param {Gamut} [gamut=defaultGamut] - The gamut supported by the light.
|
|
191
|
-
* @return {number[]} xy - The closest matching CIE 1931 colour,
|
|
192
|
-
* x, y between 0.0000 and 1.0000.
|
|
193
|
-
*/
|
|
194
|
-
static hsvToXy (h, s, gamut = Colour.defaultGamut) {
|
|
195
|
-
// Gamma correction (inverse sRGB Companding).
|
|
196
|
-
function invCompand (v) {
|
|
197
|
-
return v > 0.04045 ? Math.pow((v + 0.055) / (1.0 + 0.055), 2.4) : v / 12.92
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
let { r, g, b } = Colour.hsvToRgb(h, s)
|
|
201
|
-
|
|
202
|
-
// RGB to XYZ to xyY
|
|
203
|
-
r = invCompand(r)
|
|
204
|
-
g = invCompand(g)
|
|
205
|
-
b = invCompand(b)
|
|
206
|
-
const X = r * 0.664511 + g * 0.154324 + b * 0.162028
|
|
207
|
-
const Y = r * 0.283881 + g * 0.668433 + b * 0.047685
|
|
208
|
-
const Z = r * 0.000088 + g * 0.072310 + b * 0.986039
|
|
209
|
-
const sum = X + Y + Z
|
|
210
|
-
const p = sum === 0.0 ? { x: 0.0, y: 0.0 } : { x: X / sum, y: Y / sum }
|
|
211
|
-
const q = closestInGamut(p, gamut)
|
|
212
|
-
return [Math.round(q.x * 10000) / 10000, Math.round(q.y * 10000) / 10000]
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/** Transform [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space)
|
|
216
|
-
* `xy` to [sRGB](https://en.wikipedia.org/wiki/SRGB)
|
|
217
|
-
* {@link Colour.HSV HSV}.
|
|
218
|
-
*
|
|
219
|
-
* See [Hue developer portal](https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/).
|
|
220
|
-
* @param {number[]} xy - The CIE 1931 xy colour,
|
|
221
|
-
* x, y between 0.0000 and 1.0000.
|
|
222
|
-
* @param {Gamut} [gamut=defaultGamut] - The gamut supported by the light.
|
|
223
|
-
* @return {HSV} hsv - The closest matching sRGB colour.
|
|
224
|
-
*/
|
|
225
|
-
static xyToHsv (xy, gamut = Colour.defaultGamut) {
|
|
226
|
-
// Inverse Gamma correction (sRGB Companding).
|
|
227
|
-
function compand (v) {
|
|
228
|
-
return v <= 0.0031308
|
|
229
|
-
? 12.92 * v
|
|
230
|
-
: (1.0 + 0.055) * Math.pow(v, (1.0 / 2.4)) - 0.055
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Correction for negative values is missing from Philips' documentation.
|
|
234
|
-
function correctNegative () {
|
|
235
|
-
const m = Math.min(r, g, b)
|
|
236
|
-
if (m < 0.0) {
|
|
237
|
-
r -= m
|
|
238
|
-
g -= m
|
|
239
|
-
b -= m
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function rescale () {
|
|
244
|
-
const M = Math.max(r, g, b)
|
|
245
|
-
if (M > 1.0) {
|
|
246
|
-
r /= M
|
|
247
|
-
g /= M
|
|
248
|
-
b /= M
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// xyY to XYZ to RGB
|
|
253
|
-
const p = closestInGamut({ x: xy[0], y: xy[1] }, gamut)
|
|
254
|
-
const x = p.x
|
|
255
|
-
const y = p.y === 0.0 ? 0.000001 : p.y
|
|
256
|
-
const z = 1.0 - x - y
|
|
257
|
-
const Y = 1.0
|
|
258
|
-
const X = (Y / y) * x
|
|
259
|
-
const Z = (Y / y) * z
|
|
260
|
-
let r = X * 1.656492 + Y * -0.354851 + Z * -0.255038
|
|
261
|
-
let g = X * -0.707196 + Y * 1.655397 + Z * 0.036152
|
|
262
|
-
let b = X * 0.051713 + Y * -0.121364 + Z * 1.011530
|
|
263
|
-
correctNegative()
|
|
264
|
-
rescale()
|
|
265
|
-
r = compand(r)
|
|
266
|
-
g = compand(g)
|
|
267
|
-
b = compand(b)
|
|
268
|
-
rescale()
|
|
269
|
-
return Colour.rgbToHsv(r, g, b)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/** Transform
|
|
273
|
-
* [colour temperature](https://en.wikipedia.org/wiki/Color_temperature) to
|
|
274
|
-
* [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space) `xy`.
|
|
275
|
-
*
|
|
276
|
-
* Source: [deCONZ REST API plugin](https://github.com/dresden-elektronik/deconz-rest-plugin/blob/master/colorspace.cpp).
|
|
277
|
-
* The results don't match exactly the `xy` values as returned by a Hue
|
|
278
|
-
* LCT015 light, but seem to be close enough.
|
|
279
|
-
* @param {integer} ct - The colour temperature
|
|
280
|
-
* in [mired](https://en.wikipedia.org/wiki/Mired).
|
|
281
|
-
* @return {number[]} xy - The closest matching CIE 1931 colour,
|
|
282
|
-
* x, y between 0.0000 and 1.0000.
|
|
283
|
-
*/
|
|
284
|
-
static ctToXy (ct) {
|
|
285
|
-
const kelvin = 1000000 / ct
|
|
286
|
-
let x, y
|
|
287
|
-
|
|
288
|
-
if (kelvin < 4000) {
|
|
289
|
-
x = 11790 +
|
|
290
|
-
57520658 / kelvin +
|
|
291
|
-
-15358885888 / kelvin / kelvin +
|
|
292
|
-
-17440695910400 / kelvin / kelvin / kelvin
|
|
293
|
-
} else {
|
|
294
|
-
x = 15754 +
|
|
295
|
-
14590587 / kelvin +
|
|
296
|
-
138086835814 / kelvin / kelvin +
|
|
297
|
-
-198301902438400 / kelvin / kelvin / kelvin
|
|
298
|
-
}
|
|
299
|
-
if (kelvin < 2222) {
|
|
300
|
-
y = -3312 +
|
|
301
|
-
35808 * x / 0x10000 +
|
|
302
|
-
-22087 * x * x / 0x100000000 +
|
|
303
|
-
-18126 * x * x * x / 0x1000000000000
|
|
304
|
-
} else if (kelvin < 4000) {
|
|
305
|
-
y = -2744 +
|
|
306
|
-
34265 * x / 0x10000 +
|
|
307
|
-
-22514 * x * x / 0x100000000 +
|
|
308
|
-
-15645 * x * x * x / 0x1000000000000
|
|
309
|
-
} else {
|
|
310
|
-
y = -6062 +
|
|
311
|
-
61458 * x / 0x10000 +
|
|
312
|
-
-96229 * x * x / 0x100000000 +
|
|
313
|
-
50491 * x * x * x / 0x1000000000000
|
|
314
|
-
}
|
|
315
|
-
y *= 4
|
|
316
|
-
x /= 0xFFFF
|
|
317
|
-
y /= 0xFFFF
|
|
318
|
-
|
|
319
|
-
return [Math.round(x * 10000) / 10000, Math.round(y * 10000) / 10000]
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
module.exports = Colour
|
package/lib/CommandLineParser.js
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
// homebridge-lib/lib/CommandLineParser.js
|
|
2
|
-
//
|
|
3
|
-
// Library for Homebridge plugins.
|
|
4
|
-
// Copyright © 2017-2023 Erik Baauw. All rights reserved.
|
|
5
|
-
|
|
6
|
-
// TODO:
|
|
7
|
-
// - Change parameters to (params, callback) with:
|
|
8
|
-
// - params.shortKey
|
|
9
|
-
// - params.longKey
|
|
10
|
-
// - params.key
|
|
11
|
-
// - params.optional
|
|
12
|
-
// - params.minumum
|
|
13
|
-
// - params.helpText
|
|
14
|
-
|
|
15
|
-
'use strict'
|
|
16
|
-
|
|
17
|
-
const homebridgeLib = require('../index')
|
|
18
|
-
|
|
19
|
-
const chalk = require('chalk')
|
|
20
|
-
|
|
21
|
-
const packageJson = require('../package.json')
|
|
22
|
-
|
|
23
|
-
// Force colors when output is re-directed.
|
|
24
|
-
chalk.enabled = true
|
|
25
|
-
chalk.level = 1
|
|
26
|
-
|
|
27
|
-
/** Usage error.
|
|
28
|
-
* @hideconstructor
|
|
29
|
-
* @extends Error
|
|
30
|
-
* @memberof CommandLineParser
|
|
31
|
-
*/
|
|
32
|
-
class UsageError extends Error {}
|
|
33
|
-
|
|
34
|
-
/** Parser and validator for command-line arguments.
|
|
35
|
-
*/
|
|
36
|
-
class CommandLineParser {
|
|
37
|
-
static get UsageError () { return UsageError }
|
|
38
|
-
|
|
39
|
-
/** Create a new parser instance.
|
|
40
|
-
* @params {string} pkgJson - The contents of `package.json` to retrieve
|
|
41
|
-
* the version and homepage for the command-line tool.
|
|
42
|
-
*/
|
|
43
|
-
constructor (pkgJson = packageJson) {
|
|
44
|
-
this._callbacks = {
|
|
45
|
-
flags: {},
|
|
46
|
-
options: {},
|
|
47
|
-
parameters: [],
|
|
48
|
-
remaining: null
|
|
49
|
-
}
|
|
50
|
-
this._packageJson = pkgJson
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
_toShort (value) {
|
|
54
|
-
if (value == null) {
|
|
55
|
-
return null
|
|
56
|
-
}
|
|
57
|
-
if (typeof value !== 'string' || value.length !== 1) {
|
|
58
|
-
throw new TypeError(`${value}: invalid short key`)
|
|
59
|
-
}
|
|
60
|
-
if (this._callbacks.flags[value] != null) {
|
|
61
|
-
throw new SyntaxError(`${value}: duplicate short key`)
|
|
62
|
-
}
|
|
63
|
-
return value
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
_toLong (value) {
|
|
67
|
-
if (value == null) {
|
|
68
|
-
return null
|
|
69
|
-
}
|
|
70
|
-
if (typeof value !== 'string' || value.length === 1) {
|
|
71
|
-
throw new TypeError(`${value}: invalid long key`)
|
|
72
|
-
}
|
|
73
|
-
if (this._callbacks.options[value] != null) {
|
|
74
|
-
throw new SyntaxError(`${value}: duplicate long key`)
|
|
75
|
-
}
|
|
76
|
-
return value
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** Add a flag to print help text and exit.
|
|
80
|
-
*
|
|
81
|
-
* See {@link CommandLineParser#flag flag()}.
|
|
82
|
-
*
|
|
83
|
-
* For now, the help text needs to be specified explicitly.
|
|
84
|
-
* <br>TODO: Generate helpText automatically from
|
|
85
|
-
* {@link CommandLineParser#flag flag()},
|
|
86
|
-
* {@link CommandLineParser#option option()},
|
|
87
|
-
* {@link CommandLineParser#parameter parameter()}, and
|
|
88
|
-
* {@link CommandLineParser#remaining remaining()}
|
|
89
|
-
* @param {string} shortKey - The short key (e.g. `h` for `-h`).
|
|
90
|
-
* @param {string} longKey - The long key (e.g. `help` for `--help`).
|
|
91
|
-
* @param {string} helpText - The help text.
|
|
92
|
-
* @return {CommandLineParser} this - For chaining.
|
|
93
|
-
*/
|
|
94
|
-
help (shortKey, longKey, helpText) {
|
|
95
|
-
helpText = homebridgeLib.OptionParser.toString('helpText', helpText, true)
|
|
96
|
-
this.flag(shortKey, longKey, () => {
|
|
97
|
-
console.log(helpText)
|
|
98
|
-
console.log(`
|
|
99
|
-
See ${this._packageJson.homepage.split('#')[0]} for more info.
|
|
100
|
-
(${this._packageJson.name} v${this._packageJson.version}, node ${process.version})`
|
|
101
|
-
)
|
|
102
|
-
process.exit(0)
|
|
103
|
-
})
|
|
104
|
-
return this
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Add a flag to print the version and exit.
|
|
108
|
-
*
|
|
109
|
-
* See {@link CommandLineParser#flag flag()}.
|
|
110
|
-
*
|
|
111
|
-
* @param {string} shortKey - The short key (e.g. `V` for `-V`).
|
|
112
|
-
* @param {string} longKey - The long key (e.g. `version` for `--version`).
|
|
113
|
-
* @return {CommandLineParser} this - For chaining.
|
|
114
|
-
*/
|
|
115
|
-
version (shortKey, longKey) {
|
|
116
|
-
this.flag(shortKey, longKey, () => {
|
|
117
|
-
console.log(this._packageJson.version)
|
|
118
|
-
process.exit(0)
|
|
119
|
-
})
|
|
120
|
-
return this
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Add a callback for a flag.
|
|
124
|
-
*
|
|
125
|
-
* A flag is an optional command-line parameter, identified by a short key
|
|
126
|
-
* (a single character, like `-v`), or by a long key (a word, like
|
|
127
|
-
* `--verbose`).
|
|
128
|
-
*
|
|
129
|
-
* @param {string} shortKey - The short key (e.g. `v` for `-v`).
|
|
130
|
-
* @param {string} longKey - The long key (e.g. `verbose` for `--verbose`).
|
|
131
|
-
* @param {function} callback - The callback function.<br>
|
|
132
|
-
* The function will be called when the flag is present, with the
|
|
133
|
-
* following parameters:
|
|
134
|
-
*
|
|
135
|
-
* Name | Type | Attributes | Description
|
|
136
|
-
* ---- | ---- | ---------- | -----------
|
|
137
|
-
* `key` | string | | The key.
|
|
138
|
-
* @return {CommandLineParser} this - For chaining.
|
|
139
|
-
*/
|
|
140
|
-
flag (shortKey, longKey, callback) {
|
|
141
|
-
shortKey = this._toShort(shortKey)
|
|
142
|
-
longKey = this._toLong(longKey)
|
|
143
|
-
callback = homebridgeLib.OptionParser.toFunction('callback', callback)
|
|
144
|
-
if (shortKey != null) {
|
|
145
|
-
this._callbacks.flags[shortKey] = callback
|
|
146
|
-
}
|
|
147
|
-
if (longKey != null) {
|
|
148
|
-
this._callbacks.flags[longKey] = callback
|
|
149
|
-
}
|
|
150
|
-
return this
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/** Add a callback for an option.
|
|
154
|
-
*
|
|
155
|
-
* An option is an optional command-line paramater that takes a value.
|
|
156
|
-
* The option is identified by a short key (a single character, like `-t`),
|
|
157
|
-
* or by a long key (a word, like `--timeout`).
|
|
158
|
-
* The value can specified in the next or in the same command-line parameter:
|
|
159
|
-
* `-t5` `--timeout=5`, `-t 5`, or `--timeout 5`
|
|
160
|
-
*
|
|
161
|
-
* @param {string} shortKey - The short key (e.g. `t` for `-t`).
|
|
162
|
-
* @param {string} longKey - The long key (e.g. `timeout` for `--timeout`).
|
|
163
|
-
* @param {function} callback - The callback function.<br>
|
|
164
|
-
* The function will be called when the option is present, with the
|
|
165
|
-
* following parameters:
|
|
166
|
-
*
|
|
167
|
-
* Name | Type | Attributes | Description
|
|
168
|
-
* ---- | ---- | ---------- | -----------
|
|
169
|
-
* `value` | string | | The value.
|
|
170
|
-
* `key` | string | | The (short or long) key.
|
|
171
|
-
* @return {CommandLineParser} this - For chaining.
|
|
172
|
-
*/
|
|
173
|
-
option (shortKey, longKey, callback) {
|
|
174
|
-
shortKey = this._toShort(shortKey)
|
|
175
|
-
longKey = this._toLong(longKey)
|
|
176
|
-
callback = homebridgeLib.OptionParser.toFunction('callback', callback)
|
|
177
|
-
if (shortKey != null) {
|
|
178
|
-
this._callbacks.options[shortKey] = callback
|
|
179
|
-
}
|
|
180
|
-
if (longKey != null) {
|
|
181
|
-
this._callbacks.options[longKey] = callback
|
|
182
|
-
}
|
|
183
|
-
return this
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/** Add a callback for a positional parameter.
|
|
187
|
-
*
|
|
188
|
-
* A positional paramater is a mandatory command-line parameter.
|
|
189
|
-
* It is specified as a single value, e.g. `get`
|
|
190
|
-
*
|
|
191
|
-
* @param {string} key - The parameter key (e.g. `command`).
|
|
192
|
-
* @param {function} callback - The callback function.<br>
|
|
193
|
-
* The function will be called with the following parameters:
|
|
194
|
-
*
|
|
195
|
-
* Name | Type | Attributes | Description
|
|
196
|
-
* ---- | ---- | ---------- | -----------
|
|
197
|
-
* `value` | string | | The parameter value.
|
|
198
|
-
* `key` | string | | The parameter key.
|
|
199
|
-
* @return {CommandLineParser} this - For chaining.
|
|
200
|
-
*/
|
|
201
|
-
parameter (key, callback, optional = false) {
|
|
202
|
-
key = homebridgeLib.OptionParser.toString('key', key, true)
|
|
203
|
-
callback = homebridgeLib.OptionParser.toFunction('callback', callback)
|
|
204
|
-
this._callbacks.parameters.push({ key, callback, optional })
|
|
205
|
-
return this
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// * @param {string} key - The name of the remaining parameters (e.g.
|
|
209
|
-
// * `file` for `[`_file_` ...]`).
|
|
210
|
-
/** Add a callback for the remaining parameters.
|
|
211
|
-
*
|
|
212
|
-
* The remaining parameters are any additional commmand-line parameters,
|
|
213
|
-
* after the positional paramers, typically indicated as `[file ...]`.
|
|
214
|
-
* @param {function} callback - The callback function.<br>
|
|
215
|
-
* This function will be called with the following paramters:
|
|
216
|
-
*
|
|
217
|
-
* Name | Type | Attributes | Description
|
|
218
|
-
* ---- | ---- | ---------- | -----------
|
|
219
|
-
* `values` | string[] | | A list of values of the remaining parameters.
|
|
220
|
-
* @return {CommandLineParser} this - For chaining.
|
|
221
|
-
*/
|
|
222
|
-
remaining (/* key, */ callback) {
|
|
223
|
-
callback = homebridgeLib.OptionParser.toFunction('callback', callback)
|
|
224
|
-
this._callbacks.remaining = callback
|
|
225
|
-
return this
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** Parse the command-line parameters.
|
|
229
|
-
*
|
|
230
|
-
* @throws {UsageError} In case of invalid command-line paramters.
|
|
231
|
-
*/
|
|
232
|
-
parse (wordList = process.argv.slice(2)) {
|
|
233
|
-
// process.argv[0]: node executable, process.argv[1]: javascript file
|
|
234
|
-
wordList = homebridgeLib.OptionParser.toArray('wordList', wordList)
|
|
235
|
-
let wordIndex = 0
|
|
236
|
-
let charIndex
|
|
237
|
-
|
|
238
|
-
function handleWord (word, long) {
|
|
239
|
-
const key = long ? word.split('=')[0] : word[0]
|
|
240
|
-
const option = (long ? '--' : '-') + key
|
|
241
|
-
let value = long ? word.split('=')[1] : null
|
|
242
|
-
let callback = this._callbacks.flags[key]
|
|
243
|
-
if (callback) {
|
|
244
|
-
if (value != null) {
|
|
245
|
-
throw new UsageError(`${option}: option doesn't allow an argument`)
|
|
246
|
-
}
|
|
247
|
-
callback(option)
|
|
248
|
-
return long
|
|
249
|
-
}
|
|
250
|
-
callback = this._callbacks.options[key]
|
|
251
|
-
if (callback) {
|
|
252
|
-
value = long ? word.split('=')[1] : word.substring(1)
|
|
253
|
-
if (value) {
|
|
254
|
-
charIndex = word.length
|
|
255
|
-
} else {
|
|
256
|
-
if (wordIndex >= wordList.length) {
|
|
257
|
-
throw new UsageError(`${option}: option requires an argument`)
|
|
258
|
-
}
|
|
259
|
-
value = wordList[wordIndex++]
|
|
260
|
-
}
|
|
261
|
-
callback(value, option)
|
|
262
|
-
return long
|
|
263
|
-
}
|
|
264
|
-
throw new UsageError(`${option}: unknown option`)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Parse flags and options.
|
|
268
|
-
while (wordIndex < wordList.length) {
|
|
269
|
-
const word = wordList[wordIndex++]
|
|
270
|
-
if (word[0] !== '-' || word === '-') {
|
|
271
|
-
wordIndex -= 1
|
|
272
|
-
break
|
|
273
|
-
}
|
|
274
|
-
if (word === '--') {
|
|
275
|
-
break
|
|
276
|
-
}
|
|
277
|
-
if (word[1] === '-') {
|
|
278
|
-
handleWord.call(this, word.substring(2), true)
|
|
279
|
-
continue
|
|
280
|
-
}
|
|
281
|
-
charIndex = 1
|
|
282
|
-
while (charIndex < word.length) {
|
|
283
|
-
if (handleWord.call(this, word.substring(charIndex++), false)) {
|
|
284
|
-
break
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
// Parse parameters.
|
|
289
|
-
for (const p of this._callbacks.parameters) {
|
|
290
|
-
if (wordIndex >= wordList.length) {
|
|
291
|
-
if (!p.optional) {
|
|
292
|
-
throw new UsageError(`parameter ${p.key} missing`)
|
|
293
|
-
}
|
|
294
|
-
break
|
|
295
|
-
}
|
|
296
|
-
const parameter = wordList[wordIndex++]
|
|
297
|
-
p.callback(parameter)
|
|
298
|
-
}
|
|
299
|
-
const remaining = wordList.slice(wordIndex, wordList.length)
|
|
300
|
-
const callback = this._callbacks.remaining
|
|
301
|
-
if (callback) {
|
|
302
|
-
callback(remaining)
|
|
303
|
-
return
|
|
304
|
-
}
|
|
305
|
-
if (remaining.length > 0) {
|
|
306
|
-
throw new UsageError('too many parameters')
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
module.exports = CommandLineParser
|