Skip to content

Commit

Permalink
feature: add support for Digital Yacht’s iKonvert
Browse files Browse the repository at this point in the history
  • Loading branch information
sbender9 committed Oct 19, 2018
1 parent 58d37b2 commit 09f16f9
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 25 deletions.
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ module.exports = {
toPgn: require('./lib/toPgn').toPgn,
toActisenseSerialFormat: require('./lib/toPgn').toActisenseSerialFormat,
pgnToActisenseSerialFormat: require('./lib/toPgn').pgnToActisenseSerialFormat,
canbus: require('./lib/canbus')
pgnToiKonvertSerialFormat: require('./lib/toPgn').pgnToiKonvertSerialFormat,
canbus: require('./lib/canbus'),
iKonvert: require('./lib/ikonvert')
}
19 changes: 1 addition & 18 deletions lib/candevice.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const debug = require('debug')('canboatjs:candevice')
const EventEmitter = require('events')
const _ = require('lodash')
const Uint64LE = require('int64-buffer').Uint64LE
const { getManufacturerCode, getIndustryCode, getDeviceClassCode, getCanIdFromPGN } = require('./utilities')
const { getManufacturerCode, getIndustryCode, getDeviceClassCode, getCanIdFromPGN, defaultTransmitPGNs } = require('./utilities')
const { toPgn } = require('./toPgn')

const addressClaim = {
Expand All @@ -36,23 +36,6 @@ const addressClaim = {
"Reserved2": 2
}

const defaultTransmitPGNs = [
60928,
59904,
126996,
126464,
128267,
129794,
129038,
129041,
127506,
127508,
129026,
129025,
129029,
127250,
130306
]

class CanDevice extends EventEmitter {
constructor (canbus, options) {
Expand Down
28 changes: 23 additions & 5 deletions lib/fromPgn.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ class Parser extends EventEmitter {
var split = pgn_data.split(',')

var pgn = {}
var array
var buffer
var len

if ( split[0] === '$PCDIN' ) {
// $PCDIN,01F119,00000000,0F,2AAF00D1067414FF*59
Expand All @@ -281,24 +282,41 @@ class Parser extends EventEmitter {
if ( data.indexOf('*') != -1 ) {
data = data.split('*')[0]
}
array = new Int16Array(data.length/2)
let array = new Int16Array(data.length/2)
for ( var i = 0, j = 0; i < data.length; i += 2, j++ ) {
array[j] = parseInt(data.slice(i, i+2), 16)
}
buffer = new Buffer(array)
len = data.length/2
} else if ( split[0] === '!PDGY' ) {
//iKonvert
pgn.pgn = Number(split[1])
pgn.timestamp = new Date().toISOString()
pgn.prio = Number(split[2])
pgn.src = Number(split[3])
pgn.dst = Number(split[4])

if ( split.length < 7 ) {
this.emit('warning', pgn, `ignoring pgn ${pgn_data}`)
return
}

buffer = new Buffer(split[6], 'base64')
len = buffer.length
} else {
mainFields.forEach((key, index) => {
var val = split[index]
pgn[key] = key === 'timestamp' ? val : Number(val)
})

var len = Number(split[5])
array = new Int16Array(len)
len = Number(split[5])
let array = new Int16Array(len)
for ( var i = 6; i < (len+6); i++ ) {
array[i-6] = parseInt(split[i], 16)
}
buffer = new Buffer(array)
}

var buffer = new Buffer(array)
var bv = new BitView(buffer);
var bs = new BitStream(bv)

Expand Down
123 changes: 123 additions & 0 deletions lib/ikonvert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* 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.
*/

const debug = require('debug')('canboatjs:canbus')
const Transform = require('stream').Transform
const isArray = require('lodash').isArray
const BitStream = require('bit-buffer').BitStream
const BitView = require('bit-buffer').BitView
const {toPgn, pgnToiKonvertSerialFormat} = require('./toPgn')
const Parser = require('./fromPgn').Parser
const _ = require('lodash')
const CanDevice = require('./candevice')
const spawn = require('child_process').spawn
const { getPGNFromCanId, getCanIdFromPGN, actisenseSerialToBuffer, defaultTransmitPGNs } = require('./utilities')

function iKonvertStream (options) {
if (!(this instanceof iKonvertStream)) {
return new iKonvertStream(options)
}

Transform.call(this, {
objectMode: true
})

this.plainText = false
this.reconnect = options.reconnect || true
this.options = options
this.cansend = false
this.buffer = new Buffer(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)
}
: () => {}

var that = this

if ( this.options.app ) {
options.app.on('nmea2000out', (msg) => {
that.sendPGN(msg)
})
options.app.on('nmea2000JsonOut', (msg) => {
that.sendPGN(msg)
})

//this.options.app.emit('nmea2000OutAvailable')
}
}

require('util').inherits(iKonvertStream, Transform)

iKonvertStream.prototype.start = function () {
}

iKonvertStream.prototype.sendString = function (msg) {
this.options.app.emit('ikonvertOut', msg + '\r\n')
}

iKonvertStream.prototype.sendPGN = function (pgn) {
if ( this.cansend ) {
let msg = toiKonvertSerialFormat(pgn)
this.sendString(msg)
}
}

iKonvertStream.prototype.setup = function () {
let txPgns = '$PDGY,TX_LIST'
defaultTransmitPGNs.forEach(pgn => {
txPgns = txPgns + `,${pgn}`
})
this.sendString(txPgns)
this.sendString('$PDGY,N2NET_INIT,ALL')
}

iKonvertStream.prototype._transform = function (chunk, encoding, done) {
let line = chunk.trim()

if ( line.startsWith('$PDGY') ) {
if ( line === '$PDGY,000000,,,,,,,' ) {
//the iKonvert is not initialized
this.setup()
this.setProviderStatus('Initialized')
} else if ( line.startsWith('$PDGY,000000') && !this.cansend ) {
this.cansend = true;
this.setProviderStatus('Connected')
} else if ( line.startsWith('$PDGY,NAK') ) {
let parts = line.split(',')
let msg = `iKonvert error ${parts[2]}: ${parts[3]}`
console.error(msg)
this.setProviderError(msg)
}
} else {
this.push(line)
}

done()
}

iKonvertStream.prototype.end = function () {
}

module.exports = iKonvertStream
11 changes: 10 additions & 1 deletion lib/toPgn.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,14 @@ function toActisenseSerialFormat(pgn, data, dst=255, src=0) {
);
}

function toiKonvertSerialFormat(pgn, data, dst=255) {
return `!PDGY,${pgn},${dst},${data.toString('base64')}`
}

function pgnToiKonvertSerialFormat(pgn) {
return toiKonvertSerialFormat(pgn.pgn, toPgn(pgn), pgn.dst)
}

fieldTypeWriters['ASCII text'] = (field, value, bs) => {
if ( _.isUndefined(value) ) {
value = ""
Expand Down Expand Up @@ -378,4 +386,5 @@ fieldTypeMappers['Pressure'] = (field, value) => {
module.exports.canboat2Buffer = canboat2Buffer
module.exports.toPgn = toPgn
module.exports.toActisenseSerialFormat = toActisenseSerialFormat

module.exports.toiKonvertSerialFormat = toiKonvertSerialFormat
module.exports.pgnToiKonvertSerialFormat = pgnToiKonvertSerialFormat
19 changes: 19 additions & 0 deletions lib/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,24 @@ function getDeviceClassName(code) {
return deviceClassCodes[code]
}

const defaultTransmitPGNs = [
60928,
59904,
126996,
126464,
128267,
129794,
129038,
129041,
127506,
127508,
129026,
129025,
129029,
127250,
130306
]

module.exports.getCanIdFromPGN = getCanIdFromPGN
module.exports.getPGNFromCanId = getPGNFromCanId
module.exports.actisenseSerialToBuffer = actisenseSerialToBuffer
Expand All @@ -266,3 +284,4 @@ module.exports.getIndustryCode = getIndustryCode
module.exports.getManufacturerCode = getManufacturerCode
module.exports.getDeviceClassName = getDeviceClassName
module.exports.getDeviceClassCode = getDeviceClassCode
module.exports.defaultTransmitPGNs = defaultTransmitPGNs
81 changes: 81 additions & 0 deletions test/ikonvert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
debugger

const chai = require('chai')
chai.Should()
chai.use(require('chai-things'))
chai.use(require('chai-json-equal'));

const { FromPgn, pgnToiKonvertSerialFormat } = require('../index')

const pgns = [
{
pdgy: '!PDGY,126992,3,2,255,0.563,d2009e45b3b8821d',
expected: {
"pgn":126992,
"src":2,
"dst":255,
"prio":3,
"fields":{
"Date": "2141.11.12",
"Reserved1": "6",
"SID": 119,
"Source": 13,
"Time": "55:11:40.08140"
},
"description":"System Time"
}
},
{
pdgy: '!PDGY,126996,6,0,255,4.19,3408276e4e4d4541203230303020504320496e7465726661636520284e47542d3129ffff312e3130302c20322e353630ffffffffffffffffffffffffffffffffffffffff4e47542d312d55534220206876312e3033ffffffffffffffffffffffffffffff313734323836ffffffffffffffffffffffffffffffffffffffffffffffffffff0201',
expected: {
pgn: 126996,
src: 0,
dst: 255,
prio: 6,
description: "Product Information"
}
}
]

const output = '!PDGY,126992,255,d2009e45b3Y='

describe('to ikconnect data converts', function () {
it(`to 126992 converts`, function (done) {
let msg = pgnToiKonvertSerialFormat(pgns[0].expected)
msg.should.equal(output)
done()
})
})

describe('from ikconnect data converts', function () {

pgns.forEach(info => {
it(`from ${info.expected.pgn} converts`, function (done) {

var fromPgn = new FromPgn()

fromPgn.on('error', (pgn, error) => {
console.error(`Error parsing ${pgn.pgn} ${error}`)
console.error(error.stack)
done(error)
})

fromPgn.on('warning', (pgn, warning) => {
done(new Error(`${pgn.pgn} ${warning}`))
})

fromPgn.on('pgn', (pgn) => {
try {
//console.log(JSON.stringify(pgn))
info.expected.timestamp = pgn.timestamp
pgn.should.jsonEqual(info.expected)
done()
} catch ( e ) {
done(e)
}
})

fromPgn.parseString(info.pdgy)
})
})
})

0 comments on commit 09f16f9

Please sign in to comment.