I'm searching to calculate CRC-16 for concox VTS. After search a lot I've got several formula, lookup table, CRC32.net library etc and tried them. But didn't get the actual result which I've wanted.
For example, when I use crc32.net library :
byte[] data = { 11, 01, 03, 51, 51, 00, 94, 10, 95, 20, 20, 08, 25, 81, 00, 23 };
UInt32 crcOut = Crc32Algorithm.ComputeAndWriteToEnd(data);
Console.WriteLine(crcOut.ToString());
It returns : 3232021645
But actually it should return : 90DD
I've tried another example too but they also did not return proper value.
Edit :
Here is the RAW data from Device :
{78}{78}{11}{01}{03}{51}{51}{00}{94}{10}{95}{20}{20}{08}{25}{81}{00}{23}{90}{DD}{0D}{0A}
When split by following data sheet, it looks like -
{78}{78} = Start Bit
{11} = Packet Length(17) = (01 + 12 + 02 + 02) = Decimal 17 = Hexadecimal 11
{01} = Protocol No
{03}{51}{51}{00}{94}{10}{95}{20} = TerminalID = 0351510094109520
{20}{08} = Model Identification Code
{25}{81} = Time Zone Language
{00}{23} = Information Serial No
{90}{DD} = Error Check (CRC : Packet Length to Information Serial No)
{0D}{0A} = Stop Bit
They told in error check it need CRC from Packet Length to Information Serial No. To make reply this packet I also need to make a data packet with CRC code.
I've found an online calculator from below link. The data match with CRC-16/X-25.
Now I need to calculate it by C# code.
https://crccalc.com/?crc=11,%2001,%2003,%2051,%2051,%2000,%2094,%2010,%2095,%2020,%2020,%2008,%2025,%2081,%2000,%2023&method=CRC-16/X-25&datatype=hex&outtype=0
Waiting for your reply.
Thanks
The CRC-16 you assert that you need in your comment (which needs to be in your question) is the CRC-16/X-25. On your data, that CRC gives 0xcac0, not 0x90dd.
In fact, none of the documented CRC-16's listed in that catalog produce 0x90dd for your data. You need to provide a reference for the CRC that you need, and how you determined that 0x90dd is the expected result for that data.
Update for updated question:
The bytes you provided in your example data are in decimal:
byte[] data = { 11, 01, 03, 51, 51, 00, 94, 10, 95, 20, 20, 08, 25, 81, 00, 23 };
That is completely wrong, since, based on the actual data message data in your updated question that you want the CRC for, those digits must be interpreted as hexadecimal. (Just by chance, none of those numbers have hexadecimal digits in a..f.) To represent that test vector in your code correctly, it needs to be:
byte[] data = { 0x11, 0x01, 0x03, 0x51, 0x51, 0x00, 0x94, 0x10, 0x95, 0x20, 0x20, 0x08, 0x25, 0x81, 0x00, 0x23 };
This computes the CRC-16/X-25:
ushort crc16_x25(byte[] data, int len) {
ushort crc = 0xffff;
for (int i = 0; i < len; i++) {
crc ^= data[i];
for (unsigned k = 0; k < 8; k++)
crc = (crc & 1) != 0 ? (crc >> 1) ^ 0x8408 : crc >> 1;
}
return ~crc;
}
Related
I know this is probably a very rare question.
I have a service written with Delphi, and a client written with C#. The Delphi service tries to read a 10-byte Extended data type from the C# client.
After some research, I found some sample code in C# to convert a 10-byte Extended to a number (Convert Delphi Extended to C#). But I couldn't find any sample to convert a number to a 10-byte Extended, so that I can send it back to the service.
I tried to write code by myself, but the calculation is very difficult for me to understand.
Can anyone help me?
Delphi (32 bit target) natively support Extended data type. You can just copy the 10 bytes in the Extended variable. For example:
const
// Binary representation of Extended number "123456789012345678"
Bin : array [0..9] of Byte = (0, 167, 121, 24, 211,
165, 77, 219, 55, 64);
procedure TForm1.Button1Click(Sender: TObject);
var
V : Extended;
I : Integer;
begin
V := PExtended(#Bin[0])^; // Copy Bin to V
Memo1.Lines.Add(Format('%22f', [V]));
end;
The binary format for extended data type can be found here.
A better description of the format is here.
Sorry for not make question clear, but thanks for all the comments here.
I got the code working, it looks not that perfect, but unit testing is passed.
Thanks for the link sent by #fpiette, it gave me bellow thoughts.
public static byte[] WriteExtendedToBuffer(double value)
{
var extendedBuffer = Enumerable.Repeat((byte)0x0, 10).ToArray();
if (!double.IsNaN(value) && !double.IsInfinity(value) && (value != 0))
{
var doubleBuff = BitConverter.GetBytes(value);
var sign = doubleBuff[7] & 0x80;
doubleBuff[7] = (byte)(doubleBuff[7] & 0x7F);
var exp = BitConverter.ToUInt16(doubleBuff, 6);
doubleBuff[7] = 0;
doubleBuff[6] = (byte)(doubleBuff[6] & 0x0F);
var massive = BitConverter.ToUInt64(doubleBuff);
exp >>= 4;
if (exp == 0)
{
exp = 16383 - 1022;
Buffer.BlockCopy(BitConverter.GetBytes(exp), 0, extendedBuffer, 8, 2);
extendedBuffer[9] = (byte)(extendedBuffer[9] | sign);
massive <<= 11;
Buffer.BlockCopy(BitConverter.GetBytes(massive), 0, extendedBuffer, 0, 8);
}
else
{
exp = (ushort)(16383 + exp - 1023);
Buffer.BlockCopy(BitConverter.GetBytes(exp), 0, extendedBuffer, 8, 2);
extendedBuffer[9] = (byte)(extendedBuffer[9] | sign);
massive <<= 11;
Buffer.BlockCopy(BitConverter.GetBytes(massive), 0, extendedBuffer, 0, 8);
extendedBuffer[7] = (byte)(extendedBuffer[7] | 0x80);
}
}
return extendedBuffer;
}
I have the following byte array which is coming in from a BLE device. Each time I read the byte array I receive different cvhunks of the byte array, sometimes 3, 7, 16, 17,etc. I have implemented a queue to make sure that I receive all of the data. However I am having trouble finding the start of the byte array. I am sending a null terminator byte(0x00) on the other side at the beginning of the array before I send 4 float variables.
Sending this byte array repeating in the stream:
00 3F 8F CB 92 3F C8 AD AC 3F F4 7E 28 3F 8E 59 4B
which are the float numbers 1.1234, 1.5678, 1.9101, 1.1121
The problem is that I my code can't find the beginning of each bytea sequence and the end to convert to the correct float.
Here is my current code:
I have checked the endinaess and it is correct.
static float EnterDataQueue (byte[] bytes) {
//Array.Reverse(bytes);
ArduinoHM10Test aTest = new ArduinoHM10Test ();
//always load the data byte array in full
for (int i = 0; i < bytes.Length; i++) {
aTest.myQueue.Enqueue (bytes[i]);
}
//Dequeue the queue and check if 4 bytes have been dequeued
//Dequeue and check for 0
Debug.Log ("ValueCheckQueueLength1: " + aTest.myQueue.Count.ToString ());
if (aTest.myQueue.Count >= 16) {
byte[] byteArray = new byte[4];
int i = 0;
while (i < 4) {
byte tempVal = aTest.myQueue.Dequeue ();
if (tempVal != 00) {
byteArray[i] = tempVal;
i++;
} else {
i = 0;
}
}
PrintHexBytes (byteArray);
aTest.floatnum = BitConverter.ToSingle (byteArray, 0);
Debug.Log ("ValueCheckQueueLength2: " + aTest.myQueue.Count.ToString ());
Debug.Log ("ValueCheckfloatnumDataQueue: " + aTest.floatnum.ToString ());
}
return aTest.floatnum;
}
Can you please help me correct my code so that my floats are converted correctly and not someting like 1.06335e-14 instead of 1.1121 (taking the bytes 283F8E59 or some other sequence).
Your examples were incorrect; neither of us can count - the LAST FOUR hex digits in your example are 3F 8E 59 4B. This equates to decimal numbers 63, 142, 89, 75.
Running this through C# gives;
BitConverter.ToSingle(new byte[] {63, 142, 89, 75}, 0) an answer of 14257727.
However, if we reverse the bytes;
BitConverter.ToSingle(new byte[] {75, 89, 142, 63}, 0) we get 1.1121.
So essentially your byte order is incorrect. Either load the data in reverse at the other end, or dequeue the data into the byte array backwards; such as
if (tempVal != 00) {
byteArray[3 - i] = tempVal;
i++;
(Completely untested, but I hope you get the idea). I'm sure there are better ways to do this.
I'm trying to send a command to a PLC that controls electronic lockers via a TCP Client. I am able to connect but it appears my command is not being read by the PLC.
I have the following code:
private const string STX = "0x02";
private const string ETX = "0x03";
private const string STATUS = "0x30";
private const string OPEN = "0x31";
private const string SUM = STX + ETX;
static void Main(string[] args)
{
var tcpClient = new TcpClient();
tcpClient.Connect("192.168.1.190", 4000);
if (tcpClient.Connected)
{
var networkStream = tcpClient.GetStream();
if (networkStream.CanWrite)
{
var ADDY = "00";
var asciiEncode = new ASCIIEncoding();
byte[] b = asciiEncode.GetBytes(STX + ADDY + OPEN + ETX + SUM);
networkStream.Write(b, 0, b.Length);
byte[] b1 = new byte[100];
var k = networkStream.Read(b1, 0, 100);
for (var i = 0; i < k; i++)
{
Console.WriteLine(Convert.ToChar(b1[i]));
}
}
}
}
STATUS/OPEN are the commands that can be sent. The PLC came with some documentation and here is a picture of it. I assuming my CMD is wrong, how do I fix it? This is my first time trying to connect to and send/retrieve commands from a PLC. Any help is appreciated.
You're on the right track, but the encoding of your command is wrong. Low-level protocols like these are tricky to get right.
Your byte array b contains the ASCII-encoded string "0x02000x310x030x020x03", encoded in ASCII, which translates to byte[22] { 48, 120, 48, 50, 48, 48, 48, 120, 51, 49, 48, 120, 48, 51, 48, 120, 48, 50, 48, 120, 48, 51 }while you want to be sending an array of the actual bytes 0x02, etc.
Try something like:
byte[b] = new byte { 0x02, 0x00, 0x31, 0x30, 0x02, 0x03 }
See also http://www.december.com/html/spec/ascii.html to see how STX and ETX relate to the other ASCII characters (eg a-z, 0-9, etc).
I need to port a snippet of C++ to C# that decodes some BCD bytes, but I'm pretty new to C#, so I've run into a problem with using the %, >> and & operators.
Here's the encoding description.
Data on the FASC-N is encoded using a process called Binary Coded
Decimal (BCD). It uses 5 bits per character (4 data bits and 1 parity
bit) and results in a 16-character set. Encoding the full 40-character
FASC-N in BCD digit format results in 200 bits of information. Rather
than transmit the data one character at a time, the data can be packed
such that each transmitted byte contains 8 meaningful bits (e.g. the
full 5 from Character One plus the first 3 from the Character Two).
These 200 bits can thus be transmitted in the form of 25 bytes (200
bits divided by 8 bits per byte). Thus the 40-character FASC-N becomes
a 25-byte BCD encoded transmittal.
I have the 25 byte data and need to decode to 40 bytes.
Here's the C++:
byte byBCD, byBCDs, byBits, byShift = 0x80, by, nn;
byte FASCN_ReadChars[40] = {0};
// an example raw FASCN
byte FASCN[25] = { 0xd1, 0x38, 0x10, 0xd8, 0x21, 0x0c, 0x2c, 0xd2, 0x54, 0x88, 0x85, 0xa1, 0x68, 0x58, 0x21, 0x08, 0x42, 0x10, 0x84, 0x30, 0x81, 0x38, 0x10, 0xc3, 0xf3 };
nn = 0;
byBCD = 0;
byBits = 0;
byBCDs = 0;
for (nn = 0; nn < 200; nn++)
{
if (FASCN[(nn / 8)] & (byShift >> (nn % 8))) /* Databit = 1 */
byBCD = (byBCD | (0x01 << (nn % 5)));
byBits++; /* bit counter (per 5) */
if (byBits == 5)
{
/* each 5 bits is a character */
for (by = 0; by < NO_OF_ABA_CHARS; by++)
{
if (byBCD == abyABAMap[by])
{
FASCN_ReadChars[byBCDs++] = by;
break;
}
}
byBits = byBCD = 0; /* reset bit counter and byBCD */
}
}
In moving to C# the line below complains, "Cannot implicitly covert type 'int' to 'bool'"
if ((FASCN[(nn / 8)]) & (byShift >> (nn % 8)))
So I broke that line down into each operation to see which was complaining.
byte b1 = FASCN[(nn / 8)];
byte b2 = (nn % 8);
byte b3 = (byShift >> b2);
The bottom two gave type errors so I cast them to (byte).
byte b2 = (byte)(nn % 8);
byte b3 = (byte)(byShift >> b2);
So I tried the if() with b1 and b3, but again get a, "Cannot implicitly covert type 'int' to 'bool'"
if(b1 & b3)
Any ideas on how design that if statement in C#?
Anyone interested can review the FASCN more by reading sections 5.4, 6.0 and 6.1 of this doc - http://fips201ep.cio.gov/documents/TIG_SCEPACS_v2.2.pdf
C/C++ will treat any non 0 value as true and 0 as false, but C# expects a boolean expression to evaluate to either true or false.
Try the following
if (b1 & b2 != 0)
Well, I got my HexString (PacketS) for example "70340A0100000000000000" I want to split every time after 2 chars and put it into an byte array (Stream).
Means {70, 34, 0A, 01, 00, 00, 00, 00, 00, 00, 00}
The shortest path (.NET 4+) is (depending the length or origin):
byte[] myBytes = BigInteger.Parse("70340A0100000000000000", NumberStyles.HexNumber).ToByteArray();
Array.Reverse(myBytes);
myStram.write(myBytes, 0, myBytes.Length);
For previous versions string.length/2 also defines the length of a byte array than can be filled for each parsed pair. This byte array can be written on stream as above.
For both cases, if your origin string is too long, and you want to avoid a huge byte array, proceed with steps getting groups of N characters from your origin.
This actually worked perfect! I am sorry if your code does the same but I just do not understand.
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
}
byte[] HexAsBytes = new byte[hexString.Length / 2];
for (int index = 0; index < HexAsBytes.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return HexAsBytes;