homebridge-lib 6.3.6 → 6.3.7
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/hap.js +2 -80
- package/cli/json.js +2 -154
- package/cli/sysinfo.js +2 -69
- package/cli/upnp.js +2 -138
- package/index.js +6 -0
- package/lib/HapTool.js +92 -0
- package/lib/JsonTool.js +166 -0
- package/lib/SysinfoTool.js +79 -0
- package/lib/UpnpTool.js +148 -0
- package/package.json +1 -1
package/cli/hap.js
CHANGED
|
@@ -9,84 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict'
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const { HapTool } = require('../index')
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const { b, u } = homebridgeLib.CommandLineTool
|
|
17
|
-
|
|
18
|
-
const usage = `${b('hap')} [${b('-hVlrs')}] [${b('-t')} ${u('timeout')}]`
|
|
19
|
-
const help = `Logger for HomeKit accessory announcements.
|
|
20
|
-
|
|
21
|
-
Usage: ${usage}
|
|
22
|
-
|
|
23
|
-
Search for HomeKit accessory announcements
|
|
24
|
-
Parameters:
|
|
25
|
-
${b('-h')} Print this help and exit.
|
|
26
|
-
${b('-V')} Print version and exit.
|
|
27
|
-
${b('-d')} Listen for Bonjour alive broadcasts instead of searching.
|
|
28
|
-
${b('-s')} Do not output timestamps (useful when running as service).
|
|
29
|
-
${b('-t')} ${u('timeout')} Search for ${u('timeout')} seconds instead of default ${b('5')}.`
|
|
30
|
-
|
|
31
|
-
class Main extends homebridgeLib.CommandLineTool {
|
|
32
|
-
constructor () {
|
|
33
|
-
super()
|
|
34
|
-
this.usage = usage
|
|
35
|
-
this.options = { timeout: 15 }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
parseArguments () {
|
|
39
|
-
const parser = new homebridgeLib.CommandLineParser()
|
|
40
|
-
parser
|
|
41
|
-
.help('h', 'help', help)
|
|
42
|
-
.version('V', 'version')
|
|
43
|
-
.flag('l', 'listen', (key) => { this.options.mode = 'daemon' })
|
|
44
|
-
.flag('s', 'service', (key) => { this.options.mode = 'service' })
|
|
45
|
-
.option('t', 'timeout', (value, key) => {
|
|
46
|
-
this.options.timeout = homebridgeLib.OptionParser.toInt(
|
|
47
|
-
'timeout', value, 1, 60, true
|
|
48
|
-
)
|
|
49
|
-
})
|
|
50
|
-
.parse()
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
onUp (obj) {
|
|
54
|
-
delete obj.rawTxt
|
|
55
|
-
this.log('found accessory: %s', obj.name, this.jsonFormatter.stringify(obj))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async main () {
|
|
59
|
-
try {
|
|
60
|
-
this.parseArguments()
|
|
61
|
-
this.jsonFormatter = new homebridgeLib.JsonFormatter(
|
|
62
|
-
this.options.mode === 'service'
|
|
63
|
-
? { noWhiteSpace: true, sortKeys: true }
|
|
64
|
-
: { sortKeys: true }
|
|
65
|
-
)
|
|
66
|
-
if (this.options.mode) {
|
|
67
|
-
this.setOptions({ mode: this.options.mode })
|
|
68
|
-
} else {
|
|
69
|
-
setTimeout(() => {
|
|
70
|
-
this.log('search done')
|
|
71
|
-
bonjour4.destroy()
|
|
72
|
-
// bonjour6.destroy()
|
|
73
|
-
}, this.options.timeout * 1000)
|
|
74
|
-
}
|
|
75
|
-
this.log('searching for HomeKit accessories')
|
|
76
|
-
const bonjour4 = new Bonjour()
|
|
77
|
-
const browser4 = bonjour4.find({ type: 'hap' })
|
|
78
|
-
browser4.on('up', this.onUp.bind(this))
|
|
79
|
-
// const bonjour6 = new Bonjour({
|
|
80
|
-
// type: 'udp6',
|
|
81
|
-
// interface: '::%en0', // TODO: how to determine the interface?!
|
|
82
|
-
// ip: 'ff02::fb'
|
|
83
|
-
// })
|
|
84
|
-
// const browser6 = bonjour6.find({ type: 'hap' })
|
|
85
|
-
// browser6.on('up', this.onUp.bind(this))
|
|
86
|
-
} catch (error) {
|
|
87
|
-
await this.fatal(error)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
new Main().main()
|
|
14
|
+
new HapTool().main()
|
package/cli/json.js
CHANGED
|
@@ -9,158 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict'
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const { JsonTool } = require('../index')
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
const util = require('util')
|
|
16
|
-
const zlib = require('zlib')
|
|
17
|
-
|
|
18
|
-
const gunzip = util.promisify(zlib.unzip)
|
|
19
|
-
|
|
20
|
-
const { b, u } = homebridgeLib.CommandLineTool
|
|
21
|
-
|
|
22
|
-
const usage = `${b('json')} [${b('-hVsnjuatlkv')}] [${b('-p')} path] [${b('-d')} depth] [${b('-c')} ${u('string')}]... [${u('file')}]...`
|
|
23
|
-
const help = `JSON formatter.
|
|
24
|
-
|
|
25
|
-
Usage: ${usage}
|
|
26
|
-
|
|
27
|
-
By default, ${b('json')} reads JSON from stdin, formats it, and prints it to stdout.
|
|
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.`
|
|
81
|
-
|
|
82
|
-
class Main extends homebridgeLib.CommandLineTool {
|
|
83
|
-
constructor () {
|
|
84
|
-
super()
|
|
85
|
-
this.usage = usage
|
|
86
|
-
this.options = {}
|
|
87
|
-
this.stringList = []
|
|
88
|
-
this.fileList = []
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
parseArguments () {
|
|
92
|
-
const parser = new homebridgeLib.CommandLineParser()
|
|
93
|
-
parser
|
|
94
|
-
.help('h', 'help', help)
|
|
95
|
-
.version('V', 'version')
|
|
96
|
-
.flag('s', 'sortKeys', () => { this.options.sortKeys = true })
|
|
97
|
-
.flag('n', 'noWhiteSpace', () => { this.options.noWhiteSpace = true })
|
|
98
|
-
.flag('j', 'jsonArray', () => { this.options.jsonArray = true })
|
|
99
|
-
.flag('u', 'joinKeys', () => { this.options.joinKeys = true })
|
|
100
|
-
.flag('a', 'ascii', () => { this.options.ascii = true })
|
|
101
|
-
.flag('t', 'topOnly', () => { this.options.topOnly = true })
|
|
102
|
-
.option('d', 'maxDepth', (value, option) => {
|
|
103
|
-
this.options.maxDepth = homebridgeLib.OptionParser.toInt(
|
|
104
|
-
'maxDepth', value, 0, undefined, true)
|
|
105
|
-
})
|
|
106
|
-
.option('p', 'fromPath', (value, option) => {
|
|
107
|
-
this.options.fromPath = homebridgeLib.OptionParser.toPath(
|
|
108
|
-
'fromPath', value, true
|
|
109
|
-
)
|
|
110
|
-
})
|
|
111
|
-
.flag('l', 'leavesOnly', () => { this.options.leavesOnly = true })
|
|
112
|
-
.flag('k', 'keysOnly', () => { this.options.keysOnly = true })
|
|
113
|
-
.flag('v', 'valuesOnly', () => { this.options.valuesOnly = true })
|
|
114
|
-
.option('c', 'string', (value) => { this.stringList.push(value) })
|
|
115
|
-
.remaining((list) => { this.fileList = list })
|
|
116
|
-
.parse()
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
processString (s) {
|
|
120
|
-
let value
|
|
121
|
-
try {
|
|
122
|
-
value = JSON.parse(s)
|
|
123
|
-
} catch (error) {
|
|
124
|
-
throw new Error(error.message) // Convert SyntaxError to Error.
|
|
125
|
-
}
|
|
126
|
-
const output = this.jsonFormatter.stringify(value)
|
|
127
|
-
if (this.n++ > 0) {
|
|
128
|
-
this.print('------')
|
|
129
|
-
}
|
|
130
|
-
if (output !== '') {
|
|
131
|
-
this.print(output)
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
async main () {
|
|
136
|
-
try {
|
|
137
|
-
this.parseArguments()
|
|
138
|
-
this.jsonFormatter = new homebridgeLib.JsonFormatter(this.options)
|
|
139
|
-
if (this.fileList.length === 0 && this.stringList.length === 0) {
|
|
140
|
-
this.fileList = ['-']
|
|
141
|
-
}
|
|
142
|
-
this.n = 0
|
|
143
|
-
this.stringList.forEach((s) => {
|
|
144
|
-
try {
|
|
145
|
-
this.processString(s)
|
|
146
|
-
} catch (error) {
|
|
147
|
-
this.error(error)
|
|
148
|
-
}
|
|
149
|
-
})
|
|
150
|
-
this.fileList.forEach(async (file) => {
|
|
151
|
-
try {
|
|
152
|
-
const s = file.endsWith('.gz')
|
|
153
|
-
? await gunzip(fs.readFileSync(file))
|
|
154
|
-
: fs.readFileSync(file === '-' ? 0 : file, 'utf8')
|
|
155
|
-
this.processString(s)
|
|
156
|
-
} catch (error) {
|
|
157
|
-
this.error(error)
|
|
158
|
-
}
|
|
159
|
-
})
|
|
160
|
-
} catch (error) {
|
|
161
|
-
await this.fatal(error)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
new Main().main()
|
|
14
|
+
new JsonTool().main()
|
package/cli/sysinfo.js
CHANGED
|
@@ -9,73 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict'
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const { SysinfoTool } = require('../index')
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const usage = `${b('sysinfo')} [${b('-hVDj')}]`
|
|
17
|
-
const help = `System information tool.
|
|
18
|
-
|
|
19
|
-
Print Hardware and Operating System information.
|
|
20
|
-
|
|
21
|
-
Usage: ${usage}
|
|
22
|
-
|
|
23
|
-
Parameters:
|
|
24
|
-
${b('-h')}, ${b('--help')}
|
|
25
|
-
Print this help and exit.
|
|
26
|
-
|
|
27
|
-
${b('-V')}, ${b('--version')}
|
|
28
|
-
Print version and exit.
|
|
29
|
-
|
|
30
|
-
${b('-D')}, ${b('--debug')}
|
|
31
|
-
Print debug messages.
|
|
32
|
-
|
|
33
|
-
${b('-j')}, ${b('--json')}
|
|
34
|
-
Print full info in json.`
|
|
35
|
-
|
|
36
|
-
class Main extends homebridgeLib.CommandLineTool {
|
|
37
|
-
constructor () {
|
|
38
|
-
super()
|
|
39
|
-
this.usage = usage
|
|
40
|
-
this.options = {
|
|
41
|
-
noWhiteSpace: false
|
|
42
|
-
}
|
|
43
|
-
this.upnp = {}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
parseArguments () {
|
|
47
|
-
const parser = new homebridgeLib.CommandLineParser()
|
|
48
|
-
parser
|
|
49
|
-
.help('h', 'help', help)
|
|
50
|
-
.version('V', 'version')
|
|
51
|
-
.flag('D', 'debug', () => { this.setOptions({ debug: true }) })
|
|
52
|
-
.flag('j', 'json', () => { this.json = true })
|
|
53
|
-
.parse()
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async main () {
|
|
57
|
-
try {
|
|
58
|
-
this.parseArguments()
|
|
59
|
-
this.systemInfo = new homebridgeLib.SystemInfo()
|
|
60
|
-
this.systemInfo
|
|
61
|
-
.on('error', (error) => { this.error(error) })
|
|
62
|
-
.on('exec', (command) => { this.debug('exec: %s', command) })
|
|
63
|
-
.on('readFile', (fileName) => { this.debug('read file: %s', fileName) })
|
|
64
|
-
await this.systemInfo.init()
|
|
65
|
-
if (this.json) {
|
|
66
|
-
const jsonFormatter = new homebridgeLib.JsonFormatter(this.options)
|
|
67
|
-
this.print(jsonFormatter.stringify({
|
|
68
|
-
hardware: this.systemInfo.hwInfo,
|
|
69
|
-
os: this.systemInfo.osInfo
|
|
70
|
-
}))
|
|
71
|
-
} else {
|
|
72
|
-
this.print(this.systemInfo.hwInfo.prettyName)
|
|
73
|
-
this.print(this.systemInfo.osInfo.prettyName)
|
|
74
|
-
}
|
|
75
|
-
} catch (error) {
|
|
76
|
-
await this.fatal(error)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
new Main().main()
|
|
14
|
+
new SysinfoTool().main()
|
package/cli/upnp.js
CHANGED
|
@@ -9,142 +9,6 @@
|
|
|
9
9
|
|
|
10
10
|
'use strict'
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const { UpnpTool } = require('../index')
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const usage = `${b('upnp')} [${b('-hVDadnprsz')}] [${b('-c')} ${u('class')}] [${b('-t')} ${u('timeout')}]`
|
|
17
|
-
const help = `UPnP tool.
|
|
18
|
-
|
|
19
|
-
Search for UPnP devices and print found devices as JSON.
|
|
20
|
-
When running as daemon or service, log UPnP alive broadcasts as JSON.
|
|
21
|
-
|
|
22
|
-
Usage: ${usage}
|
|
23
|
-
|
|
24
|
-
Parameters:
|
|
25
|
-
${b('-h')}, ${b('--help')}
|
|
26
|
-
Print this help and exit.
|
|
27
|
-
|
|
28
|
-
${b('-V')}, ${b('--version')}
|
|
29
|
-
Print version and exit.
|
|
30
|
-
|
|
31
|
-
${b('-D')}, ${b('--debug')}
|
|
32
|
-
Print debug messages.
|
|
33
|
-
|
|
34
|
-
${b('-a')}, ${b('--all')}
|
|
35
|
-
Short for ${b('-c ssdp:all')}.
|
|
36
|
-
|
|
37
|
-
${b('-c')} ${u('class')}, ${b('--class=')}${u('class')}
|
|
38
|
-
Search for ${u('class')} instead of default ${b('ssdp:rootdevice')}.
|
|
39
|
-
|
|
40
|
-
${b('-d')}, ${b('--daemon')}
|
|
41
|
-
Run as daemon. Listen for UPnP alive broadcasts instead of searching.
|
|
42
|
-
|
|
43
|
-
${b('-n')}, ${b('--noWhiteSpace')}
|
|
44
|
-
Do not include spaces nor newlines in JSON output.
|
|
45
|
-
|
|
46
|
-
${b('-p')}, ${b('--hue')}
|
|
47
|
-
Search for Philips Hue bridges and/or deCONZ gateways.
|
|
48
|
-
|
|
49
|
-
${b('-r')}, ${b('--raw')}
|
|
50
|
-
Do not parse messages, output raw message data instead of JSON.
|
|
51
|
-
|
|
52
|
-
${b('-s')}, ${b('--service')}
|
|
53
|
-
Run as daemon. Listen for UPnP alive broadcasts instead of searching.
|
|
54
|
-
|
|
55
|
-
${b('-t')} ${u('timeout')}, ${b('--timeout=')}${u('timeout')}
|
|
56
|
-
Search for ${u('timeout')} seconds instead of default ${b('5')}.
|
|
57
|
-
|
|
58
|
-
${b('-z')}, ${b('--sonos')}
|
|
59
|
-
Search for Sonos Zone Players.`
|
|
60
|
-
|
|
61
|
-
class Main extends homebridgeLib.CommandLineTool {
|
|
62
|
-
constructor () {
|
|
63
|
-
super()
|
|
64
|
-
this.usage = usage
|
|
65
|
-
this.options = {
|
|
66
|
-
noWhiteSpace: false
|
|
67
|
-
}
|
|
68
|
-
this.upnp = {}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
parseArguments () {
|
|
72
|
-
const parser = new homebridgeLib.CommandLineParser()
|
|
73
|
-
parser
|
|
74
|
-
.help('h', 'help', help)
|
|
75
|
-
.version('V', 'version')
|
|
76
|
-
.flag('D', 'debug', () => { this.setOptions({ debug: true }) })
|
|
77
|
-
.flag('a', 'all', (key) => { this.upnp.class = 'ssdp:all' })
|
|
78
|
-
.option('c', 'class', (value, key) => { this.upnp.class = value })
|
|
79
|
-
.flag('d', 'daemon', (key) => { this.options.mode = 'daemon' })
|
|
80
|
-
.flag('n', 'noWhiteSpace', () => { this.options.noWhiteSpace = true })
|
|
81
|
-
.flag('r', 'raw', (key) => { this.options.raw = true })
|
|
82
|
-
.flag('s', 'service', (key) => { this.options.mode = 'service' })
|
|
83
|
-
.option('t', 'timeout', (value, key) => {
|
|
84
|
-
this.upnp.timeout = homebridgeLib.OptionParser.toInt(
|
|
85
|
-
'timeout', value, 1, 60, true
|
|
86
|
-
)
|
|
87
|
-
})
|
|
88
|
-
.flag('p', 'hue', (key) => {
|
|
89
|
-
this.upnp.filter = (message) => {
|
|
90
|
-
return /^[0-9A-F]{16}$/.test(message['hue-bridgeid'])
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
.flag('z', 'sonos', (key) => {
|
|
94
|
-
this.upnp.class = 'urn:schemas-upnp-org:device:ZonePlayer:1'
|
|
95
|
-
})
|
|
96
|
-
.parse()
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async destroy () {
|
|
100
|
-
if (this.upnpClient == null) {
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
return this.upnpClient.stopListen()
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async main () {
|
|
107
|
-
try {
|
|
108
|
-
this.parseArguments()
|
|
109
|
-
const jsonFormatter = new homebridgeLib.JsonFormatter({
|
|
110
|
-
noWhiteSpace: this.options.noWhiteSpace
|
|
111
|
-
})
|
|
112
|
-
this.upnpClient = new homebridgeLib.UpnpClient(this.upnp)
|
|
113
|
-
this.upnpClient
|
|
114
|
-
.on('error', (error) => { this.error(error) })
|
|
115
|
-
.on('listening', (host) => { this.debug('listening on %s', host) })
|
|
116
|
-
.on('stopListening', (host) => { this.debug('stopped listening on %s', host) })
|
|
117
|
-
.on('deviceAlive', (address, obj, message) => {
|
|
118
|
-
if (!this.options.raw) {
|
|
119
|
-
message = jsonFormatter.stringify(obj)
|
|
120
|
-
}
|
|
121
|
-
this.log('%s: %s', address, message)
|
|
122
|
-
})
|
|
123
|
-
.on('searching', (host) => { this.debug('listening on %s', host) })
|
|
124
|
-
.on('request', (request) => {
|
|
125
|
-
this.debug(
|
|
126
|
-
'%s: request %d: %s %s', request.host, request.id,
|
|
127
|
-
request.method, request.resource
|
|
128
|
-
)
|
|
129
|
-
})
|
|
130
|
-
.on('searchDone', (host) => { this.debug('search done') })
|
|
131
|
-
.on('deviceFound', (address, obj, message) => {
|
|
132
|
-
if (!this.options.raw) {
|
|
133
|
-
message = jsonFormatter.stringify(obj)
|
|
134
|
-
}
|
|
135
|
-
this.print('%s: %s', address, message)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
if (this.options.mode) {
|
|
139
|
-
this.setOptions({ mode: this.options.mode })
|
|
140
|
-
this.upnpClient.listen()
|
|
141
|
-
} else {
|
|
142
|
-
this.upnpClient.search()
|
|
143
|
-
}
|
|
144
|
-
} catch (error) {
|
|
145
|
-
await this.fatal(error)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
new Main().main()
|
|
14
|
+
new UpnpTool().main()
|
package/index.js
CHANGED
|
@@ -210,6 +210,12 @@ class homebridgeLib {
|
|
|
210
210
|
*/
|
|
211
211
|
static get UpnpClient () { return require('./lib/UpnpClient') }
|
|
212
212
|
|
|
213
|
+
// Command-line tools.
|
|
214
|
+
static get HapTool () { return require('./lib/HapTool') }
|
|
215
|
+
static get JsonTool () { return require('./lib/JsonTool') }
|
|
216
|
+
static get SysinfoTool () { return require('./lib/SysinfoTool') }
|
|
217
|
+
static get UpnpTool () { return require('./lib/UpnpTool') }
|
|
218
|
+
|
|
213
219
|
/** Resolve after given period, delaying execution.
|
|
214
220
|
*
|
|
215
221
|
* E.g. to delay execution for 1.5 seconds, issue:
|
package/lib/HapTool.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// homebridge-lib/lib/HapTool.js
|
|
4
|
+
//
|
|
5
|
+
// Library for Homebridge plugins.
|
|
6
|
+
// Copyright © 2018-2023 Erik Baauw. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
// Logger for HomeKit accessory announcements.
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
const homebridgeLib = require('../index')
|
|
13
|
+
|
|
14
|
+
const Bonjour = require('bonjour-hap')
|
|
15
|
+
|
|
16
|
+
const { b, u } = homebridgeLib.CommandLineTool
|
|
17
|
+
|
|
18
|
+
const usage = `${b('hap')} [${b('-hVlrs')}] [${b('-t')} ${u('timeout')}]`
|
|
19
|
+
const help = `Logger for HomeKit accessory announcements.
|
|
20
|
+
|
|
21
|
+
Usage: ${usage}
|
|
22
|
+
|
|
23
|
+
Search for HomeKit accessory announcements
|
|
24
|
+
Parameters:
|
|
25
|
+
${b('-h')} Print this help and exit.
|
|
26
|
+
${b('-V')} Print version and exit.
|
|
27
|
+
${b('-d')} Listen for Bonjour alive broadcasts instead of searching.
|
|
28
|
+
${b('-s')} Do not output timestamps (useful when running as service).
|
|
29
|
+
${b('-t')} ${u('timeout')} Search for ${u('timeout')} seconds instead of default ${b('5')}.`
|
|
30
|
+
|
|
31
|
+
class HapTool extends homebridgeLib.CommandLineTool {
|
|
32
|
+
constructor () {
|
|
33
|
+
super()
|
|
34
|
+
this.usage = usage
|
|
35
|
+
this.options = { timeout: 15 }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
parseArguments () {
|
|
39
|
+
const parser = new homebridgeLib.CommandLineParser()
|
|
40
|
+
parser
|
|
41
|
+
.help('h', 'help', help)
|
|
42
|
+
.version('V', 'version')
|
|
43
|
+
.flag('l', 'listen', (key) => { this.options.mode = 'daemon' })
|
|
44
|
+
.flag('s', 'service', (key) => { this.options.mode = 'service' })
|
|
45
|
+
.option('t', 'timeout', (value, key) => {
|
|
46
|
+
this.options.timeout = homebridgeLib.OptionParser.toInt(
|
|
47
|
+
'timeout', value, 1, 60, true
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
.parse()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onUp (obj) {
|
|
54
|
+
delete obj.rawTxt
|
|
55
|
+
this.log('found accessory: %s', obj.name, this.jsonFormatter.stringify(obj))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async main () {
|
|
59
|
+
try {
|
|
60
|
+
this.parseArguments()
|
|
61
|
+
this.jsonFormatter = new homebridgeLib.JsonFormatter(
|
|
62
|
+
this.options.mode === 'service'
|
|
63
|
+
? { noWhiteSpace: true, sortKeys: true }
|
|
64
|
+
: { sortKeys: true }
|
|
65
|
+
)
|
|
66
|
+
if (this.options.mode) {
|
|
67
|
+
this.setOptions({ mode: this.options.mode })
|
|
68
|
+
} else {
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
this.log('search done')
|
|
71
|
+
bonjour4.destroy()
|
|
72
|
+
// bonjour6.destroy()
|
|
73
|
+
}, this.options.timeout * 1000)
|
|
74
|
+
}
|
|
75
|
+
this.log('searching for HomeKit accessories')
|
|
76
|
+
const bonjour4 = new Bonjour()
|
|
77
|
+
const browser4 = bonjour4.find({ type: 'hap' })
|
|
78
|
+
browser4.on('up', this.onUp.bind(this))
|
|
79
|
+
// const bonjour6 = new Bonjour({
|
|
80
|
+
// type: 'udp6',
|
|
81
|
+
// interface: '::%en0', // TODO: how to determine the interface?!
|
|
82
|
+
// ip: 'ff02::fb'
|
|
83
|
+
// })
|
|
84
|
+
// const browser6 = bonjour6.find({ type: 'hap' })
|
|
85
|
+
// browser6.on('up', this.onUp.bind(this))
|
|
86
|
+
} catch (error) {
|
|
87
|
+
await this.fatal(error)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = HapTool
|
package/lib/JsonTool.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// homebridge-lib/lib/JsonTool.js
|
|
4
|
+
//
|
|
5
|
+
// Library for Homebridge plugins.
|
|
6
|
+
// Copyright © 2018-2023 Erik Baauw. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
// JSON formatter.
|
|
9
|
+
|
|
10
|
+
'use strict'
|
|
11
|
+
|
|
12
|
+
const homebridgeLib = require('../index')
|
|
13
|
+
|
|
14
|
+
const fs = require('fs')
|
|
15
|
+
const util = require('util')
|
|
16
|
+
const zlib = require('zlib')
|
|
17
|
+
|
|
18
|
+
const gunzip = util.promisify(zlib.unzip)
|
|
19
|
+
|
|
20
|
+
const { b, u } = homebridgeLib.CommandLineTool
|
|
21
|
+
|
|
22
|
+
const usage = `${b('json')} [${b('-hVsnjuatlkv')}] [${b('-p')} path] [${b('-d')} depth] [${b('-c')} ${u('string')}]... [${u('file')}]...`
|
|
23
|
+
const help = `JSON formatter.
|
|
24
|
+
|
|
25
|
+
Usage: ${usage}
|
|
26
|
+
|
|
27
|
+
By default, ${b('json')} reads JSON from stdin, formats it, and prints it to stdout.
|
|
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.`
|
|
81
|
+
|
|
82
|
+
class JsonTool extends homebridgeLib.CommandLineTool {
|
|
83
|
+
constructor () {
|
|
84
|
+
super()
|
|
85
|
+
this.usage = usage
|
|
86
|
+
this.options = {}
|
|
87
|
+
this.stringList = []
|
|
88
|
+
this.fileList = []
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
parseArguments () {
|
|
92
|
+
const parser = new homebridgeLib.CommandLineParser()
|
|
93
|
+
parser
|
|
94
|
+
.help('h', 'help', help)
|
|
95
|
+
.version('V', 'version')
|
|
96
|
+
.flag('s', 'sortKeys', () => { this.options.sortKeys = true })
|
|
97
|
+
.flag('n', 'noWhiteSpace', () => { this.options.noWhiteSpace = true })
|
|
98
|
+
.flag('j', 'jsonArray', () => { this.options.jsonArray = true })
|
|
99
|
+
.flag('u', 'joinKeys', () => { this.options.joinKeys = true })
|
|
100
|
+
.flag('a', 'ascii', () => { this.options.ascii = true })
|
|
101
|
+
.flag('t', 'topOnly', () => { this.options.topOnly = true })
|
|
102
|
+
.option('d', 'maxDepth', (value, option) => {
|
|
103
|
+
this.options.maxDepth = homebridgeLib.OptionParser.toInt(
|
|
104
|
+
'maxDepth', value, 0, undefined, true)
|
|
105
|
+
})
|
|
106
|
+
.option('p', 'fromPath', (value, option) => {
|
|
107
|
+
this.options.fromPath = homebridgeLib.OptionParser.toPath(
|
|
108
|
+
'fromPath', value, true
|
|
109
|
+
)
|
|
110
|
+
})
|
|
111
|
+
.flag('l', 'leavesOnly', () => { this.options.leavesOnly = true })
|
|
112
|
+
.flag('k', 'keysOnly', () => { this.options.keysOnly = true })
|
|
113
|
+
.flag('v', 'valuesOnly', () => { this.options.valuesOnly = true })
|
|
114
|
+
.option('c', 'string', (value) => { this.stringList.push(value) })
|
|
115
|
+
.remaining((list) => { this.fileList = list })
|
|
116
|
+
.parse()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
processString (s) {
|
|
120
|
+
let value
|
|
121
|
+
try {
|
|
122
|
+
value = JSON.parse(s)
|
|
123
|
+
} catch (error) {
|
|
124
|
+
throw new Error(error.message) // Convert SyntaxError to Error.
|
|
125
|
+
}
|
|
126
|
+
const output = this.jsonFormatter.stringify(value)
|
|
127
|
+
if (this.n++ > 0) {
|
|
128
|
+
this.print('------')
|
|
129
|
+
}
|
|
130
|
+
if (output !== '') {
|
|
131
|
+
this.print(output)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async main () {
|
|
136
|
+
try {
|
|
137
|
+
this.parseArguments()
|
|
138
|
+
this.jsonFormatter = new homebridgeLib.JsonFormatter(this.options)
|
|
139
|
+
if (this.fileList.length === 0 && this.stringList.length === 0) {
|
|
140
|
+
this.fileList = ['-']
|
|
141
|
+
}
|
|
142
|
+
this.n = 0
|
|
143
|
+
this.stringList.forEach((s) => {
|
|
144
|
+
try {
|
|
145
|
+
this.processString(s)
|
|
146
|
+
} catch (error) {
|
|
147
|
+
this.error(error)
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
this.fileList.forEach(async (file) => {
|
|
151
|
+
try {
|
|
152
|
+
const s = file.endsWith('.gz')
|
|
153
|
+
? await gunzip(fs.readFileSync(file))
|
|
154
|
+
: fs.readFileSync(file === '-' ? 0 : file, 'utf8')
|
|
155
|
+
this.processString(s)
|
|
156
|
+
} catch (error) {
|
|
157
|
+
this.error(error)
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
} catch (error) {
|
|
161
|
+
await this.fatal(error)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = JsonTool
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// homebridge-lib/lib/SysinfoTool.js
|
|
4
|
+
//
|
|
5
|
+
// Show system info.
|
|
6
|
+
// Copyright © 2021-2023 Erik Baauw. All rights reserved.
|
|
7
|
+
|
|
8
|
+
'use strict'
|
|
9
|
+
|
|
10
|
+
const homebridgeLib = require('../index')
|
|
11
|
+
|
|
12
|
+
const { b } = homebridgeLib.CommandLineTool
|
|
13
|
+
|
|
14
|
+
const usage = `${b('sysinfo')} [${b('-hVDj')}]`
|
|
15
|
+
const help = `System information tool.
|
|
16
|
+
|
|
17
|
+
Print Hardware and Operating System information.
|
|
18
|
+
|
|
19
|
+
Usage: ${usage}
|
|
20
|
+
|
|
21
|
+
Parameters:
|
|
22
|
+
${b('-h')}, ${b('--help')}
|
|
23
|
+
Print this help and exit.
|
|
24
|
+
|
|
25
|
+
${b('-V')}, ${b('--version')}
|
|
26
|
+
Print version and exit.
|
|
27
|
+
|
|
28
|
+
${b('-D')}, ${b('--debug')}
|
|
29
|
+
Print debug messages.
|
|
30
|
+
|
|
31
|
+
${b('-j')}, ${b('--json')}
|
|
32
|
+
Print full info in json.`
|
|
33
|
+
|
|
34
|
+
class SysinfoTool extends homebridgeLib.CommandLineTool {
|
|
35
|
+
constructor () {
|
|
36
|
+
super()
|
|
37
|
+
this.usage = usage
|
|
38
|
+
this.options = {
|
|
39
|
+
noWhiteSpace: false
|
|
40
|
+
}
|
|
41
|
+
this.upnp = {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
parseArguments () {
|
|
45
|
+
const parser = new homebridgeLib.CommandLineParser()
|
|
46
|
+
parser
|
|
47
|
+
.help('h', 'help', help)
|
|
48
|
+
.version('V', 'version')
|
|
49
|
+
.flag('D', 'debug', () => { this.setOptions({ debug: true }) })
|
|
50
|
+
.flag('j', 'json', () => { this.json = true })
|
|
51
|
+
.parse()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async main () {
|
|
55
|
+
try {
|
|
56
|
+
this.parseArguments()
|
|
57
|
+
this.systemInfo = new homebridgeLib.SystemInfo()
|
|
58
|
+
this.systemInfo
|
|
59
|
+
.on('error', (error) => { this.error(error) })
|
|
60
|
+
.on('exec', (command) => { this.debug('exec: %s', command) })
|
|
61
|
+
.on('readFile', (fileName) => { this.debug('read file: %s', fileName) })
|
|
62
|
+
await this.systemInfo.init()
|
|
63
|
+
if (this.json) {
|
|
64
|
+
const jsonFormatter = new homebridgeLib.JsonFormatter(this.options)
|
|
65
|
+
this.print(jsonFormatter.stringify({
|
|
66
|
+
hardware: this.systemInfo.hwInfo,
|
|
67
|
+
os: this.systemInfo.osInfo
|
|
68
|
+
}))
|
|
69
|
+
} else {
|
|
70
|
+
this.print(this.systemInfo.hwInfo.prettyName)
|
|
71
|
+
this.print(this.systemInfo.osInfo.prettyName)
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
await this.fatal(error)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = SysinfoTool
|
package/lib/UpnpTool.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// homebridge-lib/cli/upnp.js
|
|
4
|
+
//
|
|
5
|
+
// Logger for UPnP device announcements.
|
|
6
|
+
// Copyright © 2018-2023 Erik Baauw. All rights reserved.
|
|
7
|
+
|
|
8
|
+
'use strict'
|
|
9
|
+
|
|
10
|
+
const homebridgeLib = require('../index')
|
|
11
|
+
|
|
12
|
+
const { b, u } = homebridgeLib.CommandLineTool
|
|
13
|
+
|
|
14
|
+
const usage = `${b('upnp')} [${b('-hVDadnprsz')}] [${b('-c')} ${u('class')}] [${b('-t')} ${u('timeout')}]`
|
|
15
|
+
const help = `UPnP tool.
|
|
16
|
+
|
|
17
|
+
Search for UPnP devices and print found devices as JSON.
|
|
18
|
+
When running as daemon or service, log UPnP alive broadcasts as JSON.
|
|
19
|
+
|
|
20
|
+
Usage: ${usage}
|
|
21
|
+
|
|
22
|
+
Parameters:
|
|
23
|
+
${b('-h')}, ${b('--help')}
|
|
24
|
+
Print this help and exit.
|
|
25
|
+
|
|
26
|
+
${b('-V')}, ${b('--version')}
|
|
27
|
+
Print version and exit.
|
|
28
|
+
|
|
29
|
+
${b('-D')}, ${b('--debug')}
|
|
30
|
+
Print debug messages.
|
|
31
|
+
|
|
32
|
+
${b('-a')}, ${b('--all')}
|
|
33
|
+
Short for ${b('-c ssdp:all')}.
|
|
34
|
+
|
|
35
|
+
${b('-c')} ${u('class')}, ${b('--class=')}${u('class')}
|
|
36
|
+
Search for ${u('class')} instead of default ${b('ssdp:rootdevice')}.
|
|
37
|
+
|
|
38
|
+
${b('-d')}, ${b('--daemon')}
|
|
39
|
+
Run as daemon. Listen for UPnP alive broadcasts instead of searching.
|
|
40
|
+
|
|
41
|
+
${b('-n')}, ${b('--noWhiteSpace')}
|
|
42
|
+
Do not include spaces nor newlines in JSON output.
|
|
43
|
+
|
|
44
|
+
${b('-p')}, ${b('--hue')}
|
|
45
|
+
Search for Philips Hue bridges and/or deCONZ gateways.
|
|
46
|
+
|
|
47
|
+
${b('-r')}, ${b('--raw')}
|
|
48
|
+
Do not parse messages, output raw message data instead of JSON.
|
|
49
|
+
|
|
50
|
+
${b('-s')}, ${b('--service')}
|
|
51
|
+
Run as daemon. Listen for UPnP alive broadcasts instead of searching.
|
|
52
|
+
|
|
53
|
+
${b('-t')} ${u('timeout')}, ${b('--timeout=')}${u('timeout')}
|
|
54
|
+
Search for ${u('timeout')} seconds instead of default ${b('5')}.
|
|
55
|
+
|
|
56
|
+
${b('-z')}, ${b('--sonos')}
|
|
57
|
+
Search for Sonos Zone Players.`
|
|
58
|
+
|
|
59
|
+
class UpnpTool extends homebridgeLib.CommandLineTool {
|
|
60
|
+
constructor () {
|
|
61
|
+
super()
|
|
62
|
+
this.usage = usage
|
|
63
|
+
this.options = {
|
|
64
|
+
noWhiteSpace: false
|
|
65
|
+
}
|
|
66
|
+
this.upnp = {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
parseArguments () {
|
|
70
|
+
const parser = new homebridgeLib.CommandLineParser()
|
|
71
|
+
parser
|
|
72
|
+
.help('h', 'help', help)
|
|
73
|
+
.version('V', 'version')
|
|
74
|
+
.flag('D', 'debug', () => { this.setOptions({ debug: true }) })
|
|
75
|
+
.flag('a', 'all', (key) => { this.upnp.class = 'ssdp:all' })
|
|
76
|
+
.option('c', 'class', (value, key) => { this.upnp.class = value })
|
|
77
|
+
.flag('d', 'daemon', (key) => { this.options.mode = 'daemon' })
|
|
78
|
+
.flag('n', 'noWhiteSpace', () => { this.options.noWhiteSpace = true })
|
|
79
|
+
.flag('r', 'raw', (key) => { this.options.raw = true })
|
|
80
|
+
.flag('s', 'service', (key) => { this.options.mode = 'service' })
|
|
81
|
+
.option('t', 'timeout', (value, key) => {
|
|
82
|
+
this.upnp.timeout = homebridgeLib.OptionParser.toInt(
|
|
83
|
+
'timeout', value, 1, 60, true
|
|
84
|
+
)
|
|
85
|
+
})
|
|
86
|
+
.flag('p', 'hue', (key) => {
|
|
87
|
+
this.upnp.filter = (message) => {
|
|
88
|
+
return /^[0-9A-F]{16}$/.test(message['hue-bridgeid'])
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
.flag('z', 'sonos', (key) => {
|
|
92
|
+
this.upnp.class = 'urn:schemas-upnp-org:device:ZonePlayer:1'
|
|
93
|
+
})
|
|
94
|
+
.parse()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async destroy () {
|
|
98
|
+
if (this.upnpClient == null) {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
return this.upnpClient.stopListen()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async main () {
|
|
105
|
+
try {
|
|
106
|
+
this.parseArguments()
|
|
107
|
+
const jsonFormatter = new homebridgeLib.JsonFormatter({
|
|
108
|
+
noWhiteSpace: this.options.noWhiteSpace
|
|
109
|
+
})
|
|
110
|
+
this.upnpClient = new homebridgeLib.UpnpClient(this.upnp)
|
|
111
|
+
this.upnpClient
|
|
112
|
+
.on('error', (error) => { this.error(error) })
|
|
113
|
+
.on('listening', (host) => { this.debug('listening on %s', host) })
|
|
114
|
+
.on('stopListening', (host) => { this.debug('stopped listening on %s', host) })
|
|
115
|
+
.on('deviceAlive', (address, obj, message) => {
|
|
116
|
+
if (!this.options.raw) {
|
|
117
|
+
message = jsonFormatter.stringify(obj)
|
|
118
|
+
}
|
|
119
|
+
this.log('%s: %s', address, message)
|
|
120
|
+
})
|
|
121
|
+
.on('searching', (host) => { this.debug('listening on %s', host) })
|
|
122
|
+
.on('request', (request) => {
|
|
123
|
+
this.debug(
|
|
124
|
+
'%s: request %d: %s %s', request.host, request.id,
|
|
125
|
+
request.method, request.resource
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
.on('searchDone', (host) => { this.debug('search done') })
|
|
129
|
+
.on('deviceFound', (address, obj, message) => {
|
|
130
|
+
if (!this.options.raw) {
|
|
131
|
+
message = jsonFormatter.stringify(obj)
|
|
132
|
+
}
|
|
133
|
+
this.print('%s: %s', address, message)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
if (this.options.mode) {
|
|
137
|
+
this.setOptions({ mode: this.options.mode })
|
|
138
|
+
this.upnpClient.listen()
|
|
139
|
+
} else {
|
|
140
|
+
this.upnpClient.search()
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
await this.fatal(error)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = UpnpTool
|