-2

This question is related to: C# How to extract bytes from byte array? With known starting byte

I have "100 bytes byte[]", that is composed with several "14 bytes byte[]" that occur in the bigger byte randomly.

My smaller byte[] start with the (byte) 0x55 and end 16 bytes later

I'm using the code:

        byte[] results = new byte[16];
        int index = Array.IndexOf(readBuffer, (byte)0x55, 2);
        Array.Copy(readBuffer, index, results, 0, 16);

But with this, I only get the first occurrence of my smaller byte[].

How do I get ALL the smaller byte[] blocks?

PS: I'm working with .Net Micro Framework

Community
  • 1
  • 1
Jónatas Brás
  • 82
  • 1
  • 2
  • 11
  • 1
    How about a `for` loop which would iterate over the original array? What are you supposed to do with resulting sub arrays? – vgru Feb 18 '15 at 12:11
  • You simply need to wrap all that code in a loop – Sriram Sakthivel Feb 18 '15 at 12:16
  • 1
    If your smaller array has only 14 elements, how can it end 16 bytes later? How can multiples of 14, 15 or 16 bytes fit in 100 bytes? Your question is hard to understand. Oh, I missed the "randomly" part. Is your idea that 0x55 always starts a sequence of 15 bytes, itself included? – Peter - Reinstate Monica Feb 18 '15 at 12:17
  • *"that occur in the bigger byte randomly"* Wait a second. What does randomly mean? Aren't they laid sequentially? What if a byte sequence *contains* the value 0x55 in the middle? I presume it's 0x55 + 14 bytes + checksum byte? – vgru Feb 18 '15 at 12:19
  • @PeterSchneider, yes, ox55 always start a sequence of 16 bytes including itself. forget the 14, it was a mistake. :) – Jónatas Brás Feb 18 '15 at 12:50
  • @Groo, the 0x55 Always is in the beggining of the sequence. Forget the 14, it was a mistake, it's 16, 0x55 included. randomly means that 0x55 can appear in any place in the source byte array, always followed by another 15. Checksum is included too. by order: 0x55 + 1syncbyte + 2 checksum + 12 databytes. – Jónatas Brás Feb 18 '15 at 12:53
  • @Jónatas: Ok, then the algorithm is similar to the one posted below, it's just the offsets that are slightly different from what I presumed. – vgru Feb 18 '15 at 13:12
  • @Groo. thank you, I'll try and let you know. By the way, why are people downvoting my question? Is it that stupid? or is it that bad written? – Jónatas Brás Feb 18 '15 at 14:07
  • @JónatasBrás: Well, questions which seem to ask for code are considered off topic on SO, and you are also expected to put some effort into the solution (e.g. post some code you tried but didn't work). It's also rather similar to your previous question, and you didn't specify your exact requirements (e.g. checksum, actual protocol, etc.) – vgru Feb 18 '15 at 14:26
  • @Groo Ok. thank you. I'm new to SO and I don't have much experience in programming. I thought I was doing good putting this question separated from the previous one. I tried some things, but as I said, I'm limited not only because I'm not a programmer, but also because I'm using .Net microframework and some things I'm used to work (lists, for example) aren't available. – Jónatas Brás Feb 18 '15 at 14:45
  • I downvoted because the question was poorly written (I could only guess what you wanted) and because any likely meaning was trivial, i.e. uninteresting. The algorithm (loop over the data until you hit 0x55, collect your data, loop on) as well as the language features needed (a loop, for goodness' sake) were obvious. The downvoting was intended to -- sorry to be so blunt -- keep others from wasting their time here. I think you were able to figure the solution out for yourself if you really tried. I hope. – Peter - Reinstate Monica Feb 18 '15 at 15:01
  • Thank you for your honesty. :) really apreciate it. I hope I'll get better and better in programing. I'm a mechatronics technician and the first time I had to program something (in other language besides Ladder) was 1 and half week ago. And this kind of trivial things are still a big question for me, I had no ideia how to do this. – Jónatas Brás Feb 18 '15 at 15:09
  • @Jónatas: I hope you've had some time to try to implement it. Since you are only beginning programming, I've added an example of how you might code this for you to compare with your attempt so try to step through the code using a debugger and see what's going on. – vgru Feb 18 '15 at 15:22

1 Answers1

1

I am presuming that your message is composed of a starting cookie byte 0x55, 14 bytes of actual data, and 1 checksum byte (since you used 14 and 16 bytes interchangeably). The only way for randomly occuring subarrays to make sense is to have a checksum value at the end, to confirm your starting byte is actually a valid cookie (instead of being a data byte).

(edited after your update)

So, your actual data is 0x55 + 1syncbyte + 2 checksum + 12 databytes, meaning that your function should:

Start with index i = 0 and repeat while i + 15 < input length:

  1. Check the cookie at index i.
    • If cookie is not 0x55, increment i and start again.
  2. Check the byte at index i + 1.
    • If incorrect sync byte, increment i and start again.
  3. Read the 16-bit checksum at i + 2/i + 3, calculate actual data checksum and compare.
    • If checksum doesn't match, increment i and start again.
  4. Copy bytes i + 4 to i + 15 into a segment of size 12.
    • Either yield return this result or process it right away.
  5. Increase i by 16 to skip the processed block and start again.

You can do skip to the first occurrence of 0x55 using Array.IndexOf, but since you need to keep track of the index anyway, you may as well just do the check yourself and simplify the code (algorithmic complexity is the same O(n)).

One way to code this would be something like:

private static IEnumerable<byte[]> EnumerateSegments(byte[] input)
{
    var i = 0;
    while (i + 15 < input.Length)
    {
        // check if it starts with 'sync' bytes
        // (not sure which is the second one, though?)
        var cookie = input[i];
        if (input[i] != 0x55 || input[i + 1] != 0xAA)
        {
            i++;
            continue;
        }

        // get the 16-bit checksum
        // (check if this is the correct endian, i.e. you
        // might need to swap bytes)
        var receivedChecksum = (input[i + 2] << 8) | (input[i + 3]);

        // calculate the checksum over data only
        var calculatedChecksum = CalculateChecksum(input, i + 4, 12);
        if (receivedChecksum != calculatedChecksum)
        {
            i++;
            continue;
        }

        // if we're here, data should be valid, so the last
        // thing left to do is to copy the data into the subarray
        var segment = new byte[12];
        Array.Copy(input, i + 4, segment, 0, 12);
        yield return segment;

        // skip this segment
        i += 16;
    }
}

And you would use it in a foreach loop to iterate over segments:

foreach (var segment in EnumerateSegments(input)) 
{
    ProcessSegment(segment);
}

Or you can get a list of segments if you want to iterate through elements several times:

List<byte[]> listOfSegments = EnumerateSegments(input).ToList();

Since you are new to C# (and generally programming), I suggest you place a breakpoint inside the method and go step by step to understand what's going on.

vgru
  • 49,838
  • 16
  • 120
  • 201
  • Thank you. Before your example I started trying to implement it and I got to a solution close to yours. But then I saw yours and I was intrigued about this line: var receivedChecksum = (input[i + 2] << 8) | (input[i + 3]); I didn't know why there was a "or" in there. But then I found bitwise operators. thanks for that. I'm still working on implementing this and some other stuff, when I'm finished I'll let you know. Thank you again – Jónatas Brás Feb 18 '15 at 17:14