From 8c29fd977945c2750289194832272d44c2d33cd9 Mon Sep 17 00:00:00 2001 From: Scott Bender Date: Thu, 13 Aug 2020 14:29:34 -0400 Subject: [PATCH 1/2] feature: set the transmit pgn list on the Actisens NGT-1 --- lib/candevice.js | 4 +- lib/codes.js | 11 +-- lib/serial.js | 216 ++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 194 insertions(+), 37 deletions(-) diff --git a/lib/candevice.js b/lib/candevice.js index 7a55e32..1a0fbe6 100644 --- a/lib/candevice.js +++ b/lib/candevice.js @@ -36,6 +36,8 @@ const addressClaim = { "Reserved2": 2 } +const deviceTransmitPGNs = [ 60928, 59904, 126996, 126464 ] + class CanDevice extends EventEmitter { constructor (canbus, options) { super() @@ -50,7 +52,7 @@ class CanDevice extends EventEmitter { this.foundConflict = false this.devices = {} - this.transmitPGNs = defaultTransmitPGNs + this.transmitPGNs = _.union(deviceTransmitPGNs, defaultTransmitPGNs) if ( this.options.transmitPGNs ) { this.transmitPGNs = _.union(this.transmitPGNs, this.options.transmitPGNs) diff --git a/lib/codes.js b/lib/codes.js index 980e7bf..35fbf88 100644 --- a/lib/codes.js +++ b/lib/codes.js @@ -35,10 +35,7 @@ const industryNames = invert(industryCodes) industryNames['Marine'] = 4 const defaultTransmitPGNs = [ - 60928, - 59904, - 126996, - 126464, + 126992, 128267, 129794, 129038, @@ -54,7 +51,11 @@ const defaultTransmitPGNs = [ 126720, 127489, 127488, - 130312 + 130311, + 130312, + 127257, + 128259, + 127502 ] const manufacturerCodes = invert(manufacturerNames) diff --git a/lib/serial.js b/lib/serial.js index 82ef736..19225f2 100644 --- a/lib/serial.js +++ b/lib/serial.js @@ -14,7 +14,7 @@ * limitations under the License. */ -const debug = require('debug')('signalk:canbusjs') +const debug = require('debug')('signalk:actisense-serial') const debugOut = require('debug')('signalk:actisense-out') const Transform = require('stream').Transform const SerialPort = require('serialport') @@ -23,6 +23,7 @@ const BitStream = require('bit-buffer').BitStream const BitView = require('bit-buffer').BitView const { toPgn } = require('./toPgn') const { encodeActisense } = require('./stringMsg') +const { defaultTransmitPGNs } = require('./codes') const _ = require('lodash') /* ASCII characters used to mark packet start/stop */ @@ -66,6 +67,13 @@ function SerialStream (options) { this.reconnect = options.reconnect || true this.serial = null this.options = options + + this.transmitPGNs = defaultTransmitPGNs + if ( this.options.transmitPGNs ) { + this.transmitPGNs = _.union(this.transmitPGNs, + this.options.transmitPGNs) + } + this.start() } @@ -103,22 +111,7 @@ SerialStream.prototype.start = function () { } : () => {} var that = this - this.serial.on( - 'open', - function () { - try { - setProviderStatus(`Connected to ${that.options.device}`) - var buf = composeMessage(NGT_MSG_SEND, Buffer.from(NGT_STARTUP_MSG), NGT_STARTUP_MSG.length) - that.serial.write(buf) - debug('sent startup message') - } catch ( err ) { - setProviderError(err.message) - console.error(err) - console.error(err.stack) - } - } - ) - + this.serial.on('data', (data) => { try { readData(this, data) @@ -130,24 +123,28 @@ SerialStream.prototype.start = function () { if ( this.options.app ) { this.options.app.on('nmea2000out', msg => { - debugOut(`sending ${msg}`) - var buf = parseInput(msg) - buf = composeMessage(N2K_MSG_SEND, buf, buf.length) - that.serial.write(buf) + if ( this.outAvailable ) { + debugOut(`sending ${msg}`) + var buf = parseInput(msg) + buf = composeMessage(N2K_MSG_SEND, buf, buf.length) + that.serial.write(buf) + } }) this.options.app.on('nmea2000JsonOut', msg => { - var data = toPgn(msg) - var actisense = encodeActisense({ pgn: msg.pgn, data, dst: msg.dst}) - debugOut(`sending ${actisense}`) - var buf = parseInput(actisense) - buf = composeMessage(N2K_MSG_SEND, buf, buf.length) - that.serial.write(buf) + if ( this.outAvailable ) { + var data = toPgn(msg) + var actisense = encodeActisense({ pgn: msg.pgn, data, dst: msg.dst}) + debugOut(`sending ${actisense}`) + var buf = parseInput(actisense) + buf = composeMessage(N2K_MSG_SEND, buf, buf.length) + that.serial.write(buf) + } }) - - this.options.app.emit('nmea2000OutAvailable') } + this.outAvailable = false + this.serial.on('error', function (x) { setProviderError(x.message) console.log(x) @@ -156,6 +153,27 @@ SerialStream.prototype.start = function () { setProviderError('Closed, reconnecting...') this.start.bind(this) }) + this.serial.on( + 'open', + function () { + try { + setProviderStatus(`Connected to ${that.options.device}`) + var buf = composeMessage(NGT_MSG_SEND, Buffer.from(NGT_STARTUP_MSG), NGT_STARTUP_MSG.length) + that.serial.write(buf) + debug('sent startup message') + setTimeout(() => { + if ( this.outAvailable == false ) { + debug('retry startup message...') + that.serial.write(buf) + } + }, 5000) + } catch ( err ) { + setProviderError(err.message) + console.error(err) + console.error(err.stack) + } + } + ) } } @@ -194,7 +212,7 @@ function read1Byte(that, c) processN2KMessage(that, that.buffer, that.bufferOffset) //that.push(that.buffer.slice(2, that.bufferOffset)) } else if ( that.buffer[0] == NGT_MSG_RECEIVED) { - processNTGMessage(that.buffer.slice(2, that.bufferOffset)) + processNTGMessage(that, that.buffer, that.bufferOffset) } that.bufferOffset = 0 that.stat = MSG_START; @@ -241,8 +259,92 @@ function read1Byte(that, c) } } -function processNTGMessage(buffer) +function enableTXPGN(serial, pgn) { + debug('enabling pgn %d', pgn) + serial.write(composeEnablePGN(pgn)) +} + +function enableOutput(that) { + debug('outputEnabled') + that.outAvailable = true + if ( that.options.app ) { + that.options.app.emit('nmea2000OutAvailable') + } +} + +function processNTGMessage(that, buffer, len) { + var checksum = 0 + + for ( var i = 0; i < len; i++ ) { + checksum = addUInt8(checksum, buffer[i]) + } + + if ( checksum != 0 ) { + debug('received message with invalid checksum') + return + } + + const command = buffer[2] + + /* + console.log('got msg ' + command.toString(16)) + + if ( command != 0xf2 ) { + let data = new Uint32Array(buffer.slice(0, len)) + .reduce(function(acc, i) { + acc.push(i.toString(16)); + return acc; + }, []) + .map(x => (x.length === 1 ? "0" + x : x)) + .join(" ") + console.log(data) + }*/ + + if ( command === 0x11 ) { + //confirm startup + debug('request tx pgns...') + that.serial.write(composeRequestTXPGNList()) + } else if ( command === 0x49 && buffer[3] === 1 ) { + const pgnCount = buffer[14]; + let bv = new BitView(buffer.slice(15, that.bufferOffset)); + let bs = new BitStream(bv) + let pgns = [] + for ( let i = 0; i < pgnCount; i++ ) { + pgns.push(bs.readUint32()) + } + debug('tx pgns: %j', pgns) + + that.neededTransmitPGNs = that.transmitPGNs.filter(pgn => { + return pgns.indexOf(pgn) == -1 + }) + debug('needed pgns: %j', that.neededTransmitPGNs) + } else if ( command === 0x49 && buffer[3] === 4 ) { + if ( that.neededTransmitPGNs.length ) { + enableTXPGN(that.serial, that.neededTransmitPGNs[0]) + } else { + enableOutput(that) + } + } else if ( command === 0x47 ) { + if ( buffer[3] === 1 ) { + debug('enabled %d', that.neededTransmitPGNs[0]) + that.neededTransmitPGNs = that.neededTransmitPGNs.slice(1) + if ( that.neededTransmitPGNs.length === 0 ) { + that.serial.write(composeCommitTXPGN()) + } else { + enableTXPGN(that.serial, that.neededTransmitPGNs[0]) + } + } else { + debug('bad response from Enable TX: %d', buffer[3]) + } + } else if ( command === 0x01 ) { + debug('commited tx list') + that.serial.write(composeActivateTXPGN()) + } else if ( command === 0x4b ) { + debug('activated tx list') + enableOutput(that) + } + /* if (buffer.length < 12) { @@ -389,6 +491,58 @@ function parseInput(msg) return bs.view.buffer.slice(0, bs.byteIndex) } +function composeCommitTXPGN() { + let msg = new Uint32Array([0x01]) + return composeMessage(NGT_MSG_SEND, Buffer.from(msg), msg.length) +} + +function composeActivateTXPGN() { + let msg = new Uint32Array([0x4b]) + return composeMessage(NGT_MSG_SEND, Buffer.from(msg), msg.length) +} + +function composeRequestTXPGNList() { + let msg = new Uint32Array([0x49]) + return composeMessage(NGT_MSG_SEND, Buffer.from(msg), msg.length) +} + +function composeEnablePGN(pgn) { + var outBuf = Buffer.alloc(14); + let out = new BitStream(outBuf) + out.writeUint8(0x47) + out.writeUint32(pgn) + out.writeUint8(1) //enabled + + out.writeUint32(0xfffffffe) + out.writeUint32(0xfffffffe) + + let res = composeMessage(NGT_MSG_SEND, out.view.buffer.slice(0, out.byteIndex), out.byteIndex) + + //debug('composeEnablePGN: %o', res) + + return res; +} + +function composeDisablePGN(pgn) { + var outBuf = Buffer.alloc(14); + let out = new BitStream(outBuf) + out.writeUint8(0x47) + out.writeUint32(pgn) + out.writeUint8(0) //disabled + + //disbale system time + //10 02 a1 0e 47 10 10 f0 01 00 00 e8 03 00 00 00 00 00 00 1e 10 03 + + out.writeUint32(0x000003e8) //??? + out.writeUint32(0x00) + + let res = composeMessage(NGT_MSG_SEND, out.view.buffer.slice(0, out.byteIndex), out.byteIndex) + + debug('composeDisablePGN: %o', res) + + return res; +} + SerialStream.prototype.end = function () { this.serial.close() } From d80e7e84b630d60e3db9acd8d8008a5220576e07 Mon Sep 17 00:00:00 2001 From: Scott Bender Date: Thu, 13 Aug 2020 19:22:52 -0400 Subject: [PATCH 2/2] fix: check for outputAvailable incorrect --- lib/serial.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/serial.js b/lib/serial.js index 19225f2..8231fb7 100644 --- a/lib/serial.js +++ b/lib/serial.js @@ -162,7 +162,7 @@ SerialStream.prototype.start = function () { that.serial.write(buf) debug('sent startup message') setTimeout(() => { - if ( this.outAvailable == false ) { + if ( that.outAvailable === false ) { debug('retry startup message...') that.serial.write(buf) } @@ -213,7 +213,7 @@ function read1Byte(that, c) //that.push(that.buffer.slice(2, that.bufferOffset)) } else if ( that.buffer[0] == NGT_MSG_RECEIVED) { processNTGMessage(that, that.buffer, that.bufferOffset) - } + } that.bufferOffset = 0 that.stat = MSG_START; } @@ -274,7 +274,7 @@ function enableOutput(that) { function processNTGMessage(that, buffer, len) { - var checksum = 0 + var checksum = 0 for ( var i = 0; i < len; i++ ) { checksum = addUInt8(checksum, buffer[i]) @@ -343,7 +343,7 @@ function processNTGMessage(that, buffer, len) } else if ( command === 0x4b ) { debug('activated tx list') enableOutput(that) - } + } /* if (buffer.length < 12)