0

I have a console application that is communicating with a custom machine through RS232 Comm port. According to documentation of the machine there are commands such as

  1. Start machine Command:DC1
    Complete Command:'STX' STN 'DC1' 'ETX' BCC
    hex codes(02 31 11 03 47)
  2. Stop machine Command:DC2
    Complete Command:'STX' STN 'DC2' 'ETX' BCC
    hex codes(02 31 12 03 48)

I am able to start and stop machine with this:

byte[] _startMachine = new byte[] { 0x02, 0x31, 0x11, 0x03, 0x47 };  
        _serialPort.Write(_startMachine, 0, _startMachine.Length);

    byte[] _stopMachine = new byte[] { 0x02, 0x31, 0x12, 0x03, 0x48 };   
    _serialPort.Write(_stopMachine, 0, _stopMachine.Length);

However I am stuck on this command 4. Read out batch total Command: DC4
Complete command:'STX' STN 'DC4' 'ETX' BCC
hex codes(02 31 14 03 4A)

Following the previous logic I am assuming that this should work.

byte[] _getBatchTotal = new byte[] { 0x02, 0x31, 0x14, 0x03, 0x4A };  
   _serialPort.Write(_getBatchTotal, 0, _getBatchTotal.Length);

I am following the same logic but I think the tricky part is the end of the command, am I translating the hex correctly?

Not sure if thats mistake in the documentation but it is also written that the everywhere used BCC (= Block Check Character) is calculated as sum of all bytes already read (incl. STX and ETX) . So for example starting machine command is simply Example: STX STN DC1 ETX BCC HEX: 02+31+11+03 == 47

Why is the BCC of the read batch command in this weird format then '4A'. Thank you.

Vladimir
  • 322
  • 1
  • 17
  • Do you know what 0x31 means? It's the hexadecimal (or _hex_) value for the character `'1'`. It's equivalent to (3x16+1) or 49. So, 02+31 is 33 hex, +14 is 47 and then add 03. To do that you add the 7 and the 3 and get 10, but this is hex, there are 16 digits (0-9 then a-f). The digit after 9 is A. So the result is 4A or 4a. But, you know... you have a computer. Let it calculate your checksum – Flydog57 Nov 13 '21 at 17:15
  • @Flydog57 Thanks, yes I understand the last bytes is a sum of previous values, so 2+31+14+3 is 50, so is the last value correct? Is 4A sum of 0x02, 0x31, 0x14, 0x03? – Vladimir Nov 13 '21 at 19:33
  • Does the computer you are working with have a calculator applet? Does it have a "programmer" (or "hex") mode? Use it to add those values up – Flydog57 Nov 13 '21 at 19:49
  • 2+31+14+3 is not 50, if you are working in hex. Remember that 0x31 is 3x16+1 (49 decimal) and 0x14 is 1x16+4 (20 decimal). So what you really have is 2+49+20+3 = 74. If you convert 74 to hex, it's 0x4a – Flydog57 Nov 13 '21 at 19:53
  • Was my answer of any use to you? Is there something I can do to improve it to better meet your needs? – Flydog57 Nov 14 '21 at 06:25
  • @Flydog57 Thanks for your help and deep explanation, I am going to try your solution – Vladimir Nov 14 '21 at 08:56
  • @Flydog57 Ok I tried that but anyway even with your solution the command is the same and byte[] _getBatchTotal = new byte[] { 0x02, 0x31, 0x14, 0x03, 0x4a }; should bring back total but it is not working, so will have to find out why – Vladimir Nov 14 '21 at 09:13
  • @Flydog57 so the command is right, I installed some ComDebug software and thanks to your explanation I was manually sending hex codes and I was able to decode the message received from a machine, which means there is something wrong with my console application, it is not receiving data maybe it is not compatible but anyway I will open another post for that because thats something different – Vladimir Nov 14 '21 at 11:17

1 Answers1

1

Here's how I would do it. First I'd set up the message formats as simple strings:

private const string StartMachineMessage = "\x02{0}\x11\x03";
private const string StopMachineMessage = "\x02{0}\x12\x03";
private const string ReadBatchMachineMessage = "\x02{0}\x14\x03";

Note that the {0} placeholder to hold the station number (it's always 1 in your case (which is what 0x31 represents), but it could be variable). Since it's always one here:

private const int StationNumber = 1;

Then I'd need a way to calculate the BCC of a bunch of bytes. This will do it for any array of bytes (which may be useful if you have longer messages):

private static byte GetBccOfBytes (byte[] bytes)
{
    var bcc = 0;
    foreach (var byt in bytes)
    {
        bcc += byt;
    }
    return (byte)(bcc & 0xff);
}

I'm assuming that the BCC is the lower 8 bits of the sum, so I use 0xff as a mask.

Now comes the meat of the problem, formatting the message and converting it to a byte array with a BCC:

public static byte[] GetMessageWithBcc (string format, int stationNumber)
{
    var messageWithStation = string.Format(format, stationNumber);  //mix the station number into the format string
    var noBccBytes = Encoding.ASCII.GetBytes(messageWithStation);   //convert the string to an array of ASCII bytes
    var result = new byte[noBccBytes.Length + 1];                   //allocate a buffer to hold the result, note room for BCC
    for (var i = 0; i < noBccBytes.Length; ++i)                     //copy the first byte array to the result byte array
    {
        result[i] = noBccBytes[i];
    }
    result[noBccBytes.Length] = GetBccOfBytes(noBccBytes);          //calculate and append the BCC
    return result;
}    

Then I need a way of seeing what these byte arrays look like, so convert them to a string with a space between each byte hex representation:

private static string BytesAsHexString (byte[] bytes)
{
    bool started = false;
    var buffer = new StringBuilder(bytes.Length * 3 - 1);
    foreach (var byt in bytes)
    {
        if (started)
        {
            buffer.Append(" ");
        }
        started = true;
        buffer.Append($"{byt:x02}");
    }
    return buffer.ToString();
}

If you want to see other, more efficient ways of doing this, How do you convert a byte array to a hexadecimal string, and vice versa?

Finally, some test code:

public static void Test()
{
    var messages = new Dictionary<string, string>
    {
        {nameof(StartMachineMessage), StartMachineMessage },
        {nameof(StopMachineMessage), StopMachineMessage },
        {nameof(ReadBatchMachineMessage), ReadBatchMachineMessage },
    };

    foreach (var msgPair in messages)
    {
        var result = GetMessageWithBcc(msgPair.Value, StationNumber);
        Console.WriteLine($"{msgPair.Key}: {BytesAsHexString(result)}");
    }
}

The output of this looks like:

StartMachineMessage: 02 31 11 03 47
StopMachineMessage: 02 31 12 03 48
ReadBatchMachineMessage: 02 31 14 03 4a
Flydog57
  • 6,851
  • 2
  • 17
  • 18