UNPKG

signalk-server

Version:

An implementation of a [Signal K](http://signalk.org) server for boats.

114 lines 4.72 kB
"use strict"; /* * Copyright 2015 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. */ Object.defineProperty(exports, "__esModule", { value: true }); const net_1 = require("net"); const debug_1 = require("../debug"); const types_1 = require("../types"); const debug = (0, debug_1.createDebug)('signalk-server:interfaces:tcp:nmea0183'); const BUFFER_LIMIT = process.env.BACKPRESSURE_ENTER ? parseInt(process.env.BACKPRESSURE_ENTER, 10) : 512 * 1024; const MAX_BUFFER = process.env.MAXSENDBUFFERSIZE ? parseInt(process.env.MAXSENDBUFFERSIZE, 10) : 4 * 512 * 1024; const MAX_BUFFER_TIME = process.env.MAXSENDBUFFERCHECKTIME ? parseInt(process.env.MAXSENDBUFFERCHECKTIME, 10) : 30 * 1000; module.exports = (app) => { 'use strict'; const openSockets = {}; const bufferExceededSince = {}; let idSequence = 0; let server = null; let sendListener = null; const port = Number(process.env.NMEA0183PORT) || 10110; const api = new types_1.Interface(); api.start = () => { debug('Starting tcp interface'); server = (0, net_1.createServer)((socket) => { socket.id = idSequence++; socket.name = socket.remoteAddress + ':' + socket.remotePort; debug('Connected:' + socket.id + ' ' + socket.name); openSockets[socket.id] = socket; socket.on('data', (data) => { app.emit('tcpserver0183data', data.toString()); }); socket.on('end', () => { debug('Ended:' + socket.id + ' ' + socket.name); delete openSockets[socket.id]; delete bufferExceededSince[socket.id]; }); socket.on('error', (err) => { debug('Error:' + err + ' ' + socket.id + ' ' + socket.name); delete openSockets[socket.id]; delete bufferExceededSince[socket.id]; }); }); sendListener = (data) => { Object.values(openSockets).forEach((socket) => { try { if (socket.writableLength > BUFFER_LIMIT) { debug('Dropping NMEA sentence for slow client %s (buffer: %d)', socket.name, socket.writableLength); if (MAX_BUFFER > 0 && socket.writableLength > MAX_BUFFER) { if (!bufferExceededSince[socket.id]) { console.warn(`NMEA TCP ${socket.name} buffer exceeded max: ${socket.writableLength}`); bufferExceededSince[socket.id] = Date.now(); } if (Date.now() - bufferExceededSince[socket.id] > MAX_BUFFER_TIME) { console.error('NMEA TCP buffer overflow, terminating ' + socket.name); socket.destroy(); delete openSockets[socket.id]; delete bufferExceededSince[socket.id]; } } return; } delete bufferExceededSince[socket.id]; socket.write(data + '\r\n'); } catch (e) { console.error(e + ' ' + socket); } }); }; app.signalk.on('nmea0183', sendListener); app.on('nmea0183out', sendListener); server.on('listening', () => debug('NMEA0183 tcp server listening on ' + port)); server.on('error', (e) => { console.error(`NMEA0183 tcp server error: ${e.message}`); }); server.listen(port); }; api.stop = () => { if (sendListener) { app.signalk.removeListener('nmea0183', sendListener); app.removeListener('nmea0183out', sendListener); sendListener = null; } if (server) { server.close(); server = null; } }; api.mdns = { name: '_nmea-0183', type: 'tcp', port }; return api; }; //# sourceMappingURL=nmea-tcp.js.map