Помогите пожалуйста с преобразованием Int2ByteArray

Мининова
Offline
Зарегистрирован: 08.06.2012

Добрый день, коллеги!

Помогите пожалуйста с функцией преобразования. Очевидно, что я что то не так делаю. Использую ее для того, чтобы послать INT в NetworkClient.write()

Вот функция и пример ее использования

void integerToBytes(ште val, byte b[2]) {
  b[0] = (byte)((val >> 8) & 0xFF);
  b[1] = (byte)(val & 0xFF);
}

// --------------------------------------------
  byte packet[4+COUNT];
  byte b_act[2];
  client.write(b_act, sizeof(int));
        
  byte b_offset[2];
  int NR = NUM_OF_REG;
  client.write(b_offset, sizeof(int));

Посылаю 0 и 2

На клиенте принимаю - получается 0 и вместо 2 - 255.
 

   stream = client.GetStream();
   // Read responce from stream
   BinaryReader bR = new BinaryReader(stream);

   int act = bR.ReadInt16();
   Console.WriteLine("ACT " + act);
                     
   if (act == 0)
   {
      int offset = bR.ReadInt16();
      Console.WriteLine("OFFSET " + offset);
   }

Вроде и там и там 4 байта уходит \ приходит ...
 

Мининова
Offline
Зарегистрирован: 08.06.2012

Поправка. как то так.

void integerToBytes(int val, byte b[2]) {
 b[0] = (byte)((val >> 8) & 0xFF);
 b[1] = (byte)(val & 0xFF);
}

// --------------------

        byte b_act[2];
        int ACT = 0;
        integerToBytes(ACT, b_act);
        client.write(b_act, sizeof(int));
        
        byte b_offset[2];
        int NR = NUM_OF_REG;
        integerToBytes(NR, b_offset);
        client.write(b_offset, sizeof(int));

Да, и когда посылаю просто байты - все работает как часики

byte b_act[]={0x01,0x00};
client.write(b_act, 2);  

 

Borland
Offline
Зарегистрирован: 17.05.2012

а что бы не сделать union

union toobytes {
int val;
byte b_act[2];
};
кода займет меньше

 Да, и когда вы шлете

1 byte b_act[]={0x00,0x02};
2 client.write(b_act, 2);

принимете 2 ?

в самой int2bytearray ошибок не  вижу.

Мининова
Offline
Зарегистрирован: 08.06.2012

да, я пробовал и union - думаю что проблема в принимающей стороне. Но вот как понять в чем дело, никак не могу.

Когда я шлю {0x00,0x02} принимаю 512 =)

Borland
Offline
Зарегистрирован: 17.05.2012

c BinaryReader не знаком, но интуитивно 512 это 0x200 , меняется порядок байтов, нада просто своп байтов сделать тем же union в клиенте

или физически их перекинуть аналогично int2bytearray

полагаю если пользоваться байтами в union на обоих сторонах одинаково, то не нужно заморачиваться, как они реально лежат в машинном слове.

maksim
Offline
Зарегистрирован: 12.02.2012

Покажите код которым принимаете 

Мининова
Offline
Зарегистрирован: 08.06.2012
вот мой метод для передачи и приема данных
public HubData WriteData (Hub hub, HubCommandAction cmd)
        {
            var data = new List<byte>();
            HubData hubData = new HubData();

            if (client.Connected)
            {
                NetworkStream stream = null;

                try
                {
                    int data_len = hub.LightData.Count;
                    data.AddRange(Utils.ConvertInt32ToByteArray((int)cmd)); // 4 BYTE ACTION

                    switch (cmd)
                    {
                        case HubCommandAction.STATUS:
                            {
                                // just nothing else =)
                            }
                            break;
                        case HubCommandAction.TRANSMIT:
                            data.AddRange(Utils.ConvertInt32ToByteArray(data_len)); // 4 BYTE DATA LEN
                            data.AddRange(hub.LightData); // BYTE ARRAY DATA
                            data.AddRange(hub.LightBlink); // BYTE ARRAY DATA_BLINK
                            break;
                    }

                    // Write to stream
                    byte[] prepaired_data = data.ToArray();
                    stream = client.GetStream();
                    stream.Write(prepaired_data, 0, prepaired_data.Length);
                    
                    // Read responce from stream
                    BinaryReader bR = new BinaryReader(stream);

                    int act = bR.ReadInt16();
                    Console.WriteLine("ACT " + act);

                    switch (act)
                    {
                        case 0:
                            {
                                hubData.Answer = HubResponceStatus.OK;
                                //TODO
                                hubData.BlinkData = null;
                                hubData.LightData = null;
                                int offset = bR.ReadInt16();
                                Console.WriteLine("OFFSET " + offset);

                                break;
                            }
                        case 1:
                            {
                                hubData.Answer = HubResponceStatus.OK;
                                hubData.BlinkData = null;
                                hubData.LightData = null;
                                break;
                            }
                        
                        
                        default:
                            
                            break;
                    }

                    bR.Close();
                    stream.Close();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    if (stream != null) { stream.Close(); }
                    hubData.Answer = HubResponceStatus.ERROR;
                }
                
            }
            return hubData;
        }

 

Borland
Offline
Зарегистрирован: 17.05.2012

так второй конец на JAva ? Я решил что две дуины пишут, читают

ну там все что угодно может быть

на яве int 4 байта

ошибки при приеме не дуине или наоборот?

Мининова
Offline
Зарегистрирован: 08.06.2012

Ну это ECMA script (C#)

там точно 2 байта в инт 16 (это short)

Отправлется из инта 4 байта - Ардуина принимает все отлично.  А вот на прием какая то лажа. И большей частью что не нахожу - все передают текст мол "OK" или что то еще, а мне нужно состояние массива в памяти передать и не одного..

Вобщем пока не знаю что делать...

Borland
Offline
Зарегистрирован: 17.05.2012

int act = bR.ReadInt16();
Console.WriteLine("ACT " + act);

тут ошибка ?

 

ну сделайте своп байтов

типа

unsigned int lowbyte,highbyte

highbyte=(act&0xff00)>>8;

lowbyte=act&0x00ff

act=(lowbyte<<8)|highbyte;

act  желательно unsigned int

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну вообщем, как вам правильно подсказал товарищь Borland, "товарищь сержант у вас ручки местами перепутанны". Вначале должен посылатся младший байт, а потом старший. Достаточно в вашем функции из #1 переставить местами строки 2,3 

void integerToBytes(int val, byte b[2]) {
 b[0] = (byte)(val & 0xFF);
 b[1] = (byte)((val >> 8) & 0xFF);
}

И уже должно заработать. Потом вглядется в них и понять что тут есть лишние &0xFF и привидения типов которые и так неявно происходят. Выкидываем лишние и получаем

void integerToBytes(int val, byte b[2]) {
 b[0] = val & 0xFF;
 b[1] = val >> 8;
}

Потом опять чухаем маковку и думаем "а нафига нам разбирать на байты если оно уже в памяти в виде байтов лежит? Причем в нужном нам порядке. И выкидываем нафиг фунцию integerToBytes волевым решением

Посылку делаем как-то так (тупо говорим компилятору "вот эту область памяти считай массивом байтов")

int NR = NUM_OF_REG;
client.write((byte *)&NR, sizeof(NR));

В этом случае, если мы вместо NR подставим сразу какой-то массив int-тов  (да вообщем-то вообще что угодно) - оно тоже отправится сразу "одним махом". Без необходимости бегать по элементам.

 

И еще.

>Отправлется из инта 4 байта

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

Перейтиде со стороны C# с четерех-байтовых int , на двух байтовые ushort (если знак не нужен) или Int16 (если числа только положительные)

Ну или, если не хочется менять тип переменных, можно тупо закастить  перед отправкой ((ushor)data_len)

И, напоследок, 

 Utils.ConvertInt32ToByteArray тоже смахивает на самописный велосипед. Есть "родной"  BitConverter.GetBytes(MySomeValue); 

P.S. а кстати, изначально неплохо-бы было дать ссылки на библиотеки ардуины которую вы юзаете для коммуникации. А то о функциях которые "есть в наличии" и какие у них типа параметров - можно только гадать.

 

 

Мининова
Offline
Зарегистрирован: 08.06.2012

Вот спасибо, как всегда меня выручаете =) Волевым решением, выкидываю.

Сейчас я юзаю Int16 для передачи. Там вобще и byte мог бы сойти

Utils.ConvertInt32ToByteArray - это оно и есть, просто для удобство в утилсы запихнул.

        public static byte[] ConvertInt32ToByteArray(Int32 I32)
        {
            return BitConverter.GetBytes(I32);
        }

        public static byte[] ConvertIntToByteArray(Int16 I16)
        {
            return BitConverter.GetBytes(I16);
        }

М.. ну только эти.. больше ничего

#include <SPI.h>
#include <Ethernet.h>
#include <MsTimer2.h>
 

leshak
Offline
Зарегистрирован: 29.09.2011

 >Сейчас я юзаю Int16 для передачи. Там вобще и byte мог бы сойти

Ну если байт, так пусть и будет байт. Тогда вообще можно будет послать нафиг все эти конвертеры. Должен быть сдоровый минимализм-обленизм.

>Utils.ConvertInt32ToByteArray - это оно и есть, просто для удобство в утилсы запихнул.

Ну это же "осталось за кадром".  Кстати, если воспользоватся Extention методами (дабавить слово this перед Int32 I32 ) и переименовать методов в просто ToByteArray(), то можно будет "конверсию" вызвать еще компактней data_len.ToByteArray();

>М.. ну только эти.. больше ничего

Ну вот Ethernet.h имелся ввиду. Что это за либа? (их столько имеется под этим именем :)  Где ее брали. Ну вообще-то не очень важно, просто иногда такая инфа облегчает задачу дать полее корректный совет. И, со стороны C#, просто любопытно, объект client он какого типа?