How to convert string to int then to string?
Asked Answered
C

4

6

I have tried to search for the duplicates of my problem, but could not find. Also, sorry for the not so understandable title. I am so confused about what I am searching, and also about the terminology. I am an electronics engineer with very little knowledge on .Net framework, so treat me well :)

My current project is a heart rate monitor that can store measured heart rates to an EEPROM to be sent to a PC for later log viewing.

I am interfacing with an 8-bit microcontroller using RS-232 (serial) protocol. Whenever I send a char l, which stands for log, to the microcontroller, it will send me back some information in the following format:

0x1E 0x21 0x01 0x13 0x14 0x35 0x46 0x1E 0x21 0x01 0x13 0x14 0x43 0x48 0x0A 0x0D

Empty spaces are for information purposes, these bytes are not seperated from each other.

These 8 bit HEX values that are sent from the microcontroller include a start of record information, which is 0x1E, the date and time in the format DD MM YY HH MM and also the recorded heart rate. When all the records are echoed, then 0x0A and 0x0D character is sent.

For example, above code means:

Record start.
21.01.13 14:35
Heart Rate: 70
Record start.
21.01.13 14:43
Heart Rate: 72
End of records.

How can I get the string value like this: "S210113143570S210113144372", where S can be anything. Afterwards, I am going to apply a regex syntax to this and divide it to groups so that I can add these values to a listviewcontrol.

Edit after comments and answers:

I have not written the sample wrong. Unfortunately, the encoding is exactly like above.

Courtland answered 21/1, 2013 at 12:12 Comment(8)
Can you show as the relevant piece of codeInstallation
Does two digits in your string represents an single integer value ?Pollux
Seems like the Date and Time part is not sent as HEX, is it?Imogeneimojean
I really liked your humble introduction. I am not that good at RegExp so I won't be of much help. But I truly liked how you stated your question.Busra
I was wondering why you are treating beat rate as hex and other information as string. this does not seem proper (take it as a side note from an electrical engineer)...Heriot
you stated that 0x1E is the start of record; but what if the beat rate of patient is 31 (do not know whether this is possible)?Heriot
@MichaelViktorStarberg thanks :) But RegExp is not in the scope of this question. I can take care of it myself.Courtland
@Heriot you are right. I get your point now.Courtland
R
5

So, actually each byte represents a number. I assume you somehow already have a byte[] array containing these values:

var data = new byte[] { 0x1E, 0x21, 0x01, 0x13, 0x14, 0x35, 0x46,
                        0x1E, 0x21, 0x01, 0x13, 0x14, 0x43, 0x48, 0x0A, 0x0D };

You now could create real objects like this:

class LogEntry
{
    public DateTime Timestamp { get; set; }
    public int HeartRate { get; set; }
}

var logEntries = new List<LogEntry>();

for(int i = 0; i < data.Length; i+= 7)
{
    if(data[i] == 0x0a && data[i + 1] == 0x0d)
        break;
    if(data[i] != 0x1e)
        throw new InvalidDataException();

    var logEntry = new LogEntry();
    var year = BcdToDecimal(data[i + 3]) + 2000;
    var month = BcdToDecimal(data[i + 2]);
    var day = BcdToDecimal(data[i + 1]);
    var hour = BcdToDecimal(data[i + 4]);
    var minute = BcdToDecimal(data[i + 5]);
    var heartRate = data[i + 6];
    logEntry.Timestamp = new DateTime(year, month, day, hour, minute, 0);
    logEntry.HeartRate = heartRate;
    logEntries.Add(logEntry);
}

byte BcdToDecimal(byte bcdValue)
{
    return (byte)((bcdValue / 16 * 10) + (bcdValue % 16));
}

The method BcdToDecimal converts the BCDs to their real value.

Rad answered 21/1, 2013 at 12:22 Comment(14)
Where are you converting those HEX values to int?Imogeneimojean
@AbZy: There is an implicit conversion going on when passing them into the DateTime constructor and when assigning them to the HeartRate property.Rad
Thanks for the answer. Actually, the date and time values are correct in my sample. That is the reason I am struggling..Courtland
@abdullahkahraman: Please check update, there is a new method BcdToDecimal.Rad
@DanielHilgarth Hmm, thanks for the edit. It seems like there is no method in the framework that I can use out of the box. Then, I will port my own libraries from C code.Courtland
@abdullahkahraman: What is the problem with my suggestion of BcdToDecimal?Rad
@DanielHilgarth If I pass 0x13 which is 19 to it, it should output 13. (19/16)*10 = 11,875. And 19%16=3. (byte)(11,875+3) = (byte)(14,875) = 14 or 15? I could not understand it..Courtland
Here is my C routine for it: return ((bcd_number>>4)*10 + (bcd_number&0x0F));Courtland
@abdullahkahraman: You can't use regular math here as we are working with integral type variables. All calculations are done using ints, even the intermediate results will be ints. This means 19/16 is 1. Multiplying with 10 results in 10, adding 3 from the modulo results in 13, just as expected. I actually tested that code before posting it, so rest assured, that conversion is correct.Rad
@abdullahkahraman: However, if you feel better using your code, you can do so too. The result is the same and it can be used without changes in C#.Rad
@DanielHilgarth Thanks for your help and efforts for me! By the way, it is frustrating to see that there is no built-in method in the .Net framewrok for these kind of operations :(Courtland
@abdullahkahraman: Why is it frustrating? Your typical .NET application doesn't need this kind of conversion and because it is very simple to develop yourself it is not included in the .NET framework. Also, please read this on why a certain feature is not implemented. Last but not least, there is a huge .NET community providing libraries for all kinds of stuff. I am pretty sure there exists one that has BCD conversion built in. But again, it is so simple to build, it is implemented faster than it takes to search for a libraryRad
@DanielHilgarth Agreed, they are doing a great job. Sorry if I sounded ignorant, but I was not trying to be, really.Courtland
@abdullahkahraman: Not a problem. I just wanted to give some context and background on why one can't expect every single functionality in a framework.Rad
S
0

brother i think you should consider using string i.e.,

string heartRate=70;
string recordStart=21.01.13 14:35;
string fullValue = heartRate + '|' + recordStart;

now instead of applying regex, you can easily split that string using split method e.g.,

string splittedValues[]=fullValue.Split('|');

and u will get these values when needed like

splittedValues[0] \\it will be heard rate string (at index zero)
similarly
splittedValues[1] \\it will be record start string (at index one)

i still don't understand your problem, and if my answer is irrelevant please do tell me and i will clarify

Schoenberg answered 21/1, 2013 at 12:22 Comment(1)
Unfortunately, as I am working with an 8-bit microcontroller, this stuff is very low-level. Using strings will cost me lots of my precious clock cycles. Thanks for your effort, though.Courtland
D
0
public static String ParseData(String data)
{
    MatchCollection matches = Regex.Matches(data, "0[xX]([a-fA-F0-9]{2})");

    Int32 count = 0;
    String result = String.Empty;

    foreach (Match match in matches)
    {
        switch (count)
        {
            case 0:
            {
                if (match.Value.Equals("0x1E", StringComparison.OrdinalIgnoreCase))
                {
                    result += "S";
                    break;
                }

                goto End;
            }

            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                result += match.Groups[1].Value;
                break;

            case 6:
                result += Int32.Parse(match.Groups[1].Value, NumberStyles.HexNumber).ToString();
                count = -1;
                break;
        }

        ++count;
    }

    End:;

    return result;
}
Delivery answered 21/1, 2013 at 13:14 Comment(5)
Sorry if I was not clear, but the notation 0x0F is to show 8-bit hexadecimal values.Courtland
This returns exactly what you expected. "0x1E0x210x010x130x140x350x460x1E0x210x010x130x140x430x480x0A0x0D" returns "S210113143570S210113144372".Delivery
Then which method do I use to read these datas from the serial port? Because my input is not a string like 0x1E0x210x010x130x140x350x460x1E0x210x010x130x140x430x480x0A0x0D.Courtland
...These 8 bit HEX values that are sent from the microcontro.... Sorry that this was not an explanation that is not clear enough. I will try harder next time.Courtland
Don't worry man, take it easy. I was just wondering which format was it.Delivery
C
0

I am so sorry for the very silly mistake of mine. I saw that it is really easy and not so clock cycle consuming thing to do this on the microcontroller side. Now that I have done this, it is really easy to parse the values now.

I have used this routine on the microcontroller side:

unsigned char BCDtoDecimal(unsigned char bcd_number)
{
  return ((bcd_number>>4)*10 + (bcd_number&0x0F));
}

So, the code is really easy on the C# side:

    private void buttonGetLogs_Click(object sender, EventArgs e)
    {
        string inputBuffer;
        char[] charArray;
        try
        {
            serialPort.Write("l");
            inputBuffer = serialPort.ReadLine();
            charArray = inputBuffer.ToCharArray();
            inputBuffer = string.Empty;
            foreach (char item in charArray)
            {
                inputBuffer += Convert.ToInt32(item).ToString();
            }
        }
        catch (Exception) { }
    }
Courtland answered 21/1, 2013 at 13:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.