C# - S7 1200 DB auslesen ohne externe Library

MarkusB.

Level-2
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,

ich denke es ist besser dafür einen eigenen Thread aufzumachen. Und zwar versuche ich mich ein wenig in C# in Verdingung mit Simatic. Ich möchte gerne bei einer
S7 1200 lediglich ein Datenwort aus einem DB oder einen Bereich auslesen, da ich mehr die Kommunikation verstehen möchte. Die Verbindung zur SPS funktioniert auch soweit, auch in Wireshark sieht das gesendete Paket soweit plausible aus. Das Problem ist das ich keine Antwort der SPS auf diesen Readrequest erhalte. Ich habe die Vermutung, das da irgendwas mit der Reihenfolge oder Syntax nicht stimmt.
Hier mal der ReadRequest

C#:
byte[] readRequest = new byte[]
{
    // TPKT-Header (4 Bytes)
    0x03, 0x00, 0x00, 0x20,      // Länge = 32 Bytes

    // COTP-Header (3 Bytes)
    0x02, 0xF0, 0x80,

    // S7-Protokoll-Header (10 Bytes)
    0x32,       // Protokollkennung: 0x32
    0x01,       // Job Request
    0x00, 0x00, // Reserved
    0x00, 0x01, // PDU-Referenz
    0x00, 0x0F, // Parameterlänge: 15 Bytes
    0x00, 0x00, // Datenteil-Länge: 0

    // Parameterblock (15 Bytes)
    0x04,       // Funktion: Read Variable
    0x01,       // Anzahl der Items: 1
    0x12,       // Variablenspezifikation: S7 ANY Pointer
    0x0A,       // Länge der Adressierungsspezifikation: 10 Bytes
    0x10,       // Syntax-ID: S7-Adressierung
    0x04,       // Transportgröße: Word (0x04)
    0x00, 0x02, // Anzahl der zu lesenden Bytes: 6 (3 * 2)
    0x00, 0x08, // Datenbausteinnummer: DB8
    0x84,       // Speicherbereich: DB (0x84)
    0x00, 0x00, 0x00, // Offset in Bits: 16 (2 Byte * 8) → Beginn bei Word 1
    0x00        // Bit-Offset: 0
};

in Wireshark sieht es eigentlich soweit gut aus.


Code:
S7 Communication
    Header: (Job)
        Protocol Id: 0x32
        ROSCTR: Job (1)
        Redundancy Identification (Reserved): 0x0000
        Protocol Data Unit Reference: 1
        Parameter length: 15
        Data length: 0
    Parameter: (Read Var)
        Function: Read Var (0x04)
        Item count: 1
        Item [1]: (DB 8.DBX 0.0 WORD 2)
            Variable specification: 0x12
            Length of following address specification: 10
            Syntax Id: S7ANY (0x10)
            Transport size: WORD (4)
            Length: 2
            DB number: 8
            Area: Data blocks (DB) (0x84)
            Address: 0x000000
                .... .000 0000 0000 0000 0... = Byte Address: 0
                .... .... .... .... .... .000 = Bit Address: 0

hier noch die connection

Code:
ISO 8073/X.224 COTP Connection-Oriented Transport Protocol
    Length: 17
    PDU Type: CC Connect Confirm (0x0d)
    Destination reference: 0x0001
    Source reference: 0x0004
    0000 .... = Class: 0
    .... ..0. = Extended formats: False
    .... ...0 = No explicit flow control: False
    Parameter code: tpdu-size (0xc0)
    Parameter length: 1
    TPDU size: 512
    Parameter code: src-tsap (0xc1)
    Parameter length: 2
    Source TSAP: 0100
    Parameter code: dst-tsap (0xc2)
    Parameter length: 2
    Destination TSAP: 0101

Hat eventuell jemand eine Idee was an dem Readrequest falsch sein könnte? Oder hat eventuell jemand ein funktionierendes Beispiel?

Viele Grüße
Markus
 
Zuletzt bearbeitet:
Hallo,

ist zwar alles schon ein paar Jahre her, aber eventuell kannst du mit den Ausschnitten von meinem Programm etwas anfangen.
Soweit du es bis jetzt gepostet hast, verbindest du dich mit dem ISOonTCP, jedoch fehlt dir noch der Zwischenschritt um die S7-Communication aufzubauen. Wenn du es so wie beschrieben machst, dann schickst du eine ReadRequest obwohl die S7-Verbindung noch nicht aktiv ist.

Sieht bei mir etwas anders aus und ein paar Variablen sind definiert, denke aber es sollte z.B.: klar sein, dass der TSAP für verschiedene CPU-Typen umgestellt werden muss.

Zuerst ISOonTCP:
1739178637491.png

Dann die S7Setup für die S7-Verbindung:
1739178659284.png

Und dann die ReadRequest, vorallem das Pointerformat für die Startadresse ist hier wichtig:
1739178706802.png


Ich hoffe du kannst mit den Snipps etwas herausfinden ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Super, vielen Dank, das werde ich mal ausprobieren. Weißt du noch für was für eine CPU das war ?
Den Connect habe ich eigentlich drin aber da bin ich mir auch nicht sicher ob der so richtig ist.
Verbindung steht zwar, aber auf einen Read Request kommt keine plausible Antwort.
C#:
  byte[] connectRequest = new byte[]
 {
          3, 0, 0, 22,            // TPKT-Header: Version = 3, Reserved = 0, Länge = 22 Bytes
          0x11, 0xE0, 0x00, 0x00, // COTP-Header: 0x11 signalisiert Connect Request, gefolgt von weiteren Steuerbytes
          0x00, 0x01, 0x00, 0xC1, // Lokaler TSAP: Parametercode 0xC1 plus 0x00, 0x01 als Teil des TSAP-Werts
          0x02, 0x01, 0x00,       // Lokaler TSAP-Wert: entspricht 0x02, 0x01, 0x00 (also 0x0100)
          0xC2, 2, 1, 0,          // Remote TSAP: Parametercode 0xC2 plus Wert 0x02, 0x01, 0x00 (also 0x0100)
          0xC0, 1, 9              // PDU-Größe: Parametercode 0xC0, Länge 1 Byte, Wert 9 (entspricht einer PDU-Größe von 2^9 = 512 Bytes)
  };
 
Bei mir war es eine 1500er CPU, sollte auch passen.
Ich denke die PUT/GET Kommunikation hast du eingeschaltet? Ansonsten würde auch der normale Verbindungsaufbau nicht funktionieren.

Wie sieht das Antwort-Telegramm aus?
 
Hallo Rabi,

also was ich jetzt mal versucht habe ist mit WireShark eine OPC Kepware Verbindung aufzuzeichen die das Datenwort liest. Lokaler und remote TSAP sehen komplett anders aus als ich das kenne. Wie auch immer mit Kepware kann ich das Datenwort ja lesen und der Mechanismus ist ja der selbe.

Hier mal das Ergenis meines Tests:

Code:
TCP-Verbindung hergestellt.
[1/3] Sende COTP-Connect-Request:
03 00 00 16 11 E0 00 00 00 01 00 C0 01 0A C1 02 4B 54 C2 02 03 01

[2/3] COTP-Connect-Response:
03 00 00 16 11 D0 00 01 00 06 00 C0 01 0A C1 02 4B 54 C2 02 03 01

[3/3] Sende S7-Leseanfrage:
03 00 00 20 02 F0 80 32 01 00 00 00 01 00 0E 00 00 04 01 12 0A 10 02 00 04 00 08 84 00 00 02 00

S7-Leseantwort:

Hier mal der Mitschnitt der Leseanfrage:
Code:
S7 Communication
    Header: (Job)
        Protocol Id: 0x32
        ROSCTR: Job (1)
        Redundancy Identification (Reserved): 0x0000
        Protocol Data Unit Reference: 1
        Parameter length: 14
        Data length: 0
    Parameter: (Read Var)
        Function: Read Var (0x04)
        Item count: 1
        Item [1]: (DB 8.DBX 0.2 BYTE 4)
            Variable specification: 0x12
            Length of following address specification: 10
            Syntax Id: S7ANY (0x10)
            Transport size: BYTE (2)
            Length: 4
            DB number: 8
            Area: Data blocks (DB) (0x84)
            Address: 0x000002
                .... .000 0000 0000 0000 0... = Byte Address: 0
                .... .... .... .... .... .010 = Bit Address: 2

Auf die Leseanfrage antwortet die SPS mit folgendem Paket

Code:
Frame 643: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) on interface \Device\NPF_{1694CB0F-xxxxx3F8AC8C6}, id 0
    Section number: 1
    Interface id: 0 (\Device\NPF_{16xxxxxxx-8448-4AD0-AA7D-32Dxxxxxxx})
    Encapsulation type: Ethernet (1)
    Arrival Time: Feb 10, 2025 16:31:22.120850000 Mitteleuropäische Zeit
    UTC Arrival Time: Feb 10, 2025 15:31:22.120850000 UTC
    Epoch Arrival Time: 1739201482.120850000
    [Time shift for this packet: 0.000000000 seconds]
    [Time delta from previous captured frame: 0.005722000 seconds]
    [Time delta from previous displayed frame: 0.005722000 seconds]
    [Time since reference or first frame: 39.144845000 seconds]
    Frame Number: 643
    Frame Length: 60 bytes (480 bits)
    Capture Length: 60 bytes (480 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp]
    [Coloring Rule Name: TCP SYN/FIN]
    [Coloring Rule String: tcp.flags & 0x02 || tcp.flags.fin == 1]
Ethernet II, Src: SiemensNumer_08:xx:cd (00:xx:06:08:xx:cd), Dst: Intel_46:91:a5 (xx:c9:xx:46:xx:xx)
    Destination: Intel_46:91:a5 (34:xxx:a5)
    Source: SiemensNumer_08:1b:cd (00:1c:xxxxx:cd)
    Type: IPv4 (0x0800)
    [Stream index: 8]
    Padding: 000000000000
Internet Protocol Version 4, Src: 192.168.178.9, Dst: 192.168.178.20
    0100 .... = Version: 4
    .... 0101 = Header Length: 20 bytes (5)
    Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
    Total Length: 40
    Identification: 0x00f7 (247)
    000. .... = Flags: 0x0
    ...0 0000 0000 0000 = Fragment Offset: 0
    Time to Live: 30
    Protocol: TCP (6)
    Header Checksum: 0xb66a [validation disabled]
    [Header checksum status: Unverified]
    Source Address: 192.168.178.9
    Destination Address: 192.168.178.20
    [Stream index: 6]
Transmission Control Protocol, Src Port: 102, Dst Port: 63963, Seq: 23, Ack: 54, Len: 0
    Source Port: 102
    Destination Port: 63963
    [Stream index: 1]
    [Conversation completeness: Complete, WITH_DATA (63)]
    [TCP Segment Len: 0]
    Sequence Number: 23    (relative sequence number)
    Sequence Number (raw): 197039
    [Next Sequence Number: 24    (relative sequence number)]
    Acknowledgment Number: 54    (relative ack number)
    Acknowledgment number (raw): 2833262550
    0101 .... = Header Length: 20 bytes (5)
    Flags: 0x011 (FIN, ACK)
    Window: 4096
    [Calculated window size: 4096]
    [Window size scaling factor: -2 (no window scaling used)]
    Checksum: 0xedb9 [unverified]
    [Checksum Status: Unverified]
    Urgent Pointer: 0
    [Timestamps]
        [Time since first frame in this TCP stream: 35.663173000 seconds]
        [Time since previous frame in this TCP stream: 0.005722000 seconds]
    [SEQ/ACK analysis]
        [This is an ACK to the segment in frame: 642]
        [The RTT to ACK the segment was: 0.005722000 seconds]
        [iRTT: 0.112653000 seconds]
 
Zuviel Werbung?
-> Hier kostenlos registrieren
kann es sein das ich da einen Schritt vergessen habe? Und zwar sende ich jetzt mal nach dem Connect request das Kommunikationssetup vor dem read request. Jetzt bekomme ich auch eine Antwort auf mein Readrequest

Hier mal das "Setup Communicaton" was ich vor dem read request sende:

Code:
 byte[] communicationSetup = new byte[]
 {
     0x03,0x00,0x00,0x19,
     0x02,0xf0,0x80,
     0x32,0x01,0x00,0x00,0x00,0x02,0x00,
     0x08,0x00,0x00,0xf0,0x00,0x00,0x01,0x00,0x01,0x03,0xc0

 };

Als Antwort bekomme ich nun von der SPS:
Code:
Frame 142: 73 bytes on wire (584 bits), 73 bytes captured (584 bits) on interface \Device\NPF_{1xxxxD-3xxxxxxC8C6}, id 0
Ethernet II, Src: SiemensNumer_08:1b:cd (00:xxxxxb:cd), Dst: Intel_46:91:a5 (34:c9:xxxxxxa5)
Internet Protocol Version 4, Src: 192.168.178.9, Dst: 192.168.178.20
Transmission Control Protocol, Src Port: 102, Dst Port: 65367, Seq: 50, Ack: 79, Len: 19
TPKT, Version: 3, Length: 19
    Version: 3
    Reserved: 0
    Length: 19
ISO 8073/X.224 COTP Connection-Oriented Transport Protocol
    Length: 2
    PDU Type: DT Data (0x0f)
    [Destination reference: 0x1f0000]
    .000 0000 = TPDU number: 0x00
    1... .... = Last data unit: Yes
S7 Communication
    Header: (Ack)
        Protocol Id: 0x32
        ROSCTR: Ack (2)
        Redundancy Identification (Reserved): 0x0000
        Protocol Data Unit Reference: 1
        Parameter length: 0
        Data length: 0
        Error class: Error on supplies (0x85)
        Error code: 0x00
        [Error code: S7 protocol error: Wrong frames (0x8500)]

Was ja schon einen Schritt weiter ist :)
 
Genau, wie du richtig sagst, es muss die Reihenfolge eingehalten werden.
Connection Request - Setup Communication - ReadRequest

Ich denke aber du hast ein paar Telegramme vermischt, für mich wäre es einfacher wenn du mir den Export von Wireshark anhängst - ich denke deine Längenangaben in den Telegrammen sind falsch.
 
Juhuiu glaube das war der entscheidende Hinweis... :)
Code:
    Header: (Ack_Data)
        Protocol Id: 0x32
        ROSCTR: Ack_Data (3)
        Redundancy Identification (Reserved): 0x0000
        Protocol Data Unit Reference: 1
        Parameter length: 2
        Data length: 8
        Error class: No error (0x00)
        Error code: 0x00
    Parameter: (Read Var)
        Function: Read Var (0x04)
        Item count: 1
    Data
        Item [1]: (Success)
            Return code: Success (0xff)
            Transport size: BYTE/WORD/DWORD (0x04)
            Length: 4
            Data: 00220022

Viiiiiiiiielen vielen DANK !!!!

Jetzt kann ich meinen Code mal aufräumen, kommentieren und weiterspielen :)
 
Super wenn es jetzt funktioniert.
Falls du noch weitere Fragen hast, kannst du gerne anklopfen, ich habe damals auch eine Library geschrieben - vor allem bei großen Datenmengen wird das ganze sehr interessant ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Werde bestimmt auf dein Angebot zurückkommen :-) Bin mit C# noch weit am Anfang und das hier ist mächtig interessant zum ausprobieren. Muss aber die ganze Kommunikation und Adressierung besser verstehen.
 
Zurück
Oben