UNPKG

@canboat/canboatjs

Version:

Native javascript version of canboat

245 lines 8.34 kB
"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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.filterPGN = exports.setupFilters = exports.byteStringArray = exports.byteString = exports.hexByte = exports.arrBuff = exports.rmChecksum = exports.trimWrap = exports.createDebug = void 0; exports.getPlainPGNs = getPlainPGNs; exports.isPGNProprietary = isPGNProprietary; exports.compute0183Checksum = compute0183Checksum; exports.binToActisense = binToActisense; const debug_1 = require("debug"); const fp_1 = require("lodash/fp"); const createDebug = (name, appOptions = undefined) => { if (appOptions !== undefined && appOptions.createDebug !== undefined) { return appOptions.createDebug(name); } else { return (0, debug_1.debug)(name); } }; exports.createDebug = createDebug; function getPlainPGNs(buffer) { const res = []; let bucket = 0x40; // 64 const first = Buffer.alloc(8); first.writeUInt8(bucket++, 0); first.writeUInt8(buffer.length, 1); buffer.copy(first, 2, 0, 6); res.push(first); for (let index = 6; index < buffer.length; index += 7) { const next = Buffer.alloc(8); next.writeUInt8(bucket++, 0); let end = index + 7; let fill = 0; if (end > buffer.length) { fill = end - buffer.length; end = buffer.length; } buffer.copy(next, 1, index, end); if (fill > 0) { for (let i = end - index + 1; i < 8; i++) { next.writeUInt8(0xff, i); } } res.push(next); } return res; } // NMEA 2000 proprietary PGN ranges: // - 61184, 61440: PDU1 single-frame proprietary // - 65280–65535: PDU1 proprietary // - 126720–126975: PDU2 proprietary fast-packet function isPGNProprietary(pgn) { return (pgn === 61184 || pgn === 61440 || (pgn >= 65280 && pgn <= 65535) || (pgn >= 126720 && pgn <= 126975)); } const m_hex = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' ]; function toHexString(v) { const msn = (v >> 4) & 0x0f; const lsn = (v >> 0) & 0x0f; return m_hex[msn] + m_hex[lsn]; } function compute0183Checksum(sentence) { // skip the $ let i = 1; // init to first character let c1 = sentence.charCodeAt(i); // process rest of characters, zero delimited for (i = 2; i < sentence.length; ++i) { c1 = c1 ^ sentence.charCodeAt(i); } return '*' + toHexString(c1); } function binToActisense(pgn, timestamp, data, length) { const arr = []; return (timestamp + `,${pgn.prio},${pgn.pgn},${pgn.src},${pgn.dst},${length},` + new Uint32Array(data) .reduce(function (acc, i) { acc.push(i.toString(16)); return acc; }, arr) .map((x) => (x.length === 1 ? '0' + x : x)) .join(',')); } exports.trimWrap = (0, fp_1.trimChars)('()<>[]'); const rmChecksum = (str) => str.includes('*') ? str.split('*', 1)[0] : str; exports.rmChecksum = rmChecksum; const arrBuff = (arr, encoding = 'hex') => Buffer.from(arr.join(''), encoding); exports.arrBuff = arrBuff; const hexByte = (x) => (0, fp_1.padCharsStart)('0', 2, Number(x).toString(16)); exports.hexByte = hexByte; const byteString = (data, separator = ',') => // Uint32Array map method doesn't work as expect. _.map does. (0, fp_1.map)(exports.hexByte, new Uint32Array(data)).join(separator); exports.byteString = byteString; const byteStringArray = (data) => // Uint32Array map method doesn't work as expect. _.map does. (0, fp_1.map)(exports.hexByte, new Uint8Array(data)); exports.byteStringArray = byteStringArray; const setupFilters = (filterOptions) => { let pgn_filter = undefined; if (filterOptions.pgn !== undefined) { if (Array.isArray(filterOptions.pgn)) { pgn_filter = filterOptions.pgn.map((p) => typeof p === 'string' ? Number(p) : p); } else { pgn_filter = [ typeof filterOptions.pgn === 'string' ? Number(filterOptions.pgn) : filterOptions.pgn ]; } } let src_filter = undefined; if (filterOptions.src !== undefined) { if (Array.isArray(filterOptions.src)) { src_filter = filterOptions.src.map((s) => typeof s === 'string' ? Number(s) : s); } else { src_filter = [ typeof filterOptions.src === 'string' ? Number(filterOptions.src) : filterOptions.src ]; } } let dst_filter = undefined; if (filterOptions.dst !== undefined) { if (Array.isArray(filterOptions.dst)) { dst_filter = filterOptions.dst.map((d) => typeof d === 'string' ? Number(d) : d); } else { dst_filter = [ typeof filterOptions.dst === 'string' ? Number(filterOptions.dst) : filterOptions.dst ]; } } let manufacturer_filter = undefined; if (filterOptions.manufacturer !== undefined) { if (Array.isArray(filterOptions.manufacturer)) { manufacturer_filter = filterOptions.manufacturer; } else { manufacturer_filter = [filterOptions.manufacturer]; } } let id_filter = undefined; if (filterOptions.id !== undefined) { if (Array.isArray(filterOptions.id)) { id_filter = filterOptions.id; } else { id_filter = [filterOptions.id]; } } let js_filter = undefined; const filter = filterOptions.filter; if (filter !== undefined && filter.length > 0) { try { js_filter = new Function('pgn', `return ${filter}`); } catch (e) { console.error(`Invalid filter expression: ${e.message}`); //process.exit(1) } } return { pgn_filter, manufacturer_filter, src_filter, dst_filter, js_filter, id_filter }; }; exports.setupFilters = setupFilters; const filterPGN = (pgn, filter) => { if ((filter.src_filter === undefined || filter.src_filter.length === 0 || filter.src_filter.find((s) => pgn.src === s)) && (filter.dst_filter === undefined || filter.dst_filter.length === 0 || filter.dst_filter.find((d) => pgn.dst === d)) && (filter.manufacturer_filter === undefined || filter.manufacturer_filter.length === 0 || filter.manufacturer_filter.find((m) => pgn.fields?.manufacturerCode === m))) { // Check if PGN passes either filter (when filters are defined) const hasPgnFilter = filter.pgn_filter !== undefined && filter.pgn_filter.length > 0; const hasIdFilter = filter.id_filter !== undefined && filter.id_filter.length > 0; if (hasPgnFilter || hasIdFilter) { const passesNumberFilter = hasPgnFilter && filter.pgn_filter.includes(pgn.pgn); const passesIdFilter = hasIdFilter && filter.id_filter.includes(pgn.id); if (!passesNumberFilter && !passesIdFilter) { return false; } } if (filter.js_filter !== undefined) { try { return filter.js_filter(pgn); } catch (e) { console.error(`Error evaluating filter on PGN ${pgn.pgn}: ${e.message}`); return false; } } return true; } return false; }; exports.filterPGN = filterPGN; //# sourceMappingURL=utilities.js.map