@canboat/canboatjs
Version:
Native javascript version of canboat
120 lines (104 loc) • 3.31 kB
JavaScript
const CanDevice = require('./candevice')
const debug = require('debug')('canboatjs:simpleCan')
const { encodeCanId, parseCanId } = require('./canId')
const { toActisenseSerialFormat, parseActisense } = require('./stringMsg')
const { toPgn } = require('./toPgn')
const { getPlainPGNs } = require('./utilities')
const _ = require('lodash')
function SimpleCan (options, messageCb) {
this.options = options
this.messageCb = messageCb
this.plainText = false
this.socketcan = require('socketcan')
}
SimpleCan.prototype.start = function () {
const canDevice = this.options.canDevice || 'can0'
this.channel = this.socketcan.createRawChannel(canDevice);
if ( this.messageCb ) {
this.channel.addListener('onMessage', (msg) => {
var pgn = parseCanId(msg.id)
if ( this.candevice && this.candevice.cansend && pgn.src == this.candevice.address ) {
return
}
pgn.timestamp = new Date().toISOString()
if ( this.plainText ) {
this.messageCb(binToActisense(pgn, msg.data, msg.data.length))
} else {
this.messageCb({ pgn, length: msg.data.length, data: msg.data })
}
})
}
this.channel.start()
this.candevice = new CanDevice(this,
{...this.options,
disableDefaultTransmitPGNs: true,
disableNAKs: true
},
)
this.candevice.start()
}
SimpleCan.prototype.sendPGN = function (msg) {
if ( this.candevice ) {
if ( !this.candevice.cansend && msg.pgn !== 59904 && msg.pgn !== 60928 && msg.pgn !== 126996 ) {
debug('ignoring %j', msg)
return
}
debug('sending %j', msg)
let src = msg.pgn === 59904 || msg.forceSrc ? msg.src : this.candevice.address
if ( _.isString(msg) ) {
var split = msg.split(',')
split[3] = src
msg = split.join(',')
} else {
msg.src = src
if ( _.isUndefined(msg.prio) ) {
msg.prio = 3
}
if ( _.isUndefined(msg.dst) ) {
msg.dst = 255
}
}
var canid
var buffer
var pgn
if ( _.isObject(msg) ) {
canid = encodeCanId(msg)
buffer = toPgn(msg)
pgn = msg
} else {
pgn = parseActisense(msg)
canid = encodeCanId(pgn)
buffer = pgn.data
}
if ( debug.enabled ) {
var str = toActisenseSerialFormat(pgn.pgn, buffer, pgn.dst, pgn.src)
debug(str)
}
//seems as though 126720 should always be encoded this way
if ( buffer.length > 8 || pgn.pgn == 126720 ) {
var pgns = getPlainPGNs(buffer)
pgns.forEach(pbuffer => {
this.channel.send({id: canid, ext:true, data: pbuffer})
})
} else {
this.channel.send({id: canid, ext:true, data: buffer})
}
}
}
SimpleCan.prototype.sendActisenseFormat = function (msg) {
this.sendPGN(msg)
}
function binToActisense(pgn, data, length) {
return (
pgn.timestamp +
`,${pgn.prio},${pgn.pgn},${pgn.src},${pgn.dst},${length},` +
new Uint32Array(data)
.reduce(function(acc, i) {
acc.push(i.toString(16));
return acc;
}, [])
.map(x => (x.length === 1 ? "0" + x : x))
.join(",")
);
}
module.exports = SimpleCan