From 209e73932ee15f3ecb77c5d4ab3da949849125d2 Mon Sep 17 00:00:00 2001 From: Scott Bender Date: Wed, 5 Jun 2019 08:55:42 -0400 Subject: [PATCH] feature: limit the transmission rates of pgns per the n2k spec --- conversions/ais.js | 5 +-- conversions/battery.js | 1 + conversions/cogSOG.js | 1 + conversions/depth.js | 1 + conversions/engineParameters.js | 2 ++ conversions/gps.js | 58 ++++++++++++++------------------- conversions/heading.js | 1 + conversions/speed.js | 1 + conversions/systemTime.js | 1 + conversions/tanks.js | 1 + conversions/temperature.js | 4 +++ conversions/wind.js | 1 + index.js | 55 +++++++++++++++++++++++-------- package-lock.json | 16 ++++----- 14 files changed, 92 insertions(+), 56 deletions(-) diff --git a/conversions/ais.js b/conversions/ais.js index 4a4ef83..90e4f9f 100644 --- a/conversions/ais.js +++ b/conversions/ais.js @@ -50,6 +50,7 @@ module.exports = (app, plugin) => { sourceType: 'onDelta', //outputType: 'buffer', optionKey: 'AISv2', + pgns: [ static_pgn, position_pgn, aton_pgn ], callback: (delta) => { var selfContext = 'vessels.' + app.selfId @@ -191,11 +192,11 @@ function generatePosition(vessel, mmsi, delta) { status = 0 } - if ( cog > Math.PI*2 ) { + if ( cog >= Math.PI*2 ) { cog = undefined } - if ( heading > Math.PI*2 ) { + if ( heading >= Math.PI*2 ) { heading = undefined } diff --git a/conversions/battery.js b/conversions/battery.js index 74a7703..8d62e34 100644 --- a/conversions/battery.js +++ b/conversions/battery.js @@ -15,6 +15,7 @@ module.exports = (app, plugin) => { return { title: 'Battery (127506 & 127508)', optionKey: 'BATTERYv2', + pgns: [127506, 127508], context: 'vessels.self', properties: { batteries: { diff --git a/conversions/cogSOG.js b/conversions/cogSOG.js index 34d1261..c4b3214 100644 --- a/conversions/cogSOG.js +++ b/conversions/cogSOG.js @@ -6,6 +6,7 @@ module.exports = (app, plugin) => { return { title: 'COG & SOG (129026)', optionKey: 'COG_SOGv2', + pgns: [ 129026 ], keys: ["navigation.courseOverGroundTrue", "navigation.speedOverGround"], callback: (course, speed) => { try { diff --git a/conversions/depth.js b/conversions/depth.js index be71464..8fb3330 100644 --- a/conversions/depth.js +++ b/conversions/depth.js @@ -4,6 +4,7 @@ module.exports = (app, plugin) => { return { title: 'Depth (128267)', optionKey: 'DEPTHv2', + pgns: [ 128267 ], keys: ["environment.depth.belowTransducer"], callback: (belowTransducer) => { var surfaceToTransducer = _.get(app.signalk.self, diff --git a/conversions/engineParameters.js b/conversions/engineParameters.js index daa9c60..86b2a9e 100644 --- a/conversions/engineParameters.js +++ b/conversions/engineParameters.js @@ -27,6 +27,7 @@ module.exports = (app, plugin) => { return [{ title: 'Temperature, exhaust (130312)', optionKey: 'EXHAUST_TEMPERATURE', + pgns: [ 130312 ], context: 'vessels.self', properties: { engines: { @@ -74,6 +75,7 @@ module.exports = (app, plugin) => { { title: 'Engine Parameters (127489,127488)', optionKey: 'ENGINE_PARAMETERS', + pgns: [ 127489, 127488 ], context: 'vessels.self', properties: { engines: { diff --git a/conversions/gps.js b/conversions/gps.js index 05caaf6..6813d88 100644 --- a/conversions/gps.js +++ b/conversions/gps.js @@ -1,11 +1,10 @@ const _ = require('lodash') module.exports = (app, plugin) => { - var lastUpdate = null - return { title: 'Location (129025,129029)', optionKey: 'GPS_LOCATIONv2', + pgns: [ 129025, 129029 ], keys: ["navigation.position"], callback: (position) => { //app.debug(`position: ${JSON.stringify(position)}`) @@ -17,38 +16,31 @@ module.exports = (app, plugin) => { } ] - - if ( - lastUpdate == null || - (new Date().getTime() - lastUpdate.getTime()) > 1000 - ) { - lastUpdate = new Date() - - var dateObj = new Date(); - var date = Math.trunc(dateObj.getTime() / 86400 / 1000); - var time = - dateObj.getUTCHours() * (60 * 60) + - dateObj.getUTCMinutes() * 60 + - dateObj.getUTCSeconds(); - - res.push({ - pgn: 129029, - Date: date, - Time: time, - Latitude: position.latitude, - Longitude: position.longitude, - 'GNSS type': 'GPS+SBAS/WAAS', - Method: 'DGNSS fix', - Integrity: 'No integrity checking', - 'Number of SVs': 16, - HDOP:0.64, - 'Geoidal Separation': -0.01, - 'Reference Stations': 1, - 'Reference Station Type': 'GPS+SBAS/WAAS', - 'Reference Station ID': 7 + var dateObj = new Date(); + var date = Math.trunc(dateObj.getTime() / 86400 / 1000); + var time = + dateObj.getUTCHours() * (60 * 60) + + dateObj.getUTCMinutes() * 60 + + dateObj.getUTCSeconds(); + + res.push({ + pgn: 129029, + Date: date, + Time: time, + Latitude: position.latitude, + Longitude: position.longitude, + 'GNSS type': 'GPS+SBAS/WAAS', + Method: 'DGNSS fix', + Integrity: 'No integrity checking', + 'Number of SVs': 16, + HDOP:0.64, + 'Geoidal Separation': -0.01, + 'Reference Stations': 1, + 'Reference Station Type': 'GPS+SBAS/WAAS', + 'Reference Station ID': 7 //'Age of DGNSS Corrections': - }) - } + }) + return res } } diff --git a/conversions/heading.js b/conversions/heading.js index 0a2faef..cd9e182 100644 --- a/conversions/heading.js +++ b/conversions/heading.js @@ -4,6 +4,7 @@ module.exports = (app, plugin) => { pgn: 127250, title: 'Heading (127250)', optionKey: 'HEADINGv2', + pgns: [ 127250 ], keys: [ "navigation.headingMagnetic", 'navigation.magneticVariation' diff --git a/conversions/speed.js b/conversions/speed.js index d9e151a..83bebbd 100644 --- a/conversions/speed.js +++ b/conversions/speed.js @@ -4,6 +4,7 @@ module.exports = (app, plugin) => { pgns: [ 128259 ], title: 'Speed (128259)', optionKey: 'SPEED', + pgns: 128259, keys: ["navigation.speedThroughWater"], callback: (speed) => { diff --git a/conversions/systemTime.js b/conversions/systemTime.js index e9fdc35..6ecf154 100644 --- a/conversions/systemTime.js +++ b/conversions/systemTime.js @@ -5,6 +5,7 @@ module.exports = (app, plugin) => { sourceType: 'timer', interval: 1000, optionKey: 'SYSTEM_TIMEv2', + pgns: [ 126992 ], callback: (app) => { var dateObj = new Date(); var date = Math.trunc(dateObj.getTime() / 86400 / 1000); diff --git a/conversions/tanks.js b/conversions/tanks.js index ac92a89..5108745 100644 --- a/conversions/tanks.js +++ b/conversions/tanks.js @@ -15,6 +15,7 @@ module.exports = (app, plugin) => { return { title: 'Tank Levels (127505)', optionKey: 'TANKS', + pgns: [ 127505 ], context: 'vessels.self', properties: () => { var tanks = _.get(app.signalk.self, 'tanks') diff --git a/conversions/temperature.js b/conversions/temperature.js index fbe46f8..761638b 100644 --- a/conversions/temperature.js +++ b/conversions/temperature.js @@ -15,6 +15,7 @@ module.exports = (app, plugin) => { pgn: 130312, title: 'Outside Temperature (130312)', optionKey: 'TEMPERATURE_OUTSIDE', + pgns: [ 130312 ], keys: [ "environment.outside.temperature" ], @@ -26,6 +27,7 @@ module.exports = (app, plugin) => { pgn: 130312, title: 'Inside Temperature (130312)', optionKey: 'TEMPERATURE_INSIDE', + pgns: 130312, keys: [ "environment.inside.temperature" ], @@ -37,6 +39,7 @@ module.exports = (app, plugin) => { pgn: 130312, title: 'Engine Room Temperature (130312)', optionKey: 'TEMPERATURE_ENGINEROOM', + pgns: [ 130312 ], keys: [ "environment.inside.engineRoom.temperature" ], @@ -48,6 +51,7 @@ module.exports = (app, plugin) => { pgn: 130312, title: 'Refridgerator Temperature (130312)', optionKey: 'TEMPERATURE_refridgerator', + pgns: [ 130312 ], keys: [ "environment.inside.refrigerator.temperature" ], diff --git a/conversions/wind.js b/conversions/wind.js index bf45954..df759b1 100644 --- a/conversions/wind.js +++ b/conversions/wind.js @@ -3,6 +3,7 @@ module.exports = (app, plugin) => { return { title: 'Wind (130306)', optionKey: 'WINDv2', + pgns: [ 130306 ], keys: ["environment.wind.angleApparent", "environment.wind.speedApparent"], callback: (angle, speed) => { try { diff --git a/index.js b/index.js index b06de48..7713d39 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,9 @@ const path = require('path') const fs = require('fs') module.exports = function(app) { - var plugin = {}; + var plugin = { + lastUpdates: {} + }; var unsubscribes = []; var timers = [] var conversions = load_conversions(app, plugin) @@ -104,6 +106,7 @@ module.exports = function(app) { if ( subConversions != null ) { subConversions.forEach(subConversion => { var type = _.isUndefined(subConversion.sourceType) ? 'onValueChange' : subConversion.sourceType + var mapper = sourceTypes[type] if ( _.isUndefined(mapper) ) { console.error(`Unknown conversion type: ${type}`) @@ -156,13 +159,22 @@ module.exports = function(app) { function processToN2K(pgns) { if ( pgns ) { pgns.filter(pgn => pgn != null).forEach(pgn => { - try { - app.debug("emit %j", pgn) - app.emit("nmea2000JsonOut", pgn); - } - catch ( err ) { - console.error(`error writing pgn ${JSON.stringify(pgn)}`) - console.error(err.stack) + + const key = `${pgn.pgn}.${pgn.Instance}` + const lastUpdate = plugin.lastUpdates[key] + const rate = updateRates[pgn.pgn] + if ( !_.isUndefined(rate) && !_.isUndefined(lastUpdate) && Date.now() - lastUpdate < rate ) { + return + } else { + plugin.lastUpdates[key] = Date.now() + try { + app.debug("emit %j", pgn) + app.emit("nmea2000JsonOut", pgn); + } + catch ( err ) { + console.error(`error writing pgn ${JSON.stringify(pgn)}`) + console.error(err.stack) + } } }) } @@ -172,7 +184,9 @@ module.exports = function(app) { outputTypes[conversion.outputType](output) } - function mapBaconjs(conversion) { + function mapBaconjs(conversion, options) { + let lastUpdate + unsubscribes.push( timeoutingArrayStream( conversion.keys, @@ -187,7 +201,7 @@ module.exports = function(app) { ); } - function mapOnDelta(conversion) { + function mapOnDelta(conversion, options) { app.signalk.on('delta', (delta) => { try { processOutput(conversion, conversion.callback(delta)) @@ -271,13 +285,28 @@ module.exports = function(app) { }) const result = combinedBus.debounce(10) if (app.debug.enabled) { - unsubscribes.push(result.onValue(x => app.debug(`${keys}:${x}`))) + unsubscribes.push(result.onValue(x => app.debug(`${keys}:${JSON.stringify(x)}`))) } return result } - -}; +} const notDefined = x => typeof x === 'undefined' const isDefined = x => typeof x !== 'undefined' + +const updateRates = { + 127506: 1500, + 127508: 1500, + 129026: 250, + 128267: 1000, + 130312: 2000, + 127489: 500, + 129025: 100, + 129029: 1000, + 127250: 100, + 126992: 1000, + 127505: 2500, + 130306: 100 +} + diff --git a/package-lock.json b/package-lock.json index bd1de36..9dfc5ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,7 +140,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -973,7 +973,7 @@ }, "ansi-colors": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-0.2.0.tgz", "integrity": "sha1-csMd4qDZoszQysMMyYI+6y9kNLU=", "dev": true, "requires": { @@ -3818,7 +3818,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -4027,7 +4027,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -4059,7 +4059,7 @@ }, "log-utils": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz", + "resolved": "http://registry.npmjs.org/log-utils/-/log-utils-0.2.1.tgz", "integrity": "sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8=", "dev": true, "requires": { @@ -5660,7 +5660,7 @@ }, "lodash": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true } @@ -5702,7 +5702,7 @@ }, "commander": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.9.0.tgz", "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", "dev": true, "requires": { @@ -5990,7 +5990,7 @@ }, "slice-ansi": { "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true },