# Upload von Block zur S7



## Jochen Kühner (16 November 2012)

Bin gerade am Upload von Bausteinen auf die S7. dazu ist zwar in libnodave was realisiert, aber Ich denke das in dem Block noch ein CRC Code Oder was ähnliches drinsteckt! Versuche mich gearde am Upload von Datenbausteinen. Es scheint so, das sicher der Code nur ändert, wenn man die Struktur des Datenbausteines ändert, wenn sich die Werte ändern, beliebt der Code gleich.
Der Code steht im Byte 10 und 9 von hinten in dem "Download Block" Telegramm (wenn man S7Comm von Thomas V2 in Wireshark verwendet!).
Hat da jemand vielleicht nähere Infos dazu??


----------



## Thomas_v2.1 (16 November 2012)

Der Teil ist genauso aufgebaut wie eine detaillierte Blockinfo Abfrage (Autor, Familie, Name, Version, was unbekanntes, Prüfsumme). Die genannten Bytes sind die Baustein-Prüfsumme. Den Wert kann man sich auch über den Simatic Manager anzeigen lassen wenn man einen Bausteinvergleich durchführt und die Bausteine unterschiedlich sind. Ist nur die Frage wie und über welche Bytes diese gebildet wird.


----------



## Jochen Kühner (16 November 2012)

Also bei einem DB beeinflussen die Anfangswerte die Prüfsumme nicht, die Aktual-Werte und die DB Struktur schon... Genauso haben Autor und Version keinen Einfluss darauf! ich mach mich mal dran herauszufinden wie diese berechnet wird...


----------



## Jochen Kühner (17 November 2012)

Thomas_v2.1 schrieb:


> Der Teil ist genauso aufgebaut wie eine detaillierte Blockinfo Abfrage (Autor, Familie, Name, Version, was unbekanntes, Prüfsumme). Die genannten Bytes sind die Baustein-Prüfsumme. Den Wert kann man sich auch über den Simatic Manager anzeigen lassen wenn man einen Bausteinvergleich durchführt und die Bausteine unterschiedlich sind. Ist nur die Frage wie und über welche Bytes diese gebildet wird.



Hast du dich damit eigentlich schon mal beschäftigt und was rausgefunden? Über welche Bytes wird ja noch rauszufinden sein... Aber wie...


----------



## Thomas_v2.1 (17 November 2012)

Jochen Kühner schrieb:


> Hast du dich damit eigentlich schon mal beschäftigt und was rausgefunden? Über welche Bytes wird ja noch rauszufinden sein... Aber wie...


Beschäftigt nicht. Aber ich würde erstmal prüfen ob die Prüfsumme die übers Netzwerk übertragen ist die gleiche ist die auch in den dbase Dateien im Feld CHECKSUM eingetragen wird. Wenn diese gleich ist, würde ich als ersten Ansatz davon ausgehen dass die Prüfsumme über den Inhalt einer einzelnen dbase Zelle gebildet wird. Am wahrscheinlichsten wäre wohl MC5CODE.

Als Prüfsummenverfahren wird wohl irgendein CRC zum Einsatz kommen. Diese unterscheiden sich aber oftmals in den Startwerten. Wenn man immer nur ein einzelnes Byte in dem Code ändert und sich dann wieder die Prüfsumme generieren lässt, wird man bestimmt irgendwie zurückrechnen können. Mit den ganzen XORs aber wohl nicht trivial.

Am Besten wäre natürlich wenn man dem Step7 Editor ein komplettes Null-Feld zur Prüfsummengenerierung unterjubeln könnte, aber das wird wohl nicht so einfach...


----------



## Jochen Kühner (17 November 2012)

Denke das Feld ssbpart wird auf jeden fall auch noch verwendet! da in der dbf zeile in der checksum gebildet wird, bei einem db der mc5 code leer ist. muss mal schauen ob in der spalte die parameter infos stecken...

Null Feld unterjubeln... Gute Idee, Ich muss mal schauen, ob die checksume bei jedem übertragen neu gebildet wird, oder nur wenn man den bausteineditor benutzt (das wäre schlecht). und ob step 7 beim übertragen aus dem simatic manger einfach die werte aus dem dbf file nutzt... (hoffentlich die checksume aber nicht)...
Ich schau mal wie ich weiterkomme...


----------



## Jochen Kühner (19 November 2012)

Hatte noch einen anderen Fehler, der Upload von Bausteinen funktioniert nun. Die Prüfsumme wird bei den normalen Bausteinen nicht benötigt. Diese wird anscheinen nur bei Safe CPUs und Safe Bausteinen geprüft (diese Info hab Ich von einem anderen Forumsmitglied)


----------



## Georgi (15 Januar 2016)

Die Prüfsumme eines Simatic S7 Bausteins wird berechnet:
Es ist eine CRC16 Prüfsumme mit dem Generator Polynom 0x9003 , Init = 0x0000 , RefIn = False, RefOut = False, XorOut = 0x0000.
Die Prüfsumme wird aus folgenden Bytes gebildet:
Byte 5, Bausteinkennung ( 0x0A for DB, 0x0C für FC, .... )
Byte 34, 35 Länge des Arbeitsspeicher in Bytes ( ohne die 36 Bytes Header Länge ) Länge MC7 Code
Byte 36 bis Byte ( 36+ Länge des Arbeitsspeicher -1 ) 
Habe das Anhand von Memory Card Dateien ( *.wld ) ausgiebig getestet.


----------



## Jochen Kühner (17 Januar 2016)

Ich werds einbauen!!


----------



## Jochen Kühner (18 Januar 2016)

Es gibt ja versch. CRC16 implementierungen, hast du auch etwas Code dazu?


----------



## Georgi (29 September 2016)

Sorry für die verspätete Antwort!
Hier meine JAVA Experimente zum Lesen/Anallysieren einer *.wld der 1 S7 Baustein beeinhaltet:

package WLD;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Calendar;

public class WLD {
    public static void main(String arg[]) {
        final String fileName = "fb5.wld";
        try {
            RandomAccessFile wldStream = new RandomAccessFile(fileName, "r");
            Long fileLen = wldStream.length();
            System.out.println("Length of File: " + fileLen+ " Bytes");
            // Read 36 Byte Header
            final int headLen = 36;
            wldStream.seek(0); // Byte 0..1 = 0x7070 Sync
            if (wldStream.readUnsignedShort() != 0x7070) {
                System.out.println("No Sync at BlockStart");
            }
            wldStream.seek(8); // Byte 8..11 = LoadMemory
            int loadMemLen = wldStream.readInt(); // Load Memory
            System.out.println("Length of Load Memory: " + loadMemLen + " Bytes");
            String s7BlockLang;
            wldStream.seek(4); // Byte 4 = BlockLanguage "AWL,KOP,FUP,SCL,DB,SDB"
            switch (wldStream.readByte()) {
            case 0x01: // AWL
                s7BlockLang= "AWL";
                break;
            case 0x02: // KOP
                s7BlockLang= "KOP";
                break;
            case 0x03: // FUP
                s7BlockLang= "FUP";
                break;
            case 0x04: // SCL
                s7BlockLang= "SCL";
                break;
            case 0x05: // DB
                s7BlockLang= "DB";
                break;
            case 0x06: // GRAPH
                s7BlockLang= "GRAPH";
                break;
            case 0x07: // SDB
                s7BlockLang= "SDB";
                break;
            default:
                s7BlockLang = "Unknown";
            }
            System.out.println(s7BlockLang);
            wldStream.seek(5); // Byte 5 = Block Type ID "DB,FC,FB,SDB"
            byte s7BlockType = wldStream.readByte();
            String s7BlockTypeS;
            switch (s7BlockType) {
            case 0x08: // OB
                s7BlockTypeS = "OB";
                break;
            case 0x0A: // DB
                s7BlockTypeS = "DB";
                break;
            case 0x0B: // SDB
                s7BlockTypeS = "SDB";
                break;
            case 0x0C: // FC
                s7BlockTypeS = "FC";
                break;
            case 0x0D: // SFC
                s7BlockTypeS = "SFC";
                break;
            case 0x0E: // FB 
                s7BlockTypeS = "FB";
                break;
            case 0x0F: // SFB
                s7BlockTypeS = "SFB";
                break;
            default:
                s7BlockTypeS = "Unknown";
            }
            wldStream.seek(6); // Byte 6..7 = BlockNumber
            int blockNo = wldStream.readUnsignedShort();
            System.out.println(s7BlockTypeS+" "+blockNo);
            wldStream.seek(15); //
            boolean knowHowProtect = (wldStream.readByte() == 3);
            System.out.println("KnowHowProtected: " + Boolean.toString(knowHowProtect));
            // ---------------------------------
            Calendar calTimeStampChanged = Calendar.getInstance();
            calTimeStampChanged.set(Calendar.YEAR, 1984);
            calTimeStampChanged.set(Calendar.MONTH, 0); // 0 = Januar!
            calTimeStampChanged.set(Calendar.DAY_OF_MONTH, 1);
            calTimeStampChanged.set(Calendar.HOUR_OF_DAY, 0);
            calTimeStampChanged.set(Calendar.MINUTE, 0);
            calTimeStampChanged.set(Calendar.SECOND, 0);
            calTimeStampChanged.set(Calendar.MILLISECOND, 0);
            wldStream.seek(16); // TimeStamp Changed Byte 16-21
            int msSinceMidnight = wldStream.readInt();
            wldStream.seek(20); // TimeStamp Changed Byte 20-21
            int days1184 = wldStream.readUnsignedShort(); // Days since
                                                            // 1.Jan.1984
            calTimeStampChanged.add(Calendar.DAY_OF_YEAR, days1184);
            calTimeStampChanged.add(Calendar.MILLISECOND, msSinceMidnight);
            System.out.printf("Changed: ");
            System.out.printf("%tD", calTimeStampChanged); // 01/01/84
            System.out.printf(" ");
            System.out.printf("%tT%n", calTimeStampChanged);
            // wldStream.seek(22); // TimeStamp Schnittstellen Änderung Byte
            // 22-27
            Calendar calTimeStampIfChanged = Calendar.getInstance();
            calTimeStampIfChanged.set(Calendar.YEAR, 1984);
            calTimeStampIfChanged.set(Calendar.MONTH, 0); // 0 = Januar!
            calTimeStampIfChanged.set(Calendar.DAY_OF_MONTH, 1);
            calTimeStampIfChanged.set(Calendar.HOUR_OF_DAY, 0);
            calTimeStampIfChanged.set(Calendar.MINUTE, 0);
            calTimeStampIfChanged.set(Calendar.SECOND, 0);
            calTimeStampIfChanged.set(Calendar.MILLISECOND, 0);
            wldStream.seek(22); // TimeStamp Changed Byte 22-25 Millisecond
                                // since Mindnight 0:00:00
            int msIfSinceMidnight = wldStream.readInt();
            wldStream.seek(26); // TimeStamp Changed Byte 26-27 Days since
                                // 1.Jan.1984
            int daysIf1184 = wldStream.readUnsignedShort();
            calTimeStampIfChanged.add(Calendar.DAY_OF_YEAR, daysIf1184);
            calTimeStampIfChanged.add(Calendar.MILLISECOND, msIfSinceMidnight);
            System.out.printf("IF Changed : ");
            System.out.printf("%tD", calTimeStampIfChanged);
            System.out.printf(" ");
            System.out.printf("%tT%n", calTimeStampIfChanged);
            wldStream.seek(28); // Len of Structure Datas [Bytes]
            int structDataLen = wldStream.readUnsignedShort();
            System.out.println("Length of Structure Datas: " + structDataLen + " Bytes");
            wldStream.seek(30); // Len of Sdb Datas [Bytes]
            int sdbDataLen = wldStream.readUnsignedShort();
            System.out.println("Length of SDB Datas: " + sdbDataLen + " Bytes");
            wldStream.seek(34); // Len of Working Memory Datas [Bytes]
            int workMemLen = wldStream.readUnsignedShort();
            System.out.println("Length of Working Memory without Header: " + workMemLen + " Bytes");
            System.out.println("Length of Working Memory: " + (workMemLen + headLen) + " Bytes");
            // Reading Working Memory Datas, Starting at Byte 36 (= headLen)
            // wldStream.seek(headLen);
            // Reading Structure Datas, Starting at Byte headLen+workMemLen
            if (s7BlockTypeS=="DB"){
             wldStream.seek(headLen + workMemLen + 1);// Blocknumber in Structure, Datas are in Big Endian!
            int blockNoStruct = wldStream.readUnsignedByte() | (wldStream.readUnsignedByte() << 8);
            if( blockNoStruct != blockNo){
                System.out.println("Unequal DB Number in Struct Data! :" + blockNoStruct);
            }
              wldStream.seek(3); // Byte 3 = Retain / Linked
            byte retainLinked = wldStream.readByte();
            boolean linked = (retainLinked & 0x01) == 0x01;
            boolean nonRetain = (retainLinked & 0x20) == 0x20;
            System.out.println("Linked: " + Boolean.toString(linked));
            System.out.println("Non-Retain: " + Boolean.toString(nonRetain));
            wldStream.seek(33); // ReadOnly
            boolean readOnly = (wldStream.readByte() & 0x1) == 0x1;
            System.out.println("ReadOnly: " + Boolean.toString(readOnly));
            }
            if (s7BlockTypeS=="FC" || s7BlockTypeS=="FB"){
                wldStream.seek(32); // Local Memory need
                int locMemLen = wldStream.readUnsignedShort();
                System.out.println("Length of Local Memory: " + locMemLen + " Bytes");
            }
            byte[] bufferChar = new byte[8];
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen); // Read 8 Byte Author
            wldStream.readFully(bufferChar);
            String author = new String(bufferChar, "UTF-8");
            System.out.println("Author: " + author);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 8); // Read 8 Byte Family
            wldStream.readFully(bufferChar);
            String family = new String(bufferChar, "UTF-8");
            System.out.println("Familie: " + family);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 16); // Read 8 Byte Name (Header)
            wldStream.readFully(bufferChar);
            String name = new String(bufferChar, "UTF-8");
            System.out.println("Name: " + name);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 24);// Read 1 Byte Version Number
            byte versionNumber = wldStream.readByte();
            System.out.println("Version Number: "+ ((versionNumber & 0xF0) >> 4) + "." + (versionNumber & 0xF));
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 26);// Read 2 Byte Checksum
            int checkSum = wldStream.readUnsignedShort();
            System.out.println("Checksum: 0x" + Integer.toHexString(checkSum));
*            // CRC Calculation
            wldStream.seek(headLen-2); // Len MC7 Code + MC7 Code
            int crc = 0x0000;
            int polynomial = 0x9003;
            byte b;
            b = s7BlockType;
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7-i) & 1) == 1);
                boolean c15 = ((crc >> 15    & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit) crc ^= polynomial;
            }        
            for (int count = 0; count < workMemLen+2; count++) {
            b = wldStream.readByte();
                for (int i = 0; i < 8; i++) {
                    boolean bit = ((b >> (7-i) & 1) == 1);
                    boolean c15 = ((crc >> 15    & 1) == 1);
                    crc <<= 1;
                    if (c15 ^ bit) crc ^= polynomial;
                 }
            }
            crc &=0xFFFF;
*            System.out.println("Checksum Calculated: 0x" + Integer.toHexString(crc));
            // End of CRC Calculation
            wldStream.close();
        } catch (FileNotFoundException ex) {
            System.out.println("Unable to open file '" + fileName + "'");
        } catch (IOException ex) {
            System.out.println("Error reading file '" + fileName + "'");
            // Or we could just do this:
            // ex.printStackTrace();
        }
    } // End Main
} // End Class


----------



## Thomas_v2.1 (29 September 2016)

Mach doch bitte mal code-Tags um deine Funktion, dann verschwinden auch die Smilies.


----------



## Georgi (29 September 2016)

Ja die  Smiley's, sind mir dann doch auch aufgefallen!

```
package WLD;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Calendar;

public class WLD {
    public static void main(String arg[]) {
        final String fileName = "fb5.wld";
        try {
            RandomAccessFile wldStream = new RandomAccessFile(fileName, "r");
            Long fileLen = wldStream.length();
            System.out.println("Length of File: " + fileLen+ " Bytes");
            // Read 36 Byte Header
            final int headLen = 36;
            wldStream.seek(0); // Byte 0..1 = 0x7070 Sync
            if (wldStream.readUnsignedShort() != 0x7070) {
                System.out.println("No Sync at BlockStart");
            }
            wldStream.seek(8); // Byte 8..11 = LoadMemory
            int loadMemLen = wldStream.readInt(); // Load Memory
            System.out.println("Length of Load Memory: " + loadMemLen + " Bytes");
            String s7BlockLang;
            wldStream.seek(4); // Byte 4 = BlockLanguage "AWL,KOP,FUP,SCL,DB,SDB"
            switch (wldStream.readByte()) {
            case 0x01: // AWL
                s7BlockLang= "AWL";
                break;
            case 0x02: // KOP
                s7BlockLang= "KOP";
                break;
            case 0x03: // FUP
                s7BlockLang= "FUP";
                break;
            case 0x04: // SCL
                s7BlockLang= "SCL";
                break;
            case 0x05: // DB
                s7BlockLang= "DB";
                break;
            case 0x06: // GRAPH
                s7BlockLang= "GRAPH";
                break;
            case 0x07: // SDB
                s7BlockLang= "SDB";
                break;
            default:
                s7BlockLang = "Unknown";
            }
            System.out.println(s7BlockLang);
            wldStream.seek(5); // Byte 5 = Block Type ID "DB,FC,FB,SDB"
            byte s7BlockType = wldStream.readByte();
            String s7BlockTypeS;
            switch (s7BlockType) {
            case 0x08: // OB
                s7BlockTypeS = "OB";
                break;
            case 0x0A: // DB
                s7BlockTypeS = "DB";
                break;
            case 0x0B: // SDB
                s7BlockTypeS = "SDB";
                break;
            case 0x0C: // FC
                s7BlockTypeS = "FC";
                break;
            case 0x0D: // SFC
                s7BlockTypeS = "SFC";
                break;
            case 0x0E: // FB 
                s7BlockTypeS = "FB";
                break;
            case 0x0F: // SFB
                s7BlockTypeS = "SFB";
                break;
            default:
                s7BlockTypeS = "Unknown";
            }
            wldStream.seek(6); // Byte 6..7 = BlockNumber
            int blockNo = wldStream.readUnsignedShort();
            System.out.println(s7BlockTypeS+" "+blockNo);
            wldStream.seek(15); //
            boolean knowHowProtect = (wldStream.readByte() == 3);
            System.out.println("KnowHowProtected: " + Boolean.toString(knowHowProtect));
            // ---------------------------------
            Calendar calTimeStampChanged = Calendar.getInstance();
            calTimeStampChanged.set(Calendar.YEAR, 1984);
            calTimeStampChanged.set(Calendar.MONTH, 0); // 0 = Januar!
            calTimeStampChanged.set(Calendar.DAY_OF_MONTH, 1);
            calTimeStampChanged.set(Calendar.HOUR_OF_DAY, 0);
            calTimeStampChanged.set(Calendar.MINUTE, 0);
            calTimeStampChanged.set(Calendar.SECOND, 0);
            calTimeStampChanged.set(Calendar.MILLISECOND, 0);
            wldStream.seek(16); // TimeStamp Changed Byte 16-21
            int msSinceMidnight = wldStream.readInt();
            wldStream.seek(20); // TimeStamp Changed Byte 20-21
            int days1184 = wldStream.readUnsignedShort(); // Days since
                                                            // 1.Jan.1984
            calTimeStampChanged.add(Calendar.DAY_OF_YEAR, days1184);
            calTimeStampChanged.add(Calendar.MILLISECOND, msSinceMidnight);
            System.out.printf("Changed: ");
            System.out.printf("%tD", calTimeStampChanged); // 01/01/84
            System.out.printf(" ");
            System.out.printf("%tT%n", calTimeStampChanged);
            // wldStream.seek(22); // TimeStamp Schnittstellen Änderung Byte
            // 22-27
            Calendar calTimeStampIfChanged = Calendar.getInstance();
            calTimeStampIfChanged.set(Calendar.YEAR, 1984);
            calTimeStampIfChanged.set(Calendar.MONTH, 0); // 0 = Januar!
            calTimeStampIfChanged.set(Calendar.DAY_OF_MONTH, 1);
            calTimeStampIfChanged.set(Calendar.HOUR_OF_DAY, 0);
            calTimeStampIfChanged.set(Calendar.MINUTE, 0);
            calTimeStampIfChanged.set(Calendar.SECOND, 0);
            calTimeStampIfChanged.set(Calendar.MILLISECOND, 0);
            wldStream.seek(22); // TimeStamp Changed Byte 22-25 Millisecond
                                // since Mindnight 0:00:00
            int msIfSinceMidnight = wldStream.readInt();
            wldStream.seek(26); // TimeStamp Changed Byte 26-27 Days since
                                // 1.Jan.1984
            int daysIf1184 = wldStream.readUnsignedShort();
            calTimeStampIfChanged.add(Calendar.DAY_OF_YEAR, daysIf1184);
            calTimeStampIfChanged.add(Calendar.MILLISECOND, msIfSinceMidnight);
            System.out.printf("IF Changed : ");
            System.out.printf("%tD", calTimeStampIfChanged);
            System.out.printf(" ");
            System.out.printf("%tT%n", calTimeStampIfChanged);
            wldStream.seek(28); // Len of Structure Datas [Bytes]
            int structDataLen = wldStream.readUnsignedShort();
            System.out.println("Length of Structure Datas: " + structDataLen + " Bytes");
            wldStream.seek(30); // Len of Sdb Datas [Bytes]
            int sdbDataLen = wldStream.readUnsignedShort();
            System.out.println("Length of SDB Datas: " + sdbDataLen + " Bytes");
            wldStream.seek(34); // Len of Working Memory Datas [Bytes]
            int workMemLen = wldStream.readUnsignedShort();
            System.out.println("Length of Working Memory without Header: " + workMemLen + " Bytes");
            System.out.println("Length of Working Memory: " + (workMemLen + headLen) + " Bytes");
            // Reading Working Memory Datas, Starting at Byte 36 (= headLen)
            // wldStream.seek(headLen);
            // Reading Structure Datas, Starting at Byte headLen+workMemLen
            if (s7BlockTypeS=="DB"){
             wldStream.seek(headLen + workMemLen + 1);// Blocknumber in Structure, Datas are in Big Endian!
            int blockNoStruct = wldStream.readUnsignedByte() | (wldStream.readUnsignedByte() << 8);
            if( blockNoStruct != blockNo){
                System.out.println("Unequal DB Number in Struct Data! :" + blockNoStruct);
            }
              wldStream.seek(3); // Byte 3 = Retain / Linked
            byte retainLinked = wldStream.readByte();
            boolean linked = (retainLinked & 0x01) == 0x01;
            boolean nonRetain = (retainLinked & 0x20) == 0x20;
            System.out.println("Linked: " + Boolean.toString(linked));
            System.out.println("Non-Retain: " + Boolean.toString(nonRetain));
            wldStream.seek(33); // ReadOnly
            boolean readOnly = (wldStream.readByte() & 0x1) == 0x1;
            System.out.println("ReadOnly: " + Boolean.toString(readOnly));
            }
            if (s7BlockTypeS=="FC" || s7BlockTypeS=="FB"){
                wldStream.seek(32); // Local Memory need
                int locMemLen = wldStream.readUnsignedShort();
                System.out.println("Length of Local Memory: " + locMemLen + " Bytes");
            }
            byte[] bufferChar = new byte[8];
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen); // Read 8 Byte Author
            wldStream.readFully(bufferChar);
            String author = new String(bufferChar, "UTF-8");
            System.out.println("Author: " + author);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 8); // Read 8 Byte Family
            wldStream.readFully(bufferChar);
            String family = new String(bufferChar, "UTF-8");
            System.out.println("Familie: " + family);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 16); // Read 8 Byte Name (Header)
            wldStream.readFully(bufferChar);
            String name = new String(bufferChar, "UTF-8");
            System.out.println("Name: " + name);
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 24);// Read 1 Byte Version Number
            byte versionNumber = wldStream.readByte();
            System.out.println("Version Number: "+ ((versionNumber & 0xF0) >> 4) + "." + (versionNumber & 0xF));
            wldStream.seek(headLen + workMemLen + sdbDataLen + structDataLen + 26);// Read 2 Byte Checksum
            int checkSum = wldStream.readUnsignedShort();
            System.out.println("Checksum: 0x" + Integer.toHexString(checkSum));
            // CRC Calculation
            wldStream.seek(headLen-2); // Len MC7 Code + MC7 Code
            int crc = 0x0000;
            int polynomial = 0x9003;
            byte b;
            b = s7BlockType;
            for (int i = 0; i < 8; i++) {
                boolean bit = ((b >> (7-i) & 1) == 1);
                boolean c15 = ((crc >> 15    & 1) == 1);
                crc <<= 1;
                if (c15 ^ bit) crc ^= polynomial;
            }        
            for (int count = 0; count < workMemLen+2; count++) {
            b = wldStream.readByte();
                for (int i = 0; i < 8; i++) {
                    boolean bit = ((b >> (7-i) & 1) == 1);
                    boolean c15 = ((crc >> 15    & 1) == 1);
                    crc <<= 1;
                    if (c15 ^ bit) crc ^= polynomial;
                 }
            }
            crc &=0xFFFF;
            System.out.println("Checksum Calculated: 0x" + Integer.toHexString(crc));
            // End of CRC Calculation
            wldStream.close();
        } catch (FileNotFoundException ex) {
            System.out.println("Unable to open file '" + fileName + "'");
        } catch (IOException ex) {
            System.out.println("Error reading file '" + fileName + "'");
            // Or we could just do this:
            // ex.printStackTrace();
        }
    } // End Main
} // End Class
```


----------



## Bernd_Otter (7 Oktober 2016)

Hallo Georgi,

erstmal vielen Dank für die Infos. Ich versuche gerade die CRC-Summe für einen kurzen FC nach Deinen Angaben zu berechnen, komme jedoch nicht auf das Ergebnis was für diesen FC in der SUBBLK.DBF abgelegt ist. Um herauszufinden wo der Fehler liegt oder ob die Berechnung der CRC in der SUBBLK.DBF anders erfolgt hier mein Vorgehen.


Um möglichst die gleichen Voraussetzungen zu haben wie Du habe ich meinen FC in eine wld-Datei exportiert und die folgenden Bytes für die Generierung der Prüfsumme identifiziert:
Byte 5 = 0x0C [da ein FC vorliegt]
Byte 34, 35 = 0x00 0x0E [da der MC7code 14 Byte lang ist]
Byte 36 bis 36+14-1 = 0xC0 0x00 0xC1 0x00 0xC3 0x00 0xC4 0x00 0xC5 0x00 0xD8 0x80 0x65 0x00 [MC7code]
Zusammen = 0x0C 0x00 0x0E 0xC0 0x00 0xC1 0x00 0xC3 0x00 0xC4 0x00 0xC5 0x00 0xD8 0x80 0x65 0x00
Jetzt habe ich Deine Parameter und die in Punkt 1 zusammengefügten Eingangsdaten für die CRC-Berechnung in folgende Webseite eingegeben http://www.sunshine2k.de/coding/javascript/crc/crc_js.html.



Das Ergebnis lautet 0x7822 was 30754 entspricht. In der SUBBLK.DBF sind jedoch 8824 angegeben was 0x2278 entspricht. Habe ich bei der Berechnung einen Fehler gemacht?


Viele Grüße

Otter


----------



## Jochen Kühner (14 Oktober 2016)

Vlt. musst du die bytes noch drehen, endianess


----------



## Bernd_Otter (2 Januar 2017)

Hallo Jochen,

das war es! Bin zwischenzeitlich auch drauf gekommen. Damit stimmen die Checksummen auch mit den Einträgen in der SUBBLK.DBF überein!

Viele Grüße und Frohes Neues Jahr


----------



## Jochen Kühner (2 Januar 2017)

Hab die CRC berechnung mal in meine Toolbox mit eingebaut (https://github.com/dotnetprojects/DotNetSiemensPLCToolBoxLibrary). Muss es noch mit einer CPU testen, und die crc bytes ins telegram einbauen


----------

