diff --git a/companion/manifest.json b/companion/manifest.json index a192315..0971f1f 100644 --- a/companion/manifest.json +++ b/companion/manifest.json @@ -1,4 +1,5 @@ { + "$schema": "../node_modules/@companion-module/base/assets/manifest.schema.json", "id": "bmd-smartview", "name": "bmd-smartview", "shortname": "smart", @@ -22,5 +23,14 @@ }, "manufacturer": "Blackmagic Design", "products": ["SmartView", "SmartScope"], - "keywords": ["Scope", "Monitor"] + "keywords": ["Scope", "Monitor"], + "bonjourQueries": { + "bonjourHost": { + "type": "blackmagic", + "protocol": "tcp", + "txt": { + "class": "SmartView" + } + } + } } diff --git a/package.json b/package.json index 42fd5b4..8739f0f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bmd-smartview", - "version": "2.1.0", "main": "src/index.js", + "version": "2.2.0", "main": "src/index.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", diff --git a/src/index.js b/src/index.js index d5900cd..9377cb3 100644 --- a/src/index.js +++ b/src/index.js @@ -84,13 +84,29 @@ class BlackmagicSmartviewInstance extends InstanceBase { */ getConfigFields() { return [ + { + type: 'bonjour-device', + id: 'bonjourHost', + label: 'Device', + width: 12, + }, { type: 'textinput', id: 'host', label: 'Target IP', width: 6, + isVisible: (options) => !options['bonjourHost'], + default: '', regex: Regex.IP, }, + { + type: 'static-text', + id: 'host-filler', + width: 6, + label: '', + isVisible: (options) => !!options['bonjourHost'], + value: '', + }, { type: 'static-text', id: 'info', @@ -110,6 +126,37 @@ class BlackmagicSmartviewInstance extends InstanceBase { ] } + /** + * INTERNAL: returns the IP and port from the Bonjour host. + * + * @returns {Object} the IP and port object + * @access protected + * @since 2.2.0 + */ + parseIpAndPort() { + // TODO: Switch to Regex.IP when we can convert that into a RegExp object... (it will need some processing) + const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/ + + if (this.config.bonjourHost) { + const [ip, rawPort] = this.config.bonjourHost.split(':') + const port = Number(rawPort) + if (ip.match(ipRegex) && !isNaN(port)) { + return { + ip, + port, + } + } + } else if (this.config.host) { + if (this.config.host.match(ipRegex)) { + return { + ip: this.config.host, + port: undefined, + } + } + } + return null + } + /** * INTERNAL: returns the desired monitor object. * @@ -182,18 +229,20 @@ class BlackmagicSmartviewInstance extends InstanceBase { */ initTCP() { this.receiveBuffer = '' + let target = this.parseIpAndPort() if (this.socket !== undefined) { this.socket.destroy() delete this.socket } - if (this.config.port === undefined) { - this.config.port = 9992 + if (target && target.port === undefined) { + self.log('info', 'Setting port to default') + target.port = 9992 } - if (this.config.host) { - this.socket = new TCPHelper(this.config.host, this.config.port) + if (target && target.ip) { + this.socket = new TCPHelper(target.ip, target.port) this.socket.on('status_change', (status, message) => { this.updateStatus(status, message) @@ -258,6 +307,9 @@ class BlackmagicSmartviewInstance extends InstanceBase { this.log('debug', 'weird response from smartview', line, line.length) } }) + } else { + this.log('error', 'Didn\'t get a target to connect to') + this.updateStatus(InstanceStatus.Disconnected) } }