﻿<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
  <POU Name="UDP_handler" Id="{83ee5e09-d442-0094-0c87-3f9e62857880}" SpecialFunc="None">
    <Declaration><![CDATA[FUNCTION_BLOCK UDP_handler
VAR_INPUT
	config 				: REFERENCE TO ConfigUDP;
END_VAR
VAR
	socket 				: FB_ConnectionlessSocket;
	send 				: FB_SocketUdpSendTo;
	state				: UINT;
	watchdog 			: TON;			// will reset system if no data are sent
	sendTimer			: TON;			// triggers transmission at given intervals
	fbSocketCloseAll 	: FB_SocketCloseAll;
	bCloseAll 			: BOOL := TRUE;

END_VAR


]]></Declaration>
    <Implementation>
      <ST><![CDATA[IF bCloseAll THEN   	//On error, PLC reset or program download close all old connections 
	bCloseAll := FALSE;
	fbSocketCloseAll( sSrvNetId:= '', bExecute:= TRUE, tTimeout:= T#10S );
	state := 0;
ELSE
	fbSocketCloseAll( bExecute:= FALSE );
END_IF
IF fbSocketCloseAll.bBusy THEN
	RETURN;
END_IF


sendTimer(IN := NOT sendTimer.Q, PT := T#35MS); // Send every 50mS

watchdog(IN:= TRUE, PT := T#10S);		// watchdog will reset UDP if no messages are sent within the specified time period
IF watchdog.Q THEN
	bCloseAll := TRUE;
END_IF

CASE state OF
	0:		// initial step
		socket(bEnable := FALSE);
		state := 10;
		
	10:		// create socket
		socket(bEnable := TRUE, nMode :=  SEL(config.enableDebug, 0, CONNECT_MODE_ENABLEDBG),  sLocalHost := '10.183.6.170',  nLocalPort := config.localIpPort,  tReconnect := T#30S);
		state := 20;
		
	20:		// wait for soket to be created
		socket();
		IF  socket.bError THEN 
			state := 0;
		ELSIF (socket.eState = eSOCKET_CREATED) THEN
			state := 25;
		END_IF
		
	25:		// config UDP sender
		send.sRemoteHost := config.RxIPaddress; // REMOTE_IP;
		send.nRemotePort := config.RxIpPort;
		send.hSocket:= socket.hSocket;
		send.cbLen := 30; // Only send relevant data, not the full struct  SIZEOF(ObjModbus.data.bytes)+1, 
		send.pSrc :=  ADR(ObjModbus.data.bytes); 
		send.tTimeout := T#10S;
		state := 30;
	
	30:		// startSendUDP
		socket();
		send(bExecute := FALSE );
		IF sendTimer.Q THEN
			send(bExecute := TRUE);
			state := 40;
			watchdog(IN:= FALSE); // reset watchdog
		END_IF
		
	40:		// waitForUDP to finish 
		socket();
		send(bExecute := FALSE );	
		IF send.bBusy THEN // still working
			; //send();
		ELSE
			//send(bExecute := FALSE );
			IF  NOT (socket.eState = eSOCKET_CREATED) OR socket.bError THEN
				state := 0;
			ELSIF NOT socket.bBusy THEN		// ready to send again
				state := 30; 
			END_If	
		END_IF				
END_CASE]]></ST>
    </Implementation>
  </POU>
</TcPlcObject>