@canboat/canboatjs
Version:
Native javascript version of canboat
234 lines • 8.91 kB
JavaScript
"use strict";
/**
* Copyright 2018 Scott Bender (scott@scottbender.net)
*
* 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 });
exports.iKonvertStream = iKonvertStream;
const utilities_1 = require("./utilities");
const stream_1 = require("stream");
const toPgn_1 = require("./toPgn");
const fromPgn_1 = require("./fromPgn");
const lodash_1 = __importDefault(require("lodash"));
const codes_1 = require("./codes");
const util_1 = __importDefault(require("util"));
//const pgnsSent = {}
function iKonvertStream(options) {
if (this == undefined) {
return new iKonvertStream(options);
}
this.debug = (0, utilities_1.createDebug)('canboatjs:ikonvert', options);
this.debugOut = (0, utilities_1.createDebug)('canboatjs:n2k-out', options);
stream_1.Transform.call(this, {
objectMode: true
});
this.isTcp = options.tcp === true;
this.outEvent = this.isTcp ? 'navlink2-out' : 'ikonvertOut';
this.plainText = false;
this.reconnect = options.reconnect || true;
this.options = options;
this.cansend = false;
this.buffer = Buffer.alloc(500);
this.bufferOffset = 0;
this.start();
this.setProviderStatus =
options.app && options.app.setProviderStatus
? (msg) => {
options.app.setProviderStatus(options.providerId, msg);
}
: () => { };
this.setProviderError =
options.app && options.app.setProviderError
? (msg) => {
options.app.setProviderError(options.providerId, msg);
}
: () => { };
this.transmitPGNs = codes_1.defaultTransmitPGNs;
if (this.options.transmitPGNs) {
this.transmitPGNs = lodash_1.default.union(this.transmitPGNs, this.options.transmitPGNs);
}
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
if (this.options.app) {
options.app.on(this.options.outEevent || 'nmea2000out', (msg) => {
if (typeof msg === 'string') {
that.sendActisensePGN(msg);
}
else {
that.sendPGN(msg);
}
options.app.emit('connectionwrite', { providerId: options.providerId });
});
options.app.on(options.jsonOutEvent || 'nmea2000JsonOut', (msg) => {
that.sendPGN(msg);
options.app.emit('connectionwrite', { providerId: options.providerId });
});
this.isSetup = false;
//this.cansend = true
this.state = 0;
this.setupCommands = this.getSetupCommands();
this.expecting = false;
this.debug('started');
}
}
util_1.default.inherits(iKonvertStream, stream_1.Transform);
iKonvertStream.prototype.start = function () { };
iKonvertStream.prototype.sendString = function (msg) {
this.debugOut('sending %s', msg);
if (this.isTcp) {
msg = msg + '\n\r';
}
this.options.app.emit(this.outEvent, msg);
};
iKonvertStream.prototype.sendPGN = function (pgn) {
if (this.cansend) {
//let now = Date.now()
//let lastSent = pgnsSent[pgn.pgn]
const msg = (0, toPgn_1.pgnToiKonvertSerialFormat)(pgn);
if (this.options.app.listenerCount('canboatjs:rawsend') > 0) {
this.options.app.emit('canboatjs:rawsend', { data: msg });
}
this.sendString(msg);
//pgnsSent[pgn.pgn] = now
}
};
iKonvertStream.prototype.sendActisensePGN = function (msg) {
if (this.cansend) {
if (!this.parser) {
this.parser = new fromPgn_1.Parser(this.options);
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
this.parser.on('error', (pgn, error) => {
console.error(`Error parsing ${pgn.pgn} ${error}`);
console.error(error.stack);
});
this.parser.on('pgn', (pgn) => {
//let now = Date.now()
//let lastSent = pgnsSent[pgn.pgn]
const msg = (0, toPgn_1.pgnToiKonvertSerialFormat)(pgn);
if (this.options.app.listenerCount('canboatjs:rawsend') > 0) {
this.options.app.emit('canboatjs:rawsend', { data: msg });
}
that.sendString(msg);
//pgnsSent[pgn.pgn] = now
});
}
this.parser.parseString(msg);
}
};
iKonvertStream.prototype.setup = function () {
let txPgns = '$PDGY,TX_LIST';
this.transmitPGNs.forEach((pgn) => {
txPgns = txPgns + `,${pgn}`;
});
this.debug('sending pgn tx list');
this.sendString(txPgns);
};
iKonvertStream.prototype.getSetupCommands = function () {
let txPgns = '$PDGY,TX_LIST';
this.transmitPGNs.forEach((pgn) => {
txPgns = txPgns + `,${pgn}`;
});
const setupCommands = [];
setupCommands.push('$PDGY,N2NET_OFFLINE:$PDGY,TEXT,Digital_Yacht_');
if (this.isTcp) {
setupCommands.push('$PDGY,N2NET_MODE,15:$PDGY,ACK,N2NET_MODE');
}
setupCommands.push('$PDGY,TX_LIMIT,OFF:$PDGY,'); // NACK is ok with old firmware
setupCommands.push(`${txPgns}:$PDGY,ACK,TX_LIST`);
setupCommands.push('$PDGY,N2NET_INIT,ALL:$PDGY,ACK,N2NET_INIT,ALL');
return setupCommands;
};
iKonvertStream.prototype._transform = function (chunk, encoding, done) {
let line = chunk.toString().trim();
line = line.substring(0, line.length); // take off the \r
if (line.startsWith('$PDGY,TEXT')) {
this.debug(line);
}
else if (line.startsWith('$PDGY,000000,')) {
const parts = line.split(',');
//FIXME, camelCase?
if (this.options.sendNetworkStats && parts[2] && parts[2].length > 0) {
const pgn = {
pgn: 0x40100,
prio: 7,
dst: 255,
src: 0,
'CAN network load': Number(parts[2]),
Errors: Number(parts[3]),
'Device count': Number(parts[4]),
Uptime: Number(parts[5]),
'Gateway address': Number(parts[6]),
'Rejected TX requests': Number(parts[7])
};
const buf = (0, toPgn_1.toPgn)(pgn);
if (buf) {
this.push(`!PDGY,${pgn.pgn},${pgn.prio},${pgn.src},${pgn.dst},0,${buf.toString('base64')}`);
}
done();
return;
}
}
else if (line.startsWith('$PDGY,NAK')) {
const parts = line.split(',');
const msg = `NavLink2 error ${parts[2]}: ${parts[3]}`;
console.error(msg);
//this.setProviderError(msg)
}
if (!this.isSetup) {
this.debug(line);
let command = this.setupCommands[this.state].split(':');
if (!this.expecting) {
this.sendString(command[0]);
this.expecting = true;
this.sentTime = Date.now();
this.debug(`Waiting for ${command[1]}`);
}
else {
if (line.startsWith(command[1])) {
this.state = this.state + 1;
if (this.state == this.setupCommands.length) {
this.isSetup = true;
this.cansend = true;
this.options.app.emit('nmea2000OutAvailable');
this.debug('Setup completed');
}
else {
command = this.setupCommands[this.state].split(':');
this.sendString(command[0]);
this.expecting = true;
this.sentTime = Date.now();
this.debug(`Waiting for ${command[1]}`);
}
}
else if (Date.now() - this.sentTime > 5000) {
this.debug(`Did not receive expected: ${command[1]}, retrying...`);
this.sendString(command[0]);
this.sentTime = Date.now();
}
}
}
else {
this.push(line);
if (this.options.app.listenerCount('canboatjs:rawoutput') > 0) {
this.options.app.emit('canboatjs:rawoutput', line);
}
}
done();
};
iKonvertStream.prototype.end = function () { };
//# sourceMappingURL=ikonvert.js.map