Parsing CAN frames from a ByteArray











up vote
2
down vote

favorite












Here's my method used for parsing a ByteArray into multiple frames of CAN interface. It works now correctly but it's somewhat ugly in my opinion.



It's written in Kotlin with use of RxJava2



private fun parseCanFrameBytes(frame: ByteArray): Observable<CanFrame> {
return Observable.create { emitter ->
var index = 0
while (index < frame.size) {
val byte = frame[index]

if(byte xor IFM_FRAME_HEADER == BYTE_ZERO) {
try {
val ifmIndex = index
val length = frame[ifmIndex + 1].toInt()
val dlc1 = length - 3
val dlc2 = length - 5
val command = frame[ifmIndex + 2].toInt()
val data = frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length)
val isChecksumValid = frame[ifmIndex + 2 + length].toInt() == frame.copyOfRange(ifmIndex, ifmIndex + 2 + length).calculate8XorChecksum()
if (!isChecksumValid) {
index++
continue
}

val canFrame = when (command) {
0 -> {
val pgn = data.copyOfRange(0, 2).toHexString()
CanFrame(
type = "DLC1",
pgn = pgn,
id = pgn,
value = data.copyOfRange(2, 2 + dlc1).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
2 -> {
val pgn = data.copyOfRange(0, 4).toHexString()
CanFrame(
type = "DLC2",
pgn = pgn,
id = pgn,
value = data.copyOfRange(4, 4 + dlc2).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
else -> null
} ?: continue

emitter.onNext(canFrame)
index = ifmIndex + length + 4
} catch (ex: IllegalArgumentException) {
index++
}
} else {
index++
}
}
}
}









share|improve this question
















bumped to the homepage by Community 9 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.















  • Can you add some more context, what exactly is CanFrame ?
    – Simon Forsberg
    Jun 21 at 14:08










  • I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
    – Ernest Zamelczyk
    Jun 21 at 14:13










  • I'd recommend you to read Simon's guide to a good question
    – Simon Forsberg
    Jun 21 at 16:20















up vote
2
down vote

favorite












Here's my method used for parsing a ByteArray into multiple frames of CAN interface. It works now correctly but it's somewhat ugly in my opinion.



It's written in Kotlin with use of RxJava2



private fun parseCanFrameBytes(frame: ByteArray): Observable<CanFrame> {
return Observable.create { emitter ->
var index = 0
while (index < frame.size) {
val byte = frame[index]

if(byte xor IFM_FRAME_HEADER == BYTE_ZERO) {
try {
val ifmIndex = index
val length = frame[ifmIndex + 1].toInt()
val dlc1 = length - 3
val dlc2 = length - 5
val command = frame[ifmIndex + 2].toInt()
val data = frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length)
val isChecksumValid = frame[ifmIndex + 2 + length].toInt() == frame.copyOfRange(ifmIndex, ifmIndex + 2 + length).calculate8XorChecksum()
if (!isChecksumValid) {
index++
continue
}

val canFrame = when (command) {
0 -> {
val pgn = data.copyOfRange(0, 2).toHexString()
CanFrame(
type = "DLC1",
pgn = pgn,
id = pgn,
value = data.copyOfRange(2, 2 + dlc1).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
2 -> {
val pgn = data.copyOfRange(0, 4).toHexString()
CanFrame(
type = "DLC2",
pgn = pgn,
id = pgn,
value = data.copyOfRange(4, 4 + dlc2).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
else -> null
} ?: continue

emitter.onNext(canFrame)
index = ifmIndex + length + 4
} catch (ex: IllegalArgumentException) {
index++
}
} else {
index++
}
}
}
}









share|improve this question
















bumped to the homepage by Community 9 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.















  • Can you add some more context, what exactly is CanFrame ?
    – Simon Forsberg
    Jun 21 at 14:08










  • I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
    – Ernest Zamelczyk
    Jun 21 at 14:13










  • I'd recommend you to read Simon's guide to a good question
    – Simon Forsberg
    Jun 21 at 16:20













up vote
2
down vote

favorite









up vote
2
down vote

favorite











Here's my method used for parsing a ByteArray into multiple frames of CAN interface. It works now correctly but it's somewhat ugly in my opinion.



It's written in Kotlin with use of RxJava2



private fun parseCanFrameBytes(frame: ByteArray): Observable<CanFrame> {
return Observable.create { emitter ->
var index = 0
while (index < frame.size) {
val byte = frame[index]

if(byte xor IFM_FRAME_HEADER == BYTE_ZERO) {
try {
val ifmIndex = index
val length = frame[ifmIndex + 1].toInt()
val dlc1 = length - 3
val dlc2 = length - 5
val command = frame[ifmIndex + 2].toInt()
val data = frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length)
val isChecksumValid = frame[ifmIndex + 2 + length].toInt() == frame.copyOfRange(ifmIndex, ifmIndex + 2 + length).calculate8XorChecksum()
if (!isChecksumValid) {
index++
continue
}

val canFrame = when (command) {
0 -> {
val pgn = data.copyOfRange(0, 2).toHexString()
CanFrame(
type = "DLC1",
pgn = pgn,
id = pgn,
value = data.copyOfRange(2, 2 + dlc1).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
2 -> {
val pgn = data.copyOfRange(0, 4).toHexString()
CanFrame(
type = "DLC2",
pgn = pgn,
id = pgn,
value = data.copyOfRange(4, 4 + dlc2).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
else -> null
} ?: continue

emitter.onNext(canFrame)
index = ifmIndex + length + 4
} catch (ex: IllegalArgumentException) {
index++
}
} else {
index++
}
}
}
}









share|improve this question















Here's my method used for parsing a ByteArray into multiple frames of CAN interface. It works now correctly but it's somewhat ugly in my opinion.



It's written in Kotlin with use of RxJava2



private fun parseCanFrameBytes(frame: ByteArray): Observable<CanFrame> {
return Observable.create { emitter ->
var index = 0
while (index < frame.size) {
val byte = frame[index]

if(byte xor IFM_FRAME_HEADER == BYTE_ZERO) {
try {
val ifmIndex = index
val length = frame[ifmIndex + 1].toInt()
val dlc1 = length - 3
val dlc2 = length - 5
val command = frame[ifmIndex + 2].toInt()
val data = frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length)
val isChecksumValid = frame[ifmIndex + 2 + length].toInt() == frame.copyOfRange(ifmIndex, ifmIndex + 2 + length).calculate8XorChecksum()
if (!isChecksumValid) {
index++
continue
}

val canFrame = when (command) {
0 -> {
val pgn = data.copyOfRange(0, 2).toHexString()
CanFrame(
type = "DLC1",
pgn = pgn,
id = pgn,
value = data.copyOfRange(2, 2 + dlc1).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
2 -> {
val pgn = data.copyOfRange(0, 4).toHexString()
CanFrame(
type = "DLC2",
pgn = pgn,
id = pgn,
value = data.copyOfRange(4, 4 + dlc2).toHexString(),
ts = timestamp(),
data = frame.copyOfRange(ifmIndex, ifmIndex + 4 + length).toHexString()
)
}
else -> null
} ?: continue

emitter.onNext(canFrame)
index = ifmIndex + length + 4
} catch (ex: IllegalArgumentException) {
index++
}
} else {
index++
}
}
}
}






serialization kotlin rx-java






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 30 at 2:44









200_success

127k15148411




127k15148411










asked Jun 21 at 7:40









Ernest Zamelczyk

1112




1112





bumped to the homepage by Community 9 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community 9 mins ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.














  • Can you add some more context, what exactly is CanFrame ?
    – Simon Forsberg
    Jun 21 at 14:08










  • I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
    – Ernest Zamelczyk
    Jun 21 at 14:13










  • I'd recommend you to read Simon's guide to a good question
    – Simon Forsberg
    Jun 21 at 16:20


















  • Can you add some more context, what exactly is CanFrame ?
    – Simon Forsberg
    Jun 21 at 14:08










  • I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
    – Ernest Zamelczyk
    Jun 21 at 14:13










  • I'd recommend you to read Simon's guide to a good question
    – Simon Forsberg
    Jun 21 at 16:20
















Can you add some more context, what exactly is CanFrame ?
– Simon Forsberg
Jun 21 at 14:08




Can you add some more context, what exactly is CanFrame ?
– Simon Forsberg
Jun 21 at 14:08












I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
– Ernest Zamelczyk
Jun 21 at 14:13




I don't think that's important at all. What I want to achieve is more concise and better looking code. It's pretty niche thing but if you want you can read about it here en.wikipedia.org/wiki/CAN_bus
– Ernest Zamelczyk
Jun 21 at 14:13












I'd recommend you to read Simon's guide to a good question
– Simon Forsberg
Jun 21 at 16:20




I'd recommend you to read Simon's guide to a good question
– Simon Forsberg
Jun 21 at 16:20










1 Answer
1






active

oldest

votes

















up vote
0
down vote













Probably very little beautification. I would be curious to see someone beautify it and prove me wrong. Initially I thought you could use Kotlin streams on the frame ByteArray. This way you could have done something equivalent to frame.filterIndexed(..).map(it->CanFrame(..)) etc. However then I noticed you were doing random access on the ByteArray: ex: ifmIndex + length + 4 , frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length) which would negate the purpose of streams which go one by one.






share|improve this answer





















  • Also try using Arrow FP library (arrow-kt.io)
    – Ananth Raghuraman
    Jul 1 at 18:16











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196952%2fparsing-can-frames-from-a-bytearray%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote













Probably very little beautification. I would be curious to see someone beautify it and prove me wrong. Initially I thought you could use Kotlin streams on the frame ByteArray. This way you could have done something equivalent to frame.filterIndexed(..).map(it->CanFrame(..)) etc. However then I noticed you were doing random access on the ByteArray: ex: ifmIndex + length + 4 , frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length) which would negate the purpose of streams which go one by one.






share|improve this answer





















  • Also try using Arrow FP library (arrow-kt.io)
    – Ananth Raghuraman
    Jul 1 at 18:16















up vote
0
down vote













Probably very little beautification. I would be curious to see someone beautify it and prove me wrong. Initially I thought you could use Kotlin streams on the frame ByteArray. This way you could have done something equivalent to frame.filterIndexed(..).map(it->CanFrame(..)) etc. However then I noticed you were doing random access on the ByteArray: ex: ifmIndex + length + 4 , frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length) which would negate the purpose of streams which go one by one.






share|improve this answer





















  • Also try using Arrow FP library (arrow-kt.io)
    – Ananth Raghuraman
    Jul 1 at 18:16













up vote
0
down vote










up vote
0
down vote









Probably very little beautification. I would be curious to see someone beautify it and prove me wrong. Initially I thought you could use Kotlin streams on the frame ByteArray. This way you could have done something equivalent to frame.filterIndexed(..).map(it->CanFrame(..)) etc. However then I noticed you were doing random access on the ByteArray: ex: ifmIndex + length + 4 , frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length) which would negate the purpose of streams which go one by one.






share|improve this answer












Probably very little beautification. I would be curious to see someone beautify it and prove me wrong. Initially I thought you could use Kotlin streams on the frame ByteArray. This way you could have done something equivalent to frame.filterIndexed(..).map(it->CanFrame(..)) etc. However then I noticed you were doing random access on the ByteArray: ex: ifmIndex + length + 4 , frame.copyOfRange(ifmIndex + 3, ifmIndex + 2 + length) which would negate the purpose of streams which go one by one.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jun 29 at 23:11









Ananth Raghuraman

1




1












  • Also try using Arrow FP library (arrow-kt.io)
    – Ananth Raghuraman
    Jul 1 at 18:16


















  • Also try using Arrow FP library (arrow-kt.io)
    – Ananth Raghuraman
    Jul 1 at 18:16
















Also try using Arrow FP library (arrow-kt.io)
– Ananth Raghuraman
Jul 1 at 18:16




Also try using Arrow FP library (arrow-kt.io)
– Ananth Raghuraman
Jul 1 at 18:16


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196952%2fparsing-can-frames-from-a-bytearray%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

TypeError: fit_transform() missing 1 required positional argument: 'X'