Comparing version 2.7.2 to 2.8.0
@@ -8,3 +8,3 @@ { | ||
"description": "A SocketCAN abstraction layer for NodeJS.", | ||
"version": "2.7.2", | ||
"version": "2.8.0", | ||
"license": "MIT", | ||
@@ -18,5 +18,7 @@ "repository": { | ||
"build": "node-gyp build", | ||
"test": "NODE_PATH=. nodeunit tests" | ||
"test": "mocha" | ||
}, | ||
"devDependencies": { | ||
"mocha": "^7.1.1", | ||
"nyc": "^15.0.1", | ||
"node-gyp": ">=1.0.0" | ||
@@ -23,0 +25,0 @@ }, |
335
parse_kcd.js
@@ -26,220 +26,209 @@ /* Copyright Sebastian Haas <sebastian$sebastianhaas.info>. All rights reserved. | ||
//----------------------------------------------------------------------------- | ||
function get_signal_from_xml(signal, value, labelset) { | ||
var _s = { | ||
name: signal.name, | ||
bitLength: signal.length ? parseInt(signal.length) : 1, | ||
endianess: signal.endianess ? signal.endianess : 'little', | ||
spn : signal.spn, | ||
labels : {}, | ||
} | ||
exports.parseKcdFile = function(file) { | ||
var result = {}; // Result will be a dictionary describing the whole network | ||
// add Values from the database | ||
if (Array.isArray(value)) { | ||
_s.slope = value[0]['$'].slope ? parseFloat(value[0]['$'].slope) : 1.0; | ||
_s.intercept = value[0]['$'].intercept ? parseFloat(value[0]['$'].intercept) : 0.0; | ||
_s.unit = value[0]['$'].unit ? value[0]['$'].unit : ""; | ||
_s.minValue = value[0]['$'].min ? value[0]['$'].min : undefined; | ||
_s.maxValue = value[0]['$'].max ? value[0]['$'].max : undefined; | ||
_s.type = value[0]['$'].type ? value[0]['$'].type : "unsigned"; | ||
_s.defaultValue = value[0]['$'].defaultValue ? parseFloat(value[0]['$'].defaultValue) : 0.0 ; | ||
} | ||
var data = fs.readFileSync(file); | ||
// add label sets from the database. | ||
if (Array.isArray(labelset)) { | ||
var labels = labelset[0]['Label']; | ||
if (labels != undefined) { | ||
for ( var i = 0 ; i < labels.length; i++ ) { | ||
_s.labels[labels[i]['$'].value] = labels[i]['$'].name; | ||
} | ||
} | ||
} | ||
var parser = new xml2js.Parser({explicitArray: true}); | ||
_s.bitOffset = parseInt(signal.offset); | ||
parser.parseString(data, function(e, i) { | ||
result.nodes = {}; | ||
return _s | ||
} | ||
var d = i['NetworkDefinition']; | ||
exports.parseKcdFile = function(file) { | ||
var result = {}; // Result will be a dictionary describing the whole network | ||
for (n in d['Node']) { | ||
var node = d['Node'][n]['$']; | ||
var data = fs.readFileSync(file); | ||
result.nodes[node['id']] = {}; | ||
result.nodes[node['id']].name = node['name']; | ||
result.nodes[node['id']].buses = {}; | ||
result.nodes[node['id']].device = node['device']; | ||
result.nodes[node['id']].J1939 = { | ||
'AAC' : node['J1939AAC'], | ||
'Function' : node['J1939Function'], | ||
'Vehicle' : node['J1939Vehicle'], | ||
'Identity' : node['J1939IdentityNumber'], | ||
'Industry' : node['J1939IndustryGroup'], | ||
'System' : node['J1939System'], | ||
'Manufacture': node['J1939ManufacturerCode'], | ||
getName : function(){ | ||
var name = Buffer.alloc(8); | ||
name[7] = ((this.AAC & 0x1) << 7) | ((this.Industry & 0x7) << 4) | (this.Vehicle & 0xF); | ||
name[6] = (this.System) << 1 & 0xFE; | ||
name[5] = this.Function & 0xFF; | ||
name[4] = 0; // function Instance & ECU instance | ||
name[3] = (this.Manufacture >> 3) & 0xFF ; | ||
name[2] = ((this.Manufacture & 0x7) << 5) | ( (this.Identity >> 16) & 0x1F ); | ||
name[1] = (this.Identity >> 8 ) & 0xFF; | ||
name[0] = this.Identity & 0xFF; | ||
var parser = new xml2js.Parser({explicitArray: true}); | ||
return name; | ||
}, | ||
} | ||
parser.parseString(data, function(e, i) { | ||
result.nodes = {}; | ||
var d = i['NetworkDefinition']; | ||
} | ||
for (n in d['Node']) { | ||
var node = d['Node'][n]['$']; | ||
result.buses = {}; | ||
for (b in d['Bus']) { | ||
var bus = d['Bus'][b]['$']; | ||
result.nodes[node['id']] = {}; | ||
result.nodes[node['id']].name = node['name']; | ||
result.nodes[node['id']].buses = {}; | ||
result.nodes[node['id']].device = node['device']; | ||
result.nodes[node['id']].J1939 = { | ||
'AAC' : node['J1939AAC'], | ||
'Function' : node['J1939Function'], | ||
'Vehicle' : node['J1939Vehicle'], | ||
'Identity' : node['J1939IdentityNumber'], | ||
'Industry' : node['J1939IndustryGroup'], | ||
'System' : node['J1939System'], | ||
'Manufacture': node['J1939ManufacturerCode'], | ||
getName: function() { | ||
var name = Buffer.alloc(8); | ||
name[7] = ((this.AAC & 0x1) << 7) | ((this.Industry & 0x7) << 4) | (this.Vehicle & 0xF); | ||
name[6] = (this.System) << 1 & 0xFE; | ||
name[5] = this.Function & 0xFF; | ||
name[4] = 0; // function Instance & ECU instance | ||
name[3] = (this.Manufacture >> 3) & 0xFF ; | ||
name[2] = ((this.Manufacture & 0x7) << 5) | ( (this.Identity >> 16) & 0x1F ); | ||
name[1] = (this.Identity >> 8 ) & 0xFF; | ||
name[0] = this.Identity & 0xFF; | ||
result.buses[bus['name']] = {}; | ||
var new_bus = result.buses[bus['name']]; | ||
return name; | ||
}, | ||
} | ||
} | ||
new_bus['messages'] = []; | ||
for (m in d['Bus'][b]['Message']) { | ||
var message = d['Bus'][b]['Message'][m]['$']; | ||
var producers = d['Bus'][b]['Message'][m]['Producer']; | ||
result.buses = {}; | ||
for (b in d['Bus']) { | ||
var bus = d['Bus'][b]['$']; | ||
var multiplex = d['Bus'][b]['Message'][m]['Multiplex']; | ||
result.buses[bus['name']] = {}; | ||
var new_bus = result.buses[bus['name']]; | ||
var _m = { | ||
name: message.name, | ||
id: parseInt(message.id, 16), | ||
ext: message.format == 'extended', | ||
triggered: message.triggered == 'true', | ||
length: message.length ? parseInt(message.length) : 0, | ||
interval: message.interval ? parseInt(message.interval) : 0, | ||
muxed : (multiplex != undefined ), | ||
}; | ||
new_bus['messages'] = []; | ||
for (m in d['Bus'][b]['Message']) { | ||
var message = d['Bus'][b]['Message'][m]['$']; | ||
var producers = d['Bus'][b]['Message'][m]['Producer']; | ||
// Add messages going out and from whom. | ||
for (p in producers) { | ||
for (n in producers[p]['NodeRef']) { | ||
var id = producers[p]['NodeRef'][n]['$']['id']; | ||
var multiplex = d['Bus'][b]['Message'][m]['Multiplex']; | ||
if (result.nodes[id]) | ||
{ | ||
if (result.nodes[id].buses[bus['name']] == undefined) | ||
result.nodes[id].buses[bus['name']] = { produces: [], consumes: []} | ||
var _m = { | ||
name: message.name, | ||
id: parseInt(message.id, 16), | ||
ext: message.format == 'extended', | ||
triggered: message.triggered == 'true', | ||
length: message.length ? parseInt(message.length) : 0, | ||
interval: message.interval ? parseInt(message.interval) : 0, | ||
muxed: (multiplex != undefined), | ||
mux: undefined | ||
}; | ||
result.nodes[id].buses[bus['name']].produces.push(_m.id); | ||
} | ||
} | ||
} | ||
// Add messages going out and from whom. | ||
for (p in producers) { | ||
for (n in producers[p]['NodeRef']) { | ||
var id = producers[p]['NodeRef'][n]['$']['id']; | ||
if (!_m.interval) | ||
_m.interval = 0; | ||
if (result.nodes[id]) | ||
{ | ||
if (result.nodes[id].buses[bus['name']] == undefined) | ||
result.nodes[id].buses[bus['name']] = { produces: [], consumes: []} | ||
new_bus['messages'].push(_m); | ||
result.nodes[id].buses[bus['name']].produces.push(_m.id); | ||
} | ||
} | ||
} | ||
_m.signals = []; | ||
if (!_m.interval) | ||
_m.interval = 0; | ||
var maxOffset = 0; | ||
new_bus['messages'].push(_m); | ||
// look for multiplexed messages | ||
for (mux in multiplex){ | ||
for (mg in multiplex[mux]['MuxGroup']){ | ||
var muxmsg = multiplex[mux]['MuxGroup'][mg]['$']; | ||
_m.signals = []; | ||
for (s in multiplex[mux]['MuxGroup'][mg]['Signal']) { | ||
var signal = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['$']; | ||
var value = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['Value']; | ||
var labelset = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['LabelSet']; | ||
var maxOffset = 0; | ||
var _s = { | ||
name: signal.name, | ||
mux : parseInt(muxmsg['count']), | ||
bitLength: signal.length ? parseInt(signal.length) : 1, | ||
endianess: signal.endianess ? signal.endianess : 'little', | ||
spn : signal.spn, | ||
labels : {}, | ||
}; | ||
// add Values from the database | ||
if (Array.isArray(value)) { | ||
_s.slope = value[0]['$'].slope ? parseFloat(value[0]['$'].slope) : 1.0; | ||
_s.intercept = value[0]['$'].intercept ? parseFloat(value[0]['$'].intercept) : 0.0; | ||
_s.unit = value[0]['$'].unit ? value[0]['$'].unit : ""; | ||
_s.minValue = value[0]['$'].min ? value[0]['$'].min : undefined; | ||
_s.maxValue = value[0]['$'].max ? value[0]['$'].max : undefined; | ||
_s.type = value[0]['$'].type ? value[0]['$'].type : "unsigned"; | ||
_s.defaultValue = value[0]['$'].defaultValue ? parseFloat(value[0]['$'].defaultValue) : 0.0 ; | ||
} | ||
// look for multiplexed messages | ||
for (mux in multiplex) { | ||
_m.mux = { | ||
name: multiplex[mux]['$']['name'], | ||
offset: parseInt(multiplex[mux]['$']['offset']), | ||
length: parseInt(multiplex[mux]['$']['length']) | ||
} | ||
// add label sets from the database. | ||
if (Array.isArray(labelset)) { | ||
var labels = labelset[0]['Label']; | ||
if (labels != undefined) { | ||
for ( var i = 0 ; i < labels.length; i++ ) { | ||
_s.labels[labels[i]['$'].value] = labels[i]['$'].name; | ||
} | ||
} | ||
} | ||
for (mg in multiplex[mux]['MuxGroup']) { | ||
var muxmsg = multiplex[mux]['MuxGroup'][mg]['$']; | ||
var offset_num = parseInt(signal.offset) + _s.bitLength; | ||
for (s in multiplex[mux]['MuxGroup'][mg]['Signal']) { | ||
var signal = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['$']; | ||
var value = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['Value']; | ||
var labelset = multiplex[mux]['MuxGroup'][mg]['Signal'][s]['LabelSet']; | ||
if (offset_num > maxOffset) | ||
maxOffset = offset_num; | ||
var _s = get_signal_from_xml(signal, value, labelset) | ||
_s.bitOffset = parseInt(signal.offset); | ||
// Added multiplexor | ||
_s.mux = parseInt(muxmsg['count']) | ||
_m.signals.push(_s); | ||
} | ||
} | ||
_m.signals.push(_s); | ||
} | ||
var offset_num = _s.bitOffset + _s.bitLength; | ||
for (s in d['Bus'][b]['Message'][m]['Signal']) { | ||
var signal = d['Bus'][b]['Message'][m]['Signal'][s]['$']; | ||
var value = d['Bus'][b]['Message'][m]['Signal'][s]['Value']; | ||
var labelset = d['Bus'][b]['Message'][m]['Signal'][s]['LabelSet']; | ||
var consumers = d['Bus'][b]['Message'][m]['Signal'][s]['Consumer']; | ||
if (offset_num > maxOffset) | ||
maxOffset = offset_num; | ||
} | ||
} | ||
var _s = { | ||
name: signal.name, | ||
bitLength: signal.length ? parseInt(signal.length) : 1, | ||
endianess: signal.endianess ? signal.endianess : 'little', | ||
spn : signal.spn, | ||
labels : {}, | ||
}; | ||
// only one muxer supported right now | ||
break | ||
} | ||
// add Values from the database | ||
if (Array.isArray(value)) { | ||
_s.slope = value[0]['$'].slope ? parseFloat(value[0]['$'].slope) : 1.0; | ||
_s.intercept = value[0]['$'].intercept ? parseFloat(value[0]['$'].intercept) : 0.0; | ||
_s.unit = value[0]['$'].unit ? value[0]['$'].unit : ""; | ||
_s.minValue = value[0]['$'].min ? value[0]['$'].min : undefined; | ||
_s.maxValue = value[0]['$'].max ? value[0]['$'].max : undefined; | ||
_s.type = value[0]['$'].type ? value[0]['$'].type : "unsigned"; | ||
_s.defaultValue = value[0]['$'].defaultValue ? parseFloat(value[0]['$'].defaultValue) : 0.0 ; | ||
} | ||
for (s in d['Bus'][b]['Message'][m]['Signal']) { | ||
var signal = d['Bus'][b]['Message'][m]['Signal'][s]['$']; | ||
var value = d['Bus'][b]['Message'][m]['Signal'][s]['Value']; | ||
var labelset = d['Bus'][b]['Message'][m]['Signal'][s]['LabelSet']; | ||
var consumers = d['Bus'][b]['Message'][m]['Signal'][s]['Consumer']; | ||
// add label sets from the database. | ||
if (Array.isArray(labelset)) { | ||
var labels = labelset[0]['Label']; | ||
if (labels != undefined) { | ||
for ( var i = 0 ; i < labels.length; i++ ) { | ||
_s.labels[labels[i]['$'].value] = labels[i]['$'].name; | ||
} | ||
} | ||
} | ||
var _s = get_signal_from_xml(signal, value, labelset) | ||
// Add listeners / targets for the message. | ||
for (c in consumers) { | ||
for (n in consumers[c]['NodeRef']) { | ||
var id = consumers[c]['NodeRef'][n]['$']['id']; | ||
// Add listeners / targets for the message. | ||
for (c in consumers) { | ||
for (n in consumers[c]['NodeRef']) { | ||
var id = consumers[c]['NodeRef'][n]['$']['id']; | ||
if (result.nodes[id]) | ||
{ | ||
if (result.nodes[id].buses[bus['name']] == undefined) | ||
result.nodes[id].buses[bus['name']] = { produces: [], consumes: []} | ||
if (result.nodes[id]) | ||
{ | ||
if (result.nodes[id].buses[bus['name']] == undefined) | ||
result.nodes[id].buses[bus['name']] = { produces: [], consumes: []} | ||
result.nodes[id].buses[bus['name']].consumes.push({ id: _m.id, signal_name: _s.name }); | ||
} | ||
} | ||
} | ||
result.nodes[id].buses[bus['name']].consumes.push({ id: _m.id, signal_name: _s.name }); | ||
} | ||
} | ||
} | ||
var offset_num = parseInt(signal.offset) + _s.bitLength; | ||
_m.signals.push(_s); | ||
if (offset_num > maxOffset) | ||
maxOffset = offset_num; | ||
var offset_num = _s.bitOffset + _s.bitLength; | ||
_s.bitOffset = parseInt(signal.offset); | ||
if (offset_num > maxOffset) | ||
maxOffset = offset_num; | ||
} | ||
_m.signals.push(_s); | ||
} | ||
// Calculate length based on define signals | ||
if (!_m.length) { | ||
_m.length = parseInt(maxOffset / 8); | ||
if (!_m.length) { | ||
_m.length = parseInt(maxOffset / 8); | ||
if (maxOffset % 8 > 0) | ||
_m.length++; | ||
} | ||
} | ||
} | ||
}); | ||
if (maxOffset % 8 > 0) | ||
_m.length++; | ||
} | ||
} | ||
} | ||
}); | ||
// NOTE: Not sure if it is safe here to access result, but I guess parsing the XML file is more or less synchronous. | ||
// NOTE: Not sure if it is safe here to access result, but I guess parsing the XML file is more or less synchronous. | ||
return result; | ||
return result; | ||
} |
424
socketcan.js
@@ -38,3 +38,3 @@ /* Copyright Sebastian Haas <sebastian@sebastianhaas.info>. All rights reserved. | ||
{ | ||
return new can.RawChannel(channel, timestamps, protocol, false); | ||
return new can.RawChannel(channel, timestamps, protocol, false); | ||
} | ||
@@ -51,9 +51,9 @@ | ||
{ | ||
if (options === undefined) options = {} | ||
if (options === undefined) options = {} | ||
if (options.timestamps === undefined) options.timestamps = false; | ||
if (options.protocol === undefined) options.protocol = 1; /* CAN RAW */ | ||
if (options.non_block_send === undefined) options.non_block_send = false; | ||
if (options.timestamps === undefined) options.timestamps = false; | ||
if (options.protocol === undefined) options.protocol = 1; /* CAN RAW */ | ||
if (options.non_block_send === undefined) options.non_block_send = false; | ||
return new can.RawChannel(channel, options.timestamps, options.protocol, options.non_block_send); | ||
return new can.RawChannel(channel, options.timestamps, options.protocol, options.non_block_send); | ||
} | ||
@@ -78,43 +78,43 @@ | ||
{ | ||
/** | ||
* Symbolic name | ||
* @attribute name | ||
* @final | ||
*/ | ||
this.name = desc['name']; | ||
this.spn = desc['spn']; | ||
/** | ||
* Symbolic name | ||
* @attribute name | ||
* @final | ||
*/ | ||
this.name = desc['name']; | ||
this.spn = desc['spn']; | ||
this.bitOffset = desc['bitOffset']; | ||
this.bitLength = desc['bitLength']; | ||
this.endianess = desc['endianess']; | ||
this.type = desc['type']; | ||
this.bitOffset = desc['bitOffset']; | ||
this.bitLength = desc['bitLength']; | ||
this.endianess = desc['endianess']; | ||
this.type = desc['type']; | ||
this.intercept = desc['intercept']; | ||
this.slope = desc['slope']; | ||
this.intercept = desc['intercept']; | ||
this.slope = desc['slope']; | ||
this.minValue = desc['minValue']; | ||
this.maxValue = desc['maxValue']; | ||
this.minValue = desc['minValue']; | ||
this.maxValue = desc['maxValue']; | ||
this.unit = desc['unit']; | ||
this.unit = desc['unit']; | ||
/** | ||
* Label set for defined states of the signal. | ||
*/ | ||
this.labels = desc['labels']; | ||
/** | ||
* Label set for defined states of the signal. | ||
*/ | ||
this.labels = desc['labels']; | ||
/** | ||
* this will allow triggering on mux'ed message ids. | ||
*/ | ||
this.muxGroup = [ desc['mux'] ]; | ||
/** | ||
* this will allow triggering on mux'ed message ids. | ||
*/ | ||
this.muxGroup = [ desc['mux'] ]; | ||
/** | ||
* Current value | ||
* | ||
* @attribute value | ||
* @final | ||
*/ | ||
this.value = null; | ||
/** | ||
* Current value | ||
* | ||
* @attribute value | ||
* @final | ||
*/ | ||
this.value = null; | ||
this.changelisteners = []; | ||
this.updateListeners = []; | ||
this.changelisteners = []; | ||
this.updateListeners = []; | ||
} | ||
@@ -129,4 +129,4 @@ | ||
Signal.prototype.onChange = function(listener) { | ||
this.changelisteners.push(listener); | ||
return listener; | ||
this.changelisteners.push(listener); | ||
return listener; | ||
} | ||
@@ -141,4 +141,4 @@ | ||
Signal.prototype.onUpdate = function(listener) { | ||
this.updateListeners.push(listener); | ||
return listener; | ||
this.updateListeners.push(listener); | ||
return listener; | ||
} | ||
@@ -153,6 +153,6 @@ | ||
Signal.prototype.removeListener = function(listener) { | ||
var idx = this.changelisteners.indexOf(listener); | ||
if (idx >= 0) this.changelisteners.splice(idx, 1); | ||
idx = this.updateListeners.indexOf(listener); | ||
if (idx >= 0) this.updateListeners.splice(idx, 1); | ||
var idx = this.changelisteners.indexOf(listener); | ||
if (idx >= 0) this.changelisteners.splice(idx, 1); | ||
idx = this.updateListeners.indexOf(listener); | ||
if (idx >= 0) this.updateListeners.splice(idx, 1); | ||
} | ||
@@ -170,23 +170,25 @@ | ||
if (newValue > this.maxValue) { | ||
console.error("ERROR : " + this.name + " value= " + newValue | ||
+ " is outof bounds > " + this.maxValue); | ||
} else if (newValue < this.minValue) { | ||
console.error("ERROR : " + this.name + " value= " + newValue | ||
+ " is outof bounds < " + this.minValue); | ||
} | ||
var changed = this.value !== newValue; | ||
this.value = newValue; | ||
// Update all updateListeners, that the signal updated | ||
for (f in this.updateListeners) { | ||
this.updateListeners[f](this); | ||
} | ||
// Nothing changed | ||
if ( ! changed) return; | ||
if (newValue > this.maxValue) { | ||
console.error("ERROR : " + this.name + " value= " + newValue | ||
+ " is outof bounds > " + this.maxValue); | ||
} else if (newValue < this.minValue) { | ||
console.error("ERROR : " + this.name + " value= " + newValue | ||
+ " is outof bounds < " + this.minValue); | ||
} | ||
// Update all changelisteners, that the signal changed | ||
for (f in this.changelisteners) { | ||
this.changelisteners[f](this); | ||
} | ||
var changed = this.value !== newValue; | ||
this.value = newValue; | ||
// Update all updateListeners, that the signal updated | ||
for (f in this.updateListeners) { | ||
this.updateListeners[f](this); | ||
} | ||
// Nothing changed | ||
if (!changed) return; | ||
// Update all changelisteners, that the signal changed | ||
for (f in this.changelisteners) { | ||
this.changelisteners[f](this); | ||
} | ||
} | ||
@@ -201,62 +203,71 @@ | ||
{ | ||
/** | ||
* CAN identifier | ||
* @attribute id | ||
* @final | ||
*/ | ||
this.id = desc.id; | ||
/** | ||
* CAN identifier | ||
* @attribute id | ||
* @final | ||
*/ | ||
this.id = desc.id; | ||
/** | ||
* Extended Frame Format used | ||
* @attribute ext | ||
* @final | ||
*/ | ||
this.ext = desc.ext; | ||
/** | ||
* Extended Frame Format used | ||
* @attribute ext | ||
* @final | ||
*/ | ||
this.ext = desc.ext; | ||
/** | ||
* Symbolic name | ||
* @attribute name | ||
* @final | ||
*/ | ||
this.name = desc.name; | ||
/** | ||
* Symbolic name | ||
* @attribute name | ||
* @final | ||
*/ | ||
this.name = desc.name; | ||
/** | ||
* Length in bytes of resulting CAN message | ||
* | ||
* @attribute len | ||
* @final | ||
*/ | ||
this.len = desc.length; | ||
/** | ||
* Length in bytes of resulting CAN message | ||
* | ||
* @attribute len | ||
* @final | ||
*/ | ||
this.len = desc.length; | ||
/** | ||
* This is the time frame that the message gets generated | ||
* | ||
* @attribute interval | ||
* @final | ||
*/ | ||
this.interval = desc.interval; | ||
/** | ||
* This is the time frame that the message gets generated | ||
* | ||
* @attribute interval | ||
* @final | ||
*/ | ||
this.interval = desc.interval; | ||
/** | ||
* This is tells us the message is mutliplexed. | ||
* | ||
* @attribute muxed | ||
* @final | ||
*/ | ||
this.muxed = desc.muxed; | ||
/** | ||
* This tells us the message is mutliplexed. | ||
* | ||
* @attribute muxed | ||
* @final | ||
*/ | ||
this.muxed = desc.muxed; | ||
/** | ||
* Named array of signals within this message. Accessible via index and name. | ||
* @attribute {Signal} signals | ||
* @final | ||
*/ | ||
this.signals = []; | ||
/** | ||
* Multiplexor parameter (just one supported right now). | ||
* | ||
* @attribute mux | ||
* @final | ||
*/ | ||
this.mux = desc.mux; | ||
for (i in desc['signals']) { | ||
var s = desc['signals'][i]; | ||
if (this.signals[s.name] && this.signals[s.name].muxGroup) { | ||
this.signals[s.name].muxGroup.push(s.mux); | ||
} else { | ||
this.signals[s.name] = new Signal(s); | ||
} | ||
} | ||
/** | ||
* Named array of signals within this message. Accessible via index and name. | ||
* @attribute {Signal} signals | ||
* @final | ||
*/ | ||
this.signals = []; | ||
for (i in desc['signals']) { | ||
var s = desc['signals'][i]; | ||
if (this.signals[s.name] && this.signals[s.name].muxGroup) { | ||
this.signals[s.name].muxGroup.push(s.mux); | ||
} else { | ||
this.signals[s.name] = new Signal(s); | ||
} | ||
} | ||
} | ||
@@ -276,21 +287,21 @@ | ||
function DatabaseService(channel, db_desc) { | ||
this.channel = channel; | ||
this.channel = channel; | ||
/** | ||
* Named array of known messages. Accessible via index and name. | ||
* @attribute {Message} messages | ||
*/ | ||
this.messages = []; | ||
/** | ||
* Named array of known messages. Accessible via index and name. | ||
* @attribute {Message} messages | ||
*/ | ||
this.messages = []; | ||
for (i in db_desc['messages']) { | ||
var m = db_desc['messages'][i]; | ||
var id = m.id | (m.ext ? 1 : 0) << 31; | ||
for (i in db_desc['messages']) { | ||
var m = db_desc['messages'][i]; | ||
var id = m.id | (m.ext ? 1 : 0) << 31; | ||
var nm = new Message(m); | ||
this.messages[id] = nm; | ||
this.messages[m.name] = nm; | ||
} | ||
var nm = new Message(m); | ||
this.messages[id] = nm; | ||
this.messages[m.name] = nm; | ||
} | ||
// Subscribe to any incoming messages | ||
channel.addListener("onMessage", this.onMessage, this); | ||
// Subscribe to any incoming messages | ||
channel.addListener("onMessage", this.onMessage, this); | ||
} | ||
@@ -300,44 +311,47 @@ | ||
DatabaseService.prototype.onMessage = function (msg) { | ||
if (msg == undefined) | ||
return; | ||
if (msg.rtr) | ||
return; | ||
if (msg == undefined) | ||
return; | ||
id = msg.id | (msg.ext ? 1 : 0) << 31; | ||
// RTR (Remote-Transmit-Request) dont have payload | ||
if (msg.rtr) | ||
return; | ||
var m = this.messages[id]; | ||
id = msg.id | (msg.ext ? 1 : 0) << 31; | ||
if (!m) | ||
{ | ||
return; | ||
} | ||
var m = this.messages[id]; | ||
// this is the possible multiplexor for the signals coming in. | ||
var b1mux = _signals.decode_signal(msg.data, 0, 8, true, false); | ||
if (!m) { | ||
return; | ||
} | ||
// Let the C-Portition extract and convert the signal | ||
for (i in m.signals) { | ||
var s = m.signals[i]; | ||
if (m.muxed) { | ||
b_mux = _signals.decode_signal(msg.data, m.mux.offset, m.mux.length, true, false); | ||
var mux_count = b_mux[0] + (b_mux[1] << 32) | ||
} | ||
if (s.value === undefined) | ||
continue; | ||
// Let the C-Portition extract and convert the signal | ||
for (i in m.signals) { | ||
var s = m.signals[i]; | ||
// if this is a mux signal and the muxor isnt in my list... | ||
if (m.muxed && s.muxGroup && s.muxGroup.indexOf(b1mux[0]) == -1) { | ||
continue; | ||
} | ||
if (s.value === undefined) | ||
continue; | ||
var ret = _signals.decode_signal(msg.data, s.bitOffset, s.bitLength, | ||
s.endianess == 'little', s.type == 'signed'); | ||
// if this is a mux signal and the muxor isnt in my list... | ||
if (m.muxed && s.muxGroup.indexOf(mux_count) == -1) { | ||
continue; | ||
} | ||
var val = ret[0] + (ret[1] << 32) | ||
var ret = _signals.decode_signal(msg.data, s.bitOffset, s.bitLength, | ||
s.endianess == 'little', s.type == 'signed'); | ||
if (s.slope) | ||
val *= s.slope; | ||
var val = ret[0] + (ret[1] << 32) | ||
if (s.intercept) | ||
val += s.intercept; | ||
if (s.slope) | ||
val *= s.slope; | ||
s.update(val); | ||
} | ||
if (s.intercept) | ||
val += s.intercept; | ||
s.update(val); | ||
} | ||
} | ||
@@ -349,57 +363,57 @@ | ||
* @method send | ||
* @param msg_name Name of the message to generate | ||
* @param msg_name Name of the message to generate (indicate mux by append .MUX_VALUE in hex) | ||
* @for DatabaseService | ||
*/ | ||
DatabaseService.prototype.send = function (msg_name) { | ||
var args = msg_name.split("."); // allow for mux'ed messages sent. | ||
var args = msg_name.split("."); // allow for mux'ed messages sent. | ||
var m = this.messages[args[0]]; | ||
var mux = (args.length > 1) ? args[1] : undefined; | ||
var m = this.messages[args[0]]; | ||
var mux = (args.length > 1) ? args[1] : undefined; | ||
if (!m) | ||
throw msg_name + " not defined"; | ||
if (!m) | ||
throw msg_name + " not defined"; | ||
var canmsg = { | ||
id: m.id, | ||
ext: m.ext, | ||
rtr: false, | ||
data : (m.len > 0 && m.len < 8) ? Buffer.alloc(m.len) : Buffer.alloc(8) | ||
}; | ||
var canmsg = { | ||
id: m.id, | ||
ext: m.ext, | ||
rtr: false, | ||
data : (m.len > 0 && m.len < 8) ? Buffer.alloc(m.len) : Buffer.alloc(8) | ||
}; | ||
canmsg.data.fill(0); // should be 0xFF for j1939 message def. | ||
canmsg.data.fill(0); // should be 0xFF for j1939 message def. | ||
if (mux) | ||
_signals.encode_signal(canmsg.data, m.mux.offset, m.mux.length, true, false, parseInt(mux, 16)) | ||
if (mux) { | ||
_signals.encode_signal(canmsg.data, 0, 8, true, false, | ||
parseInt(mux, 16)); | ||
} | ||
for (i in m.signals) { | ||
var s = m.signals[i]; | ||
if (s.value == undefined) | ||
continue; | ||
for (i in m.signals) { | ||
var s = m.signals[i]; | ||
if (mux) { | ||
if (s.muxGroup.indexOf(parseInt(mux, 16)) === -1) { | ||
continue; | ||
} | ||
} | ||
if (s.value == undefined) | ||
continue; | ||
var val = s.value; | ||
if (mux) { | ||
if (s.muxGroup.indexOf(parseInt(mux, 16)) === -1) { | ||
continue; | ||
} | ||
} | ||
// Apply factor/intercept and convert to Integer | ||
if (s.intercept) | ||
val -= s.intercept; | ||
var val = s.value; | ||
if (s.slope) | ||
val /= s.slope; | ||
// Apply factor/intercept and convert to Integer | ||
if (s.intercept) | ||
val -= s.intercept; | ||
if (typeof(val) == 'double') | ||
val = parseInt(Math.round(val)); | ||
if (s.slope) | ||
val /= s.slope; | ||
if (m.len == 0) { | ||
return; | ||
} | ||
if (typeof(val) == 'double') | ||
val = parseInt(Math.round(val)); | ||
if (m.len == 0) { | ||
return; | ||
} | ||
var word1 = val & 0xFFFFFFFF | ||
var word2 = 0 | ||
// shift doesn't work above 32 bit, only do this if required to save cycles | ||
@@ -409,7 +423,7 @@ if (val > 0xFFFFFFFF) | ||
_signals.encode_signal(canmsg.data, s.bitOffset, s.bitLength, | ||
_signals.encode_signal(canmsg.data, s.bitOffset, s.bitLength, | ||
s.endianess == 'little', s.type == 'signed', word1, word2 ); | ||
} | ||
} | ||
this.channel.send(canmsg); | ||
this.channel.send(canmsg); | ||
} | ||
@@ -416,0 +430,0 @@ |
@@ -8,4 +8,4 @@ Testing node-can | ||
----- | ||
1. sh prepare_test_env.sh # Create vcan-device for testing | ||
2. npm install -g nodeunit # Install nodeunit binaries | ||
1. npm install | ||
2. sh prepare_test_env.sh # Create vcan-device for testing | ||
@@ -16,2 +16,2 @@ | ||
Just execute: NODE_PATH=. nodeunit tests | ||
Just execute: npm test |
Sorry, the diff of this file is not supported yet
259223
52
2518
3