Последовательный ввод в шестнадцатеричный код для разбора C#

У меня есть Raspberry Pi, и моя среда — C#. В основном я отправляю данные GPS (GPRMC) через беспроводное устройство. Беспроводное устройство Rx считывает данные и удаляет ненужную информацию. Сторона Tx отправляет сообщение GPRMC (я использую терминал Bray)

$24GPRMC,123123.00,A,2753.13285,N,08232.29411,W,0.021,,011113,,,D*6D

Когда я использую CuteCom на RPi, я получаю следующее:

\0xaa\0x02G\0xf0y\0x7fE,\0x12 \0xc6\0x00\0xa1-\0xcfU

обычный (шестнадцатеричный вывод не отмечен)

или это в шестнадцатеричном формате (когда флажок шестнадцатеричного вывода установлен):

aa 02 47 f0 79 7f 45 2c   12 20 c6 00 a1 2d cf 55 

Шестнадцатеричный код — это ожидаемое сообщение, поскольку в нем есть все необходимые мне данные (начало, идентификатор, дата, широта, длина, lrc, конец).

Я настроил свой код С# для чтения последовательных данных, но не могу заставить его отображать данные таким образом.

Это то, что у меня есть на С#:

        public static void Main ()
    {
        SerialPort serial = new SerialPort ("/dev/ttyUSB0", 115200);
        serial.Open ();


        while (true) 
        {
            string data = ReadData(serial);

            if(!string.IsNullOrEmpty(data))
            {
                Console.WriteLine(data);

            }
        }
    }

    public static string ReadData (SerialPort serial)
    {
        string rxString = "";

        rxString += serial.ReadExisting();

        return rxString;
    }

на выходе я получаю:

?G?yE, ??-?U

Я также пробовал потоковое чтение, но это не работает:

    public static string ReadData2 (System.IO.Stream s)
    {

        StreamReader sr = new StreamReader (s);
        DataString = sr.ReadLine ();

        return DataString;
    }

и я также пытался использовать Bit Converter, который я нашел в другом посте.

    private static string ReadData3 (SerialPort serial)
    {
        GPSrxString += serial.ReadExisting();
        string GPSrxStringhex = BitConverter.ToString(Encoding.ASCII.GetBytes(GPSrxString));

        return GPSrxString;
    }

Так что после всего этого я застрял. Где я ошибся. Что мне нужно сделать, чтобы получить правильный/желаемый шестнадцатеричный вывод?

РЕДАКТИРОВАТЬ: здесь я использовал строки, но в итоге обнаружил, что строки не подходят, в этом нет необходимости. Используйте массив для хранения всех значений и идите оттуда. Вы можете рассчитать необходимые числа, такие как UTC, в ответах ниже.


person Jonathan Nath    schedule 12.03.2014    source источник
comment
Смотрите комментарии ниже для более подробного ответа   -  person Jonathan Nath    schedule 13.03.2014


Ответы (3)


Похоже, что данные двоичные, но ваша реализация ReadData обрабатывает их как строку ASCII (отсюда и странные символы). Попробуйте прочитать двоичные данные, а затем преобразовать их в строковое представление значений в шестнадцатеричном формате:

public static string ReadData(SerialPort serial)
{
    byte[] buffer = new byte[serial.BytesToRead];
    serial.Read(buffer, 0, buffer.Length);

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < buffer.Length; i++)
        sb.AppendFormat("{0:X2} ", buffer[i]);

    return sb.ToString();
}
person Chris Ballard    schedule 12.03.2014
comment
@JonathanNath, что вам действительно нужно делать со значениями? Это байтовые значения, поэтому значение правильное, выбор десятичного/шестнадцатеричного — это просто способ представить его в удобочитаемой форме. Можете ли вы привести пример следующего шага? - person Chris Ballard; 13.03.2014
comment
Так что, как оказалось, мне это не нужно как строка. Мне нужно прочитать шестнадцатеричные значения. Я вижу, что буфер имеет правильные значения, но как мне получить шестнадцатеричные значения в переменную с плавающей запятой. например, буфер [0] = 170, буфер [1] = 2, буфер [2] = 71 ... в шестнадцатеричном формате они будут 0xAA, 0x02 и 0x47 соответственно. также эти значения после объединения должны быть с плавающей запятой. 0x47f0797f = 123122,99 - person Jonathan Nath; 13.03.2014
comment
поэтому элемент 0 является заголовком сообщения 0xAA, элемент 1 в данном случае является идентификатором устройства 0x02. элементы со 2 по 5 представляют время. в данном случае это 0x47 0xf0 0x79 0x7f. Приведенный ниже URL-адрес преобразует шестнадцатеричное значение в число с плавающей запятой, результат равен 123122,99, что является ожидаемым результатом. gregstoll.dyndns.org/~gregstoll/floattohex - person Jonathan Nath; 13.03.2014
comment
добавил новый ответ, так как это новая часть вопроса. Если это представляет интерес для других людей, вы можете отредактировать сам вопрос и добавить к нему комментарии выше. - person Chris Ballard; 13.03.2014

Чтобы ответить на вторую часть вашего вопроса, согласно комментариям к моему первому ответу:

Предполагая, что у вас есть эти данные:

byte[] data = new byte[] {0xAA, 0x02, 0x47, 0xF0, 0x79, 0x7F};

Нам нужно пропустить первые два байта, затем взять оставшиеся четыре байта. Нам также нужно изменить порядок байтов, прежде чем мы сможем преобразовать в число с плавающей запятой:

byte[] data2 = data.Skip(2).Take(4).Reverse().ToArray();

Теперь мы можем конвертировать:

float val = System.BitConverter.ToSingle(data2, 0);
person Chris Ballard    schedule 13.03.2014

Я всегда использовал этот тип кода:

public static string ReadData (SerialPort s)
{
    string DataString = "";
    int nByte = s.BytesToRead;
    for (i=0;i<nByte;i++)
    {
        int byteTemp = s.ReadByte();
        DataString += (char)(byteTemp);
    }
    return DataString;
}

Это прямой перевод с VB.Net, я не уверен, что синтаксис верен на 100%.

person AlexF    schedule 12.03.2014