This is ST code running on a PLC, apparently it’s a client, that connects to a server running in Labview.
I need to create a tcp server in c# to talk to it. Any chance of breaking down what’s happening here?
// Start sequence when Trigger changes to TRUE.
IF ( (Enable=TRUE) AND (DoTCP=FALSE) AND (_Eip_EtnOnlineSta=TRUE) ) THEN
DoTCP:=TRUE;
IF (TCP_Conn_Status = _CLOSED) OR (TCP_Conn_Status = _CLOSE_WAIT) OR (TCP_Conn_Status = _CLOSING) THEN //(TCP_Conn_Status <> _ESTABLISHED) THEN
Stage := 1; //try connect if not estabilished yet
ELSE
Stage:=2; //only check status, avoid open another port and lose sync.
END_IF;
SktTCPConnect_instance(Execute:=FALSE); // Initialize instance.
SktClearBuf_instance(Execute:=FALSE); // Initialize instance.
SktGetTCPStatus_instance(Execute:=FALSE); // Initialize instance.
SktTCPSend_instance( // Initialize instance.
Execute:=FALSE,
SendDat:= dummy_dat(0)); // Dummy
SktTCPRcv_instance( // Initialize instance.
Execute:=FALSE,
RcvDat :=dummy_dat(0)); // Dummy
SktClose_instance(Execute:=FALSE); // Initialize instance.
END_IF;
IF (DoTCP=TRUE) THEN
CASE Stage OF
1: // Request a connection.
SktTCPConnect_instance(
Execute :=TRUE,
SrcTcpPort:=UINT#0, // Local TCP port number: Automatically assigned.
DstAdr :=IP_Address, // Remote IP address
DstTcpPort:=Remote_Port, // Destination TCP port number
Socket =>TCP_Conn_WkSocket); // Socket
IF (SktTCPConnect_instance.Done=TRUE) THEN
Stage:=INT#2; //check TCP status
ELSIF (SktTCPConnect_instance.Error=TRUE) THEN
error_ID := (SktTCPConnect_instance.ErrorID);
//TCP_Conn_Status := _CLOSED;
IF (error_ID = WORD#16#2008) THEN //never lock error to else state
Stage:=INT#6; //errorID=2008 - Socket Communications Resource Overflow
ELSE
Stage:=INT#2; // always check TCP status
END_IF;
END_IF;
2: //request status
SktGetTCPStatus_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket); // Socket
IF (SktGetTCPStatus_instance.Done) THEN
TCP_Conn_Status := SktGetTCPStatus_instance.TcpStatus;
IF (TCP_Conn_Status <> _ESTABLISHED) THEN //(TCP_Conn_Status = _CLOSED) OR (TCP_Conn_Status = _CLOSE_WAIT) OR (TCP_Conn_Status = _CLOSING) THEN
Stage:=INT#0; //go to end
ELSE
Stage:=INT#3; //continue normal flow
END_IF;
ELSIF (SktGetTCPStatus_instance.Error=TRUE) THEN
error_ID:=(SktGetTCPStatus_instance.ErrorID);
Stage:=INT#20; // Error end
END_IF;
3: // sending message
Payload_local:= Payload_Client_IN;
Msg_size_byte := CRC_size_byte + ToAryByte(Payload_local,_LOW_HIGH,SendSocketDat(0)) + UINT#2; ////payload size + CRC (bytes)
Msg_size:= ToAryByte(Msg_size_byte,_LOW_HIGH,SendSocketDat(0)); //replace first two bytes with payload + CRC size
Msg_size_byte :=ToAryByte(Payload_local,_LOW_HIGH,SendSocketDat(2)); //replace rest of the array with palyload as bytes
Payload_CRC_send := AryCRCCCITT(SendSocketDat(0),(Msg_size_byte+Msg_size),WORD#0,_LOW_HIGH); //calculates (size +payload) CRC
Msg_size_CRC :=ToAryByte(Payload_CRC_send,_LOW_HIGH,SendSocketDat(Msg_size_byte+Msg_size)); //append CRC as bytes to the end of the array
SktTCPSend_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket, // Socket
SendDat:= SendSocketDat(0),// TCP_Message_Send(0), // Send data
Size := Msg_size_byte+Msg_size+Msg_size_CRC); // msg payload + payload size + CRC 16
IF (SktTCPSend_instance.Done=TRUE) THEN
Stage:=INT#4; // go to read buffer
SktTCPSend_instance( // reinitialize instance.
Execute:=FALSE,
SendDat:= dummy_dat(0));
SktTCPRcv_instance( //reset instance
Execute:=FALSE,
RcvDat :=dummy_dat(0));
ELSIF (SktTCPSend_instance.Error=TRUE) THEN
error_ID:=( SktTCPSend_instance.ErrorID);
IF (error_ID = WORD#16#2006) THEN // OR error_ID = WORD#16#2003) THEN
Stage:=INT#5; // time out - clear buffer only
ELSE
Stage:=INT#30; // Error end
END_IF;
END_IF;
4: // Request receiving message size only
SktTCPRcv_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket, // Socket
TimeOut:=UINT#10, // Timeout time: 1 x (0.1 sec)
Size :=UINT#2, // Receive data size
RcvDat := RcvSocketDat(0)); // Receive data
IF (SktTCPRcv_instance.Done=TRUE) THEN
Stage:=INT#41; // Normal end
SktTCPRcv_instance( //reset instance
Execute:=FALSE,
RcvDat :=dummy_dat(0));
ELSIF (SktTCPRcv_instance.Error=TRUE) THEN
error_ID:=(SktTCPRcv_instance.ErrorID);
IF (error_ID = WORD#16#2006) THEN // OR error_ID = WORD#16#2003) THEN
Stage:=INT#5; // time out - clear buffer only
ELSE
Stage:=INT#40;
END_IF;
END_IF;
41: // Request receiving payload
AryByteTo (RcvSocketDat(0),UINT#2,_LOW_HIGH,Msg_size_byte_send); //convert byte array to message size
SktTCPRcv_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket, // Socket
TimeOut:=UINT#10, // Timeout time 10 x 0.1s - 1sec
Size :=Msg_size_byte_send, // Receive data size
RcvDat := RcvSocketDat(2)); // Receive data
IF (SktTCPRcv_instance.Done=TRUE) THEN
Stage:=INT#5; // normal end
Payload_CRC_receive_recalc:= AryCRCCCITT(RcvSocketDat(0),Msg_size_byte_send,WORD#0,_LOW_HIGH); //calculate CRC from received message (add size, but exclude CRC on the payload)
AryByteTo(RcvSocketDat(Msg_size_byte_send),UINT#2,_LOW_HIGH,Payload_CRC_receive);
IF (Payload_CRC_receive = Payload_CRC_receive_recalc) then
payload_received:=AryByteTo(RcvSocketDat(2),Msg_size_byte_send - UINT#2,_LOW_HIGH,Payload_Server_OUT); //convert array of bytes to dta type, excluding msg size and CRC
END_IF;
ELSIF (SktTCPRcv_instance.Error=TRUE) THEN
error_ID:=(SktTCPRcv_instance.ErrorID);
IF (error_ID = WORD#16#2006) THEN // OR error_ID = WORD#16#2003) THEN
Stage:=INT#5; // time out - clear buffer only
ELSE
Stage:=INT#410;
END_IF;
END_IF;
5: // Clear receive buffer.
SktClearBuf_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket); // Socket
IF (SktClearBuf_instance.Done=TRUE) THEN
Stage:=INT#0; // check connection
ELSIF (SktClearBuf_instance.Error=TRUE) THEN
error_ID:=(SktClearBuf_instance.ErrorID);
Stage:=INT#50; // Error end
END_IF;
6: // Request closing.
SktClose_instance(
Execute:=TRUE,
Socket :=TCP_Conn_WkSocket); // Socket
IF (SktClose_instance.Done=TRUE) THEN
Stage:=INT#0; // Normal end
TCP_Conn_Status:= _CLOSED;
ELSIF (SktClose_instance.Error=TRUE) THEN
error_ID:=(SktClose_instance.ErrorID);
IF (SktClose_instance.ErrorID = WORD#16#2007) THEN//errrorID = 2007 --> Socket Handle Out of Range(closed)
Stage:=0;
//TCP_Conn_Status:= _CLOSED;
ELSE
Stage:=INT#60; // Error end
END_IF;
END_IF;
0: // Normal end
DoTCP :=FALSE;
Done:= TRUE;
SktTCPSend_instance( // reinitialize instance.
Execute:=FALSE,
SendDat:= dummy_dat(0));
SktTCPRcv_instance( //reset instance
Execute:=FALSE,
RcvDat :=dummy_dat(0));
ELSE // Interrupted by error.
IF (error_ID = WORD#16#2003 OR error_ID = WORD#16#2008) THEN //Socket Status Error
//Stage:=UINT#2; //force reopen
//error_ID:=WORD#16#0;
TCP_Conn_Status:= _CLOSED;
//TCP_Conn_Status:= TCP_Conn_Status;
END_IF;
DoTCP :=FALSE;//use FALSE to reset states, use TRUE to trap error during debug
Done := FALSE;
SktTCPSend_instance( // reinitialize instance.
Execute:=FALSE,
SendDat:= dummy_dat(0));
SktTCPRcv_instance( //reset instance
Execute:=FALSE,
RcvDat :=dummy_dat(0));
//END_IF;
END_CASE;
END_IF;