CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum by 3S-Smart Software Solutions GmbH | A member of the CODESYS Group
Deutsche Version English version russian version 
It is currently Sun Dec 16, 2018 6:58 pm

All times are UTC+01:00




Post new topic  Reply to topic  [ 4 posts ] 
Author Message
 Post subject: TCP Socket communication
PostPosted: Thu Nov 08, 2018 11:42 am 
Offline

Joined: Fri Sep 07, 2018 1:51 pm
Posts: 6
I am writing a client reading data from another device using TCP socket (STREAM type). The Codesys program runs in PLC PiXtend (Raspberry Pi based PLC). The socket is created and connected successfully. The function sending data (SysSockSend) returns success and 81 bytes of sent data. Subsequent call to of SysSockRecv() return RTS_IEC_RESULT = 529 (Socket has been gracefully closed. No more sends/receives allowed.). What is wrong in my code???

Code:
VAR
   sDataSend   :STRING;
   sDataRecv   :STRING(4095);

   // IP Socket support
   addressPointer    :POINTER TO SOCKADDRESS;
    address           :SOCKADDRESS;
    ip                  :STRING(16) := '10.0.0.138';
    port               :WORD := 1367;

   iecCreateResult      :RTS_IEC_RESULT;
   iecConnectResult   :RTS_IEC_RESULT;
   iecSendResult        :RTS_IEC_RESULT;
   iecRecvResult        :RTS_IEC_RESULT;
   iecResultClose      :RTS_IEC_RESULT;
   iecResultShutdown   :RTS_IEC_RESULT;
   
    iecSocketId           :RTS_IEC_HANDLE := 0;
   xiSentBytes           :__XINT;
   xiRecvBytes           :__XINT;
END_VAR

  ...
   // Create address
   SysSockInetAddr(ip, ADR(address.sin_addr));
   address.sin_family := SOCKET_AF_INET;
   address.sin_port := SysSockHtons(port);
   addressPointer := ADR(address);
   
   // Create socket
   iecSocketId := SysSockCreate(SOCKET_AF_INET, SOCKET_STREAM, 0, ADR(iecCreateResult));
   IF iecSocketId = RTS_INVALID_HANDLE THEN
     // Socket creation failed
     ...
   ELSE
      // Connect socket
      iecConnectResult := SysSockConnect(iecSocketId, addressPointer, SIZEOF(address));

      // Send data   
       xiSentBytes := SysSockSend(iecSocketId, ADR(sDataSend), SIZEOF(sDataSend), 1, ADR(iecSendResult));
      IF xiSentBytes = 0 THEN
         // ... failed
         ...
      ELSE
         // Shudown sending data
         iecResultShutdown := SysSockShutdown(iecSocketId, SOCKET_SD_SEND);
         
         // Receive data
         // THIS CALL FAILS: iecRecvResult = 529
         xiRecvBytes := SysSockRecv(iecSocketId, ADR(sDataRecv), SIZEOF(sDataRecv), 1, ADR(iecRecvResult));
         IF xiRecvBytes = 0 THEN
            // ... failed
            ...
         ELSE
            // ... success: process result
            ...
         END_IF
      END_IF
   END_IF
   
   // Close socket after sending/getting data
   iecResultClose := SysSockClose(iecSocketId);
END_IF


Top
   
PostPosted: Thu Nov 08, 2018 3:15 pm 
Offline

Joined: Fri Sep 07, 2018 1:51 pm
Posts: 6
Additional information:
When I try to use simple Python script for same operation, it works well. In Codesys I only created same thing using another programming language.

Code:
import socket
from datetime import datetime

def netcat(host, port, content):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, int(port)))
    s.sendall(content.encode())
    s.shutdown(socket.SHUT_WR)
    result = ""
    while True:
       data = s.recv(4096)
       if not data:
            break
       result = result + data.decode()
    s.close()
    print(result)

HOST="10.0.0.138"
PORT=1367

netcat(HOST, PORT, "{\"id\":1,\"method\":\"sensor-list\",\"params\":[]}")


The Python script reads the result in a loop, my Codesys program reads it in 1 call without the loop. But an expected response is so short, that it must easily fit into a buffer in 1 call. Anyway I tried to read it in a loop too, but the result was 100% same. So the missing loops doesn't seem to be a reason of problem.


Top
   
PostPosted: Mon Nov 12, 2018 12:52 pm 
Offline

Joined: Fri Sep 07, 2018 1:51 pm
Posts: 6
No answer...… Hmmm..... I tried to rewrite using library Network/CAA Net Base Service 3.5.13.0. The code is below. Connection is OK. Sending data seems to send data successfully. Reading data... after some timeout (10s): "TCP_RECEIVE_ERROR" (code 6012).

Code:

PROGRAM POU_TCP_IFACE
VAR_INPUT
   xSend      :BOOL := FALSE;
   sDataSend      :STRING;
END_VAR
VAR
   strIPAddr      : NBS.IP_ADDR;
   uiPort      : UINT;
   
   nwClient       : NBS.TCP_Client;   
   nwTCPWrite    : NBS.TCP_Write;
   nwTCPRead    : NBS.TCP_Read;
   
   sDataRecv      :STRING := '';            // Final result value
   sDataBuff       :STRING(4095);            // Buffer for composing result string
   xBusy      :BOOL := FALSE;
   xSuccess      :BOOL := FALSE;
   xError      :BOOL := FALSE;
   iErrorCode      :INT := 0;   
   
   iStep         :INT := 0;
END_VAR

// If the send command is active and the system is busy, ignore the send request
IF xSend THEN
   IF xBusy THEN
       xSend := FALSE;
   END_IF   
END_IF

IF xSend THEN
   strIPAddr.sAddr := '10.0.0.138';
   uiPort := 1367;
   
   // Init status variables
   xSend := FALSE;
   xBusy := TRUE;
   xSuccess := FALSE;
   xError := FALSE;
   iErrorCode := 0;   
   sDataRecv := '';
   iStep := 0;
   nwClient(xEnable := FALSE);
   nwTCPRead(xEnable := FALSE);
   nwTCPWrite(xExecute := FALSE);
END_IF

IF xBusy THEN
   CASE iStep OF
      0: // Prepare connection
         nwClient(xEnable := TRUE, ipAddr := strIPAddr, uiPort := uiPort, udiTimeOut := 10000000);   
         IF nwClient.xActive THEN
            // Successfuly connected
            iStep := 1;            // JUMP TO SEND DATA
         ELSIF nwClient.xError THEN
            // Error shile connection creation
            nwClient.xEnable := FALSE;
            xError := TRUE;
            iErrorCode := 1;      // Error creating connection: reason - 1
            xBusy := FALSE;
         ELSIF NOT nwClient.xActive AND NOT nwClient.xError AND nwClient.xDone THEN
            nwClient.xEnable := FALSE;
            xError := TRUE;      
            iErrorCode := 2;      // Error creating connection: reason - 2
            xBusy := FALSE;
         END_IF
         
      1: // Send data
         IF nwTCPWrite.xBusy = FALSE AND nwTCPWrite.xError = FALSE AND nwTCPWrite.xDone = FALSE THEN
            nwTCPWrite.hConnection := nwClient.hConnection;
            nwTCPWrite.pData := ADR(sDataSend);
            nwTCPWrite.szSize := INT_TO_UDINT(LEN(sDataSend));
            nwTCPWrite.udiTimeOut := 10000000;
            
            nwTCPWrite.xExecute := TRUE;
         END_IF
      
         IF nwTCPWrite.xDone = TRUE THEN
            // Data IS SENT!
            nwTCPWrite.xExecute := FALSE;
            iStep := 2;         // JUMP TO READ
         ELSIF nwTCPWrite.xError THEN
            // Send data ERROR
            nwTCPWrite.xExecute := FALSE;
            xError := TRUE;      
            iErrorCode := 3;      // Data write error
            xBusy := FALSE;
         ELSE
            nwTCPWrite();   
         END_IF   
      
      2: // Read data
         nwTCPRead(xEnable := TRUE,
                    hConnection := nwClient.hConnection,
                  szSize := SIZEOF(sDataBuff),
                  pData  := ADR(sDataBuff));
                  
         IF nwTCPRead.xReady AND nwTCPRead.eError = 0 THEN
            IF nwTCPRead.szCount > 0 THEN
               sDataRecv := sDataBuff;
            ELSE
               sDataRecv := '';
            END_IF
            xError := FALSE;
            iErrorCode := 0;      // No error
            xSuccess := TRUE;
            xBusy := FALSE;
         ELSIF nwTCPRead.eError <> 0 THEN
            xError := TRUE;
            iErrorCode := 4;      // Data read error
            xBusy := FALSE;
         END_IF
   END_CASE;
END_IF



Top
   
PostPosted: Wed Nov 14, 2018 3:15 pm 
Offline

Joined: Fri Sep 07, 2018 1:51 pm
Posts: 6
I tried to run the program under SIMULATION mode on my development PC. Simultaneously I ran also Wireshark to capture network communication between simu-PLC and the second device. Unfortunately under simulation mode it doesn't work. No socket is opened :-( The function returns zero socket handle but the result error code is also zero. Incredible! Therefore I cannot capture network traffic between PLC and controlled device. Crazy world!!!!!! :-(


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 4 posts ] 

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited