cabana/src/utils/dbc.js

181 lines
4.1 KiB
JavaScript

function findMaxByteStateChangeCount(messages) {
return Object.values(messages)
.map((m) => m.byteStateChangeCounts)
.reduce((counts, countArr) => counts.concat(countArr), []) // flatten arrays
.reduce((count1, count2) => (count1 > count2 ? count1 : count2), 0); // find max
}
function addCanMessage(
canMessage,
dbc,
canStartTime,
messages,
prevMsgEntries,
byteStateChangeCountsByMessage
) {
const {
address, busTime, data, bus
} = canMessage;
const id = `${bus}:${address.toString(16)}`;
if (messages[id] === undefined) messages[id] = createMessageSpec(dbc, address, id, bus);
const prevMsgEntry = messages[id].entries.length > 0
? messages[id].entries[messages[id].entries.length - 1]
: prevMsgEntries[id] || null;
if (
byteStateChangeCountsByMessage[id]
&& messages[id].byteStateChangeCounts.every((c) => c === 0)
) {
messages[id].byteStateChangeCounts = byteStateChangeCountsByMessage[id];
}
const { msgEntry, byteStateChangeCounts } = parseMessage(
dbc,
busTime,
address,
data,
canStartTime,
prevMsgEntry
);
messages[id].byteStateChangeCounts = byteStateChangeCounts.map(
(count, idx) => messages[id].byteStateChangeCounts[idx] + count
);
messages[id].entries.push(msgEntry);
return msgEntry;
}
function createMessageSpec(dbc, address, id, bus) {
const frame = dbc.getMessageFrame(address);
const size = frame ? frame.size : 8;
return {
address,
id,
bus,
entries: [],
frame,
byteColors: Array(size).fill(0),
byteStateChangeCounts: Array(size).fill(0)
};
}
function determineByteStateChangeTimes(
hexData,
time,
msgSize,
lastParsedMessage
) {
const byteStateChangeCounts = Array(msgSize).fill(0);
let byteStateChangeTimes;
if (!lastParsedMessage) {
byteStateChangeTimes = Array(msgSize).fill(time);
} else {
byteStateChangeTimes = Array.from(lastParsedMessage.byteStateChangeTimes);
for (let i = 0; i < byteStateChangeTimes.length; i++) {
const currentData = hexData.substr(i * 2, 2);
const prevData = lastParsedMessage.hexData.substr(i * 2, 2);
if (currentData !== prevData) {
byteStateChangeTimes[i] = time;
byteStateChangeCounts[i] = 1;
}
}
}
return { byteStateChangeTimes, byteStateChangeCounts };
}
function createMessageEntry(
dbc,
address,
time,
relTime,
data,
byteStateChangeTimes
) {
return {
signals: dbc.getSignalValues(address, data),
time,
relTime,
hexData: Buffer.from(data).toString('hex'),
byteStateChangeTimes,
updated: Date.now()
};
}
function parseMessage(dbc, time, address, data, timeStart, lastParsedMessage) {
let hexData;
if (typeof data === 'string') {
hexData = data;
data = Buffer.from(data, 'hex');
} else {
hexData = Buffer.from(data).toString('hex');
}
const msgSpec = dbc.getMessageFrame(address);
const msgSize = msgSpec ? msgSpec.size : 8;
const relTime = time - timeStart;
const {
byteStateChangeTimes,
byteStateChangeCounts
} = determineByteStateChangeTimes(
hexData,
relTime,
msgSize,
lastParsedMessage
);
const msgEntry = createMessageEntry(
dbc,
address,
time,
relTime,
data,
byteStateChangeTimes
);
return { msgEntry, byteStateChangeCounts };
}
const BIG_ENDIAN_START_BITS = [];
for (let i = 0; i < 64; i += 8) {
for (let j = 7; j > -1; j--) {
BIG_ENDIAN_START_BITS.push(i + j);
}
}
function bigEndianBitIndex(matrixBitIndex) {
return BIG_ENDIAN_START_BITS.indexOf(matrixBitIndex);
}
function matrixBitNumber(bigEndianIndex) {
return BIG_ENDIAN_START_BITS[bigEndianIndex];
}
function setMessageByteColors(message, maxByteStateChangeCount) {
message.byteColors = message.byteStateChangeCounts
.map((count) => (isNaN(count)
? 0
: Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))))
.map((red) => `rgb(${Math.round(red)},0,0)`);
return message;
}
export default {
bigEndianBitIndex,
addCanMessage,
createMessageSpec,
matrixBitNumber,
parseMessage,
findMaxByteStateChangeCount,
setMessageByteColors,
createMessageEntry
};