UNPKG

@signalk/streams

Version:

Utilities for handling streams of Signal K data

139 lines (125 loc) 4.31 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 const isArray = require('lodash').isArray 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 ;(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) } }) } ) } require('reconnect-core')(function () { return net.connect.apply(null, arguments) })({ 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) that.debug(msg) }) .on('reconnect', (n, delay) => { 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.toString() } else { msg = err.toString() } 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) } module.exports = TcpStream