UNPKG

@canboat/visual-analyzer

Version:

NMEA 2000 data visualization utility (requires SK Server >= 2.15)

142 lines (127 loc) 4.47 kB
/* * Copyright 2014-2018 Fabian Tollenaar <fabian@decipher.industries>,Teppo Kurki <teppo.kurki@iki.fi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* Usage: This is TCP client provider that can connect to a tcp server and pass data from there to the provider pipeline. * It takes the options "host" and "port". * Example: { "type": "providers/tcp", "options": { "host": 'localhost', "port": 10110, } }, */ const net = require('net') const Transform = require('stream').Transform function TcpStream(options) { Transform.call(this, options) this.options = options this.noDataReceivedTimeout = Number.parseInt((this.options.noDataReceivedTimeout + '').trim()) * 1000 this.debug = (options.createDebug || require('debug'))('signalk:streams:tcp') this.debug(`noDataReceivedTimeout:${this.noDataReceivedTimeout}`) this.debugData = (options.createDebug || require('debug'))('signalk:streams:tcp-data') } require('util').inherits(TcpStream, Transform) TcpStream.prototype.pipe = function (pipeTo) { const that = this if (this.options.outEvent) { that.options.app.on(that.options.outEvent, function (d) { if (that.tcpStream) { that.debug('sending %s', d) that.tcpStream.write(d) setImmediate(() => { that.options.app.emit('connectionwrite', { providerId: that.options.providerId, }) }) } }) } const stdOutEvent = this.options.toStdout if (stdOutEvent) { const that = this //semicolon required here ;(Array.isArray(stdOutEvent) ? stdOutEvent : [stdOutEvent]).forEach((stdEvent) => { that.options.app.on(stdEvent, function (d) { if (that.tcpStream) { that.tcpStream.write(d + '\r\n') that.debug('event %s sending %s', stdEvent, d) } }) }) } let firstConnect = true this.re = require('reconnect-core')(function () { return net.connect.apply(null, arguments) })({ initialDelay: 1000, maxDelay: 5 * 1000 }, (tcpStream) => { if (!isNaN(this.noDataReceivedTimeout)) { tcpStream.setTimeout(this.noDataReceivedTimeout) that.debug(`Setting socket idle timeout ${this.options.host}:${this.options.port} ${this.noDataReceivedTimeout}`) tcpStream.on('timeout', () => { that.debug(`Idle timeout, closing socket ${this.options.host}:${this.options.port}`) tcpStream.end() }) } tcpStream.on('data', (data) => { if (that.debugData.enabled) { that.debugData(data.toString()) } this.write(data) }) }) .on('connect', (con) => { this.tcpStream = con const msg = `Connected to ${this.options.host} ${this.options.port}` this.options.app.setProviderStatus(this.options.providerId, msg) this.options.app.emit('connected') that.debug(msg) }) .on('reconnect', (n, delay) => { if (firstConnect) { firstConnect = false } else { const msg = `Reconnect ${this.options.host} ${this.options.port} retry ${n} delay ${delay}` this.options.app.setProviderError(this.options.providerId, msg) that.debug(msg) } }) .on('disconnect', () => { delete this.tcpStream that.debug(`Disconnected ${this.options.host} ${this.options.port}`) }) .on('error', (err) => { let msg = err if (err.message && err.message.length > 0) { msg = err.message } else if (err.errors) { msg = err.errors } this.options.app.setProviderError(this.options.providerId, msg) console.error('TcpProvider:' + msg) }) .connect(this.options) Transform.prototype.pipe.call(this, pipeTo) } TcpStream.prototype._transform = function (data, encoding, callback) { callback(null, data) } TcpStream.prototype.end = function () { if (this.tcpStream) { this.tcpStream.end() } if (this.re) { this.re.disconnect() } } module.exports = TcpStream