CRC Check

Hallo,

wie mache ich eine CRC Prüfung?

Ich bekomme folgenden Datenblock (HEX):
00101F0179077E015F004474

Die letzten beiden HEX Werte sind die 44 low Byte CRC und 74 High Byte CRC
Davor sind einzelne Hexwerte und verschiedene High Low Bytes.
In Dezimal müsste der CRC Wert 29764 sein.

Ich versuche es mit dieser Funktion:

 
 function crc16($data) { 
   $crc = 0xFFFF;
       for ($i = 0; $i < strlen($data); $i++)   {    
              $x = (($crc >> 8) ^ ord($data[$i])) & 0xFF;     $x ^= $x >> 4;     $crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;  
 }   
return $crc; 
}

Aber egal was ich durch die Funktion gebe, es kommt nicht 29764 raus.

Gruß
Steffen

Wo ist denn das Protokoll? Bei CRC-16 gibt es mehrere Variante, wie man diese Berechnen kann. Normalerweise geht dies über alle Bytes.

paresy

Hallo,

Es ist ein LevelJet. Habe heute mit dem Hersteller geredet da ich noch andere Fragen hatte. Es gibt anscheinend unterschiedliche CRC Verfahren bei seinen unterschiedlichen Gerätemodellen wenn ich das richtig verstanden habe. Er will mir Morgen die benötigten Infos schicken.

Gruß
Steffen

Wir haben für den LevelJet ein Modul. Oder verstehe ich da was falsch?

paresy

Ja weiss ich. Leider wird mir dort „nur“ die Füllmenge und Abstand zum Sensor angezeigt. Der Leveljet liefert aber noch mehr hilfreiche Informationen. Auch werden die Variablen jede Sekunde aktualisiert was für das Loggen nicht optimal ist. Vielleicht gibt es da eine Lösung für das Loggen (nur 1x täglich) die mir noch nicht bekannt ist. Für eine Zisterne mit Pumpe sind die Sekundlichen Aktualisierungen nötig aber nicht für einen Öltank.

Und da ich mich sowieso mal an das Modulschreiben ranwagen möchte werde ich das mit dem LevelJet machen.

Gruß
Steffen

Hallo,

ich komme leider bei der CRC16 Prüfung nicht weiter.

Also nochmal ein Beispiel:

Ich bekomme vom Leveljet folgenden HEX Code: 00101501830780015f2065fc
Die letzten 2 Bytes sind die CRC High und low Bytes: 65fc

Ich bin jetzt soweit gekommen, wenn ich auf dieser Seite folgende Einstellungen mache:
Sunshine’s Homepage - Online CRC Calculator Javascript
CRC width: CRC-16
CRC parametrization: CRC16-BUYPASS
(Automatisch ausgefüllt wird Polynomial: 0x8005)
CRC Input Data: Bytes Textfeld: 00101501830780015f20

Als Ergebnis bekomme ich 0xFC65
Das kommt den 65FC ja schon sehr nahe. Aber wie würde die PHP Funktion dafür heißen?

//unsigned short calculateCRC16(char input[], int lenght)function calculateCRC16( $input ){	$length = strlen( $input );	//const unsigned int SHIFTER = 0x00FF;	$SHIFTER = 0x00FF;	//unsigned short crc16table[256] =	$crc16table =	array(		0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,		0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,		0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,		0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,		0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,		0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,		0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,		0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,		0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,		0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,		0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,		0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,		0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,		0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,		0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,		0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,		0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,		0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,		0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,		0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,		0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,		0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,		0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,		0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,		0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,		0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,		0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,		0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,		0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,		0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,		0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,		0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202	);	//unsigned short CRC16 = 0;	$CRC16 = 0;	for($i = 0; $i < $length; $i++)	{		//unsigned  short tableValue = crc16table[((CRC16>>8)^*(char *)input++)&SHIFTER];		$chrval = ord($input[$i]);		$idx = (($CRC16>>8) ^ $chrval ) & $SHIFTER;		$tableValue = $crc16table[ $idx ];		$CRC16=($CRC16<<8)^$tableValue;	}	return $CRC16;} // end function//printf( calculateCRC16(0x00101501830780015f2065fc) );

Diese könnte richtig sein. Aber mit 0x00101501830780015f2065fc bekomme ich eine 0 raus.

Gruß
Steffen

Du übergibst eine Zahl an die Funktion, Welche aber einen String (aus Bytes) erwartet.
Somit kann da nix sinnvolles rauskommen.
Habe es jetzt aber selbst nicht getestet ob die Funktion korrekt ist.
Michael

Ah ok.

Wenn ich „00101501830780015f20“ übergebe kommt 206931550 raus. Denke das ist aber zu lang. ich weiß aber auch nicht wie ich diese Zahl in ein High und low Byte umwandle.

Gruß
Steffen

„00101501830780015f20“
Ist ein String welcher nur Hex-Zahlen enthält und kein String aus simplen Bytes wie du ihn z.B. aus einer RegVar oder auch innerhalb eines IPS-Moduls bekommst.

"\x00\x10\x15\x01\x83\x07\x80\x01\x5f\x20"

Sollte zum testen der Funktion reichen.
Michael

PS: Allerdings liefert deine Funktion 32 Bit anstatt 16 zurück, was einfach an den typenlosen Variablen in PHP liegt.


$crcint = calculateCRC16("\x00\x10\x15\x01\x83\x07\x80\x01\x5f\x20");
echo dechex($crcint).PHP_EOL;
$crc = pack("n",$crcint); // in ein 2Byte String konvertieren.
echo dechex(ord($crc[0])).PHP_EOL;
echo dechex(ord($crc[1])).PHP_EOL;


b5b1fc65
fc
65

Hallo,

ok so funktioniert es.

Vielen Dank :slight_smile: