Search code examples
c#arraysstringuser-inputxbee

C# Changing parts of byte array based on user input


I am sending an API frame using the following code:

byte[] bytesToSend5 = new byte[] 
{ 
    0x7E, 0x00, 0x10, 0x01, 0x00, 0x13, 
    0xA2, 0x00, 0x40, 0xA6, 0x5E, 0x23, 
    0xFF, 0xFE, 0x02, 0x44, 0x37, 0x04, 0x4D 
};
serialPort1.Write(bytesToSend5, 0, bytesToSend5.Length);

It's split up like this:

byte[] bytesToSend5 = new byte[] 
{ 
    5Startbits(won't change), 
    8IDbits(changes when a part of the device is swapped), 
    6determinationbits(tells the device what to do), 
    1checksumbit(calculated based on previous bits) 
};    

The first code example works as is desired with the current product. If, for whatever reason, a part of the device needs to be changed, it will not work because the ID bits won't fit. The ID number is printed on the device, 16 digits with numbers and letters, such as "0013A20043A25E86".

What I want to do is make a textbox where the user can input the new ID number and it will be replaced with the appropriate bits in the aforementioned byte array.

Here is my attempt using the Array.Copy function, trying to display the result in a textbox - but no change is detected. I've tried typing "1" "1,2,3" etc as well as the actual ID's "0013A20043A25E86":

        string xbee_serienr = prop1_serienr.Text;
        byte[] front = { 0x7E, 0x00, 0x10, 0x17, 0x01 };
        byte[] back = { 0xFF, 0xFE, 0x02, 0x44, 0x37, 0x04 };
        string[] xbee = { xbee_serienr };
        byte[] combined = new byte[front.Length + xbee.Length + back.Length];
        Array.Copy(front, combined, front.Length);
        Array.Copy(back, 0, combined, 5, back.Length);
        var result = string.Join(",", combined.Select(x => x.ToString()).ToArray());
        OutputWindow.Text = result;

It would have to be possible to change the 8ID bits based on user input, and calculate the last checksum bit based on the rest of the bits.

I have searched the internet and tried Array.copy, Concat etc. but I haven't made any progress with it. Any guidance or input on this would be highly appreciated, even if it means guiding me in a direction of taking a different approach.

EDIT:

I now have the desired information in the byte array "result" using roughly the same example as below (taking user input for the var "xbee_serienr"). I now want to pass this to a method that looks like this:

    private void button_D07_Lav_Click(object sender, EventArgs e)
    {
        byte[] bytesToSend5 = new byte[] { 0x7E, 0x00, 0x10, 0x01, 0x00, 0x13, 0xA2, 0x00, 0x40, 0xA6, 0x5E, 0x23, 0xFF, 0xFE, 0x02, 0x44, 0x37, 0x04, 0x4D };
        serialPort1.Write(bytesToSend5, 0, bytesToSend5.Length);

And make the "bytesToSend5" use the array "result" from the other method.

I've tried using this example, like so:

byte result { get; set; } //above and outside of the two methods

var result = string.Join(string.Empty, combined.Select(x => x.ToString("X2")).ToArray()); //this is the end of the first method

private void button_D07_Lav_Click(object sender, EventArgs e)
    {
        byte[] bytesToSend5 = new byte[] { 0x7E, 0x00, 0x10, 0x01, 0x00, 0x13, 0xA2, 0x00, 0x40, 0xA6, 0x5E, 0x23, 0xFF, 0xFE, 0x02, 0x44, 0x37, 0x04, 0x4D };
        bytesToSend5 = result; //using the array stored in result instead of the one currently in bytesToSend5.
        serialPort1.Write(bytesToSend5, 0, bytesToSend5.Length);
    }

I realize the obvious problem here, that it's not on the same form. This is why I wanted to split the array and add 0x in front of every item in the array, and separate them with commas.

I'm also going to use this for several different devices once I figure it out properly, which makes me fear there will be a lot of duplicated code, but I suspect once I'm understanding how to pass and use the array in a different method, I can always "duplicate" the code for every device, since the ID will indeed need to be different for the different devices.


Solution

  • Well, you never add the parsed string.

    var xbee_serienr = "0013A20043A25E86";
    byte[] front = { 0x7E, 0x00, 0x10, 0x17, 0x01 };
    byte[] back = { 0xFF, 0xFE, 0x02, 0x44, 0x37, 0x04 };
    var xbee = new byte[xbee_serienr.Length / 2];
    
    for (var i = 0; i < xbee.Length; i++)
    {
      xbee[i] = byte.Parse(xbee_serienr.Substring(i * 2, 2), NumberStyles.HexNumber);
    }
    
    byte[] combined;
    using (var ms = new MemoryStream(front.Length + xbee.Length + back.Length))
    {
      ms.Write(front, 0, front.Length);
      ms.Write(xbee, 0, xbee.Length);
      ms.Write(back, 0, back.Length);
    
      combined = ms.ToArray();
    }
    
    var result = string.Join(string.Empty, combined.Select(x => x.ToString("X2")).ToArray());
    

    Since you're adding multiple arrays one after another, I just used a MemoryStream. If you already have the byte[] ready (and mutable), you can write directly to that byte array and avoid allocating (and collecting) the extra array, but it doesn't make much of a difference when the limiting factor is the UI anyway.