Oscat IP_CONTROL / Socket Verbindung aufbauen

philipp75

Level-2
Beiträge
67
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo SPS-Gurus,

ich möchte ein Endgerät im LAN per Socket ansprechen. Das Protokoll läuft wie folgt ab:

- Sende 00 00 0b bc
- Sende 00 00 00 00
- Empfange ca. 800 BYTE Daten

Angehängt noch ein über ein PHP-Skript erzeugter Datenaustausch, der einwandfrei funktioniert (Wireshark Screenshot)

nach zahllosen fehlgeschlagenen Versuchen mit SysLibSockets habe ich nun den IP_CONTROL Baustein aus oscat integriert, das Problem bleibt aber ein ähnliches.
Es scheint so, dass der Versand des Pakets eher zufällig klappt, ich vermute daher meinen Fehler in der State-Maschine.

Das Programm sieht wie folgt aus, nud läuft im Hauptzyklus - separate Tasks sind nicht eingerichtet:

Wenn z.B. iStep 0 durchlaufen wird und auf iStep 1 umgestellt wird, was passiert dann mit den/dem Paket aus dem IPClient, wird das ggf. noch empfangen, verarbeitet... oder ist dann direkt Schluss und IPClient2 macht weiter?
Wie kann auf solche Events bei iStep = 1 weiter gewartet werden?

Vielen herzlichen Dank!


Code:
PROGRAM PRG_LWP_SOCKET
VAR_INPUT
   xSend            : BOOL := FALSE;
END_VAR
VAR
       (* Relevante Werte *)
       (* siehe globale Variablenliste *)
    IP_C                    : IP_C;
    IP_FIFO                : IP_FIFO;
    IPClient                : IP_CONTROL;
    IPClient2                : IP_CONTROL;
    IP_STATE                : BYTE;
    IP_ID                    : BYTE;
    R_BUF                : NETWORK_BUFFER;
    S_BUF                       : NETWORK_BUFFER;
    xBusy                    : BOOL := FALSE;
    iStep                    : UINT := 0;
    FB_CONVERT           : FB_BYTESWAP_DWORD;
    FB_SOCK_ERROR    : SysSockGetLastError;
END_VAR

Code:
(* IF the send command is active AND the system is busy, ignore the send request *)
IF xSend THEN
    (* Init status variables *)
       xSend := FALSE;
       xBusy := TRUE;
    iStep := 0;


    S_BUF.SIZE := 0; (* reset send-buffer *)


    IP_C.C_PORT := uiPort;
    IP_C.C_IP := IP4_DECODE('192.168.50.120');
    IP_C.C_MODE := 0;
    IP_C.TIME_RESET := TRUE;
    IP_C.R_OBSERVE := TRUE;
END_IF


IF xBusy THEN
   CASE iStep OF
      0: (* SEND Paket 1 *)


            S_BUF.BUFFER[0] := 16#00;
            S_BUF.BUFFER[1] := 16#00;
            S_BUF.BUFFER[2] := 16#0B;
            S_BUF.BUFFER[3] := 16#BC;
            S_BUF.SIZE := 4;


            IP_C.C_ENABLE := TRUE;
            IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
            R_BUF.SIZE := 0;
            iStep := 1;


      1: (* SEND Paket 2 *)
        IF IP_C.ERROR  = 0 THEN
            S_BUF.BUFFER[0] := 16#00;
            S_BUF.BUFFER[1] := 16#00;
            S_BUF.BUFFER[2] := 16#00;
            S_BUF.BUFFER[3] := 16#00;
            S_BUF.SIZE := 4;
            IP_C.C_ENABLE := TRUE;
            IPClient2(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
            R_BUF.SIZE := 0;
            iStep := 2;
        END_IF


    2: (* RECEIVE *)
        IF IP_C.ERROR  = 0 AND R_BUF.SIZE > 300 THEN
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[0], VAR_OUT => status);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[18], VAR_OUT => tempAussen);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[13], VAR_OUT => tempVorlauf);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[14], VAR_OUT => tempRuecklauf);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[15], VAR_OUT => tempVorlaufS);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[20], VAR_OUT => tempWWIst);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[21], VAR_OUT => tempWWSoll);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[24], VAR_OUT => tempMKVLIst);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[25], VAR_OUT => tempMKVLSoll);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[154], VAR_OUT => kwhHeizung);
            FB_CONVERT(VAR_IN := R_BUF.BUFFER[155], VAR_OUT => kwhWasser);
        ELSE
            iStep := 10;
            xBusy := FALSE;
        END_IF


    10:
        IP_C.C_ENABLE := FALSE;


     END_CASE;

(** nicht genutzt
IP_FIFO(FIFO:=IP_C.FIFO,STATE:=IP_STATE,ID:=IP_ID);
IP_C.FIFO:=IP_FIFO.FIFO;
IP_STATE := IP_FIFO.STATE;
IP_ID:=IP_FIFO.ID;
*)



END_IF
 

Anhänge

  • Unbenannt.jpg
    Unbenannt.jpg
    61,7 KB · Aufrufe: 7
Ein Update und eine Verbesserung der State Maschine liefern nun endlich genau einmal das richtige Protokoll bzw. den Ablauf.
Nun scheint es aber so, dass die Verbindung nicht sauber schließt, oder die Socket offen bleibt oder oder oder.

Ein einem Zweiten Aufruf (iStep wieder auf 0, xBusy auf FALSE und xSend auf TRUE) wird nur noch ein 00 00 Paket geschickt. dann läuft der Status nach xStep 10.
Beim Dritten Aufruf erhalte ich in der Varbiable IP_C.C_ERROR einen Fehler - in Hex FD .... das laut documentation der oscat lib bedeutet: Wert 253 – Verbindung von Remote beendet.

Beim erneuten Starten des Programms klappts meistens wieder, dann wie gehabt - Fehler, Fehler, OK... (vermutlich nicht 100% deterministisch)

Wie schließt man die Verbindung also sauber. Ich kann ja nur IP_C.C_ENABLE auf False setzen meine ich?

Hier die 3 Verbindungsversuche im Wireshark (sorry für das Gekrakel)
Unbenannt2.jpg

Und das Code Update (Variablendeklarationen sind gleich geblieben)
Code:
(* IF the send command is active AND the system is busy, ignore the send request *)
IF xSend THEN
    (* Init status variables *)
       xSend := FALSE;
       xBusy := TRUE;
    iStep := 0;


    S_BUF.SIZE := 0; (* reset send-buffer *)


    IP_C.C_PORT := uiPort;
    IP_C.C_IP := IP4_DECODE('192.168.50.120');
    IP_C.C_MODE := 0;
    IP_C.TIME_RESET := TRUE;
    IP_C.R_OBSERVE := TRUE;
    IP_C.C_ENABLE := TRUE;
    IPClient.TIME_OUT := T#500ms;
END_IF


IF xBusy THEN
   CASE iStep OF
      0: (* SEND Paket 1 *)


        S_BUF.BUFFER[0] := 16#00;
        S_BUF.BUFFER[1] := 16#00;
        S_BUF.BUFFER[2] := 16#0B;
        S_BUF.BUFFER[3] := 16#BC;
        S_BUF.SIZE := 4;


        IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
        R_BUF.SIZE := 0;
        IF IP_C.C_STATE = 255  THEN
            iStep := 1;
        END_IF


      1: (* SEND Paket 2 *)
        S_BUF.BUFFER[0] := 16#00;
        S_BUF.BUFFER[1] := 16#00;
        S_BUF.BUFFER[2] := 16#00;
        S_BUF.BUFFER[3] := 16#00;
        S_BUF.SIZE := 4;
        IPClient(IP_C := IP_C, S_BUF := S_BUF, R_BUF := R_BUF);
        R_BUF.SIZE := 0;
        IF IP_C.C_STATE = 255 OR IP_C.C_STATE = 1 THEN
            iStep := 2;
        END_IF
        IF IP_C.ERROR  = 0 THEN
            iStep := 10;
        END_IF


    2: (* CONVERT *)
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[0], VAR_OUT => status);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[18], VAR_OUT => tempAussen);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[13], VAR_OUT => tempVorlauf);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[14], VAR_OUT => tempRuecklauf);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[15], VAR_OUT => tempVorlaufS);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[20], VAR_OUT => tempWWIst);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[21], VAR_OUT => tempWWSoll);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[24], VAR_OUT => tempMKVLIst);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[25], VAR_OUT => tempMKVLSoll);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[154], VAR_OUT => kwhHeizung);
        FB_CONVERT(VAR_IN := R_BUF.BUFFER[155], VAR_OUT => kwhWasser);
        iStep := 10;


    10:
        IP_C.C_ENABLE := FALSE;
        IF IP_C.C_STATE = 0 THEN
            xBusy := FALSE;
            iStep := 0;
        END_IF


     END_CASE;
(*
IP_FIFO(FIFO:=IP_C.FIFO,STATE:=IP_STATE,ID:=IP_ID);
IP_C.FIFO:=IP_FIFO.FIFO;
IP_STATE := IP_FIFO.STATE;
IP_ID:=IP_FIFO.ID;


*)
END_IF

Again: 1000 Dank!
 
Zuletzt bearbeitet:
Zurück
Oben