@signalk/streams
Version:
Utilities for handling streams of Signal K data
144 lines (143 loc) • 5.57 kB
JavaScript
"use strict";
/*
* Copyright 2017 Signal K & Fabian Tollenaar <fabian@signalk.org>
*
* 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.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = require("stream");
const nmea0183_signalk_1 = __importDefault(require("@signalk/nmea0183-signalk"));
const nmea0183_utilities_1 = require("@signalk/nmea0183-utilities");
function isN2KOver0183(msg) {
const sentence = msg.charAt(0) === '\\' ? msg.split('\\')[2] : msg;
return sentence
? sentence.startsWith('$PCDIN,') || sentence.startsWith('$MXPGN,')
: false;
}
class Nmea0183ToSignalK extends stream_1.Transform {
debug;
parser;
parseN2KOver0183 =
// runs only once when needed, replaces itself with the actual function
// after loading the required modules
(sentence) => {
const { FromPgn } = require('@canboat/canboatjs');
const n2kParser = new FromPgn({
...this.options,
useCamelCompat: this.options.useCamelCompat ?? true
});
n2kParser.on('warning', (pgn, warning) => {
this.debug.enabled && this.debug(`[warning] ${pgn.pgn} ${warning}`);
});
n2kParser.on('error', (pgn, err) => {
this.debug.enabled && this.debug(`[error] ${pgn.input} ${err.message}`);
});
this.parseN2KOver0183 = n2kParser.parseN2KOver0183.bind(n2kParser);
this.n2kToDelta = require('@signalk/n2k-signalk').toDelta;
return this.parseN2KOver0183(sentence, () => { });
};
n2kToDelta;
n2kState = {};
app;
sentenceEvents;
appendChecksumFlag;
options;
constructor(options) {
super({ objectMode: true });
this.debug = (options.createDebug ?? require('debug'))('signalk:streams:nmea0183-signalk');
this.parser = new nmea0183_signalk_1.default(options);
this.options = options;
this.app = options.app;
this.appendChecksumFlag = options.appendChecksum ?? false;
this.sentenceEvents = options.suppress0183event ? [] : ['nmea0183'];
if (options.sentenceEvent) {
if (Array.isArray(options.sentenceEvent)) {
this.sentenceEvents = this.sentenceEvents.concat(options.sentenceEvent);
}
else {
this.sentenceEvents.push(options.sentenceEvent);
}
}
}
_transform(chunk, encoding, done) {
let sentence;
let timestamp = null;
if (chunk &&
typeof chunk === 'object' &&
!Buffer.isBuffer(chunk) &&
typeof chunk.line === 'string') {
const tsChunk = chunk;
timestamp = new Date(Number(tsChunk.timestamp));
sentence = tsChunk.line.trim();
}
else if (Buffer.isBuffer(chunk)) {
sentence = chunk.toString().trim();
}
else if (chunk && typeof chunk === 'string') {
sentence = chunk.trim();
}
if (sentence === '') {
// Empty input (e.g. trailing newline from upstream source). Drop
// silently without emitting events or invoking the parser.
done();
return;
}
if (sentence !== undefined && sentence.startsWith('#')) {
// Comment line from upstream source (e.g. gpiod-seatalk framing
// diagnostics). Log at debug level and drop without parsing or
// emitting nmea0183 events.
this.debug(sentence);
done();
return;
}
try {
if (sentence !== undefined) {
if (this.appendChecksumFlag) {
sentence = (0, nmea0183_utilities_1.appendChecksum)(sentence);
}
this.sentenceEvents.forEach((eventName) => {
this.app.emit(eventName, sentence);
this.app.signalk.emit(eventName, sentence);
});
let delta = null;
if (isN2KOver0183(sentence)) {
const pgn = this.parseN2KOver0183(sentence, () => { });
if (pgn) {
delta = this.n2kToDelta(pgn, this.n2kState, {
sendMetaData: true
});
}
}
else {
delta = this.parser.parse(sentence);
}
if (delta !== null) {
if (timestamp !== null) {
delta.updates.forEach((update) => {
update.timestamp = timestamp;
});
}
this.push(delta);
}
}
}
catch (e) {
this.debug(e);
}
done();
}
}
exports.default = Nmea0183ToSignalK;
//# sourceMappingURL=nmea0183-signalk.js.map