Last active
June 3, 2019 18:04
-
-
Save brandonros/239592a42ef0513c859869140df1b51d to your computer and use it in GitHub Desktop.
node.js implementation of chunking a CAN response into ISO-TP frames
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const FIRST_FRAME_PCI_BYTE = 0x01 | |
const CONSECUTIVE_FRAME_PCI_BYTE = 0x02 | |
const FIRST_FRAME_DATA_LENGTH = 5 | |
const CONSECUTIVE_FRAME_DATA_LENGTH = 7 | |
const PADDING_BYTE = 0xAA | |
const buildFirstFrame = (responseSid, data) => { | |
const responseLength = data.length + 1 // add a byte for response SID | |
const firstFrameData = data.slice(0, FIRST_FRAME_DATA_LENGTH) | |
const firstFrameHeader = Buffer.from([ | |
(FIRST_FRAME_PCI_BYTE << 4) ^ (responseLength >> 8), | |
responseLength & 0xFF, | |
responseSid | |
]) | |
return Buffer.concat([ | |
firstFrameHeader, | |
firstFrameData | |
]) | |
} | |
const buildConsecutiveFrame = (consecutiveFrameCounter, remainingData) => { | |
let frameData = remainingData.slice(0, CONSECUTIVE_FRAME_DATA_LENGTH) | |
// Pad last frame | |
if (frameData.length < CONSECUTIVE_FRAME_DATA_LENGTH) { | |
const paddingLength = 7 - frameData.length | |
let padding = Buffer.from(new Array(paddingLength).fill(PADDING_BYTE)) | |
frameData = Buffer.concat([frameData, padding]) | |
} | |
const consecutiveFrameHeader = Buffer.from([ | |
(CONSECUTIVE_FRAME_PCI_BYTE << 4) ^ consecutiveFrameCounter | |
]) | |
return Buffer.concat([ | |
consecutiveFrameHeader, | |
frameData | |
]) | |
} | |
const buildIsoTpFrames = (responseSid, data) => { | |
const frames = [] | |
frames.push(buildFirstFrame(responseSid, data)) | |
let remainingData = data.slice(FIRST_FRAME_DATA_LENGTH) | |
const numConsecutiveFrames = Math.ceil(remainingData.length / CONSECUTIVE_FRAME_DATA_LENGTH) | |
let consecutiveFrameCounter = 1 | |
for (let i = 0; i < numConsecutiveFrames; ++i) { | |
frames.push(buildConsecutiveFrame(consecutiveFrameCounter, remainingData)) | |
consecutiveFrameCounter += 1 | |
// Wrap consecutive frame counter | |
if (consecutiveFrameCounter === 10) { | |
consecutiveFrameCounter = 0 | |
} | |
remainingData = remainingData.slice(CONSECUTIVE_FRAME_DATA_LENGTH) | |
} | |
return frames | |
} | |
const vin = 'WDDZF8KB1KA539167' | |
const vinDataIdentifier = 0xF190 | |
const readDataResponse = Buffer.concat([ | |
Buffer.from([vinDataIdentifier >> 8, vinDataIdentifier & 0xFF]), | |
Buffer.from(vin) | |
]) | |
buildIsoTpFrames(0x62, readDataResponse) |
Author
brandonros
commented
Jun 3, 2019
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment