вторник, 26 марта 2013 г.

Работа с большими числами в SP побайтно

Появилась задача получить из контролера и обработать в платформе параметр типа Double, но в ПЛК такого типа нет и сам ПЛК читает этот параметр со счетчика ....  ПЛК получает байты в обратном порядке, и нам нужно их развернуть. Сделал разборку double на 2 integer и разворот и сборку обратно ... работает но вот правильно или нет это вопрос ....
 Дальше скрипт разборки на 2 части


'массивы байт
dim bytes8 [8] as System.Byte;
dim bytes1 [4] as System.Byte;
dim bytes2 [4] as System.Byte;
'системные переменные для работы
dim sysdouble as System.Double;
dim sysint64 as System.int64;
dim sysint32 as System.int32;
'берем число типа double из атрибута и конвертируем в масив байт
sysdouble = System.Convert.ToDouble(me.inputDouble);
bytes8[] = System.BitConverter.GetBytes(sysdouble);

'заполняем массивы типа integer на 8 и 2 по 4 элемента
'нужны нам для удобства отладки в Object Viewer
me.int8byte[1] =bytes8[1]; me.int1byte[1] =bytes8[8];
me.int8byte[2] =bytes8[2]; me.int1byte[2] =bytes8[7];
me.int8byte[3] =bytes8[3]; me.int1byte[3] =bytes8[6];
me.int8byte[4] =bytes8[4]; me.int1byte[4] =bytes8[5];

me.int8byte[5] =bytes8[5]; me.int2byte[1] =bytes8[4];
me.int8byte[6] =bytes8[6]; me.int2byte[2] =bytes8[3];
me.int8byte[7] =bytes8[7]; me.int2byte[3] =bytes8[2];
me.int8byte[8] =bytes8[8]; me.int2byte[4] =bytes8[1];

'делим наш массив из 8 байт на 2 4х байтных
bytes1[1] =bytes8[8];
bytes1[2] =bytes8[7];
bytes1[3] =bytes8[6];
bytes1[4] =bytes8[5]; 

bytes2[1] =bytes8[4];
bytes2[2] =bytes8[3];
bytes2[3] =bytes8[2];
bytes2[4] =bytes8[1];

'конвертируем 1й массив в переменную типа int32 
sysint32 = System.BitConverter.Toint32(bytes1[], 0);
'и копируем ее в атрибут 
me.int1= sysint32 ;
'конвертируем результат в 16чную и 2ичную строки для удобства отладки
me.hexStrByte1 = System.Convert.ToString( sysint32 , 16 );
me.binStrByte1 = System.Convert.ToString( sysint32 , 2 );

'конвертируем 2й массив в переменную типа int32 
sysint32 = System.BitConverter.Toint32(bytes2[], 0);
'и копируем ее в атрибут 
me.int2= sysint32 ;
'конвертируем результат в 16чную и 2ичную строки для удобства отладки
me.hexStrByte2 = System.Convert.ToString( sysint32 , 16 );
me.binStrByte2 = System.Convert.ToString( sysint32 , 2 );



me.Int1 и me.Int2 - два входных параметра которые мы принимаем в тип Double т.к. Integer для развернутых по байтно чисел может не хватить.

И скрипт сборки обратно


'массивы байт
dim bytes1 [4] as System.Byte;
dim bytes2 [4] as System.Byte;
dim bytes3 [8] as System.Byte;
'системные переменные для работы
dim sysint64 as System.int64;
dim sysdouble as System.Double;
'при конвертировании в масив байт число разворачивается
sysint64= System.Convert.ToInt64(me.Int1);
bytes1[] = System.BitConverter.GetBytes(sysint64);

sysint64= System.Convert.ToInt64(me.Int2);
bytes2[] = System.BitConverter.GetBytes(sysint64);
'заполнение переменных для отладки
me.intFromByte1[1] =bytes2[4]; me.int1FromByte[1] =bytes1[1];
me.intFromByte1[2] =bytes2[3]; me.int1FromByte[2] =bytes1[2];
me.intFromByte1[3] =bytes2[2]; me.int1FromByte[3] =bytes1[3];
me.intFromByte1[4] =bytes2[1]; me.int1FromByte[4] =bytes1[4];

me.intFromByte1[5] =bytes1[4]; me.int2FromByte[1] =bytes2[1];
me.intFromByte1[6] =bytes1[3]; me.int2FromByte[2] =bytes2[2];
me.intFromByte1[7] =bytes1[2]; me.int2FromByte[3] =bytes2[3];
me.intFromByte1[8] =bytes1[1]; me.int2FromByte[4] =bytes2[4];
'копируем масивы байт в 1 и разворачиваем
bytes3[1] =bytes2[4];
bytes3[2] =bytes2[3];
bytes3[3] =bytes2[2];
bytes3[4] =bytes2[1]; 

bytes3[5] =bytes1[4];
bytes3[6] =bytes1[3];
bytes3[7] =bytes1[2];
bytes3[8] =bytes1[1];

sysdouble = System.BitConverter.ToDouble(bytes3[], 0);
'sysint64 = System.BitConverter.Toint64(bytes3[], 0);
me.strResult = sysdouble ;
me.doubleResult = sysdouble ;


И рисунок по которому возможно лучше понятно что происходит


вот только вопрос "Правильно ли это все работает?!" пока открыт :)
велика вероятность что у меня просто четное количество ошибок :( -  НОРМ. РАБОТАЕТ :)